Only the most recent cpus support really 1cy 64-bit multiplies, and the X64 cost table represents a realistic worst case. The 1cy value was also discouraging vectorization when most vXi64 PMULDQ expansions aren't actually slower than scalarization. Noticed while investigating PR51436.
620 lines
21 KiB
LLVM
620 lines
21 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -S -indvars -indvars-predicate-loops=0 %s | FileCheck %s
|
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-unknown-linux-gnu"
|
|
|
|
define void @test1(i64 %start) {
|
|
; CHECK-LABEL: @test1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[START:%.*]], -1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, 1
|
|
%cmp1 = icmp slt i64 %indvars.iv, -1
|
|
br i1 %cmp1, label %for.end, label %loop
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @test2(i64 %start) {
|
|
; CHECK-LABEL: @test2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp sle i64 [[START:%.*]], -1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, 1
|
|
%cmp1 = icmp sle i64 %indvars.iv, -1
|
|
br i1 %cmp1, label %for.end, label %loop
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
; As long as the test dominates the backedge, we're good
|
|
define void @test3(i64 %start) {
|
|
; CHECK-LABEL: @test3(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: call void @foo()
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[START]], -1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END]], label [[LOOP]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, 1
|
|
%cmp = icmp eq i64 %indvars.iv.next, 25
|
|
br i1 %cmp, label %backedge, label %for.end
|
|
|
|
backedge:
|
|
; prevent flattening, needed to make sure we're testing what we intend
|
|
call void @foo()
|
|
%cmp1 = icmp slt i64 %indvars.iv, -1
|
|
br i1 %cmp1, label %for.end, label %loop
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @test4(i64 %start) {
|
|
; CHECK-LABEL: @test4(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: call void @foo()
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[START]], -1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP]], label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, 1
|
|
%cmp = icmp eq i64 %indvars.iv.next, 25
|
|
br i1 %cmp, label %backedge, label %for.end
|
|
|
|
backedge:
|
|
; prevent flattening, needed to make sure we're testing what we intend
|
|
call void @foo()
|
|
%cmp1 = icmp sgt i64 %indvars.iv, -1
|
|
br i1 %cmp1, label %loop, label %for.end
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @test5(i64 %start) {
|
|
; CHECK-LABEL: @test5(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: call void @foo()
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[START]], 100
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP]], label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
|
|
%indvars.iv.next = add nuw i64 %indvars.iv, 1
|
|
%cmp = icmp eq i64 %indvars.iv.next, 25
|
|
br i1 %cmp, label %backedge, label %for.end
|
|
|
|
backedge:
|
|
; prevent flattening, needed to make sure we're testing what we intend
|
|
call void @foo()
|
|
%cmp1 = icmp ugt i64 %indvars.iv, 100
|
|
br i1 %cmp1, label %loop, label %for.end
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @test6(i64 %start) {
|
|
; CHECK-LABEL: @test6(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: call void @foo()
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[START]], 100
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END]], label [[LOOP]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
|
|
%indvars.iv.next = add nuw i64 %indvars.iv, 1
|
|
%cmp = icmp eq i64 %indvars.iv.next, 25
|
|
br i1 %cmp, label %backedge, label %for.end
|
|
|
|
backedge:
|
|
; prevent flattening, needed to make sure we're testing what we intend
|
|
call void @foo()
|
|
%cmp1 = icmp ult i64 %indvars.iv, 100
|
|
br i1 %cmp1, label %for.end, label %loop
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @test7(i64 %start, i64* %inc_ptr) {
|
|
; CHECK-LABEL: @test7(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], align 8, !range [[RNG0:![0-9]+]]
|
|
; CHECK-NEXT: [[OK:%.*]] = icmp sge i64 [[INC]], 0
|
|
; CHECK-NEXT: br i1 [[OK]], label [[LOOP_PREHEADER:%.*]], label [[FOR_END:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[START:%.*]], -1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END_LOOPEXIT:%.*]], label [[LOOP]]
|
|
; CHECK: for.end.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%inc = load i64, i64* %inc_ptr, !range !0
|
|
%ok = icmp sge i64 %inc, 0
|
|
br i1 %ok, label %loop, label %for.end
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, %inc
|
|
%cmp1 = icmp slt i64 %indvars.iv, -1
|
|
br i1 %cmp1, label %for.end, label %loop
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
; Negative test - we can't show that the internal branch executes, so we can't
|
|
; fold the test to a loop invariant one.
|
|
define void @test1_neg(i64 %start) {
|
|
; CHECK-LABEL: @test1_neg(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[SKIP:%.*]]
|
|
; CHECK: skip:
|
|
; CHECK-NEXT: call void @foo()
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[BACKEDGE]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: call void @foo()
|
|
; CHECK-NEXT: br label [[LOOP]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, 1
|
|
%cmp = icmp eq i64 %indvars.iv.next, 25
|
|
br i1 %cmp, label %backedge, label %skip
|
|
skip:
|
|
; prevent flattening, needed to make sure we're testing what we intend
|
|
call void @foo()
|
|
%cmp1 = icmp slt i64 %indvars.iv, -1
|
|
br i1 %cmp1, label %for.end, label %backedge
|
|
backedge:
|
|
; prevent flattening, needed to make sure we're testing what we intend
|
|
call void @foo()
|
|
br label %loop
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
; Slightly subtle version of @test4 where the icmp dominates the backedge,
|
|
; but the exit branch doesn't.
|
|
define void @test2_neg(i64 %start) {
|
|
; CHECK-LABEL: @test2_neg(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[SKIP:%.*]]
|
|
; CHECK: skip:
|
|
; CHECK-NEXT: call void @foo()
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[BACKEDGE]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: call void @foo()
|
|
; CHECK-NEXT: br label [[LOOP]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, 1
|
|
%cmp = icmp eq i64 %indvars.iv.next, 25
|
|
%cmp1 = icmp slt i64 %indvars.iv, -1
|
|
br i1 %cmp, label %backedge, label %skip
|
|
skip:
|
|
; prevent flattening, needed to make sure we're testing what we intend
|
|
call void @foo()
|
|
br i1 %cmp1, label %for.end, label %backedge
|
|
backedge:
|
|
; prevent flattening, needed to make sure we're testing what we intend
|
|
call void @foo()
|
|
br label %loop
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
; The branch has to exit the loop if the condition is true
|
|
define void @test3_neg(i64 %start) {
|
|
; CHECK-LABEL: @test3_neg(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP]], label [[FOR_END:%.*]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, 1
|
|
%cmp1 = icmp slt i64 %indvars.iv, -1
|
|
br i1 %cmp1, label %loop, label %for.end
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @test4_neg(i64 %start) {
|
|
; CHECK-LABEL: @test4_neg(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: call void @foo()
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[INDVARS_IV]], -1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END]], label [[LOOP]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, 1
|
|
%cmp = icmp eq i64 %indvars.iv.next, 25
|
|
br i1 %cmp, label %backedge, label %for.end
|
|
|
|
backedge:
|
|
; prevent flattening, needed to make sure we're testing what we intend
|
|
call void @foo()
|
|
%cmp1 = icmp sgt i64 %indvars.iv, -1
|
|
|
|
; %cmp1 can be made loop invariant only if the branch below goes to
|
|
; %the header when %cmp1 is true.
|
|
br i1 %cmp1, label %for.end, label %loop
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @test5_neg(i64 %start, i64 %inc) {
|
|
; CHECK-LABEL: @test5_neg(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[INC:%.*]]
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, %inc
|
|
%cmp1 = icmp slt i64 %indvars.iv, -1
|
|
br i1 %cmp1, label %for.end, label %loop
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
define void @test8(i64 %start, i64* %inc_ptr) {
|
|
; CHECK-LABEL: @test8(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], align 8, !range [[RNG1:![0-9]+]]
|
|
; CHECK-NEXT: [[OK:%.*]] = icmp sge i64 [[INC]], 0
|
|
; CHECK-NEXT: br i1 [[OK]], label [[LOOP_PREHEADER:%.*]], label [[FOR_END:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[INC]]
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END_LOOPEXIT:%.*]], label [[LOOP]]
|
|
; CHECK: for.end.loopexit:
|
|
; CHECK-NEXT: br label [[FOR_END]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%inc = load i64, i64* %inc_ptr, !range !1
|
|
%ok = icmp sge i64 %inc, 0
|
|
br i1 %ok, label %loop, label %for.end
|
|
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, %inc
|
|
%cmp1 = icmp slt i64 %indvars.iv, -1
|
|
br i1 %cmp1, label %for.end, label %loop
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
; check to handle loops without preheaders, but invariant operands
|
|
; (we handle this today by inserting a preheader)
|
|
define void @test9(i1 %cnd, i64 %start) {
|
|
; CHECK-LABEL: @test9(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[CND:%.*]], label [[ENTRY1:%.*]], label [[ENTRY2:%.*]]
|
|
; CHECK: entry1:
|
|
; CHECK-NEXT: br label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: entry2:
|
|
; CHECK-NEXT: br label [[LOOP_PREHEADER]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[START:%.*]], -1
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]]
|
|
; CHECK: for.end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br i1 %cnd, label %entry1, label %entry2
|
|
entry1:
|
|
br label %loop
|
|
entry2:
|
|
br label %loop
|
|
loop:
|
|
%indvars.iv = phi i64 [ %start, %entry1 ],[ %start, %entry2 ], [ %indvars.iv.next, %loop ]
|
|
%indvars.iv.next = add nsw i64 %indvars.iv, 1
|
|
%cmp1 = icmp slt i64 %indvars.iv, -1
|
|
br i1 %cmp1, label %for.end, label %loop
|
|
|
|
for.end: ; preds = %if.end, %entry
|
|
ret void
|
|
}
|
|
|
|
declare void @use(i1 %x)
|
|
|
|
; check that we handle conditions with loop invariant operands which
|
|
; *aren't* in the header - this is a very rare and fragile case where
|
|
; we have a "loop" which is known to run exactly one iteration but
|
|
; haven't yet simplified the uses of the IV
|
|
define void @test10() {
|
|
; CHECK-LABEL: @test10(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[PHI2:%.*]], [[LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[DEC:%.*]] = add nuw nsw i32 [[PHI1]], -1
|
|
; CHECK-NEXT: br i1 false, label [[LEFT:%.*]], label [[RIGHT:%.*]]
|
|
; CHECK: left:
|
|
; CHECK-NEXT: br label [[LATCH]]
|
|
; CHECK: right:
|
|
; CHECK-NEXT: br label [[LATCH]]
|
|
; CHECK: latch:
|
|
; CHECK-NEXT: [[PHI2]] = phi i32 [ [[PHI1]], [[LEFT]] ], [ [[DEC]], [[RIGHT]] ]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 -1, undef
|
|
; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[CMP_LCSSA:%.*]] = phi i1 [ [[CMP]], [[LATCH]] ]
|
|
; CHECK-NEXT: call void @use(i1 [[CMP_LCSSA]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%phi1 = phi i32 [ %phi2, %latch ], [ 0, %entry ]
|
|
%dec = add i32 %phi1, -1
|
|
br i1 false, label %left, label %right
|
|
|
|
left:
|
|
br label %latch
|
|
|
|
right:
|
|
br label %latch
|
|
|
|
latch:
|
|
%phi2 = phi i32 [ %phi1, %left ], [ %dec, %right ]
|
|
%cmp = icmp slt i32 %phi2, undef
|
|
br i1 true, label %exit, label %loop
|
|
|
|
exit:
|
|
call void @use(i1 %cmp)
|
|
ret void
|
|
}
|
|
|
|
; check that we can figure out that iv.next > 1 from the facts that iv >= 0 and
|
|
; iv.start != 0.
|
|
define void @test11(i64* %inc_ptr) {
|
|
; CHECK-LABEL: @test11(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], align 8, !range [[RNG0]]
|
|
; CHECK-NEXT: [[NE_COND:%.*]] = icmp ne i64 [[INC]], 0
|
|
; CHECK-NEXT: br i1 [[NE_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[INC]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
|
|
; CHECK: if.true:
|
|
; CHECK-NEXT: br label [[BACKEDGE]]
|
|
; CHECK: if.false:
|
|
; CHECK-NEXT: br label [[BACKEDGE]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], 201
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%inc = load i64, i64* %inc_ptr, !range !0
|
|
%ne.cond = icmp ne i64 %inc, 0
|
|
br i1 %ne.cond, label %loop, label %exit
|
|
|
|
loop:
|
|
%iv = phi i64 [ %inc, %entry ], [ %iv.next, %backedge ]
|
|
%iv.next = add i64 %iv, 1
|
|
%brcond = icmp sgt i64 %iv.next, 1
|
|
br i1 %brcond, label %if.true, label %if.false
|
|
|
|
if.true:
|
|
br label %backedge
|
|
|
|
if.false:
|
|
br label %backedge
|
|
|
|
backedge:
|
|
%loopcond = icmp slt i64 %iv, 200
|
|
br i1 %loopcond, label %loop, label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; check that we can prove that a recurrency is greater than another recurrency
|
|
; in the same loop, with the same step, and with smaller starting value.
|
|
define void @test12(i64* %inc_ptr) {
|
|
; CHECK-LABEL: @test12(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], align 8, !range [[RNG0]]
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
|
|
; CHECK: if.true:
|
|
; CHECK-NEXT: br label [[BACKEDGE]]
|
|
; CHECK: if.false:
|
|
; CHECK-NEXT: br label [[BACKEDGE]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], 201
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%inc = load i64, i64* %inc_ptr, !range !0
|
|
%inc.minus.1 = sub i64 %inc, 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i64 [ %inc, %entry ], [ %iv.next, %backedge ]
|
|
%iv.minus.1 = phi i64 [ %inc.minus.1, %entry ], [ %iv.minus.1.next, %backedge ]
|
|
%iv.next = add i64 %iv, 1
|
|
%iv.minus.1.next = add i64 %iv.minus.1, 1
|
|
%brcond = icmp sgt i64 %iv.next, %iv.minus.1.next
|
|
br i1 %brcond, label %if.true, label %if.false
|
|
|
|
if.true:
|
|
br label %backedge
|
|
|
|
if.false:
|
|
br label %backedge
|
|
|
|
backedge:
|
|
%loopcond = icmp slt i64 %iv, 200
|
|
br i1 %loopcond, label %loop, label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
!0 = !{i64 0, i64 100}
|
|
!1 = !{i64 -1, i64 100}
|
|
|
|
declare void @foo()
|