diff --git a/llvm/test/Analysis/ScalarEvolution/trivial-phis.ll b/llvm/test/Analysis/ScalarEvolution/trivial-phis.ll new file mode 100644 index 0000000000000..3a897e957d1b2 --- /dev/null +++ b/llvm/test/Analysis/ScalarEvolution/trivial-phis.ll @@ -0,0 +1,191 @@ +; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s + +; CHECK-LABEL @test1 +; CHECK %add.lcssa.wide = phi i64 [ %indvars.iv.next, %do.body ] +; CHECK-NEXT --> %add.lcssa.wide U: [1,2147483648) S: [1,2147483648) + +define i64 @test1(i32 signext %n, float* %A) { +entry: + %0 = sext i32 %n to i64 + br label %do.body + +do.body: ; preds = %do.body, %entry + %indvars.iv = phi i64 [ %indvars.iv.next, %do.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds float, float* %A, i64 %indvars.iv + store float 1.000000e+00, float* %arrayidx, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %cmp = icmp slt i64 %indvars.iv.next, %0 + br i1 %cmp, label %do.body, label %do.end + +do.end: ; preds = %do.body + %add.lcssa.wide = phi i64 [ %indvars.iv.next, %do.body ] + ret i64 %add.lcssa.wide +} + +; CHECK-LABEL @test2 +; CHECK: %tmp24 = phi i64 [ %tmp14, %bb22 ], [ %tmp14, %bb13 ] +; CHECK-NEXT: --> %tmp24 U: full-set S: full-set Exits: <> LoopDispositions: { %bb13: Variant, %bb8: Variant, %bb17: Invariant, %bb27: Invariant } + +define void @test2(i64 %arg, i32* noalias %arg1) { +bb: + %tmp = icmp slt i64 0, %arg + br i1 %tmp, label %bb7, label %bb48 + +bb7: ; preds = %bb + br label %bb8 + +bb8: ; preds = %bb44, %bb7 + %tmp9 = phi i64 [ 0, %bb7 ], [ %tmp45, %bb44 ] + %tmp10 = add nsw i64 %arg, -1 + %tmp11 = icmp slt i64 1, %tmp10 + br i1 %tmp11, label %bb12, label %bb43 + +bb12: ; preds = %bb8 + br label %bb13 + +bb13: ; preds = %bb39, %bb12 + %tmp14 = phi i64 [ 1, %bb12 ], [ %tmp40, %bb39 ] + %tmp15 = icmp slt i64 0, %arg + br i1 %tmp15, label %bb16, label %bb23 + +bb16: ; preds = %bb13 + br label %bb17 + +bb17: ; preds = %bb19, %bb16 + %tmp18 = phi i64 [ 0, %bb16 ], [ %tmp20, %bb19 ] + br label %bb19 + +bb19: ; preds = %bb17 + %tmp20 = add nuw nsw i64 %tmp18, 1 + %tmp21 = icmp slt i64 %tmp20, %arg + br i1 %tmp21, label %bb17, label %bb22 + +bb22: ; preds = %bb19 + br label %bb23 + +bb23: ; preds = %bb22, %bb13 + %tmp24 = phi i64 [ %tmp14, %bb22 ], [ %tmp14, %bb13 ] + %tmp25 = icmp slt i64 0, %arg + br i1 %tmp25, label %bb26, label %bb37 + +bb26: ; preds = %bb23 + br label %bb27 + +bb27: ; preds = %bb33, %bb26 + %tmp28 = phi i64 [ 0, %bb26 ], [ %tmp34, %bb33 ] + %tmp29 = mul nsw i64 %tmp9, %arg + %tmp30 = getelementptr inbounds i32, i32* %arg1, i64 %tmp24 + %tmp31 = getelementptr inbounds i32, i32* %tmp30, i64 %tmp29 + %tmp32 = load i32, i32* %tmp31, align 4 + br label %bb33 + +bb33: ; preds = %bb27 + %tmp34 = add nuw nsw i64 %tmp28, 1 + %tmp35 = icmp slt i64 %tmp34, %arg + br i1 %tmp35, label %bb27, label %bb36 + +bb36: ; preds = %bb33 + br label %bb37 + +bb37: ; preds = %bb36, %bb23 + %tmp38 = phi i64 [ %tmp24, %bb36 ], [ %tmp24, %bb23 ] + br label %bb39 + +bb39: ; preds = %bb37 + %tmp40 = add nuw nsw i64 %tmp38, 1 + %tmp41 = icmp slt i64 %tmp40, %tmp10 + br i1 %tmp41, label %bb13, label %bb42 + +bb42: ; preds = %bb39 + br label %bb43 + +bb43: ; preds = %bb42, %bb8 + br label %bb44 + +bb44: ; preds = %bb43 + %tmp45 = add nuw nsw i64 %tmp9, 1 + %tmp46 = icmp slt i64 %tmp45, %arg + br i1 %tmp46, label %bb8, label %bb47 + +bb47: ; preds = %bb44 + br label %bb48 + +bb48: ; preds = %bb47, %bb + ret void +} + +; CHECK-LABEL @test3 + +; CHECK: %tmp14 = phi i64 [ %tmp40, %bb39 ], [ 1, %bb8 ] +; CHECK-NEXT: --> {1,+,1}<%bb13> U: [1,9223372036854775807) S: [1,9223372036854775807) +; CHECK-SAME: Exits: (-2 + %arg) LoopDispositions: { %bb13: Computable, %bb8: Variant, %bb17_a: Invariant, %bb27: Invariant } +; CHECK: %tmp18 = phi i64 [ %tmp20, %bb17 ], [ 0, %bb13 ] +; CHECK-NEXT: --> {0,+,1}<%bb17_a> U: [0,9223372036854775807) S: [0,9223372036854775807) +; CHECK-SAME: Exits: (-1 + %arg) LoopDispositions: { %bb17_a: Computable, %bb13: Variant, %bb8: Variant } + +; CHECK: %tmp24 = phi i64 [ %tmp14, %bb13 ], [ %tmp14, %bb17 ] +; CHECK-NEXT: --> {1,+,1}<%bb13> U: [1,9223372036854775807) S: [1,9223372036854775807) +; CHECK-SAME: Exits: (-2 + %arg) LoopDispositions: { %bb13: Computable, %bb8: Variant, %bb17_a: Invariant, %bb27: Invariant } +; CHECK: %tmp28 = phi i64 [ %tmp34, %bb27 ], [ 0, %bb23 ] +; CHECK-NEXT: --> {0,+,1}<%bb27> U: [0,9223372036854775807) S: [0,9223372036854775807) +; CHECK-SAME: Exits: (-1 + %arg) LoopDispositions: { %bb27: Computable, %bb13: Variant, %bb8: Variant } + +; CHECK: %tmp38 = phi i64 [ %tmp24, %bb23 ], [ %tmp24, %bb27 ] +; CHECK-NEXT: --> {1,+,1}<%bb13> U: [1,9223372036854775807) S: [1,9223372036854775807) +; CHECK-SAME: Exits: (-2 + %arg) LoopDispositions: { %bb13: Computable, %bb8: Variant, %bb17_a: Invariant, %bb27: Invariant } + +define void @test3(i64 %arg, i32* %arg1) { +bb: + %tmp = icmp slt i64 0, %arg + br i1 %tmp, label %bb8, label %bb48 + +bb8: ; preds = %bb, %bb44 + %tmp9 = phi i64 [ %tmp45, %bb44 ], [ 0, %bb ] + %tmp10 = add nsw i64 %arg, -1 + %tmp11 = icmp slt i64 1, %tmp10 + br i1 %tmp11, label %bb13, label %bb44 + +bb13: ; preds = %bb8, %bb39 + %tmp14 = phi i64 [ %tmp40, %bb39 ], [ 1, %bb8 ] + %tmp15 = icmp slt i64 0, %arg + br i1 %tmp15, label %bb17_a, label %bb23 + +bb17_a: + %tmp18 = phi i64 [ %tmp20, %bb17 ], [ 0, %bb13 ] + %tmp20 = add nuw nsw i64 %tmp18, 1 + + br label %bb17 + +bb17: ; preds = %bb13, %bb17 + %tmp21 = icmp slt i64 %tmp20, %arg + br i1 %tmp21, label %bb17_a, label %bb23 + +bb23: ; preds = %bb17, %bb13 + %tmp24 = phi i64 [ %tmp14, %bb13 ], [ %tmp14, %bb17 ] + %tmp25 = icmp slt i64 0, %arg + br i1 %tmp25, label %bb27, label %bb39 + +bb27: ; preds = %bb23, %bb27 + %tmp28 = phi i64 [ %tmp34, %bb27 ], [ 0, %bb23 ] + %tmp29 = mul nsw i64 %tmp9, %arg + %tmp30 = getelementptr inbounds i32, i32* %arg1, i64 %tmp24 + %tmp31 = getelementptr inbounds i32, i32* %tmp30, i64 %tmp29 + %tmp32 = load i32, i32* %tmp31, align 4 + %tmp34 = add nuw nsw i64 %tmp28, 1 + %tmp35 = icmp slt i64 %tmp34, %arg + br i1 %tmp35, label %bb27, label %bb39 + +bb39: ; preds = %bb23, %bb27 + %tmp38 = phi i64 [ %tmp24, %bb23 ], [ %tmp24, %bb27 ] + %tmp40 = add nuw nsw i64 %tmp38, 1 + %tmp41 = icmp slt i64 %tmp40, %tmp10 + br i1 %tmp41, label %bb13, label %bb44 + +bb44: ; preds = %bb8, %bb39 + %tmp45 = add nuw nsw i64 %tmp9, 1 + %tmp46 = icmp slt i64 %tmp45, %arg + br i1 %tmp46, label %bb8, label %bb48 + +bb48: ; preds = %bb44, %bb + ret void +} diff --git a/llvm/test/Transforms/IndVarSimplify/scev-expander-preserve-lcssa.ll b/llvm/test/Transforms/IndVarSimplify/scev-expander-preserve-lcssa.ll new file mode 100644 index 0000000000000..d26d3b23b7724 --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/scev-expander-preserve-lcssa.ll @@ -0,0 +1,587 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -indvars -S -indvars -verify-loop-lcssa %s | FileCheck %s + +; Make sure SCEVExpander does not crash and introduce unnecessary LCSSA PHI nodes. +; The tests are a collection of cases with crashes when preserving LCSSA PHI +; nodes directly in SCEVExpander. + +declare i1 @cond() readnone + +define void @test1(i8 %x, [512 x i8]* %ptr) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LAND_LHS_TRUE:%.*]] +; CHECK: land.lhs.true: +; CHECK-NEXT: br label [[WHILE_COND22:%.*]] +; CHECK: while.cond22: +; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_1]], label [[WHILE_COND22]], label [[WHILE_COND29_PREHEADER:%.*]] +; CHECK: while.cond29.preheader: +; CHECK-NEXT: br label [[WHILE_BODY35:%.*]] +; CHECK: while.body35: +; CHECK-NEXT: [[I_1107:%.*]] = phi i32 [ [[I_9:%.*]], [[IF_END224:%.*]] ], [ 0, [[WHILE_COND29_PREHEADER]] ] +; CHECK-NEXT: br label [[WHILE_COND192:%.*]] +; CHECK: while.cond192: +; CHECK-NEXT: switch i8 [[X:%.*]], label [[WHILE_BODY205:%.*]] [ +; CHECK-NEXT: i8 59, label [[WHILE_COND215_PREHEADER:%.*]] +; CHECK-NEXT: i8 10, label [[IF_END224_LOOPEXIT1:%.*]] +; CHECK-NEXT: ] +; CHECK: while.cond215.preheader: +; CHECK-NEXT: br label [[WHILE_COND215:%.*]] +; CHECK: while.body205: +; CHECK-NEXT: br label [[WHILE_COND192]] +; CHECK: while.cond215: +; CHECK-NEXT: [[I_8_IN:%.*]] = phi i32 [ [[I_8:%.*]], [[WHILE_COND215]] ], [ [[I_1107]], [[WHILE_COND215_PREHEADER]] ] +; CHECK-NEXT: [[I_8]] = add nsw i32 [[I_8_IN]], 1 +; CHECK-NEXT: [[IDXPROM216:%.*]] = sext i32 [[I_8]] to i64 +; CHECK-NEXT: [[ARRAYIDX217:%.*]] = getelementptr inbounds [512 x i8], [512 x i8]* [[PTR:%.*]], i64 0, i64 [[IDXPROM216]] +; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_2]], label [[WHILE_COND215]], label [[IF_END224_LOOPEXIT:%.*]] +; CHECK: if.end224.loopexit: +; CHECK-NEXT: [[I_8_LCSSA:%.*]] = phi i32 [ [[I_8]], [[WHILE_COND215]] ] +; CHECK-NEXT: br label [[IF_END224]] +; CHECK: if.end224.loopexit1: +; CHECK-NEXT: br label [[IF_END224]] +; CHECK: if.end224: +; CHECK-NEXT: [[I_9]] = phi i32 [ [[I_8_LCSSA]], [[IF_END224_LOOPEXIT]] ], [ [[I_1107]], [[IF_END224_LOOPEXIT1]] ] +; CHECK-NEXT: [[C_3:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_3]], label [[WHILE_END225:%.*]], label [[WHILE_BODY35]] +; CHECK: while.end225: +; CHECK-NEXT: br label [[LAND_LHS_TRUE]] +; +entry: + br label %land.lhs.true + +land.lhs.true: ; preds = %while.end225, %entry + br label %while.cond22 + +while.cond22: ; preds = %while.cond22, %land.lhs.true + %c.1 = call i1 @cond() + br i1 %c.1, label %while.cond22, label %while.cond29.preheader + +while.cond29.preheader: ; preds = %while.cond22 + br label %while.body35 + +while.body35: ; preds = %if.end224, %while.cond29.preheader + %i.1107 = phi i32 [ %i.9, %if.end224 ], [ 0, %while.cond29.preheader ] + br label %while.cond192 + +while.cond192: ; preds = %while.body205, %while.body35 + %i.7 = phi i32 [ %i.1107, %while.body35 ], [ %inc206, %while.body205 ] + switch i8 %x, label %while.body205 [ + i8 59, label %while.cond215 + i8 10, label %if.end224 + ] + +while.body205: ; preds = %while.cond192 + %inc206 = add nsw i32 %i.7, 1 + br label %while.cond192 + +while.cond215: ; preds = %while.cond215, %while.cond192 + %i.8.in = phi i32 [ %i.8, %while.cond215 ], [ %i.7, %while.cond192 ] + %i.8 = add nsw i32 %i.8.in, 1 + %idxprom216 = sext i32 %i.8 to i64 + %arrayidx217 = getelementptr inbounds [512 x i8], [512 x i8]* %ptr, i64 0, i64 %idxprom216 + %c.2 = call i1 @cond() + br i1 %c.2, label %while.cond215, label %if.end224 + +if.end224: ; preds = %while.cond215, %while.cond192 + %i.9 = phi i32 [ %i.8, %while.cond215 ], [ %i.7, %while.cond192 ] + %c.3 = call i1 @cond() + br i1 %c.3, label %while.end225, label %while.body35 + +while.end225: ; preds = %if.end224 + br label %land.lhs.true +} + +define void @test2(i16 %x) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_1]], label [[FOR_COND_PREHEADER:%.*]], label [[RETURN:%.*]] +; CHECK: for.cond.preheader: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: switch i16 [[X:%.*]], label [[RETURN_LOOPEXIT1:%.*]] [ +; CHECK-NEXT: i16 41, label [[FOR_END:%.*]] +; CHECK-NEXT: i16 43, label [[FOR_COND]] +; CHECK-NEXT: ] +; CHECK: for.end: +; CHECK-NEXT: [[I_0_LCSSA2:%.*]] = phi i32 [ 0, [[FOR_COND]] ] +; CHECK-NEXT: [[CMP8243:%.*]] = icmp sgt i32 [[I_0_LCSSA2]], 0 +; CHECK-NEXT: br i1 [[CMP8243]], label [[FOR_BODY84_PREHEADER:%.*]], label [[RETURN]] +; CHECK: for.body84.preheader: +; CHECK-NEXT: br label [[FOR_BODY84:%.*]] +; CHECK: for.body84: +; CHECK-NEXT: [[I_144:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END106:%.*]] ], [ 0, [[FOR_BODY84_PREHEADER]] ] +; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_2]], label [[IF_END106]], label [[RETURN_LOOPEXIT:%.*]] +; CHECK: if.end106: +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_144]], 1 +; CHECK-NEXT: [[CMP82:%.*]] = icmp slt i32 [[INC]], [[I_0_LCSSA2]] +; CHECK-NEXT: br i1 [[CMP82]], label [[FOR_BODY84]], label [[RETURN_LOOPEXIT]] +; CHECK: return.loopexit: +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return.loopexit1: +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: ret void +; +entry: + %c.1 = call i1 @cond() + br i1 %c.1, label %for.cond, label %return + +for.cond: ; preds = %for.cond, %entry + %i.0 = phi i32 [ %sub, %for.cond ], [ 0, %entry ] + %sub = add nsw i32 %i.0, -1 + switch i16 %x, label %return [ + i16 41, label %for.end + i16 43, label %for.cond + ] + +for.end: ; preds = %for.cond + %cmp8243 = icmp sgt i32 %i.0, 0 + br i1 %cmp8243, label %for.body84, label %return + +for.body84: ; preds = %if.end106, %for.end + %i.144 = phi i32 [ %inc, %if.end106 ], [ 0, %for.end ] + %c.2 = call i1 @cond() + br i1 %c.2, label %if.end106, label %return + +if.end106: ; preds = %for.body84 + %inc = add nuw nsw i32 %i.144, 1 + %cmp82 = icmp slt i32 %inc, %i.0 + br i1 %cmp82, label %for.body84, label %return + +return: ; preds = %if.end106, %for.body84, %for.end, %for.cond, %entry + ret void +} + +declare i32 @get.i32() readnone + +define void @test3(i32* %ptr) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK: while.body: +; CHECK-NEXT: br label [[FOR_BODY1208:%.*]] +; CHECK: for.body1208: +; CHECK-NEXT: [[M_0804:%.*]] = phi i32 [ 1, [[WHILE_BODY]] ], [ [[INC1499:%.*]], [[FOR_INC1498:%.*]] ] +; CHECK-NEXT: [[V:%.*]] = call i32 @get.i32() +; CHECK-NEXT: [[CMP1358:%.*]] = icmp eq i32 [[V]], 0 +; CHECK-NEXT: br i1 [[CMP1358]], label [[IF_THEN1360:%.*]], label [[FOR_INC1498]] +; CHECK: if.then1360: +; CHECK-NEXT: [[M_0804_LCSSA:%.*]] = phi i32 [ [[M_0804]], [[FOR_BODY1208]] ] +; CHECK-NEXT: br label [[FOR_COND1390:%.*]] +; CHECK: for.cond1390: +; CHECK-NEXT: [[M_2_IN:%.*]] = phi i32 [ [[M_0804_LCSSA]], [[IF_THEN1360]] ], [ 0, [[FOR_BODY1394:%.*]] ] +; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_2]], label [[FOR_BODY1394]], label [[FOR_END1469:%.*]] +; CHECK: for.body1394: +; CHECK-NEXT: br label [[FOR_COND1390]] +; CHECK: for.end1469: +; CHECK-NEXT: [[M_2_IN_LCSSA:%.*]] = phi i32 [ [[M_2_IN]], [[FOR_COND1390]] ] +; CHECK-NEXT: store i32 [[M_2_IN_LCSSA]], i32* [[PTR:%.*]], align 4 +; CHECK-NEXT: br label [[WHILE_BODY]] +; CHECK: for.inc1498: +; CHECK-NEXT: [[INC1499]] = add nuw nsw i32 [[M_0804]], 1 +; CHECK-NEXT: br label [[FOR_BODY1208]] +; +entry: + br label %while.body + +while.body: ; preds = %for.end1469, %entry + br label %for.body1208 + +for.body1208: ; preds = %for.inc1498, %while.body + %m.0804 = phi i32 [ 1, %while.body ], [ %inc1499, %for.inc1498 ] + %v = call i32 @get.i32() + %cmp1358 = icmp eq i32 %v, 0 + br i1 %cmp1358, label %if.then1360, label %for.inc1498 + +if.then1360: ; preds = %for.body1208 + br label %for.cond1390 + +for.cond1390: ; preds = %for.body1394, %if.then1360 + %m.2.in = phi i32 [ %m.0804, %if.then1360 ], [ 0, %for.body1394 ] + %c.2 = call i1 @cond() + br i1 %c.2, label %for.body1394, label %for.end1469 + +for.body1394: ; preds = %for.cond1390 + br label %for.cond1390 + +for.end1469: ; preds = %for.cond1390 + store i32 %m.2.in, i32* %ptr, align 4 + br label %while.body + +for.inc1498: ; preds = %for.body1208 + %inc1499 = add nuw nsw i32 %m.0804, 1 + br label %for.body1208 +} + +define void @test4(i32* %ptr) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK: while.body: +; CHECK-NEXT: br label [[FOR_COND1204_PREHEADER:%.*]] +; CHECK: for.cond1204.preheader: +; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN1504:%.*]], label [[FOR_BODY1208_LR_PH:%.*]] +; CHECK: for.body1208.lr.ph: +; CHECK-NEXT: br label [[FOR_BODY1208:%.*]] +; CHECK: for.body1208: +; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[FOR_BODY1208_LR_PH]] ], [ [[TMP1:%.*]], [[FOR_INC1498:%.*]] ] +; CHECK-NEXT: [[M_0804:%.*]] = phi i32 [ 1, [[FOR_BODY1208_LR_PH]] ], [ [[INC1499:%.*]], [[FOR_INC1498]] ] +; CHECK-NEXT: [[IDXPROM1212:%.*]] = zext i32 [[M_0804]] to i64 +; CHECK-NEXT: [[V:%.*]] = call i32 @get.i32() +; CHECK-NEXT: [[CMP1215:%.*]] = icmp eq i32 0, [[V]] +; CHECK-NEXT: [[YPOS1223:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 [[IDXPROM1212]] +; CHECK-NEXT: br i1 [[CMP1215]], label [[IF_THEN1217:%.*]], label [[IF_ELSE1351:%.*]] +; CHECK: if.then1217: +; CHECK-NEXT: [[M_0804_LCSSA:%.*]] = phi i32 [ [[M_0804]], [[FOR_BODY1208]] ] +; CHECK-NEXT: br label [[FOR_COND1247:%.*]] +; CHECK: for.cond1247: +; CHECK-NEXT: [[M_1_IN:%.*]] = phi i32 [ [[M_0804_LCSSA]], [[IF_THEN1217]] ], [ [[M_1:%.*]], [[IF_THEN1260:%.*]] ] +; CHECK-NEXT: [[M_1]] = add nuw nsw i32 [[M_1_IN]], 1 +; CHECK-NEXT: br label [[FOR_BODY1251:%.*]] +; CHECK: for.body1251: +; CHECK-NEXT: [[IDXPROM1255:%.*]] = zext i32 [[M_1]] to i64 +; CHECK-NEXT: [[XPOS1257:%.*]] = getelementptr inbounds i32, i32* [[PTR]], i64 [[IDXPROM1255]] +; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_2]], label [[IF_THEN1260]], label [[FOR_END1326:%.*]] +; CHECK: if.then1260: +; CHECK-NEXT: br label [[FOR_COND1247]] +; CHECK: for.end1326: +; CHECK-NEXT: br label [[IF_END1824:%.*]] +; CHECK: if.else1351: +; CHECK-NEXT: [[V_2:%.*]] = call i32 @get.i32() +; CHECK-NEXT: [[CMP1358:%.*]] = icmp eq i32 [[V_2]], 0 +; CHECK-NEXT: br i1 [[CMP1358]], label [[IF_THEN1360:%.*]], label [[FOR_INC1498]] +; CHECK: if.then1360: +; CHECK-NEXT: [[DOTLCSSA2:%.*]] = phi i32 [ [[TMP0]], [[IF_ELSE1351]] ] +; CHECK-NEXT: [[M_0804_LCSSA1:%.*]] = phi i32 [ [[M_0804]], [[IF_ELSE1351]] ] +; CHECK-NEXT: [[CMP1392:%.*]] = icmp slt i32 [[M_0804_LCSSA1]], [[DOTLCSSA2]] +; CHECK-NEXT: unreachable +; CHECK: for.inc1498: +; CHECK-NEXT: [[INC1499]] = add nuw nsw i32 [[M_0804]], 1 +; CHECK-NEXT: [[TMP1]] = load i32, i32* [[PTR]], align 8 +; CHECK-NEXT: br label [[FOR_BODY1208]] +; CHECK: if.then1504: +; CHECK-NEXT: unreachable +; CHECK: if.end1824: +; CHECK-NEXT: br label [[WHILE_BODY]] +; +entry: + br label %while.body + +while.body: ; preds = %if.end1824, %entry + br label %for.cond1204.preheader + +for.cond1204.preheader: ; preds = %while.body + %c.1 = call i1 @cond() + br i1 %c.1, label %if.then1504, label %for.body1208.lr.ph + +for.body1208.lr.ph: ; preds = %for.cond1204.preheader + br label %for.body1208 + +for.body1208: ; preds = %for.inc1498, %for.body1208.lr.ph + %0 = phi i32 [ 0, %for.body1208.lr.ph ], [ %1, %for.inc1498 ] + %m.0804 = phi i32 [ 1, %for.body1208.lr.ph ], [ %inc1499, %for.inc1498 ] + %idxprom1212 = zext i32 %m.0804 to i64 + %v = call i32 @get.i32() + %cmp1215 = icmp eq i32 0, %v + %ypos1223 = getelementptr inbounds i32, i32* %ptr , i64 %idxprom1212 + br i1 %cmp1215, label %if.then1217, label %if.else1351 + +if.then1217: ; preds = %for.body1208 + br label %for.cond1247 + +for.cond1247: ; preds = %if.then1260, %if.then1217 + %m.1.in = phi i32 [ %m.0804, %if.then1217 ], [ %m.1, %if.then1260 ] + %m.1 = add nuw nsw i32 %m.1.in, 1 + %cmp1249 = icmp slt i32 %m.1.in, %0 + br label %for.body1251 + +for.body1251: ; preds = %for.cond1247 + %idxprom1255 = zext i32 %m.1 to i64 + %xpos1257 = getelementptr inbounds i32, i32* %ptr, i64 %idxprom1255 + %c.2 = call i1 @cond() + br i1 %c.2, label %if.then1260, label %for.end1326 + +if.then1260: ; preds = %for.body1251 + br label %for.cond1247 + +for.end1326: ; preds = %for.body1251 + br label %if.end1824 + +if.else1351: ; preds = %for.body1208 + %v.2 = call i32 @get.i32() + %cmp1358 = icmp eq i32 %v.2, 0 + br i1 %cmp1358, label %if.then1360, label %for.inc1498 + +if.then1360: ; preds = %if.else1351 + %cmp1392 = icmp slt i32 %m.0804, %0 + unreachable + +for.inc1498: ; preds = %if.else1351 + %inc1499 = add nuw nsw i32 %m.0804, 1 + %1 = load i32, i32* %ptr, align 8 + br label %for.body1208 + +if.then1504: ; preds = %for.cond1204.preheader + unreachable + +if.end1824: ; preds = %for.end1326 + br label %while.body +} + +define void @test5(i8* %header, i32 %conv, i8 %n) { +; CHECK-LABEL: @test5( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[POS_42:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD85:%.*]], [[FOR_INC:%.*]] ] +; CHECK-NEXT: br label [[FOR_INNER:%.*]] +; CHECK: for.inner: +; CHECK-NEXT: [[I_0_I:%.*]] = phi i32 [ 0, [[FOR_BODY]] ], [ [[INC_I:%.*]], [[FOR_INNER]] ] +; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I_0_I]], 1 +; CHECK-NEXT: [[CMP7_I:%.*]] = icmp slt i8 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP7_I]], label [[FOR_INNER]], label [[FOR_INNER_EXIT:%.*]] +; CHECK: for.inner.exit: +; CHECK-NEXT: [[INC_I_LCSSA:%.*]] = phi i32 [ [[INC_I]], [[FOR_INNER]] ] +; CHECK-NEXT: br label [[FOR_INNER_2:%.*]] +; CHECK: for.inner.2: +; CHECK-NEXT: [[I_0_I1:%.*]] = phi i32 [ 0, [[FOR_INNER_EXIT]] ], [ [[INC_I3:%.*]], [[FOR_INNER_2]] ] +; CHECK-NEXT: [[INC_I3]] = add nuw nsw i32 [[I_0_I1]], 1 +; CHECK-NEXT: [[CMP7_I4:%.*]] = icmp slt i8 [[N]], 0 +; CHECK-NEXT: br i1 [[CMP7_I4]], label [[FOR_INNER_2]], label [[FOR_INC]] +; CHECK: for.inc: +; CHECK-NEXT: [[INC_I3_LCSSA:%.*]] = phi i32 [ [[INC_I3]], [[FOR_INNER_2]] ] +; CHECK-NEXT: [[ADD71:%.*]] = add i32 [[POS_42]], [[INC_I_LCSSA]] +; CHECK-NEXT: [[ADD85]] = add i32 [[ADD71]], [[INC_I3_LCSSA]] +; CHECK-NEXT: br i1 false, label [[FOR_BODY]], label [[WHILE_COND_PREHEADER:%.*]] +; CHECK: while.cond.preheader: +; CHECK-NEXT: [[ADD85_LCSSA:%.*]] = phi i32 [ [[ADD85]], [[FOR_INC]] ] +; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[CONV:%.*]], 2 +; CHECK-NEXT: br label [[WHILE_COND:%.*]] +; CHECK: while.cond: +; CHECK-NEXT: [[POS_8:%.*]] = phi i32 [ [[INC114:%.*]], [[WHILE_BODY:%.*]] ], [ [[ADD85_LCSSA]], [[WHILE_COND_PREHEADER]] ] +; CHECK-NEXT: [[CMP112:%.*]] = icmp ult i32 [[POS_8]], [[SHL]] +; CHECK-NEXT: br i1 [[CMP112]], label [[WHILE_BODY]], label [[CLEANUP122:%.*]] +; CHECK: while.body: +; CHECK-NEXT: [[INC114]] = add nuw i32 [[POS_8]], 1 +; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_1]], label [[WHILE_COND]], label [[CLEANUP122]] +; CHECK: cleanup122: +; CHECK-NEXT: ret void +; +entry: + %shl = shl nuw nsw i32 %conv, 2 + br label %for.body + +for.body: ; preds = %entry, %for.inc + %pos.42 = phi i32 [ 0, %entry ], [ %add85, %for.inc ] + br label %for.inner + +for.inner: ; preds = %for.body.i, %for.body + %i.0.i = phi i32 [ 0, %for.body ], [ %inc.i, %for.inner ] + %inc.i = add nuw nsw i32 %i.0.i, 1 + %cmp7.i = icmp slt i8 %n, 0 + br i1 %cmp7.i, label %for.inner, label %for.inner.exit + +for.inner.exit: ; preds = %for.body.i + %add71 = add i32 %pos.42, %inc.i + br label %for.inner.2 + +for.inner.2: ; preds = %for.body.i6, %cleanup.cont74 + %i.0.i1 = phi i32 [ 0, %for.inner.exit ], [ %inc.i3, %for.inner.2] + %inc.i3 = add nuw nsw i32 %i.0.i1, 1 + %cmp7.i4 = icmp slt i8 %n, 0 + br i1 %cmp7.i4, label %for.inner.2, label %for.inc + +for.inc: ; preds = %for.body.i6 + %add85 = add i32 %add71, %inc.i3 + br i1 false, label %for.body, label %while.cond.preheader + +while.cond.preheader: ; preds = %for.inc + br label %while.cond + +while.cond: ; preds = %while.cond.preheader, %while.body + %pos.8 = phi i32 [ %inc114, %while.body ], [ %add85, %while.cond.preheader ] + %cmp112 = icmp ult i32 %pos.8, %shl + br i1 %cmp112, label %while.body, label %cleanup122 + +while.body: ; preds = %while.cond + %inc114 = add nuw i32 %pos.8, 1 + %c.1 = call i1 @cond() + br i1 %c.1, label %while.cond, label %cleanup122 + +cleanup122: ; preds = %while.body, %while.cond + ret void +} + +define void @test6(i8 %x) { +; CHECK-LABEL: @test6( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_1]], label [[LAND_RHS:%.*]], label [[WHILE_END316:%.*]] +; CHECK: land.rhs: +; CHECK-NEXT: br label [[WHILE_BODY35:%.*]] +; CHECK: while.body35: +; CHECK-NEXT: br label [[WHILE_COND192:%.*]] +; CHECK: while.cond192: +; CHECK-NEXT: switch i8 [[X:%.*]], label [[WHILE_BODY205:%.*]] [ +; CHECK-NEXT: i8 59, label [[WHILE_COND215_PREHEADER:%.*]] +; CHECK-NEXT: i8 10, label [[IF_END224:%.*]] +; CHECK-NEXT: ] +; CHECK: while.cond215.preheader: +; CHECK-NEXT: [[I_7_LCSSA:%.*]] = phi i32 [ 0, [[WHILE_COND192]] ] +; CHECK-NEXT: br label [[WHILE_COND215:%.*]] +; CHECK: while.body205: +; CHECK-NEXT: br label [[WHILE_COND192]] +; CHECK: while.cond215: +; CHECK-NEXT: [[I_8_IN:%.*]] = phi i32 [ [[I_8:%.*]], [[WHILE_COND215]] ], [ [[I_7_LCSSA]], [[WHILE_COND215_PREHEADER]] ] +; CHECK-NEXT: [[I_8]] = add nuw nsw i32 [[I_8_IN]], 1 +; CHECK-NEXT: [[IDXPROM216:%.*]] = sext i32 [[I_8]] to i64 +; CHECK-NEXT: [[ARRAYIDX217:%.*]] = getelementptr inbounds [512 x i8], [512 x i8]* null, i64 0, i64 [[IDXPROM216]] +; CHECK-NEXT: br label [[WHILE_COND215]] +; CHECK: if.end224: +; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_2]], label [[WHILE_END225:%.*]], label [[WHILE_BODY35]] +; CHECK: while.end225: +; CHECK-NEXT: unreachable +; CHECK: while.end316: +; CHECK-NEXT: ret void +; +entry: + %c.1 = call i1 @cond() + br i1 %c.1, label %land.rhs, label %while.end316 + +land.rhs: ; preds = %entry + br label %while.body35 + +while.body35: ; preds = %if.end224, %land.rhs + br label %while.cond192 + +while.cond192: ; preds = %while.body205, %while.body35 + %i.7 = phi i32 [ 0, %while.body35 ], [ %inc206, %while.body205 ] + switch i8 %x, label %while.body205 [ + i8 59, label %while.cond215 + i8 10, label %if.end224 + ] + +while.body205: ; preds = %while.cond192 + %inc206 = add nsw i32 %i.7, 1 + br label %while.cond192 + +while.cond215: ; preds = %while.cond215, %while.cond192 + %i.8.in = phi i32 [ %i.8, %while.cond215 ], [ %i.7, %while.cond192 ] + %i.8 = add nsw i32 %i.8.in, 1 + %idxprom216 = sext i32 %i.8 to i64 + %arrayidx217 = getelementptr inbounds [512 x i8], [512 x i8]* null, i64 0, i64 %idxprom216 + br label %while.cond215 + +if.end224: ; preds = %while.cond192 + %c.2 = call i1 @cond() + br i1 %c.2, label %while.end225, label %while.body35 + +while.end225: ; preds = %if.end224 + unreachable + +while.end316: ; preds = %entry + ret void +} + +define void @test7(i32* %ptr) { +; CHECK-LABEL: @test7( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK: while.body: +; CHECK-NEXT: br label [[FOR_BODY1208:%.*]] +; CHECK: for.body1208: +; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ undef, [[WHILE_BODY]] ], [ [[TMP1:%.*]], [[FOR_INC1498:%.*]] ] +; CHECK-NEXT: [[M_048:%.*]] = phi i32 [ 1, [[WHILE_BODY]] ], [ [[INC1499:%.*]], [[FOR_INC1498]] ] +; CHECK-NEXT: [[IDXPROM1212:%.*]] = zext i32 [[M_048]] to i64 +; CHECK-NEXT: [[XPOS1214:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 [[IDXPROM1212]] +; CHECK-NEXT: [[V_1:%.*]] = call i32 @get.i32() +; CHECK-NEXT: [[CMP1215:%.*]] = icmp eq i32 0, [[V_1]] +; CHECK-NEXT: br i1 [[CMP1215]], label [[IF_THEN1217:%.*]], label [[IF_ELSE1351:%.*]] +; CHECK: if.then1217: +; CHECK-NEXT: [[DOTLCSSA:%.*]] = phi i32 [ [[TMP0]], [[FOR_BODY1208]] ] +; CHECK-NEXT: [[M_048_LCSSA:%.*]] = phi i32 [ [[M_048]], [[FOR_BODY1208]] ] +; CHECK-NEXT: [[CMP1249_NOT_NOT:%.*]] = icmp slt i32 [[M_048_LCSSA]], [[DOTLCSSA]] +; CHECK-NEXT: unreachable +; CHECK: if.else1351: +; CHECK-NEXT: [[CMP1358:%.*]] = icmp eq i32 0, undef +; CHECK-NEXT: br i1 [[CMP1358]], label [[IF_THEN1360:%.*]], label [[FOR_INC1498]] +; CHECK: if.then1360: +; CHECK-NEXT: [[M_048_LCSSA1:%.*]] = phi i32 [ [[M_048]], [[IF_ELSE1351]] ] +; CHECK-NEXT: br label [[FOR_COND1390:%.*]] +; CHECK: for.cond1390: +; CHECK-NEXT: [[M_2_IN:%.*]] = phi i32 [ [[M_048_LCSSA1]], [[IF_THEN1360]] ], [ [[M_2:%.*]], [[IF_THEN1403:%.*]] ] +; CHECK-NEXT: [[M_2]] = add nuw nsw i32 [[M_2_IN]], 1 +; CHECK-NEXT: [[IDXPROM1398:%.*]] = zext i32 [[M_2]] to i64 +; CHECK-NEXT: br label [[IF_THEN1403]] +; CHECK: if.then1403: +; CHECK-NEXT: [[XPOS1409:%.*]] = getelementptr inbounds i32, i32* [[PTR]], i64 [[IDXPROM1398]] +; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C_1]], label [[FOR_COND1390]], label [[FOR_END1469:%.*]] +; CHECK: for.end1469: +; CHECK-NEXT: br label [[IF_END1824:%.*]] +; CHECK: for.inc1498: +; CHECK-NEXT: [[INC1499]] = add nuw nsw i32 [[M_048]], 1 +; CHECK-NEXT: [[TMP1]] = load i32, i32* undef, align 8 +; CHECK-NEXT: br label [[FOR_BODY1208]] +; CHECK: if.end1824: +; CHECK-NEXT: br label [[WHILE_BODY]] +; +entry: + br label %while.body + +while.body: ; preds = %if.end1824, %entry + br label %for.body1208 + +for.body1208: ; preds = %for.inc1498, %while.body + %0 = phi i32 [ undef, %while.body ], [ %1, %for.inc1498 ] + %m.048 = phi i32 [ 1, %while.body ], [ %inc1499, %for.inc1498 ] + %idxprom1212 = zext i32 %m.048 to i64 + %xpos1214 = getelementptr inbounds i32, i32* %ptr, i64 %idxprom1212 + %v.1 = call i32 @get.i32() + %cmp1215 = icmp eq i32 0, %v.1 + br i1 %cmp1215, label %if.then1217, label %if.else1351 + +if.then1217: ; preds = %for.body1208 + %cmp1249.not.not = icmp slt i32 %m.048, %0 + unreachable + +if.else1351: ; preds = %for.body1208 + %cmp1358 = icmp eq i32 0, undef + br i1 %cmp1358, label %if.then1360, label %for.inc1498 + +if.then1360: ; preds = %if.else1351 + br label %for.cond1390 + +for.cond1390: ; preds = %if.then1403, %if.then1360 + %m.2.in = phi i32 [ %m.048, %if.then1360 ], [ %m.2, %if.then1403 ] + %m.2 = add nuw nsw i32 %m.2.in, 1 + %cmp1392.not.not = icmp slt i32 %m.2.in, %0 + %idxprom1398 = zext i32 %m.2 to i64 + br label %if.then1403 + +if.then1403: ; preds = %for.cond1390 + %xpos1409 = getelementptr inbounds i32, i32* %ptr, i64 %idxprom1398 + %c.1 = call i1 @cond() + br i1 %c.1, label %for.cond1390, label %for.end1469 + +for.end1469: ; preds = %if.then1403 + br label %if.end1824 + +for.inc1498: ; preds = %if.else1351 + %inc1499 = add nuw nsw i32 %m.048, 1 + %1 = load i32, i32* undef, align 8 + br label %for.body1208 + +if.end1824: ; preds = %for.end1469 + br label %while.body +} diff --git a/llvm/test/Transforms/LoopStrengthReduce/funclet.ll b/llvm/test/Transforms/LoopStrengthReduce/funclet.ll index 1bee3706cafab..0f725a13b2078 100644 --- a/llvm/test/Transforms/LoopStrengthReduce/funclet.ll +++ b/llvm/test/Transforms/LoopStrengthReduce/funclet.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -loop-reduce -S | FileCheck %s target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" @@ -10,13 +11,42 @@ declare void @external(i32*) declare void @reserve() define void @f() personality i32 (...)* @_except_handler3 { +; CHECK-LABEL: @f( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[THROW:%.*]] +; CHECK: throw: +; CHECK-NEXT: [[TMP96:%.*]] = getelementptr inbounds i8, i8* undef, i32 1 +; CHECK-NEXT: invoke void @reserve() +; CHECK-NEXT: to label [[THROW]] unwind label [[PAD:%.*]] +; CHECK: pad: +; CHECK-NEXT: [[PHI2:%.*]] = phi i8* [ [[TMP96]], [[THROW]] ] +; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %unreachable] unwind label [[BLAH2:%.*]] +; CHECK: unreachable: +; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] [] +; CHECK-NEXT: unreachable +; CHECK: blah2: +; CHECK-NEXT: [[CLEANUPPADI4_I_I_I:%.*]] = cleanuppad within none [] +; CHECK-NEXT: [[PHI21:%.*]] = ptrtoint i8* [[PHI2]] to i32 +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 1, [[PHI21]] +; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* undef, i32 [[TMP1]] +; CHECK-NEXT: br label [[LOOP_BODY:%.*]] +; CHECK: loop_body: +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i8* [ [[SCEVGEP2:%.*]], [[ITER:%.*]] ], [ [[SCEVGEP]], [[BLAH2]] ] +; CHECK-NEXT: [[SCEVGEP2]] = getelementptr i8, i8* [[LSR_IV]], i32 -1 +; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[SCEVGEP2]], null +; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]] +; CHECK: iter: +; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]] +; CHECK: unwind_out: +; CHECK-NEXT: cleanupret from [[CLEANUPPADI4_I_I_I]] unwind to caller +; entry: br label %throw throw: ; preds = %throw, %entry %tmp96 = getelementptr inbounds i8, i8* undef, i32 1 invoke void @reserve() - to label %throw unwind label %pad + to label %throw unwind label %pad pad: ; preds = %throw %phi2 = phi i8* [ %tmp96, %throw ] @@ -43,18 +73,45 @@ unwind_out: ; preds = %iter, %loop_body cleanupret from %cleanuppadi4.i.i.i unwind to caller } -; CHECK-LABEL: define void @f( -; CHECK: cleanuppad within none [] -; CHECK-NEXT: ptrtoint i8* %phi2 to i32 - define void @g() personality i32 (...)* @_except_handler3 { +; CHECK-LABEL: @g( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[THROW:%.*]] +; CHECK: throw: +; CHECK-NEXT: [[TMP96:%.*]] = getelementptr inbounds i8, i8* undef, i32 1 +; CHECK-NEXT: invoke void @reserve() +; CHECK-NEXT: to label [[THROW]] unwind label [[PAD:%.*]] +; CHECK: pad: +; CHECK-NEXT: [[PHI2:%.*]] = phi i8* [ [[TMP96]], [[THROW]] ] +; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label [[UNREACHABLE:%.*]], label %blah] unwind to caller +; CHECK: unreachable: +; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] [] +; CHECK-NEXT: unreachable +; CHECK: blah: +; CHECK-NEXT: [[CATCHPAD:%.*]] = catchpad within [[CS]] [] +; CHECK-NEXT: [[PHI21:%.*]] = ptrtoint i8* [[PHI2]] to i32 +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 1, [[PHI21]] +; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* undef, i32 [[TMP1]] +; CHECK-NEXT: br label [[LOOP_BODY:%.*]] +; CHECK: unwind_out: +; CHECK-NEXT: catchret from [[CATCHPAD]] to label [[LEAVE:%.*]] +; CHECK: leave: +; CHECK-NEXT: ret void +; CHECK: loop_body: +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i8* [ [[SCEVGEP2:%.*]], [[ITER:%.*]] ], [ [[SCEVGEP]], [[BLAH:%.*]] ] +; CHECK-NEXT: [[SCEVGEP2]] = getelementptr i8, i8* [[LSR_IV]], i32 -1 +; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[SCEVGEP2]], null +; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]] +; CHECK: iter: +; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]] +; entry: br label %throw throw: ; preds = %throw, %entry %tmp96 = getelementptr inbounds i8, i8* undef, i32 1 invoke void @reserve() - to label %throw unwind label %pad + to label %throw unwind label %pad pad: %phi2 = phi i8* [ %tmp96, %throw ] @@ -84,20 +141,45 @@ iter: ; preds = %loop_body br i1 undef, label %unwind_out, label %loop_body } -; CHECK-LABEL: define void @g( -; CHECK: blah: -; CHECK-NEXT: catchpad within %cs [] -; CHECK-NEXT: ptrtoint i8* %phi2 to i32 - - define void @h() personality i32 (...)* @_except_handler3 { +; CHECK-LABEL: @h( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[THROW:%.*]] +; CHECK: throw: +; CHECK-NEXT: [[TMP96:%.*]] = getelementptr inbounds i8, i8* undef, i32 1 +; CHECK-NEXT: invoke void @reserve() +; CHECK-NEXT: to label [[THROW]] unwind label [[PAD:%.*]] +; CHECK: pad: +; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label [[UNREACHABLE:%.*]], label %blug] unwind to caller +; CHECK: unreachable: +; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] [] +; CHECK-NEXT: unreachable +; CHECK: blug: +; CHECK-NEXT: [[PHI2:%.*]] = phi i8* [ [[TMP96]], [[PAD]] ] +; CHECK-NEXT: [[CATCHPAD:%.*]] = catchpad within [[CS]] [] +; CHECK-NEXT: [[PHI21:%.*]] = ptrtoint i8* [[PHI2]] to i32 +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 1, [[PHI21]] +; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* undef, i32 [[TMP1]] +; CHECK-NEXT: br label [[LOOP_BODY:%.*]] +; CHECK: unwind_out: +; CHECK-NEXT: catchret from [[CATCHPAD]] to label [[LEAVE:%.*]] +; CHECK: leave: +; CHECK-NEXT: ret void +; CHECK: loop_body: +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i8* [ [[SCEVGEP2:%.*]], [[ITER:%.*]] ], [ [[SCEVGEP]], [[BLUG:%.*]] ] +; CHECK-NEXT: [[SCEVGEP2]] = getelementptr i8, i8* [[LSR_IV]], i32 -1 +; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[SCEVGEP2]], null +; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]] +; CHECK: iter: +; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]] +; entry: br label %throw throw: ; preds = %throw, %entry %tmp96 = getelementptr inbounds i8, i8* undef, i32 1 invoke void @reserve() - to label %throw unwind label %pad + to label %throw unwind label %pad pad: %cs = catchswitch within none [label %unreachable, label %blug] unwind to caller @@ -127,19 +209,45 @@ iter: ; preds = %loop_body br i1 undef, label %unwind_out, label %loop_body } -; CHECK-LABEL: define void @h( -; CHECK: blug: -; CHECK: catchpad within %cs [] -; CHECK-NEXT: ptrtoint i8* %phi2 to i32 - define void @i() personality i32 (...)* @_except_handler3 { +; CHECK-LABEL: @i( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[THROW:%.*]] +; CHECK: throw: +; CHECK-NEXT: [[TMP96:%.*]] = getelementptr inbounds i8, i8* undef, i32 1 +; CHECK-NEXT: invoke void @reserve() +; CHECK-NEXT: to label [[THROW]] unwind label [[CATCHPAD:%.*]] +; CHECK: catchpad: +; CHECK-NEXT: [[PHI2:%.*]] = phi i8* [ [[TMP96]], [[THROW]] ] +; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %cp_body] unwind label [[CLEANUPPAD:%.*]] +; CHECK: cp_body: +; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] [] +; CHECK-NEXT: br label [[LOOP_HEAD:%.*]] +; CHECK: cleanuppad: +; CHECK-NEXT: [[TMP1:%.*]] = cleanuppad within none [] +; CHECK-NEXT: br label [[LOOP_HEAD]] +; CHECK: loop_head: +; CHECK-NEXT: [[PHI21:%.*]] = ptrtoint i8* [[PHI2]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = sub i32 1, [[PHI21]] +; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* undef, i32 [[TMP2]] +; CHECK-NEXT: br label [[LOOP_BODY:%.*]] +; CHECK: loop_body: +; CHECK-NEXT: [[LSR_IV:%.*]] = phi i8* [ [[SCEVGEP2:%.*]], [[ITER:%.*]] ], [ [[SCEVGEP]], [[LOOP_HEAD]] ] +; CHECK-NEXT: [[SCEVGEP2]] = getelementptr i8, i8* [[LSR_IV]], i32 -1 +; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[SCEVGEP2]], null +; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]] +; CHECK: iter: +; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]] +; CHECK: unwind_out: +; CHECK-NEXT: unreachable +; entry: br label %throw throw: ; preds = %throw, %entry %tmp96 = getelementptr inbounds i8, i8* undef, i32 1 invoke void @reserve() - to label %throw unwind label %catchpad + to label %throw unwind label %catchpad catchpad: ; preds = %throw %phi2 = phi i8* [ %tmp96, %throw ] @@ -169,17 +277,41 @@ unwind_out: ; preds = %iter, %loop_body unreachable } -; CHECK-LABEL: define void @i( -; CHECK: ptrtoint i8* %phi2 to i32 - define void @test1(i32* %b, i32* %c) personality i32 (...)* @__CxxFrameHandler3 { +; CHECK-LABEL: @test1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[D_0:%.*]] = phi i32* [ [[B:%.*]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR:%.*]], [[FOR_INC:%.*]] ] +; CHECK-NEXT: invoke void @external(i32* [[D_0]]) +; CHECK-NEXT: to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]] +; CHECK: for.inc: +; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i32, i32* [[D_0]], i32 1 +; CHECK-NEXT: br label [[FOR_COND]] +; CHECK: catch.dispatch: +; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %catch] unwind label [[CATCH_DISPATCH_2:%.*]] +; CHECK: catch: +; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] [i8* null, i32 64, i8* null] +; CHECK-NEXT: catchret from [[TMP0]] to label [[TRY_CONT:%.*]] +; CHECK: try.cont: +; CHECK-NEXT: invoke void @external(i32* [[C:%.*]]) +; CHECK-NEXT: to label [[TRY_CONT_7:%.*]] unwind label [[CATCH_DISPATCH_2]] +; CHECK: catch.dispatch.2: +; CHECK-NEXT: [[E_0:%.*]] = phi i32* [ [[C]], [[TRY_CONT]] ], [ [[B]], [[CATCH_DISPATCH]] ] +; CHECK-NEXT: [[CS2:%.*]] = catchswitch within none [label %catch.4] unwind to caller +; CHECK: catch.4: +; CHECK-NEXT: [[TMP1:%.*]] = catchpad within [[CS2]] [i8* null, i32 64, i8* null] +; CHECK-NEXT: unreachable +; CHECK: try.cont.7: +; CHECK-NEXT: ret void +; entry: br label %for.cond for.cond: ; preds = %for.inc, %entry %d.0 = phi i32* [ %b, %entry ], [ %incdec.ptr, %for.inc ] invoke void @external(i32* %d.0) - to label %for.inc unwind label %catch.dispatch + to label %for.inc unwind label %catch.dispatch for.inc: ; preds = %for.cond %incdec.ptr = getelementptr inbounds i32, i32* %d.0, i32 1 @@ -194,7 +326,7 @@ catch: ; preds = %catch.dispatch try.cont: ; preds = %catch invoke void @external(i32* %c) - to label %try.cont.7 unwind label %catch.dispatch.2 + to label %try.cont.7 unwind label %catch.dispatch.2 catch.dispatch.2: ; preds = %try.cont, %catchendblock %e.0 = phi i32* [ %c, %try.cont ], [ %b, %catch.dispatch ] @@ -208,21 +340,33 @@ try.cont.7: ; preds = %try.cont ret void } -; CHECK-LABEL: define void @test1( -; CHECK: for.cond: -; CHECK: %d.0 = phi i32* [ %b, %entry ], [ %incdec.ptr, %for.inc ] - -; CHECK: catch.dispatch.2: -; CHECK: %e.0 = phi i32* [ %c, %try.cont ], [ %b, %catch.dispatch ] - define i32 @test2() personality i32 (...)* @_except_handler3 { +; CHECK-LABEL: @test2( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: invoke void @reserve() +; CHECK-NEXT: to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]] +; CHECK: catch.dispatch: +; CHECK-NEXT: [[TMP18:%.*]] = catchswitch within none [label %catch.handler] unwind to caller +; CHECK: catch.handler: +; CHECK-NEXT: [[PHI_LCSSA:%.*]] = phi i32 [ [[PHI]], [[CATCH_DISPATCH]] ] +; CHECK-NEXT: [[TMP19:%.*]] = catchpad within [[TMP18]] [i8* null] +; CHECK-NEXT: catchret from [[TMP19]] to label [[DONE:%.*]] +; CHECK: done: +; CHECK-NEXT: ret i32 [[PHI_LCSSA]] +; CHECK: for.inc: +; CHECK-NEXT: [[INC]] = add i32 [[PHI]], 1 +; CHECK-NEXT: br label [[FOR_BODY]] +; entry: br label %for.body for.body: ; preds = %for.inc, %entry %phi = phi i32 [ %inc, %for.inc ], [ 0, %entry ] invoke void @reserve() - to label %for.inc unwind label %catch.dispatch + to label %for.inc unwind label %catch.dispatch catch.dispatch: ; preds = %for.body %tmp18 = catchswitch within none [label %catch.handler] unwind to caller @@ -239,7 +383,3 @@ for.inc: ; preds = %for.body %inc = add i32 %phi, 1 br label %for.body } - -; CHECK-LABEL: define i32 @test2( -; CHECK: %phi.lcssa = phi i32 [ %phi, %catch.dispatch ] -; CHECK-NEXT: catchpad within diff --git a/llvm/test/Transforms/LoopStrengthReduce/scev-expander-lcssa.ll b/llvm/test/Transforms/LoopStrengthReduce/scev-expander-lcssa.ll new file mode 100644 index 0000000000000..e05dcda85138a --- /dev/null +++ b/llvm/test/Transforms/LoopStrengthReduce/scev-expander-lcssa.ll @@ -0,0 +1,144 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -loop-reduce -S %s | FileCheck %s + +; Make sure SCEVExpander does not crash and introduce unnecessary LCSSA PHI nodes. + +define void @schedule_block() { +; CHECK-LABEL: @schedule_block( +; CHECK-NEXT: entry: +; CHECK-NEXT: switch i16 undef, label [[IF_END156_I:%.*]] [ +; CHECK-NEXT: i16 27, label [[IF_THEN_I:%.*]] +; CHECK-NEXT: i16 28, label [[IF_THEN_I]] +; CHECK-NEXT: i16 29, label [[IF_THEN13_I:%.*]] +; CHECK-NEXT: i16 32, label [[LAND_LHS_TRUE136_I:%.*]] +; CHECK-NEXT: ] +; CHECK: if.then.i: +; CHECK-NEXT: unreachable +; CHECK: if.then13.i: +; CHECK-NEXT: unreachable +; CHECK: land.lhs.true136.i: +; CHECK-NEXT: unreachable +; CHECK: if.end156.i: +; CHECK-NEXT: switch i16 undef, label [[WHILE_END256:%.*]] [ +; CHECK-NEXT: i16 29, label [[IF_THEN210:%.*]] +; CHECK-NEXT: i16 28, label [[IF_THEN210]] +; CHECK-NEXT: i16 27, label [[LAND_LHS_TRUE191:%.*]] +; CHECK-NEXT: i16 32, label [[IF_END248:%.*]] +; CHECK-NEXT: ] +; CHECK: land.lhs.true191: +; CHECK-NEXT: unreachable +; CHECK: if.then210: +; CHECK-NEXT: unreachable +; CHECK: if.end248: +; CHECK-NEXT: br label [[FOR_END:%.*]] +; CHECK: while.end256: +; CHECK-NEXT: unreachable +; CHECK: for.end: +; CHECK-NEXT: br label [[WHILE_BODY1013:%.*]] +; CHECK: while.body1013: +; CHECK-NEXT: br label [[FOR_COND_I2472:%.*]] +; CHECK: for.cond.i2472: +; CHECK-NEXT: [[I_0_I:%.*]] = phi i32 [ 0, [[WHILE_BODY1013]] ], [ [[TMP2:%.*]], [[FOR_END34_I:%.*]] ] +; CHECK-NEXT: br i1 false, label [[FOR_COND3_PREHEADER_I:%.*]], label [[IF_END107_I_LOOPEXIT:%.*]] +; CHECK: for.cond3.preheader.i: +; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[I_0_I]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[TMP0]], 1 +; CHECK-NEXT: br label [[FOR_COND3_I:%.*]] +; CHECK: for.cond3.i: +; CHECK-NEXT: [[INDVARS_IV301_I2691:%.*]] = phi i64 [ [[INDVARS_IV_NEXT302_I:%.*]], [[FOR_BODY5_I:%.*]] ], [ [[TMP1]], [[FOR_COND3_PREHEADER_I]] ] +; CHECK-NEXT: [[INDVARS_IV_NEXT302_I]] = add nsw i64 [[INDVARS_IV301_I2691]], 1 +; CHECK-NEXT: br label [[FOR_BODY5_I]] +; CHECK: for.body5.i: +; CHECK-NEXT: br i1 false, label [[FOR_COND3_I]], label [[FOR_BODY5_I_FOR_END_I2475_LOOPEXIT_CRIT_EDGE:%.*]] +; CHECK: for.body5.i.for.end.i2475.loopexit_crit_edge: +; CHECK-NEXT: [[TMP2]] = trunc i64 [[INDVARS_IV_NEXT302_I]] to i32 +; CHECK-NEXT: br label [[FOR_END34_I]] +; CHECK: for.end34.i: +; CHECK-NEXT: br i1 false, label [[FOR_COND_I2472]], label [[IF_ELSE_I2488:%.*]] +; CHECK: if.else.i2488: +; CHECK-NEXT: br i1 undef, label [[IF_END107_I:%.*]], label [[FOR_BODY45_PREHEADER_I:%.*]] +; CHECK: for.body45.preheader.i: +; CHECK-NEXT: [[TMP3:%.*]] = sext i32 [[I_0_I]] to i64 +; CHECK-NEXT: unreachable +; CHECK: if.end107.i.loopexit: +; CHECK-NEXT: br label [[IF_END107_I]] +; CHECK: if.end107.i: +; CHECK-NEXT: unreachable +; +entry: + switch i16 undef, label %if.end156.i [ + i16 27, label %if.then.i + i16 28, label %if.then.i + i16 29, label %if.then13.i + i16 32, label %land.lhs.true136.i + ] + +if.then.i: ; preds = %entry, %entry + unreachable + +if.then13.i: ; preds = %entry + unreachable + +land.lhs.true136.i: ; preds = %entry + unreachable + +if.end156.i: ; preds = %entry + switch i16 undef, label %while.end256 [ + i16 29, label %if.then210 + i16 28, label %if.then210 + i16 27, label %land.lhs.true191 + i16 32, label %if.end248 + ] + +land.lhs.true191: ; preds = %if.end156.i + unreachable + +if.then210: ; preds = %if.end156.i, %if.end156.i + unreachable + +if.end248: ; preds = %if.end156.i + br label %for.end + +while.end256: ; preds = %if.end156.i + unreachable + +for.end: ; preds = %if.end248 + br label %while.body1013 + +while.body1013: ; preds = %for.end + br label %for.cond.i2472 + +for.cond.i2472: ; preds = %for.end34.i, %while.body1013 + %i.0.i = phi i32 [ 0, %while.body1013 ], [ %2, %for.end34.i ] + br i1 undef, label %for.cond3.preheader.i, label %if.end107.i + +for.cond3.preheader.i: ; preds = %for.cond.i2472 + %0 = sext i32 %i.0.i to i64 + %1 = add nsw i64 %0, 1 + br label %for.cond3.i + +for.cond3.i: ; preds = %for.body5.i, %for.cond3.preheader.i + %indvars.iv301.i2691 = phi i64 [ %indvars.iv.next302.i, %for.body5.i ], [ %1, %for.cond3.preheader.i ] + %indvars.iv.next302.i = add nsw i64 %indvars.iv301.i2691, 1 + br label %for.body5.i + +for.body5.i: ; preds = %for.cond3.i + br i1 undef, label %for.cond3.i, label %for.body5.i.for.end.i2475.loopexit_crit_edge + +for.body5.i.for.end.i2475.loopexit_crit_edge: ; preds = %for.body5.i + %2 = trunc i64 %indvars.iv.next302.i to i32 + br label %for.end34.i + +for.end34.i: ; preds = %for.body5.i.for.end.i2475.loopexit_crit_edge + br i1 undef, label %for.cond.i2472, label %if.else.i2488 + +if.else.i2488: ; preds = %for.end34.i + br i1 undef, label %if.end107.i, label %for.body45.preheader.i + +for.body45.preheader.i: ; preds = %if.else.i2488 + %3 = sext i32 %i.0.i to i64 + unreachable + +if.end107.i: ; preds = %if.else.i2488, %for.cond.i2472 + unreachable +}