[NFC][IndVarSimplify] Autogenerate tests affected by isHighCostExpansionHelper() cost modelling (PR44668)

This commit is contained in:
Roman Lebedev 2020-01-27 23:22:30 +03:00
parent c3075e6171
commit 9c801c48ee
No known key found for this signature in database
GPG Key ID: 083C3EBB4A1689E0
7 changed files with 732 additions and 191 deletions

View File

@ -1,41 +0,0 @@
; PR28705
; RUN: opt < %s -indvars -S | FileCheck %s
; Check IndVarSimplify doesn't replace external use of the induction var
; "%inc.i.i" with "%.sroa.speculated + 1" because it is not profitable.
;
; CHECK-LABEL: @foo(
; CHECK: %[[EXIT:.+]] = phi i32 [ %inc.i.i, %for.body650 ]
; CHECK: %DB.sroa.9.0.lcssa = phi i32 [ 1, %entry ], [ %[[EXIT]], %loopexit ]
;
define void @foo(i32 %sub.ptr.div.i, i8* %ref.i1174) local_unnamed_addr {
entry:
%cmp.i1137 = icmp ugt i32 %sub.ptr.div.i, 3
%.sroa.speculated = select i1 %cmp.i1137, i32 3, i32 %sub.ptr.div.i
%cmp6483126 = icmp eq i32 %.sroa.speculated, 0
br i1 %cmp6483126, label %XZ.exit, label %for.body650.lr.ph
for.body650.lr.ph:
br label %for.body650
loopexit:
%inc.i.i.lcssa = phi i32 [ %inc.i.i, %for.body650 ]
br label %XZ.exit
XZ.exit:
%DB.sroa.9.0.lcssa = phi i32 [ 1, %entry ], [ %inc.i.i.lcssa, %loopexit ]
br label %end
for.body650:
%iv = phi i32 [ 0, %for.body650.lr.ph ], [ %inc655, %for.body650 ]
%iv2 = phi i32 [ 1, %for.body650.lr.ph ], [ %inc.i.i, %for.body650 ]
%arrayidx.i.i1105 = getelementptr inbounds i8, i8* %ref.i1174, i32 %iv2
store i8 7, i8* %arrayidx.i.i1105, align 1
%inc.i.i = add i32 %iv2, 1
%inc655 = add i32 %iv, 1
%cmp648 = icmp eq i32 %inc655, %.sroa.speculated
br i1 %cmp648, label %loopexit, label %for.body650
end:
ret void
}

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -indvars -S | FileCheck %s
; This tests that the IV is not recomputed outside of the loop when it is known
@ -21,8 +22,23 @@
declare void @func(i32)
; CHECK-LABEL: @test(
define void @test(i32 %m) nounwind uwtable {
; CHECK-LABEL: @test(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
; CHECK-NEXT: tail call void @func(i32 [[ADD]])
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
; CHECK: for.end:
; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
; CHECK-NEXT: tail call void @func(i32 [[ADD_LCSSA]])
; CHECK-NEXT: ret void
;
entry:
br label %for.body
@ -30,23 +46,32 @@ for.body: ; preds = %for.body, %entry
%i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
%a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
%add = add i32 %a.05, %m
; CHECK: tail call void @func(i32 %add)
tail call void @func(i32 %add)
%inc = add nsw i32 %i.06, 1
%exitcond = icmp eq i32 %inc, 186
br i1 %exitcond, label %for.end, label %for.body
for.end: ; preds = %for.body
; CHECK: for.end:
; CHECK-NOT: mul i32 %m, 186
; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
; CHECK-NEXT: tail call void @func(i32 %add.lcssa)
tail call void @func(i32 %add)
ret void
}
; CHECK-LABEL: @test2(
define i32 @test2(i32 %m) nounwind uwtable {
; CHECK-LABEL: @test2(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
; CHECK-NEXT: tail call void @func(i32 [[ADD]])
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
; CHECK: for.end:
; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
;
entry:
br label %for.body
@ -54,22 +79,32 @@ for.body: ; preds = %for.body, %entry
%i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
%a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
%add = add i32 %a.05, %m
; CHECK: tail call void @func(i32 %add)
tail call void @func(i32 %add)
%inc = add nsw i32 %i.06, 1
%exitcond = icmp eq i32 %inc, 186
br i1 %exitcond, label %for.end, label %for.body
for.end: ; preds = %for.body
; CHECK: for.end:
; CHECK-NOT: mul i32 %m, 186
; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
; CHECK-NEXT: ret i32 %add.lcssa
ret i32 %add
}
; CHECK-LABEL: @test3(
define void @test3(i32 %m) nounwind uwtable {
; CHECK-LABEL: @test3(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
; CHECK-NEXT: tail call void @func(i32 [[ADD]])
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
; CHECK: for.end:
; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
; CHECK-NEXT: tail call void @func(i32 [[ADD_LCSSA]])
; CHECK-NEXT: ret void
;
entry:
br label %for.body
@ -83,23 +118,34 @@ for.body: ; preds = %for.body, %entry
mul i32 %add, 1
mul i32 %add, 1
mul i32 %add, 1
; CHECK: tail call void @func(i32 %add)
tail call void @func(i32 %add)
%inc = add nsw i32 %i.06, 1
%exitcond = icmp eq i32 %inc, 186
br i1 %exitcond, label %for.end, label %for.body
for.end: ; preds = %for.body
; CHECK: for.end:
; CHECK-NOT: mul i32 %m, 186
; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
; CHECK-NEXT: tail call void @func(i32 %add.lcssa)
tail call void @func(i32 %add)
ret void
}
; CHECK-LABEL: @test4(
define void @test4(i32 %m) nounwind uwtable {
; CHECK-LABEL: @test4(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
; CHECK-NEXT: tail call void @func(i32 [[ADD]])
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
; CHECK: for.end:
; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
; CHECK-NEXT: [[SOFT_USE:%.*]] = add i32 [[ADD_LCSSA]], 123
; CHECK-NEXT: tail call void @func(i32 [[SOFT_USE]])
; CHECK-NEXT: ret void
;
entry:
br label %for.body
@ -107,25 +153,35 @@ for.body: ; preds = %for.body, %entry
%i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
%a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
%add = add i32 %a.05, %m
; CHECK: tail call void @func(i32 %add)
tail call void @func(i32 %add)
%inc = add nsw i32 %i.06, 1
%exitcond = icmp eq i32 %inc, 186
br i1 %exitcond, label %for.end, label %for.body
for.end: ; preds = %for.body
; CHECK: for.end:
; CHECK-NOT: mul i32 %m, 186
; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
; CHECK-NEXT: %soft_use = add i32 %add.lcssa, 123
; CHECK-NEXT: tail call void @func(i32 %soft_use)
%soft_use = add i32 %add, 123
tail call void @func(i32 %soft_use)
ret void
}
; CHECK-LABEL: @test5(
define void @test5(i32 %m) nounwind uwtable {
; CHECK-LABEL: @test5(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
; CHECK-NEXT: [[SOFT_USE:%.*]] = add i32 [[ADD]], 123
; CHECK-NEXT: tail call void @func(i32 [[SOFT_USE]])
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
; CHECK: for.end:
; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
; CHECK-NEXT: tail call void @func(i32 [[ADD_LCSSA]])
; CHECK-NEXT: ret void
;
entry:
br label %for.body
@ -134,23 +190,35 @@ for.body: ; preds = %for.body, %entry
%a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
%add = add i32 %a.05, %m
%soft_use = add i32 %add, 123
; CHECK: tail call void @func(i32 %soft_use)
tail call void @func(i32 %soft_use)
%inc = add nsw i32 %i.06, 1
%exitcond = icmp eq i32 %inc, 186
br i1 %exitcond, label %for.end, label %for.body
for.end: ; preds = %for.body
; CHECK: for.end:
; CHECK-NOT: mul i32 %m, 186
; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
; CHECK-NEXT: tail call void @func(i32 %add.lcssa)
tail call void @func(i32 %add)
ret void
}
; CHECK-LABEL: @test6(
define void @test6(i32 %m, i32* %p) nounwind uwtable {
; CHECK-LABEL: @test6(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
; CHECK-NEXT: [[SOFT_USE:%.*]] = add i32 [[ADD]], 123
; CHECK-NEXT: [[PIDX:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 [[ADD]]
; CHECK-NEXT: store i32 [[SOFT_USE]], i32* [[PIDX]]
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
; CHECK: for.end:
; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
; CHECK-NEXT: tail call void @func(i32 [[ADD_LCSSA]])
; CHECK-NEXT: ret void
;
entry:
br label %for.body
@ -159,7 +227,6 @@ for.body: ; preds = %for.body, %entry
%a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
%add = add i32 %a.05, %m
%soft_use = add i32 %add, 123
; CHECK: store i32 %soft_use, i32* %pidx
%pidx = getelementptr i32, i32* %p, i32 %add
store i32 %soft_use, i32* %pidx
%inc = add nsw i32 %i.06, 1
@ -167,10 +234,6 @@ for.body: ; preds = %for.body, %entry
br i1 %exitcond, label %for.end, label %for.body
for.end: ; preds = %for.body
; CHECK: for.end:
; CHECK-NOT: mul i32 %m, 186
; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
; CHECK-NEXT: tail call void @func(i32 %add.lcssa)
tail call void @func(i32 %add)
ret void
}

View File

@ -128,6 +128,7 @@ exit:
; Force SCEVExpander to look for an existing well-formed phi.
; Perform LFTR without generating extra preheader code.
define void @guardedloop([0 x double]* %matrix, [0 x double]* %vector,
;
; CHECK-LABEL: @guardedloop(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 1, [[IROW:%.*]]
@ -183,6 +184,7 @@ return:
; Avoid generating extra code to materialize a trip count. Skip LFTR.
define void @unguardedloop([0 x double]* %matrix, [0 x double]* %vector,
;
; CHECK-LABEL: @unguardedloop(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[IROW:%.*]] to i64

View File

@ -1,16 +1,24 @@
; 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-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
; CHECK: %cmp1 = icmp slt i64 %start, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
@ -19,14 +27,21 @@ for.end: ; preds = %if.end, %entry
}
define void @test2(i64 %start) {
; CHECK-LABEL: @test2
; 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
; CHECK: %cmp1 = icmp sle i64 %start, -1
%cmp1 = icmp sle i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
@ -36,7 +51,21 @@ for.end: ; preds = %if.end, %entry
; As long as the test dominates the backedge, we're good
define void @test3(i64 %start) {
; CHECK-LABEL: @test3
; 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
@ -48,8 +77,7 @@ loop:
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp slt i64 %start, -1
call void @foo()
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
@ -58,7 +86,21 @@ for.end: ; preds = %if.end, %entry
}
define void @test4(i64 %start) {
; CHECK-LABEL: @test4
; 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
@ -70,8 +112,7 @@ loop:
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp sgt i64 %start, -1
call void @foo()
%cmp1 = icmp sgt i64 %indvars.iv, -1
br i1 %cmp1, label %loop, label %for.end
@ -80,7 +121,21 @@ for.end: ; preds = %if.end, %entry
}
define void @test5(i64 %start) {
; CHECK-LABEL: @test5
; 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
@ -92,8 +147,7 @@ loop:
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp ugt i64 %start, 100
call void @foo()
%cmp1 = icmp ugt i64 %indvars.iv, 100
br i1 %cmp1, label %loop, label %for.end
@ -102,7 +156,21 @@ for.end: ; preds = %if.end, %entry
}
define void @test6(i64 %start) {
; CHECK-LABEL: @test6
; 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
@ -114,8 +182,7 @@ loop:
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp ult i64 %start, 100
call void @foo()
%cmp1 = icmp ult i64 %indvars.iv, 100
br i1 %cmp1, label %for.end, label %loop
@ -124,7 +191,21 @@ for.end: ; preds = %if.end, %entry
}
define void @test7(i64 %start, i64* %inc_ptr) {
; CHECK-LABEL: @test7
; CHECK-LABEL: @test7(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !0
; 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
@ -133,7 +214,6 @@ entry:
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
%indvars.iv.next = add nsw i64 %indvars.iv, %inc
; CHECK: %cmp1 = icmp slt i64 %start, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
@ -144,7 +224,24 @@ for.end: ; preds = %if.end, %entry
; 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-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
@ -155,13 +252,12 @@ loop:
br i1 %cmp, label %backedge, label %skip
skip:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
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()
call void @foo()
br label %loop
for.end: ; preds = %if.end, %entry
@ -169,9 +265,26 @@ for.end: ; preds = %if.end, %entry
}
; Slightly subtle version of @test4 where the icmp dominates the backedge,
; but the exit branch doesn't.
; but the exit branch doesn't.
define void @test2_neg(i64 %start) {
; CHECK-LABEL: @test2_neg
; 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
@ -179,16 +292,15 @@ 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
; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
%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()
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()
call void @foo()
br label %loop
for.end: ; preds = %if.end, %entry
@ -197,14 +309,23 @@ for.end: ; preds = %if.end, %entry
; The branch has to exit the loop if the condition is true
define void @test3_neg(i64 %start) {
; CHECK-LABEL: @test3_neg
; 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
; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %loop, label %for.end
@ -213,7 +334,21 @@ for.end: ; preds = %if.end, %entry
}
define void @test4_neg(i64 %start) {
; CHECK-LABEL: @test4_neg
; 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
@ -225,8 +360,7 @@ loop:
backedge:
; prevent flattening, needed to make sure we're testing what we intend
call void @foo()
; CHECK: %cmp1 = icmp sgt i64 %indvars.iv, -1
call void @foo()
%cmp1 = icmp sgt i64 %indvars.iv, -1
; %cmp1 can be made loop invariant only if the branch below goes to
@ -238,14 +372,23 @@ for.end: ; preds = %if.end, %entry
}
define void @test5_neg(i64 %start, i64 %inc) {
; CHECK-LABEL: @test5_neg
; 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
; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
@ -254,7 +397,23 @@ for.end: ; preds = %if.end, %entry
}
define void @test8(i64 %start, i64* %inc_ptr) {
; CHECK-LABEL: @test8
; CHECK-LABEL: @test8(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !1
; 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
@ -263,7 +422,6 @@ entry:
loop:
%indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
%indvars.iv.next = add nsw i64 %indvars.iv, %inc
; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
@ -274,8 +432,21 @@ for.end: ; preds = %if.end, %entry
; 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-LABEL: loop.preheader:
; 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:
@ -285,7 +456,6 @@ entry2:
loop:
%indvars.iv = phi i64 [ %start, %entry1 ],[ %start, %entry2 ], [ %indvars.iv.next, %loop ]
%indvars.iv.next = add nsw i64 %indvars.iv, 1
; CHECK: %cmp1 = icmp slt i64 %start, -1
%cmp1 = icmp slt i64 %indvars.iv, -1
br i1 %cmp1, label %for.end, label %loop
@ -300,7 +470,26 @@ declare void @use(i1 %x)
; 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-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
@ -317,7 +506,6 @@ right:
latch:
%phi2 = phi i32 [ %phi1, %left ], [ %dec, %right ]
; CHECK: %cmp = icmp slt i32 -1, undef
%cmp = icmp slt i32 %phi2, undef
br i1 true, label %exit, label %loop
@ -329,7 +517,29 @@ exit:
; 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-LABEL: @test11(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !0
; 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
@ -339,7 +549,6 @@ loop:
%iv = phi i64 [ %inc, %entry ], [ %iv.next, %backedge ]
%iv.next = add i64 %iv, 1
%brcond = icmp sgt i64 %iv.next, 1
; CHECK: br i1 true, label %if.true, label %if.false
br i1 %brcond, label %if.true, label %if.false
if.true:
@ -359,7 +568,24 @@ exit:
; 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-LABEL: @test12(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !0
; 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
@ -371,7 +597,6 @@ loop:
%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
; CHECK: br i1 true, label %if.true, label %if.false
br i1 %brcond, label %if.true, label %if.false
if.true:

View File

@ -1,9 +1,39 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -indvars < %s | FileCheck %s
; Do not rewrite the user outside the loop because we must keep the instruction
; inside the loop due to store. Rewrite doesn't give us any profit.
define void @f(i32 %length.i.88, i32 %length.i, i8* %tmp12, i32 %tmp10, i8* %tmp8) {
; CHECK-LABEL: @f(
; CHECK-NEXT: not_zero11.preheader:
; CHECK-NEXT: [[TMP13:%.*]] = icmp ugt i32 [[LENGTH_I:%.*]], [[LENGTH_I_88:%.*]]
; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP13]], i32 [[LENGTH_I_88]], i32 [[LENGTH_I]]
; CHECK-NEXT: [[TMP15:%.*]] = icmp sgt i32 [[TMP14]], 0
; CHECK-NEXT: br i1 [[TMP15]], label [[NOT_ZERO11_PREHEADER1:%.*]], label [[NOT_ZERO11_POSTLOOP:%.*]]
; CHECK: not_zero11.preheader1:
; CHECK-NEXT: br label [[NOT_ZERO11:%.*]]
; CHECK: not_zero11:
; CHECK-NEXT: [[V_1:%.*]] = phi i32 [ [[TMP22:%.*]], [[NOT_ZERO11]] ], [ 0, [[NOT_ZERO11_PREHEADER1]] ]
; CHECK-NEXT: [[TMP16:%.*]] = zext i32 [[V_1]] to i64
; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i8, i8* [[TMP8:%.*]], i64 [[TMP16]]
; CHECK-NEXT: [[TMP18:%.*]] = load i8, i8* [[TMP17]], align 1
; CHECK-NEXT: [[TMP19:%.*]] = zext i8 [[TMP18]] to i32
; CHECK-NEXT: [[TMP20:%.*]] = or i32 [[TMP19]], [[TMP10:%.*]]
; CHECK-NEXT: [[TMP21:%.*]] = trunc i32 [[TMP20]] to i8
; CHECK-NEXT: [[ADDR22:%.*]] = getelementptr inbounds i8, i8* [[TMP12:%.*]], i64 [[TMP16]]
; CHECK-NEXT: store i8 [[TMP21]], i8* [[ADDR22]], align 1
; CHECK-NEXT: [[TMP22]] = add nuw nsw i32 [[V_1]], 1
; CHECK-NEXT: [[TMP23:%.*]] = icmp slt i32 [[TMP22]], [[TMP14]]
; CHECK-NEXT: br i1 [[TMP23]], label [[NOT_ZERO11]], label [[MAIN_EXIT_SELECTOR:%.*]]
; CHECK: main.exit.selector:
; CHECK-NEXT: [[TMP22_LCSSA:%.*]] = phi i32 [ [[TMP22]], [[NOT_ZERO11]] ]
; CHECK-NEXT: [[TMP24:%.*]] = icmp slt i32 [[TMP22_LCSSA]], [[LENGTH_I]]
; CHECK-NEXT: br i1 [[TMP24]], label [[NOT_ZERO11_POSTLOOP]], label [[LEAVE:%.*]]
; CHECK: leave:
; CHECK-NEXT: ret void
; CHECK: not_zero11.postloop:
; CHECK-NEXT: ret void
;
not_zero11.preheader:
%tmp13 = icmp ugt i32 %length.i, %length.i.88
%tmp14 = select i1 %tmp13, i32 %length.i.88, i32 %length.i
@ -25,9 +55,6 @@ not_zero11:
br i1 %tmp23, label %not_zero11, label %main.exit.selector
main.exit.selector:
; CHECK-LABEL: main.exit.selector:
; CHECK: %tmp22.lcssa = phi i32 [ %tmp22, %not_zero11 ]
; CHECK: %tmp24 = icmp slt i32 %tmp22.lcssa, %length.
%tmp24 = icmp slt i32 %tmp22, %length.i
br i1 %tmp24, label %not_zero11.postloop, label %leave
@ -41,6 +68,32 @@ not_zero11.postloop:
; Rewrite the user outside the loop because there is no hard users inside the loop.
define void @f1(i32 %length.i.88, i32 %length.i, i8* %tmp12, i32 %tmp10, i8* %tmp8) {
; CHECK-LABEL: @f1(
; CHECK-NEXT: not_zero11.preheader:
; CHECK-NEXT: [[TMP13:%.*]] = icmp ugt i32 [[LENGTH_I:%.*]], [[LENGTH_I_88:%.*]]
; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP13]], i32 [[LENGTH_I_88]], i32 [[LENGTH_I]]
; CHECK-NEXT: [[TMP15:%.*]] = icmp sgt i32 [[TMP14]], 0
; CHECK-NEXT: br i1 [[TMP15]], label [[NOT_ZERO11_PREHEADER1:%.*]], label [[NOT_ZERO11_POSTLOOP:%.*]]
; CHECK: not_zero11.preheader1:
; CHECK-NEXT: br label [[NOT_ZERO11:%.*]]
; CHECK: not_zero11:
; CHECK-NEXT: [[V_1:%.*]] = phi i32 [ [[TMP22:%.*]], [[NOT_ZERO11]] ], [ 0, [[NOT_ZERO11_PREHEADER1]] ]
; CHECK-NEXT: [[TMP16:%.*]] = zext i32 [[V_1]] to i64
; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i8, i8* [[TMP8:%.*]], i64 [[TMP16]]
; CHECK-NEXT: [[TMP18:%.*]] = load i8, i8* [[TMP17]], align 1
; CHECK-NEXT: [[TMP19:%.*]] = zext i8 [[TMP18]] to i32
; CHECK-NEXT: [[TMP20:%.*]] = or i32 [[TMP19]], [[TMP10:%.*]]
; CHECK-NEXT: [[TMP21:%.*]] = trunc i32 [[TMP20]] to i8
; CHECK-NEXT: [[ADDR22:%.*]] = getelementptr inbounds i8, i8* [[TMP12:%.*]], i64 [[TMP16]]
; CHECK-NEXT: [[TMP22]] = add nuw nsw i32 [[V_1]], 1
; CHECK-NEXT: br i1 false, label [[NOT_ZERO11]], label [[MAIN_EXIT_SELECTOR:%.*]]
; CHECK: main.exit.selector:
; CHECK-NEXT: [[TMP24:%.*]] = icmp slt i32 [[TMP14]], [[LENGTH_I]]
; CHECK-NEXT: br i1 [[TMP24]], label [[NOT_ZERO11_POSTLOOP]], label [[LEAVE:%.*]]
; CHECK: leave:
; CHECK-NEXT: ret void
; CHECK: not_zero11.postloop:
; CHECK-NEXT: ret void
;
not_zero11.preheader:
%tmp13 = icmp ugt i32 %length.i, %length.i.88
%tmp14 = select i1 %tmp13, i32 %length.i.88, i32 %length.i
@ -61,8 +114,6 @@ not_zero11:
br i1 %tmp23, label %not_zero11, label %main.exit.selector
main.exit.selector:
; CHECK-LABEL: main.exit.selector:
; CHECK: %tmp24 = icmp slt i32 %tmp14, %length.i
%tmp24 = icmp slt i32 %tmp22, %length.i
br i1 %tmp24, label %not_zero11.postloop, label %leave

View File

@ -0,0 +1,65 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; PR28705
; RUN: opt < %s -indvars -S | FileCheck %s
; Check IndVarSimplify doesn't replace external use of the induction var
; "%inc.i.i" with "%.sroa.speculated + 1" because it is not profitable.
;
;
define void @foo(i32 %sub.ptr.div.i, i8* %ref.i1174) local_unnamed_addr {
; CHECK-LABEL: @foo(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP_I1137:%.*]] = icmp ugt i32 [[SUB_PTR_DIV_I:%.*]], 3
; CHECK-NEXT: [[DOTSROA_SPECULATED:%.*]] = select i1 [[CMP_I1137]], i32 3, i32 [[SUB_PTR_DIV_I]]
; CHECK-NEXT: [[CMP6483126:%.*]] = icmp eq i32 [[DOTSROA_SPECULATED]], 0
; CHECK-NEXT: br i1 [[CMP6483126]], label [[XZ_EXIT:%.*]], label [[FOR_BODY650_LR_PH:%.*]]
; CHECK: for.body650.lr.ph:
; CHECK-NEXT: br label [[FOR_BODY650:%.*]]
; CHECK: loopexit:
; CHECK-NEXT: [[INC_I_I_LCSSA:%.*]] = phi i32 [ [[INC_I_I:%.*]], [[FOR_BODY650]] ]
; CHECK-NEXT: br label [[XZ_EXIT]]
; CHECK: XZ.exit:
; CHECK-NEXT: [[DB_SROA_9_0_LCSSA:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[INC_I_I_LCSSA]], [[LOOPEXIT:%.*]] ]
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: for.body650:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[FOR_BODY650_LR_PH]] ], [ [[INC655:%.*]], [[FOR_BODY650]] ]
; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ 1, [[FOR_BODY650_LR_PH]] ], [ [[INC_I_I]], [[FOR_BODY650]] ]
; CHECK-NEXT: [[ARRAYIDX_I_I1105:%.*]] = getelementptr inbounds i8, i8* [[REF_I1174:%.*]], i32 [[IV2]]
; CHECK-NEXT: store i8 7, i8* [[ARRAYIDX_I_I1105]], align 1
; CHECK-NEXT: [[INC_I_I]] = add nuw nsw i32 [[IV2]], 1
; CHECK-NEXT: [[INC655]] = add nuw nsw i32 [[IV]], 1
; CHECK-NEXT: [[CMP648:%.*]] = icmp eq i32 [[INC655]], [[DOTSROA_SPECULATED]]
; CHECK-NEXT: br i1 [[CMP648]], label [[LOOPEXIT]], label [[FOR_BODY650]]
; CHECK: end:
; CHECK-NEXT: ret void
;
entry:
%cmp.i1137 = icmp ugt i32 %sub.ptr.div.i, 3
%.sroa.speculated = select i1 %cmp.i1137, i32 3, i32 %sub.ptr.div.i
%cmp6483126 = icmp eq i32 %.sroa.speculated, 0
br i1 %cmp6483126, label %XZ.exit, label %for.body650.lr.ph
for.body650.lr.ph:
br label %for.body650
loopexit:
%inc.i.i.lcssa = phi i32 [ %inc.i.i, %for.body650 ]
br label %XZ.exit
XZ.exit:
%DB.sroa.9.0.lcssa = phi i32 [ 1, %entry ], [ %inc.i.i.lcssa, %loopexit ]
br label %end
for.body650:
%iv = phi i32 [ 0, %for.body650.lr.ph ], [ %inc655, %for.body650 ]
%iv2 = phi i32 [ 1, %for.body650.lr.ph ], [ %inc.i.i, %for.body650 ]
%arrayidx.i.i1105 = getelementptr inbounds i8, i8* %ref.i1174, i32 %iv2
store i8 7, i8* %arrayidx.i.i1105, align 1
%inc.i.i = add i32 %iv2, 1
%inc655 = add i32 %iv, 1
%cmp648 = icmp eq i32 %inc655, %.sroa.speculated
br i1 %cmp648, label %loopexit, label %for.body650
end:
ret void
}

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -indvars -S | FileCheck %s
target triple = "aarch64--linux-gnu"
@ -12,15 +13,42 @@ target datalayout = "n8:16:32:64"
@e = common global i32 0, align 4
@ptr = common global i32* null, align 8
; CHECK-LABEL: @test1
; CHECK: for.body.lr.ph:
; CHECK: sext i32
; CHECK: for.cond:
; CHECK: icmp slt i64
; CHECK: for.body:
; CHECK: phi i64
define i32 @test1() {
; CHECK-LABEL: @test1(
; CHECK-NEXT: entry:
; CHECK-NEXT: store i32 -1, i32* @idx, align 4
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @e, align 4
; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP4]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY_LR_PH:%.*]]
; CHECK: for.body.lr.ph:
; CHECK-NEXT: [[TMP1:%.*]] = load i32*, i32** @ptr, align 8
; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* @e, align 4
; CHECK-NEXT: [[TMP3:%.*]] = sext i32 [[TMP2]] to i64
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV:%.*]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV]], [[TMP3]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_FOR_END_LOOPEXIT_CRIT_EDGE:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[INDVARS_IV]] = phi i64 [ [[INDVARS_IV_NEXT]], [[FOR_COND:%.*]] ], [ 0, [[FOR_BODY_LR_PH]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP4]], 0
; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[FOR_COND]]
; CHECK: if.then:
; CHECK-NEXT: [[I_05_LCSSA_WIDE:%.*]] = phi i64 [ [[INDVARS_IV]], [[FOR_BODY]] ]
; CHECK-NEXT: [[TMP5:%.*]] = trunc i64 [[I_05_LCSSA_WIDE]] to i32
; CHECK-NEXT: store i32 [[TMP5]], i32* @idx, align 4
; CHECK-NEXT: br label [[FOR_END:%.*]]
; CHECK: for.cond.for.end.loopexit_crit_edge:
; CHECK-NEXT: br label [[FOR_END_LOOPEXIT]]
; CHECK: for.end.loopexit:
; CHECK-NEXT: br label [[FOR_END]]
; CHECK: for.end:
; CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* @idx, align 4
; CHECK-NEXT: ret i32 [[TMP6]]
;
entry:
store i32 -1, i32* @idx, align 4
%0 = load i32, i32* @e, align 4
@ -61,14 +89,50 @@ for.end:
ret i32 %4
}
; CHECK-LABEL: @test2
; CHECK: for.body4.us
; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
; CHECK: %cmp2.us = icmp ult i64
; CHECK-NOT: %2 = trunc i64 %indvars.iv.next to i32
; CHECK-NOT: %cmp2.us = icmp slt i32
define void @test2([8 x i8]* %a, i8* %b, i8 %limit) {
; CHECK-LABEL: @test2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[LIMIT:%.*]] to i32
; CHECK-NEXT: br i1 undef, label [[FOR_COND1_PREHEADER_PREHEADER:%.*]], label [[FOR_COND1_PREHEADER_US_PREHEADER:%.*]]
; CHECK: for.cond1.preheader.us.preheader:
; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[CONV]] to i64
; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US:%.*]]
; CHECK: for.cond1.preheader.preheader:
; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]]
; CHECK: for.cond1.preheader.us:
; CHECK-NEXT: [[INDVARS_IV2:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER]] ], [ [[INDVARS_IV_NEXT3:%.*]], [[FOR_INC13_US:%.*]] ]
; CHECK-NEXT: br i1 true, label [[FOR_BODY4_LR_PH_US:%.*]], label [[FOR_INC13_US]]
; CHECK: for.inc13.us.loopexit:
; CHECK-NEXT: br label [[FOR_INC13_US]]
; CHECK: for.inc13.us:
; CHECK-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT3]], 4
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_END_LOOPEXIT1:%.*]]
; CHECK: for.body4.us:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY4_LR_PH_US]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY4_US:%.*]] ]
; CHECK-NEXT: [[ARRAYIDX6_US:%.*]] = getelementptr inbounds [8 x i8], [8 x i8]* [[A:%.*]], i64 [[INDVARS_IV2]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[ARRAYIDX6_US]], align 1
; CHECK-NEXT: [[IDXPROM7_US:%.*]] = zext i8 [[TMP1]] to i64
; CHECK-NEXT: [[ARRAYIDX8_US:%.*]] = getelementptr inbounds i8, i8* [[B:%.*]], i64 [[IDXPROM7_US]]
; CHECK-NEXT: [[TMP2:%.*]] = load i8, i8* [[ARRAYIDX8_US]], align 1
; CHECK-NEXT: store i8 [[TMP2]], i8* [[ARRAYIDX6_US]], align 1
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ult i64 [[INDVARS_IV_NEXT]], [[TMP0]]
; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY4_US]], label [[FOR_INC13_US_LOOPEXIT:%.*]]
; CHECK: for.body4.lr.ph.us:
; CHECK-NEXT: br label [[FOR_BODY4_US]]
; CHECK: for.cond1.preheader:
; CHECK-NEXT: br i1 false, label [[FOR_INC13:%.*]], label [[FOR_INC13]]
; CHECK: for.inc13:
; CHECK-NEXT: br i1 false, label [[FOR_COND1_PREHEADER]], label [[FOR_END_LOOPEXIT:%.*]]
; CHECK: for.end.loopexit:
; CHECK-NEXT: br label [[FOR_END:%.*]]
; CHECK: for.end.loopexit1:
; CHECK-NEXT: br label [[FOR_END]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
entry:
%conv = zext i8 %limit to i32
br i1 undef, label %for.cond1.preheader, label %for.cond1.preheader.us
@ -112,13 +176,27 @@ for.end:
ret void
}
; CHECK-LABEL: @test3
; CHECK: sext i32 %b
; CHECK: for.cond:
; CHECK: phi i64
; CHECK: icmp slt i64
define i32 @test3(i32* %a, i32 %b) {
; CHECK-LABEL: @test3(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[B:%.*]] to i64
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV]], [[TMP0]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]]
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: br label [[FOR_COND]]
; CHECK: for.end:
; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ]
; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
;
entry:
br label %for.cond
@ -143,12 +221,23 @@ for.end:
declare i32 @fn1(i8 signext)
; PR21030
; CHECK-LABEL: @test4
; CHECK: for.body:
; CHECK: phi i32
; CHECK: icmp sgt i8
define i32 @test4(i32 %a) {
; CHECK-LABEL: @test4(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 253, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[OR:%.*]] = or i32 [[A:%.*]], [[INDVARS_IV]]
; CHECK-NEXT: [[CONV3:%.*]] = trunc i32 [[OR]] to i8
; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn1(i8 signext [[CONV3]])
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i32 [[INDVARS_IV]], -1
; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[INDVARS_IV_NEXT]] to i8
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[TMP0]], -14
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.end:
; CHECK-NEXT: ret i32 0
;
entry:
br label %for.body
@ -166,13 +255,27 @@ for.end:
ret i32 0
}
; CHECK-LABEL: @test5
; CHECK: zext i32 %b
; CHECK: for.cond:
; CHECK: phi i64
; CHECK: icmp ule i64
define i32 @test5(i32* %a, i32 %b) {
; CHECK-LABEL: @test5(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[B:%.*]] to i64
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[INDVARS_IV]], [[TMP0]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]]
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: br label [[FOR_COND]]
; CHECK: for.end:
; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ]
; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
;
entry:
br label %for.cond
@ -196,10 +299,24 @@ for.end:
define i32 @test6(i32* %a, i32 %b) {
; CHECK-LABEL: @test6(
; CHECK: [[B_SEXT:%[a-z0-9]+]] = sext i32 %b to i64
; CHECK: for.cond:
; CHECK: icmp sle i64 %indvars.iv, [[B_SEXT]]
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[B:%.*]] to i64
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i64 [[INDVARS_IV]], [[TMP0]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]]
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: br label [[FOR_COND]]
; CHECK: for.end:
; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ]
; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
;
entry:
br label %for.cond
@ -223,13 +340,26 @@ for.end:
define i32 @test7(i32* %a, i32 %b) {
; CHECK-LABEL: @test7(
; CHECK: [[B_ZEXT:%[a-z0-9]+]] = zext i32 %b to i64
; CHECK: [[B_SEXT:%[a-z0-9]+]] = sext i32 %b to i64
; CHECK: for.cond:
; CHECK: icmp ule i64 %indvars.iv, [[B_ZEXT]]
; CHECK: for.body:
; CHECK: icmp sle i64 %indvars.iv, [[B_SEXT]]
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[B:%.*]] to i64
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[B]] to i64
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[INDVARS_IV]], [[TMP0]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP2]]
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i64 [[INDVARS_IV]], [[TMP1]]
; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[FOR_END]]
; CHECK: for.end:
; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ]
; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
;
entry:
br label %for.cond
@ -253,14 +383,33 @@ for.end:
}
define i32 @test8(i32* %a, i32 %b, i32 %init) {
; CHECK-LABEL: @test8(
; CHECK: [[INIT_SEXT:%[a-z0-9]+]] = sext i32 %init to i64
; CHECK: [[B_ZEXT:%[a-z0-9]+]] = zext i32 %b to i64
; CHECK: for.cond:
; Note: %indvars.iv is the sign extension of %i.0
; CHECK: %indvars.iv = phi i64 [ [[INIT_SEXT]], %for.cond.preheader ], [ %indvars.iv.next, %for.body ]
; CHECK: icmp ule i64 %indvars.iv, [[B_ZEXT]]
; CHECK-LABEL: @test8(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[E:%.*]] = icmp sgt i32 [[INIT:%.*]], 0
; CHECK-NEXT: br i1 [[E]], label [[FOR_COND_PREHEADER:%.*]], label [[LEAVE:%.*]]
; CHECK: for.cond.preheader:
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[INIT]] to i64
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[B:%.*]] to i64
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_COND_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ]
; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_COND_PREHEADER]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[INDVARS_IV]], [[TMP1]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP2]]
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i64 0, [[INDVARS_IV_NEXT]]
; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[FOR_END]]
; CHECK: for.end:
; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ]
; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
; CHECK: leave:
; CHECK-NEXT: ret i32 0
;
entry:
%e = icmp sgt i32 %init, 0
br i1 %e, label %for.cond, label %leave
@ -288,14 +437,34 @@ leave:
}
define i32 @test9(i32* %a, i32 %b, i32 %init) {
; CHECK-LABEL: @test9(
; CHECK: [[INIT_ZEXT:%[a-z0-9]+]] = zext i32 %init to i64
; CHECK: [[B_SEXT:%[a-z0-9]+]] = sext i32 %b to i64
; CHECK: for.cond:
; Note: %indvars.iv is the zero extension of %i.0
; CHECK: %indvars.iv = phi i64 [ [[INIT_ZEXT]], %for.cond.preheader ], [ %indvars.iv.next, %for.body ]
; CHECK: icmp slt i64 %indvars.iv, [[B_SEXT]]
; CHECK-LABEL: @test9(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[E:%.*]] = icmp sgt i32 [[INIT:%.*]], 0
; CHECK-NEXT: br i1 [[E]], label [[FOR_COND_PREHEADER:%.*]], label [[LEAVE:%.*]]
; CHECK: for.cond.preheader:
; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[INIT]] to i64
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[B:%.*]] to i64
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_COND_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ]
; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_COND_PREHEADER]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV]], [[TMP1]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP2]]
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32
; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[TMP3]]
; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[FOR_END]]
; CHECK: for.end:
; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ]
; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]]
; CHECK: leave:
; CHECK-NEXT: ret i32 0
;
entry:
%e = icmp sgt i32 %init, 0
br i1 %e, label %for.cond, label %leave
@ -327,18 +496,25 @@ declare void @consume.i1(i1)
define i32 @test10(i32 %v) {
; CHECK-LABEL: @test10(
entry:
; CHECK-NOT: zext
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SEXT:%.*]] = sext i32 [[V:%.*]] to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[TMP0:%.*]] = mul nsw i64 [[INDVARS_IV]], -1
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], [[SEXT]]
; CHECK-NEXT: call void @consume.i1(i1 [[TMP1]])
; CHECK-NEXT: call void @consume.i64(i64 [[TMP0]])
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], 11
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE:%.*]]
; CHECK: leave:
; CHECK-NEXT: ret i32 22
;
entry:
br label %loop
loop:
; CHECK: [[WIDE_V:%[a-z0-9]+]] = sext i32 %v to i64
; CHECK: loop:
; CHECK: %indvars.iv = phi i64 [ %indvars.iv.next, %loop ], [ 0, %entry ]
; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
; CHECK: [[MUL:%[a-z0-9]+]] = mul nsw i64 %indvars.iv, -1
; CHECK: [[CMP:%[a-z0-9]+]] = icmp eq i64 [[MUL]], [[WIDE_V]]
; CHECK: call void @consume.i1(i1 [[CMP]])
loop:
%i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
%i.inc = add i32 %i, 1
@ -350,6 +526,6 @@ define i32 @test10(i32 %v) {
call void @consume.i64(i64 %ext)
br i1 %be.cond, label %loop, label %leave
leave:
leave:
ret i32 22
}