1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 11:13:28 +01:00

[IndVarSimplify] Generate full checks for some LFTR tests; NFC

llvm-svn: 358813
This commit is contained in:
Nikita Popov 2019-04-20 12:05:53 +00:00
parent 468a932789
commit c8ff4f9460
7 changed files with 326 additions and 128 deletions

View File

@ -1,13 +1,23 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
;RUN: opt -S %s -indvars | FileCheck %s
; Provide legal integer types.
target datalayout = "n8:16:32:64"
; CHECK-LABEL: @foo(
; CHECK-NOT: %lftr.wideiv = trunc i32 %indvars.iv.next to i16
; CHECK: %exitcond = icmp ne i32 %indvars.iv.next, 512
define void @foo() #0 {
; CHECK-LABEL: @foo(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: call void @bar(i32 [[INDVARS_IV]]) #1
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INDVARS_IV_NEXT]], 512
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
entry:
br label %for.body
@ -24,9 +34,19 @@ for.end: ; preds = %for.body
}
; Check that post-incrementing the backedge taken count does not overflow.
; CHECK-LABEL: @postinc(
; CHECK: icmp eq i32 %indvars.iv, 255
define i32 @postinc() #0 {
; CHECK-LABEL: @postinc(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[DO_BODY:%.*]]
; CHECK: do.body:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ [[INDVARS_IV_NEXT:%.*]], [[DO_BODY]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: call void @bar(i32 [[INDVARS_IV]]) #1
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[INDVARS_IV]], 255
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1
; CHECK-NEXT: br i1 [[CMP]], label [[DO_END:%.*]], label [[DO_BODY]]
; CHECK: do.end:
; CHECK-NEXT: ret i32 0
;
entry:
br label %do.body

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -indvars -S | FileCheck %s
; Indvars should be able to compute the exit value of this loop
@ -8,35 +9,57 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
define void @foo(double* %p, i32 %n) nounwind {
; CHECK-LABEL: @foo(
; CHECK: add
; CHECK-NOT: add
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[N:%.*]], 0
; CHECK-NEXT: br i1 [[TMP0]], label [[BB_NPH:%.*]], label [[RETURN:%.*]]
; CHECK: bb.nph:
; CHECK-NEXT: br label [[BB2:%.*]]
; CHECK: bb2:
; CHECK-NEXT: [[I_01:%.*]] = phi i32 [ [[TMP7:%.*]], [[BB3:%.*]] ], [ 0, [[BB_NPH]] ]
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[I_01]] to i64
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr double, double* [[P:%.*]], i64 [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = load double, double* [[TMP2]], align 8
; CHECK-NEXT: [[TMP4:%.*]] = fmul double [[TMP3]], 1.100000e+00
; CHECK-NEXT: [[TMP5:%.*]] = sext i32 [[I_01]] to i64
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr double, double* [[P]], i64 [[TMP5]]
; CHECK-NEXT: store double [[TMP4]], double* [[TMP6]], align 8
; CHECK-NEXT: [[TMP7]] = add nuw nsw i32 [[I_01]], 1
; CHECK-NEXT: br label [[BB3]]
; CHECK: bb3:
; CHECK-NEXT: [[TMP8:%.*]] = icmp slt i32 [[TMP7]], [[N]]
; CHECK-NEXT: br i1 [[TMP8]], label [[BB2]], label [[BB3_RETURN_CRIT_EDGE:%.*]]
; CHECK: bb3.return_crit_edge:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: ret void
;
entry:
%0 = icmp sgt i32 %n, 0 ; <i1> [#uses=1]
br i1 %0, label %bb.nph, label %return
%0 = icmp sgt i32 %n, 0
br i1 %0, label %bb.nph, label %return
bb.nph: ; preds = %entry
br label %bb2
br label %bb2
bb2: ; preds = %bb3, %bb.nph
%i.01 = phi i32 [ %7, %bb3 ], [ 0, %bb.nph ] ; <i32> [#uses=3]
%1 = sext i32 %i.01 to i64 ; <i64> [#uses=1]
%2 = getelementptr double, double* %p, i64 %1 ; <double*> [#uses=1]
%3 = load double, double* %2, align 8 ; <double> [#uses=1]
%4 = fmul double %3, 1.100000e+00 ; <double> [#uses=1]
%5 = sext i32 %i.01 to i64 ; <i64> [#uses=1]
%6 = getelementptr double, double* %p, i64 %5 ; <double*> [#uses=1]
store double %4, double* %6, align 8
%7 = add i32 %i.01, 1 ; <i32> [#uses=2]
br label %bb3
%i.01 = phi i32 [ %7, %bb3 ], [ 0, %bb.nph ]
%1 = sext i32 %i.01 to i64
%2 = getelementptr double, double* %p, i64 %1
%3 = load double, double* %2, align 8
%4 = fmul double %3, 1.100000e+00
%5 = sext i32 %i.01 to i64
%6 = getelementptr double, double* %p, i64 %5
store double %4, double* %6, align 8
%7 = add i32 %i.01, 1
br label %bb3
bb3: ; preds = %bb2
%8 = icmp slt i32 %7, %n ; <i1> [#uses=1]
br i1 %8, label %bb2, label %bb3.return_crit_edge
%8 = icmp slt i32 %7, %n
br i1 %8, label %bb2, label %bb3.return_crit_edge
bb3.return_crit_edge: ; preds = %bb3
br label %return
br label %return
return: ; preds = %bb3.return_crit_edge, %entry
ret void
ret void
}

View File

@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -indvars -S | FileCheck %s
;
; Make sure that indvars can perform LFTR without a canonical IV.
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
@ -12,18 +13,36 @@ declare void @use(double %x)
; *p = p-base;
; }
define void @ptriv(i8* %base, i32 %n) nounwind {
; CHECK-LABEL: @ptriv(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[N:%.*]] to i64
; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[BASE:%.*]], i64 [[IDX_EXT]]
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8* [[BASE]], [[ADD_PTR]]
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
; CHECK: for.body.preheader:
; CHECK-NEXT: [[LFTR_LIMIT:%.*]] = getelementptr i8, i8* [[BASE]], i64 [[IDX_EXT]]
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[P_02:%.*]] = phi i8* [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[BASE]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint i8* [[P_02]] to i64
; CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint i8* [[BASE]] to i64
; CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]]
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[SUB_PTR_SUB]] to i8
; CHECK-NEXT: store i8 [[CONV]], i8* [[P_02]]
; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[P_02]], i32 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[INCDEC_PTR]], [[LFTR_LIMIT]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
; CHECK: for.end.loopexit:
; CHECK-NEXT: br label [[FOR_END]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
entry:
%idx.ext = sext i32 %n to i64
%add.ptr = getelementptr inbounds i8, i8* %base, i64 %idx.ext
%cmp1 = icmp ult i8* %base, %add.ptr
br i1 %cmp1, label %for.body, label %for.end
; CHECK: for.body:
; CHECK: phi i8*
; CHECK-NOT: phi
; CHECK-NOT: add
; CHECK: icmp ne i8*
; CHECK: br i1
for.body:
%p.02 = phi i8* [ %base, %entry ], [ %incdec.ptr, %for.body ]
; cruft to make the IV useful
@ -43,13 +62,45 @@ for.end:
; This test checks that SCEVExpander can handle an outer loop that has been
; simplified, and as a result the inner loop's exit test will be rewritten.
define void @expandOuterRecurrence(i32 %arg) nounwind {
; CHECK-LABEL: @expandOuterRecurrence(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
; CHECK-NEXT: br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]]
; CHECK: outer.preheader:
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[ARG]], -1
; CHECK-NEXT: br label [[OUTER:%.*]]
; CHECK: outer:
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ [[TMP0]], [[OUTER_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[OUTER_INC:%.*]] ]
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC]] ], [ 0, [[OUTER_PREHEADER]] ]
; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
; CHECK: inner.ph:
; CHECK-NEXT: br label [[INNER:%.*]]
; CHECK: inner:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[INNER_PH]] ], [ [[J_INC:%.*]], [[INNER]] ]
; CHECK-NEXT: [[J_INC]] = add nuw nsw i32 [[J]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[J_INC]], [[INDVARS_IV]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
; CHECK: outer.inc.loopexit:
; CHECK-NEXT: br label [[OUTER_INC]]
; CHECK: outer.inc:
; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i32 [[INDVARS_IV]], -1
; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[I_INC]], [[TMP0]]
; CHECK-NEXT: br i1 [[EXITCOND1]], label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: exit.loopexit:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%sub1 = sub nsw i32 %arg, 1
%cmp1 = icmp slt i32 0, %sub1
br i1 %cmp1, label %outer, label %exit
; CHECK: outer:
; CHECK: icmp slt
outer:
%i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
%sub2 = sub nsw i32 %arg, %i
@ -60,17 +111,12 @@ outer:
inner.ph:
br label %inner
; CHECK: inner:
; CHECK: br i1
inner:
%j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
%j.inc = add nsw i32 %j, 1
%cmp3 = icmp slt i32 %j.inc, %sub3
br i1 %cmp3, label %inner, label %outer.inc
; CHECK: outer.inc:
; CHECK: icmp ne
; CHECK: br i1
outer.inc:
%i.inc = add nsw i32 %i, 1
%cmp4 = icmp slt i32 %i.inc, %sub1
@ -83,16 +129,34 @@ 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,
i32 %irow, i32 %ilead) nounwind {
; CHECK: entry:
; CHECK-NOT: zext
; CHECK-NOT: add
; CHECK: loop:
; CHECK: phi i64
; CHECK: phi i64
; CHECK-NOT: phi
; CHECK: icmp ne
; CHECK: br i1
; CHECK-LABEL: @guardedloop(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 1, [[IROW:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_PREHEADER:%.*]], label [[RETURN:%.*]]
; CHECK: loop.preheader:
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[ILEAD:%.*]] to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDVARS_IV2:%.*]] = phi i64 [ 0, [[LOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT3:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[LOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], [[INDVARS_IV2]]
; CHECK-NEXT: [[MATRIXP:%.*]] = getelementptr inbounds [0 x double], [0 x double]* [[MATRIX:%.*]], i32 0, i64 [[TMP1]]
; CHECK-NEXT: [[V1:%.*]] = load double, double* [[MATRIXP]]
; CHECK-NEXT: call void @use(double [[V1]])
; CHECK-NEXT: [[VECTORP:%.*]] = getelementptr inbounds [0 x double], [0 x double]* [[VECTOR:%.*]], i32 0, i64 [[INDVARS_IV2]]
; CHECK-NEXT: [[V2:%.*]] = load double, double* [[VECTORP]]
; CHECK-NEXT: call void @use(double [[V2]])
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[TMP0]]
; CHECK-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[IROW]] to i64
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT3]], [[WIDE_TRIP_COUNT]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[RETURN_LOOPEXIT:%.*]]
; CHECK: return.loopexit:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: ret void
;
i32 %irow, i32 %ilead) nounwind {
entry:
%cmp = icmp slt i32 1, %irow
br i1 %cmp, label %loop, label %return
@ -120,18 +184,22 @@ return:
; Avoid generating extra code to materialize a trip count. Skip LFTR.
define void @unguardedloop([0 x double]* %matrix, [0 x double]* %vector,
i32 %irow, i32 %ilead) nounwind {
; CHECK-LABEL: @unguardedloop(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[IROW:%.*]] to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDVARS_IV2:%.*]] = phi i64 [ [[INDVARS_IV_NEXT3:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
; CHECK-NEXT: [[CMP196:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT3]], [[TMP0]]
; CHECK-NEXT: br i1 [[CMP196]], label [[LOOP]], label [[RETURN:%.*]]
; CHECK: return:
; CHECK-NEXT: ret void
;
i32 %irow, i32 %ilead) nounwind {
entry:
br label %loop
; CHECK: entry:
; CHECK-NOT: zext
; CHECK-NOT: add
; CHECK: loop:
; CHECK: phi i64
; CHECK-NOT: phi
; CHECK: icmp slt
; CHECK: br i1
loop:
%rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ]
%i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
@ -158,6 +226,30 @@ return:
; TODO: Fix for PR13371 currently makes this impossible. See
; IndVarSimplify.cpp hasConcreteDef(). We may want to change to undef rules.
define void @geplftr(i8* %base, i32 %x, i32 %y, i32 %n) nounwind {
; CHECK-LABEL: @geplftr(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X_EXT:%.*]] = sext i32 [[X:%.*]] to i64
; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[BASE:%.*]], i64 [[X_EXT]]
; CHECK-NEXT: [[Y_EXT:%.*]] = sext i32 [[Y:%.*]] to i64
; CHECK-NEXT: [[ADD_PTR10:%.*]] = getelementptr inbounds i8, i8* [[ADD_PTR]], i64 [[Y_EXT]]
; CHECK-NEXT: [[LIM:%.*]] = add i32 [[X]], [[N:%.*]]
; CHECK-NEXT: [[CMP_PH:%.*]] = icmp ult i32 [[X]], [[LIM]]
; CHECK-NEXT: br i1 [[CMP_PH]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
; CHECK: loop.preheader:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INC:%.*]], [[LOOP]] ], [ [[X]], [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[APTR:%.*]] = phi i8* [ [[INCDEC_PTR:%.*]], [[LOOP]] ], [ [[ADD_PTR10]], [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[APTR]], i32 1
; CHECK-NEXT: store i8 3, i8* [[APTR]]
; CHECK-NEXT: [[INC]] = add nuw i32 [[I]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INC]], [[LIM]]
; 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:
%x.ext = sext i32 %x to i64
%add.ptr = getelementptr inbounds i8, i8* %base, i64 %x.ext
@ -166,14 +258,6 @@ entry:
%lim = add i32 %x, %n
%cmp.ph = icmp ult i32 %x, %lim
br i1 %cmp.ph, label %loop, label %exit
; CHECK-LABEL: @geplftr(
; CHECK: loop:
; CHECK: phi i8*
; DISABLE-NOT: phi // This check is currently disabled
; CHECK: getelementptr
; CHECK: store
; DISABLE: icmp ne i8* // This check is currently disabled
; CHECK: br i1
loop:
%i = phi i32 [ %x, %entry ], [ %inc, %loop ]
%aptr = phi i8* [ %add.ptr10, %entry ], [ %incdec.ptr, %loop ]
@ -189,14 +273,16 @@ exit:
; Exercise backedge taken count verification with a never-taken loop.
define void @nevertaken() nounwind uwtable ssp {
; CHECK-LABEL: @nevertaken(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
; CHECK-LABEL: @nevertaken(
; CHECK: loop:
; CHECK-NOT: phi
; CHECK-NOT: add
; CHECK-NOT: icmp
; CHECK: exit:
loop:
%i = phi i32 [ 0, %entry ], [ %inc, %loop ]
%inc = add nsw i32 %i, 1
@ -209,19 +295,33 @@ exit:
; Test LFTR on an IV whose recurrence start is a non-unit pointer type.
define void @aryptriv([256 x i8]* %base, i32 %n) nounwind {
; CHECK-LABEL: @aryptriv(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[IVSTART:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[BASE:%.*]], i32 0, i32 0
; CHECK-NEXT: [[IVEND:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[BASE]], i32 0, i32 [[N:%.*]]
; CHECK-NEXT: [[CMP_PH:%.*]] = icmp ult i8* [[IVSTART]], [[IVEND]]
; CHECK-NEXT: br i1 [[CMP_PH]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
; CHECK: loop.preheader:
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[N]] to i64
; CHECK-NEXT: [[LFTR_LIMIT:%.*]] = getelementptr i8, i8* [[IVSTART]], i64 [[TMP0]]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[APTR:%.*]] = phi i8* [ [[INCDEC_PTR:%.*]], [[LOOP]] ], [ [[IVSTART]], [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[APTR]], i32 1
; CHECK-NEXT: store i8 3, i8* [[APTR]]
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[INCDEC_PTR]], [[LFTR_LIMIT]]
; 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:
%ivstart = getelementptr inbounds [256 x i8], [256 x i8]* %base, i32 0, i32 0
%ivend = getelementptr inbounds [256 x i8], [256 x i8]* %base, i32 0, i32 %n
%cmp.ph = icmp ult i8* %ivstart, %ivend
br i1 %cmp.ph, label %loop, label %exit
; CHECK: loop:
; CHECK: phi i8*
; CHECK-NOT: phi
; CHECK: getelementptr
; CHECK: store
; CHECK: icmp ne i8*
; CHECK: br i1
loop:
%aptr = phi i8* [ %ivstart, %entry ], [ %incdec.ptr, %loop ]
%incdec.ptr = getelementptr inbounds i8, i8* %aptr, i32 1

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 datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
@ -8,22 +9,38 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
define void @foo(i8* %a, i8 %n) nounwind uwtable ssp {
; CHECK-LABEL: @foo(
entry:
; CHECK-NEXT: entry:
; CHECK-NEXT: [[E:%.*]] = icmp sgt i8 [[N:%.*]], 3
; CHECK-NEXT: br i1 [[E]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
; CHECK: loop.preheader:
; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], 3
; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[TMP0]], 2
; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I1:%.*]] = phi i8 [ [[I1_INC:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[I1_INC]] = add nuw nsw i8 [[I1]], 1
; CHECK-NEXT: store volatile i8 0, i8* [[A:%.*]]
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8 [[I1_INC]], [[TMP2]]
; 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:
%e = icmp sgt i8 %n, 3
br i1 %e, label %loop, label %exit
loop:
; CHECK-LABEL: loop:
loop:
%i = phi i8 [ 0, %entry ], [ %i.inc, %loop ]
%i1 = phi i8 [ 0, %entry ], [ %i1.inc, %loop ]
%i.inc = add nsw i8 %i, 4
%i1.inc = add i8 %i1, 1
store volatile i8 0, i8* %a
%c = icmp slt i8 %i, %n
; CHECK-LABEL: %exitcond = icmp ne i8 %i1.inc
br i1 %c, label %loop, label %exit
exit:
; CHECK-LABEL: exit:
exit:
ret void
}

View File

@ -1,26 +1,41 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -indvars -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.9.0"
@data = common global [240 x i8] zeroinitializer, align 16
define void @foo(i8* %a) nounwind uwtable ssp {
; CHECK: %exitcond
; CHECK-NOT: ([240 x i8]* @data, i64 0, i64 -16)
br label %1
define void @foo(i8* %a) #0 {
; CHECK-LABEL: @foo(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[P_0:%.*]] = phi i8* [ getelementptr inbounds ([240 x i8], [240 x i8]* @data, i64 0, i64 0), [[ENTRY:%.*]] ], [ [[TMP3:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[DOT0:%.*]] = phi i8* [ [[A:%.*]], [[ENTRY]] ], [ [[TMP:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[TMP]] = getelementptr inbounds i8, i8* [[DOT0]], i64 1
; CHECK-NEXT: [[TMP2:%.*]] = load i8, i8* [[DOT0]], align 1
; CHECK-NEXT: [[TMP3]] = getelementptr inbounds i8, i8* [[P_0]], i64 1
; CHECK-NEXT: store i8 [[TMP2]], i8* [[P_0]], align 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[TMP3]], getelementptr (i8, i8* getelementptr inbounds ([240 x i8], [240 x i8]* @data, i64 0, i64 0), i64 240)
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
; <label>:1 ; preds = %0, %1
%i.0 = phi i8 [ 0, %0 ], [ %5, %1 ]
%p.0 = phi i8* [ getelementptr inbounds ([240 x i8], [240 x i8]* @data, i64 0, i64 0), %0 ], [ %4, %1 ]
%.0 = phi i8* [ %a, %0 ], [ %2, %1 ]
%2 = getelementptr inbounds i8, i8* %.0, i64 1
%3 = load i8, i8* %.0, align 1
%4 = getelementptr inbounds i8, i8* %p.0, i64 1
store i8 %3, i8* %p.0, align 1
%5 = add i8 %i.0, 1
%6 = icmp ult i8 %5, -16
br i1 %6, label %1, label %7
loop:
%i.0 = phi i8 [ 0, %entry ], [ %tmp4, %loop ]
%p.0 = phi i8* [ getelementptr inbounds ([240 x i8], [240 x i8]* @data, i64 0, i64 0), %entry ], [ %tmp3, %loop ]
%.0 = phi i8* [ %a, %entry ], [ %tmp, %loop ]
%tmp = getelementptr inbounds i8, i8* %.0, i64 1
%tmp2 = load i8, i8* %.0, align 1
%tmp3 = getelementptr inbounds i8, i8* %p.0, i64 1
store i8 %tmp2, i8* %p.0, align 1
%tmp4 = add i8 %i.0, 1
%tmp5 = icmp ult i8 %tmp4, -16
br i1 %tmp5, label %loop, label %exit
; <label>:7 ; preds = %1
exit:
ret void
}

View File

@ -1,28 +1,40 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -indvars -dce -disable-lftr -S | FileCheck %s
; LFTR should not eliminate the need for the computation of i*i completely
; due to LFTR is disabled.
; RUN: opt < %s -indvars -dce -disable-lftr -S | FileCheck %s
; Provide legal integer types.
target datalayout = "n8:16:32:64"
@A = external global i32 ; <i32*> [#uses=1]
@A = external global i32
define i32 @quadratic_setlt() {
; CHECK-LABEL: @quadratic_setlt(
; CHECK: mul
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 7, [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: store i32 [[I]], i32* @A
; CHECK-NEXT: [[I2:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[I2]], 1000
; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[LOOPEXIT:%.*]]
; CHECK: loopexit:
; CHECK-NEXT: ret i32 32
;
entry:
br label %loop
br label %loop
loop: ; preds = %loop, %entry
%i = phi i32 [ 7, %entry ], [ %i.next, %loop ] ; <i32> [#uses=5]
%i.next = add i32 %i, 1 ; <i32> [#uses=1]
store i32 %i, i32* @A
%i2 = mul i32 %i, %i ; <i32> [#uses=1]
%c = icmp slt i32 %i2, 1000 ; <i1> [#uses=1]
br i1 %c, label %loop, label %loopexit
loop:
%i = phi i32 [ 7, %entry ], [ %i.next, %loop ]
%i.next = add i32 %i, 1
store i32 %i, i32* @A
%i2 = mul i32 %i, %i
%c = icmp slt i32 %i2, 1000
br i1 %c, label %loop, label %loopexit
loopexit: ; preds = %loop
ret i32 %i
loopexit:
ret i32 %i
}

View File

@ -1,28 +1,39 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -indvars -dce -S | FileCheck %s
; LFTR should eliminate the need for the computation of i*i completely. It
; is only used to compute the exit value.
; RUN: opt < %s -indvars -dce -S | FileCheck %s
; Provide legal integer types.
target datalayout = "n8:16:32:64"
@A = external global i32 ; <i32*> [#uses=1]
@A = external global i32
define i32 @quadratic_setlt() {
; CHECK-LABEL: @quadratic_setlt(
; CHECK-NOT: mul
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 7, [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: store i32 [[I]], i32* @A
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[I_NEXT]], 33
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOPEXIT:%.*]]
; CHECK: loopexit:
; CHECK-NEXT: ret i32 32
;
entry:
br label %loop
br label %loop
loop: ; preds = %loop, %entry
%i = phi i32 [ 7, %entry ], [ %i.next, %loop ] ; <i32> [#uses=5]
%i.next = add i32 %i, 1 ; <i32> [#uses=1]
store i32 %i, i32* @A
%i2 = mul i32 %i, %i ; <i32> [#uses=1]
%c = icmp slt i32 %i2, 1000 ; <i1> [#uses=1]
br i1 %c, label %loop, label %loopexit
loop:
%i = phi i32 [ 7, %entry ], [ %i.next, %loop ]
%i.next = add i32 %i, 1
store i32 %i, i32* @A
%i2 = mul i32 %i, %i
%c = icmp slt i32 %i2, 1000
br i1 %c, label %loop, label %loopexit
loopexit: ; preds = %loop
ret i32 %i
loopexit:
ret i32 %i
}