--- /dev/null
+; 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: <<Unknown>> 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}<nuw><nsw><%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}<nuw><nsw><%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
+}
--- /dev/null
+; 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
+}
+; 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"
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 ]
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 ]
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
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 ]
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
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 ]
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
%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
--- /dev/null
+; 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
+}