+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
; REQUIRES: asserts
; RUN: opt < %s -passes="loop-reduce" -S -debug -lsr-term-fold 2>&1 | FileCheck %s
-target datalayout = "e-p:32:32:32-n32"
+target datalayout = "e-p:64:64:64-n64"
define i32 @loop_variant(ptr %ar, i32 %n, i32 %m) {
-; CHECK: Cannot fold on backedge that is loop variant
+; CHECK-LABEL: define i32 @loop_variant
+; CHECK-SAME: (ptr [[AR:%.*]], i32 [[N:%.*]], i32 [[M:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[FOR_COND:%.*]]
+; CHECK: for.cond:
+; CHECK-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[MUL:%.*]], [[FOR_COND]] ]
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[N_ADDR_0]], [[M]]
+; CHECK-NEXT: [[MUL]] = shl nsw i32 [[N_ADDR_0]], 1
+; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND]], label [[FOR_END:%.*]]
+; CHECK: for.end:
+; CHECK-NEXT: [[N_ADDR_0_LCSSA:%.*]] = phi i32 [ [[N_ADDR_0]], [[FOR_COND]] ]
+; CHECK-NEXT: ret i32 [[N_ADDR_0_LCSSA]]
+;
entry:
br label %for.cond
}
define i32 @nested_loop(ptr %ar, i32 %n, i32 %m, i32 %o) {
-; CHECK: Cannot fold on backedge that is loop variant
-; CHECK: Cannot fold on non-innermost loop
+; CHECK-LABEL: define i32 @nested_loop
+; CHECK-SAME: (ptr [[AR:%.*]], i32 [[N:%.*]], i32 [[M:%.*]], i32 [[O:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP15:%.*]] = icmp sgt i32 [[O]], 0
+; CHECK-NEXT: br i1 [[CMP15]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.cond.cleanup.loopexit:
+; CHECK-NEXT: [[CNT_1_LCSSA_LCSSA:%.*]] = phi i32 [ [[CNT_1_LCSSA:%.*]], [[FOR_COND_CLEANUP3:%.*]] ]
+; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
+; CHECK: for.cond.cleanup:
+; CHECK-NEXT: [[CNT_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[CNT_1_LCSSA_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: ret i32 [[CNT_0_LCSSA]]
+; CHECK: for.body:
+; CHECK-NEXT: [[I_017:%.*]] = phi i32 [ [[INC6:%.*]], [[FOR_COND_CLEANUP3]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[CNT_016:%.*]] = phi i32 [ [[CNT_1_LCSSA]], [[FOR_COND_CLEANUP3]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[N]], [[I_017]]
+; CHECK-NEXT: [[CMP212:%.*]] = icmp slt i32 [[SUB]], [[M]]
+; CHECK-NEXT: br i1 [[CMP212]], label [[FOR_BODY4_PREHEADER:%.*]], label [[FOR_COND_CLEANUP3]]
+; CHECK: for.body4.preheader:
+; CHECK-NEXT: br label [[FOR_BODY4:%.*]]
+; CHECK: for.cond.cleanup3.loopexit:
+; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY4]] ]
+; CHECK-NEXT: br label [[FOR_COND_CLEANUP3]]
+; CHECK: for.cond.cleanup3:
+; CHECK-NEXT: [[CNT_1_LCSSA]] = phi i32 [ [[CNT_016]], [[FOR_BODY]] ], [ [[INC_LCSSA]], [[FOR_COND_CLEANUP3_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: [[INC6]] = add nuw nsw i32 [[I_017]], 1
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC6]], [[O]]
+; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP_LOOPEXIT]]
+; CHECK: for.body4:
+; CHECK-NEXT: [[J_014:%.*]] = phi i32 [ [[MUL:%.*]], [[FOR_BODY4]] ], [ [[SUB]], [[FOR_BODY4_PREHEADER]] ]
+; CHECK-NEXT: [[CNT_113:%.*]] = phi i32 [ [[INC]], [[FOR_BODY4]] ], [ [[CNT_016]], [[FOR_BODY4_PREHEADER]] ]
+; CHECK-NEXT: [[INC]] = add nsw i32 [[CNT_113]], 1
+; CHECK-NEXT: [[MUL]] = shl nsw i32 [[J_014]], 1
+; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[MUL]], [[M]]
+; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_BODY4]], label [[FOR_COND_CLEANUP3_LOOPEXIT]]
+;
entry:
%cmp15 = icmp sgt i32 %o, 0
br i1 %cmp15, label %for.body, label %for.cond.cleanup
declare void @foo(ptr)
define void @NonAddRecIV(ptr %a) {
-; CHECK: SCEV of phi ' %lsr.iv = phi i32 [ %lsr.iv.next, %for.body ], [ 1, %entry ]'
-; CHECK: is not an affine add recursion, not qualified for the terminating condition folding.
+; CHECK-LABEL: define void @NonAddRecIV
+; CHECK-SAME: (ptr [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A]], i32 84
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1, [[ENTRY]] ]
+; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4
+; CHECK-NEXT: [[LSR_IV_NEXT]] = mul nsw i32 [[LSR_IV]], 2
+; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
+; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 65536
+; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
+; CHECK: for.end:
+; CHECK-NEXT: ret void
+;
entry:
%uglygep = getelementptr i8, ptr %a, i32 84
br label %for.body
@fp_inc = common global float 0.000000e+00, align 4
define void @NonSCEVableIV(float %init, float* %A, i32 %N) {
-; CHECK: IV of phi ' %x.05 = phi float [ %init, %entry ], [ %add, %for.body ]'
-; CHECK: is not SCEV-able, not qualified for the terminating condition folding.
+; CHECK-LABEL: define void @NonSCEVableIV
+; CHECK-SAME: (float [[INIT:%.*]], ptr [[A:%.*]], i32 [[N:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr @fp_inc, align 4
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[SCEVGEP:%.*]], [[FOR_BODY]] ], [ [[A]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 1, [[ENTRY]] ]
+; CHECK-NEXT: [[X_05:%.*]] = phi float [ [[INIT]], [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: store float [[X_05]], ptr [[LSR_IV1]], align 4
+; CHECK-NEXT: [[ADD]] = fsub float [[X_05]], [[TMP0]]
+; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[LSR_IV]] to i32
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]
+; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i64 [[LSR_IV]], 1
+; CHECK-NEXT: [[SCEVGEP]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
+; CHECK: for.end:
+; CHECK-NEXT: ret void
+;
entry:
%0 = load float, float* @fp_inc, align 4
br label %for.body
}
define void @NonIcmpEqNe(ptr %a) {
-; CHECK: Cannot fold on branching condition that is not an ICmpInst::eq / ICmpInst::ne
+; CHECK-LABEL: define void @NonIcmpEqNe
+; CHECK-SAME: (ptr [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A]], i64 84
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 379, [[ENTRY]] ]
+; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4
+; CHECK-NEXT: [[LSR_IV_NEXT]] = add nsw i64 [[LSR_IV]], -1
+; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
+; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp sle i64 [[LSR_IV_NEXT]], 0
+; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
+; CHECK: for.end:
+; CHECK-NEXT: ret void
+;
entry:
%uglygep = getelementptr i8, ptr %a, i64 84
br label %for.body
}
define void @TermCondMoreThanOneUse(ptr %a) {
-;CHECK: Cannot replace terminating condition with more than one use
+; CHECK-LABEL: define void @TermCondMoreThanOneUse
+; CHECK-SAME: (ptr [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A]], i64 84
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[LSR_IV2:%.*]] = phi i64 [ [[LSR_IV_NEXT3:%.*]], [[FOR_BODY]] ], [ -378, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY]] ]
+; CHECK-NEXT: store i32 1, ptr [[LSR_IV1]], align 4
+; CHECK-NEXT: [[UGLYGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
+; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[LSR_IV2]], 0
+; CHECK-NEXT: [[DUMMY:%.*]] = select i1 [[EXITCOND_NOT]], i8 0, i8 1
+; CHECK-NEXT: [[LSR_IV_NEXT3]] = add nsw i64 [[LSR_IV2]], 1
+; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[UGLYGEP2]], [[SCEVGEP]]
+; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
+; CHECK: for.end:
+; CHECK-NEXT: ret void
+;
entry:
%uglygep = getelementptr i8, ptr %a, i64 84
br label %for.body
@histogram_energy_boundaries = global [1001 x double] zeroinitializer, align 8
define void @ebur128_calc_gating_block(ptr %st, ptr %optional_output) {
-; CHECK: Is not safe to expand terminating value for phi node %i.026 = phi i64 [ 0, %for.body7.lr.ph ], [ %inc, %for.body7 ]
+; CHECK-LABEL: define void @ebur128_calc_gating_block
+; CHECK-SAME: (ptr [[ST:%.*]], ptr [[OPTIONAL_OUTPUT:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ST]], align 8
+; CHECK-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64
+; CHECK-NEXT: [[CMP28_NOT:%.*]] = icmp eq i32 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[CMP28_NOT]], label [[FOR_END13:%.*]], label [[FOR_COND2_PREHEADER_LR_PH:%.*]]
+; CHECK: for.cond2.preheader.lr.ph:
+; CHECK-NEXT: [[AUDIO_DATA_INDEX:%.*]] = getelementptr inbounds [[STRUCT_FFEBUR128STATE:%.*]], ptr [[ST]], i64 0, i32 3
+; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[AUDIO_DATA_INDEX]], align 8
+; CHECK-NEXT: [[DIV:%.*]] = udiv i64 [[TMP1]], [[CONV]]
+; CHECK-NEXT: [[CMP525_NOT:%.*]] = icmp ult i64 [[TMP1]], [[CONV]]
+; CHECK-NEXT: [[AUDIO_DATA:%.*]] = getelementptr inbounds [[STRUCT_FFEBUR128STATE]], ptr [[ST]], i64 0, i32 1
+; CHECK-NEXT: [[UMAX:%.*]] = tail call i64 @llvm.umax.i64(i64 [[DIV]], i64 1)
+; CHECK-NEXT: [[TMP2:%.*]] = shl nuw nsw i64 [[CONV]], 3
+; CHECK-NEXT: br label [[FOR_COND2_PREHEADER:%.*]]
+; CHECK: for.cond2.preheader:
+; CHECK-NEXT: [[LSR_IV1:%.*]] = phi i64 [ [[LSR_IV_NEXT2:%.*]], [[FOR_INC11:%.*]] ], [ 0, [[FOR_COND2_PREHEADER_LR_PH]] ]
+; CHECK-NEXT: [[CHANNEL_SUM_030:%.*]] = phi double [ 0.000000e+00, [[FOR_COND2_PREHEADER_LR_PH]] ], [ [[CHANNEL_SUM_1_LCSSA:%.*]], [[FOR_INC11]] ]
+; CHECK-NEXT: [[C_029:%.*]] = phi i64 [ 0, [[FOR_COND2_PREHEADER_LR_PH]] ], [ [[INC12:%.*]], [[FOR_INC11]] ]
+; CHECK-NEXT: br i1 [[CMP525_NOT]], label [[FOR_INC11]], label [[FOR_BODY7_LR_PH:%.*]]
+; CHECK: for.body7.lr.ph:
+; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[AUDIO_DATA]], align 8
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[TMP3]], i64 [[LSR_IV1]]
+; CHECK-NEXT: br label [[FOR_BODY7:%.*]]
+; CHECK: for.body7:
+; CHECK-NEXT: [[LSR_IV3:%.*]] = phi ptr [ [[SCEVGEP4:%.*]], [[FOR_BODY7]] ], [ [[SCEVGEP]], [[FOR_BODY7_LR_PH]] ]
+; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY7]] ], [ [[UMAX]], [[FOR_BODY7_LR_PH]] ]
+; CHECK-NEXT: [[CHANNEL_SUM_127:%.*]] = phi double [ [[CHANNEL_SUM_030]], [[FOR_BODY7_LR_PH]] ], [ [[ADD10:%.*]], [[FOR_BODY7]] ]
+; CHECK-NEXT: [[TMP4:%.*]] = load double, ptr [[LSR_IV3]], align 8
+; CHECK-NEXT: [[ADD10]] = fadd double [[CHANNEL_SUM_127]], [[TMP4]]
+; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -1
+; CHECK-NEXT: [[SCEVGEP4]] = getelementptr i8, ptr [[LSR_IV3]], i64 [[TMP2]]
+; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
+; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_INC11_LOOPEXIT:%.*]], label [[FOR_BODY7]]
+; CHECK: for.inc11.loopexit:
+; CHECK-NEXT: [[ADD10_LCSSA:%.*]] = phi double [ [[ADD10]], [[FOR_BODY7]] ]
+; CHECK-NEXT: br label [[FOR_INC11]]
+; CHECK: for.inc11:
+; CHECK-NEXT: [[CHANNEL_SUM_1_LCSSA]] = phi double [ [[CHANNEL_SUM_030]], [[FOR_COND2_PREHEADER]] ], [ [[ADD10_LCSSA]], [[FOR_INC11_LOOPEXIT]] ]
+; CHECK-NEXT: [[INC12]] = add nuw nsw i64 [[C_029]], 1
+; CHECK-NEXT: [[LSR_IV_NEXT2]] = add nuw nsw i64 [[LSR_IV1]], 8
+; CHECK-NEXT: [[EXITCOND32_NOT:%.*]] = icmp eq i64 [[INC12]], [[CONV]]
+; CHECK-NEXT: br i1 [[EXITCOND32_NOT]], label [[FOR_END13_LOOPEXIT:%.*]], label [[FOR_COND2_PREHEADER]]
+; CHECK: for.end13.loopexit:
+; CHECK-NEXT: [[CHANNEL_SUM_1_LCSSA_LCSSA:%.*]] = phi double [ [[CHANNEL_SUM_1_LCSSA]], [[FOR_INC11]] ]
+; CHECK-NEXT: br label [[FOR_END13]]
+; CHECK: for.end13:
+; CHECK-NEXT: [[CHANNEL_SUM_0_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[CHANNEL_SUM_1_LCSSA_LCSSA]], [[FOR_END13_LOOPEXIT]] ]
+; CHECK-NEXT: [[ADD14:%.*]] = fadd double [[CHANNEL_SUM_0_LCSSA]], 0.000000e+00
+; CHECK-NEXT: store double [[ADD14]], ptr [[OPTIONAL_OUTPUT]], align 8
+; CHECK-NEXT: ret void
+;
entry:
%0 = load i32, ptr %st, align 8
%conv = zext i32 %0 to i64
%struct.PAKT_INFO = type { i32, i32, i32, [0 x i32] }
define i64 @alac_seek(ptr %0) {
-; CHECK: Is not safe to expand terminating value for phi node %indvars.iv.i = phi i64 [ 0, %entry ], [ %indvars.iv.next.i, %for.body.i ]
+; CHECK-LABEL: define i64 @alac_seek
+; CHECK-SAME: (ptr [[TMP0:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[DIV:%.*]] = udiv i64 1, 0
+; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[DIV]], 1
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[TMP0]], i64 12
+; CHECK-NEXT: br label [[FOR_BODY_I:%.*]]
+; CHECK: for.body.i:
+; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[SCEVGEP2:%.*]], [[FOR_BODY_I]] ], [ [[SCEVGEP]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY_I]] ], [ [[TMP1]], [[ENTRY]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[LSR_IV1]], align 4
+; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -1
+; CHECK-NEXT: [[SCEVGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
+; CHECK-NEXT: [[EXITCOND_NOT_I:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
+; CHECK-NEXT: br i1 [[EXITCOND_NOT_I]], label [[ALAC_PAKT_BLOCK_OFFSET_EXIT:%.*]], label [[FOR_BODY_I]]
+; CHECK: alac_pakt_block_offset.exit:
+; CHECK-NEXT: ret i64 0
+;
entry:
%div = udiv i64 1, 0
br label %for.body.i
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes="loop-reduce" -S -lsr-term-fold | FileCheck %s
-; There are 3 test cases here regarding the replacing the primary iv with
-; other affine AddRec IV.
-; 1. Loop with constant tripcount
-; 2. Loop with runtime tripcount
-; 3. The replacing AddRec IV is a complicated AddRec. This tests whether
-; the fold terminating condition transformation is writing new terminating
-; condition in the correct type.
-
-target datalayout = "e-p:32:32:32-n32"
+target datalayout = "e-p:64:64:64-n64"
define void @const_tripcount(ptr %a) {
; CHECK-LABEL: @const_tripcount(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 84
-; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i32 1600
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 1600
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
; CHECK-LABEL: @runtime_tripcount(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 84
-; CHECK-NEXT: [[TMP0:%.*]] = shl i32 [[N:%.*]], 2
-; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], 84
-; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i32 [[TMP1]]
+; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N:%.*]] to i64
+; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 2
+; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 84
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP2]]
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[UGLYGEP]], [[ENTRY:%.*]] ]
ret void
}
+; The replacing AddRec IV is a complicated AddRec. This tests whether
+; the fold terminating condition transformation is writing new terminating
+; condition in the correct type.
define void @ptr_of_ptr_addrec(ptr %ptrptr, i32 %length) {
; CHECK-LABEL: @ptr_of_ptr_addrec(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[START_PTRPTR:%.*]] = getelementptr ptr, ptr [[PTRPTR:%.*]]
-; CHECK-NEXT: [[TMP0:%.*]] = shl i32 [[LENGTH:%.*]], 2
-; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[START_PTRPTR]], i32 [[TMP0]]
+; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[LENGTH:%.*]] to i64
+; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 3
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[START_PTRPTR]], i64 [[TMP1]]
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[IT_04:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[START_PTRPTR]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[IT_04]], align 8
-; CHECK-NEXT: tail call void @foo(ptr [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[IT_04]], align 8
+; CHECK-NEXT: tail call void @foo(ptr [[TMP2]])
; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds ptr, ptr [[IT_04]], i64 1
; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[INCDEC_PTR]], [[SCEVGEP]]
; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
; CHECK-NEXT: [[TOBOOL_NOT3:%.*]] = icmp eq i32 [[LENGTH:%.*]], 0
; CHECK-NEXT: br i1 [[TOBOOL_NOT3]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
; CHECK: for.body.preheader:
-; CHECK-NEXT: [[TMP0:%.*]] = shl i32 [[LENGTH]], 2
-; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[MARK:%.*]], i32 [[TMP0]]
+; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[LENGTH]] to i64
+; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 3
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[MARK:%.*]], i64 [[TMP1]]
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.cond.cleanup.loopexit:
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
; CHECK-NEXT: ret void
; CHECK: for.body:
; CHECK-NEXT: [[DST_04:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[MARK]], [[FOR_BODY_PREHEADER]] ]
-; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[DST_04]], align 8
-; CHECK-NEXT: [[TMP2:%.*]] = call ptr @foo(ptr [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DST_04]], align 8
+; CHECK-NEXT: [[TMP3:%.*]] = call ptr @foo(ptr [[TMP2]])
; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds ptr, ptr [[DST_04]], i64 1
; CHECK-NEXT: [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND:%.*]] = icmp eq ptr [[INCDEC_PTR]], [[SCEVGEP]]
; CHECK-NEXT: br i1 [[LSR_FOLD_TERM_COND_REPLACED_TERM_COND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]]
define void @inbounds_poison_use(ptr %a) {
; CHECK-LABEL: @inbounds_poison_use(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 16
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 16
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[A]], [[ENTRY:%.*]] ]
define void @iv_size(ptr %a, i128 %N) {
; CHECK-LABEL: @iv_size(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = trunc i128 [[N:%.*]] to i32
-; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[TMP0]], 2
-; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i32 [[TMP1]]
+; CHECK-NEXT: [[TMP0:%.*]] = trunc i128 [[N:%.*]] to i64
+; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 2
+; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[TMP1]]
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[UGLYGEP2:%.*]], [[FOR_BODY]] ], [ [[A]], [[ENTRY:%.*]] ]