[LSR] Preserve LCSSA when rewriting instruction with PHI user
authorDmitry Makogon <d.makogon@g.nsu.ru>
Fri, 24 Mar 2023 13:42:30 +0000 (20:42 +0700)
committerDmitry Makogon <d.makogon@g.nsu.ru>
Thu, 30 Mar 2023 07:46:28 +0000 (14:46 +0700)
Fixes https://github.com/llvm/llvm-project/issues/61182.

LoopStrengthReduce may sometimes break LCSSA form when applying a rewrite
for an instruction used in a PHI.
It happens if:
 - The PHI is in a loop exit block,
 - The edge from the corresponding exiting block to that exit is critical,
 - The PHI has at least two inputs coming from loop blocks,
 - and the rewritten instruction is inserted in the loop.

In such case we split the critical edge and then replace PHI inputs
with the rewritten instruction. However ExitBlock is no longer
a loop exit, so LCSSA form is broken.

This patch fixes it by collecting all inserted instructions for PHIs
whose parent block is not a loop exit and then forming LCSSA for them.

Differential Revision: https://reviews.llvm.org/D146811

12 files changed:
llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
llvm/test/Transforms/LoopStrengthReduce/2011-10-03-CritEdgeMerge.ll
llvm/test/Transforms/LoopStrengthReduce/AMDGPU/lsr-invalid-ptr-extend.ll
llvm/test/Transforms/LoopStrengthReduce/X86/2011-11-29-postincphi.ll
llvm/test/Transforms/LoopStrengthReduce/X86/expander-crashes.ll
llvm/test/Transforms/LoopStrengthReduce/X86/expander-reused-value-insert-point.ll
llvm/test/Transforms/LoopStrengthReduce/X86/sibling-loops.ll
llvm/test/Transforms/LoopStrengthReduce/callbr-critical-edge-splitting.ll
llvm/test/Transforms/LoopStrengthReduce/depth-limit-overrun.ll
llvm/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
llvm/test/Transforms/LoopStrengthReduce/preserve-lcssa.ll
llvm/test/Transforms/LoopStrengthReduce/uglygep.ll

index fbdc436..1900f98 100644 (file)
@@ -5538,6 +5538,13 @@ void LSRInstance::RewriteForPHI(
     PHINode *PN, const LSRUse &LU, const LSRFixup &LF, const Formula &F,
     SmallVectorImpl<WeakTrackingVH> &DeadInsts) const {
   DenseMap<BasicBlock *, Value *> Inserted;
+
+  // Inserting instructions in the loop and using them as PHI's input could
+  // break LCSSA in case if PHI's parent block is not a loop exit (i.e. the
+  // corresponding incoming block is not loop exiting). So collect all such
+  // instructions to form LCSSA for them later.
+  SmallVector<Instruction *, 4> InsertedNonLCSSAInsts;
+
   for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
     if (PN->getIncomingValue(i) == LF.OperandValToReplace) {
       bool needUpdateFixups = false;
@@ -5603,6 +5610,13 @@ void LSRInstance::RewriteForPHI(
                              FullV, LF.OperandValToReplace->getType(),
                              "tmp", BB->getTerminator());
 
+        // If the incoming block for this value is not in the loop, it means the
+        // current PHI is not in a loop exit, so we must create a LCSSA PHI for
+        // the inserted value.
+        if (auto *I = dyn_cast<Instruction>(FullV))
+          if (L->contains(I) && !L->contains(BB))
+            InsertedNonLCSSAInsts.push_back(I);
+
         PN->setIncomingValue(i, FullV);
         Pair.first->second = FullV;
       }
@@ -5645,6 +5659,9 @@ void LSRInstance::RewriteForPHI(
             }
       }
     }
+
+  IRBuilder<> Builder(L->getHeader()->getContext());
+  formLCSSAForInstructions(InsertedNonLCSSAInsts, DT, LI, &SE, Builder);
 }
 
 /// Emit instructions for the leading candidate expression for this LSRUse (this
index ba4b1b7..bf52c96 100644 (file)
@@ -20,6 +20,7 @@ define ptr @test1() {
 ; CHECK-NEXT:    [[SCEVGEP]] = getelementptr i8, ptr [[LSR_IV]], i64 1
 ; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[LOOPEXIT:%.*]]
 ; CHECK:       loopexit:
+; CHECK-NEXT:    [[SCEVGEP_LCSSA:%.*]] = phi ptr [ [[SCEVGEP]], [[LOOP]] ]
 ; CHECK-NEXT:    br i1 false, label [[BBA:%.*]], label [[BBB:%.*]]
 ; CHECK:       bbA:
 ; CHECK-NEXT:    switch i32 0, label [[BBA_BB89_CRIT_EDGE:%.*]] [
@@ -36,7 +37,7 @@ define ptr @test1() {
 ; CHECK:       bbB.bb89_crit_edge:
 ; CHECK-NEXT:    br label [[BB89]]
 ; CHECK:       bb89:
-; CHECK-NEXT:    [[TMP75PHI:%.*]] = phi ptr [ [[SCEVGEP]], [[BBA_BB89_CRIT_EDGE]] ], [ [[SCEVGEP]], [[BBB_BB89_CRIT_EDGE]] ]
+; CHECK-NEXT:    [[TMP75PHI:%.*]] = phi ptr [ [[SCEVGEP_LCSSA]], [[BBA_BB89_CRIT_EDGE]] ], [ [[SCEVGEP_LCSSA]], [[BBB_BB89_CRIT_EDGE]] ]
 ; CHECK-NEXT:    br label [[EXIT:%.*]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret ptr [[TMP75PHI]]
@@ -84,6 +85,8 @@ define ptr @test2() {
 ; CHECK-NEXT:    [[SCEVGEP]] = getelementptr i8, ptr [[LSR_IV]], i64 1
 ; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[LOOPEXIT:%.*]]
 ; CHECK:       loopexit:
+; CHECK-NEXT:    [[SCEVGEP_LCSSA1:%.*]] = phi ptr [ [[SCEVGEP]], [[LOOP]] ]
+; CHECK-NEXT:    [[SCEVGEP_LCSSA:%.*]] = phi ptr [ [[SCEVGEP]], [[LOOP]] ]
 ; CHECK-NEXT:    br i1 false, label [[BBA:%.*]], label [[BBB:%.*]]
 ; CHECK:       bbA:
 ; CHECK-NEXT:    switch i32 0, label [[BB89:%.*]] [
@@ -98,10 +101,10 @@ define ptr @test2() {
 ; CHECK:       bbB.exit_crit_edge:
 ; CHECK-NEXT:    br label [[EXIT:%.*]]
 ; CHECK:       bb89:
-; CHECK-NEXT:    [[TMP75PHI:%.*]] = phi ptr [ [[SCEVGEP]], [[BBA]] ], [ [[SCEVGEP]], [[BBA]] ], [ [[SCEVGEP]], [[BBA]] ]
+; CHECK-NEXT:    [[TMP75PHI:%.*]] = phi ptr [ [[SCEVGEP_LCSSA1]], [[BBA]] ], [ [[SCEVGEP_LCSSA1]], [[BBA]] ], [ [[SCEVGEP_LCSSA1]], [[BBA]] ]
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
-; CHECK-NEXT:    [[RESULT:%.*]] = phi ptr [ [[TMP75PHI]], [[BB89]] ], [ [[SCEVGEP]], [[BBB_EXIT_CRIT_EDGE]] ]
+; CHECK-NEXT:    [[RESULT:%.*]] = phi ptr [ [[TMP75PHI]], [[BB89]] ], [ [[SCEVGEP_LCSSA]], [[BBB_EXIT_CRIT_EDGE]] ]
 ; CHECK-NEXT:    ret ptr [[RESULT]]
 ;
 entry:
index 334a0d0..5e596f0 100644 (file)
@@ -16,10 +16,12 @@ define amdgpu_kernel void @scaledregtest() local_unnamed_addr {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 ; CHECK:       loopexit:
+; CHECK-NEXT:    [[SCEVGEP13_LCSSA:%.*]] = phi ptr [ [[SCEVGEP13:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT:    [[SCEVGEP11_LCSSA:%.*]] = phi ptr addrspace(5) [ [[SCEVGEP11:%.*]], [[FOR_BODY]] ]
 ; CHECK-NEXT:    br label [[FOR_BODY_1:%.*]]
 ; CHECK:       for.body.1:
-; CHECK-NEXT:    [[LSR_IV5:%.*]] = phi ptr addrspace(5) [ [[SCEVGEP6:%.*]], [[FOR_BODY_1]] ], [ [[SCEVGEP11:%.*]], [[LOOPEXIT:%.*]] ]
-; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[SCEVGEP2:%.*]], [[FOR_BODY_1]] ], [ [[SCEVGEP13:%.*]], [[LOOPEXIT]] ]
+; CHECK-NEXT:    [[LSR_IV5:%.*]] = phi ptr addrspace(5) [ [[SCEVGEP6:%.*]], [[FOR_BODY_1]] ], [ [[SCEVGEP11_LCSSA]], [[LOOPEXIT:%.*]] ]
+; CHECK-NEXT:    [[LSR_IV1:%.*]] = phi ptr [ [[SCEVGEP2:%.*]], [[FOR_BODY_1]] ], [ [[SCEVGEP13_LCSSA]], [[LOOPEXIT]] ]
 ; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr addrspace(5) [[LSR_IV5]], align 8
 ; CHECK-NEXT:    store ptr [[TMP0]], ptr [[LSR_IV1]], align 8
 ; CHECK-NEXT:    [[SCEVGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 8
index 841836c..fbb9e2a 100644 (file)
@@ -20,17 +20,16 @@ define i64 @sqlite3DropTriggerPtr() nounwind {
 ; CHECK-NEXT:    .p2align 4, 0x90
 ; CHECK-NEXT:  .LBB0_1: # %bb1
 ; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:    movq %rbx, %rcx
 ; CHECK-NEXT:    testb %al, %al
-; CHECK-NEXT:    je .LBB0_4
+; CHECK-NEXT:    je .LBB0_3
 ; CHECK-NEXT:  # %bb.2: # %bb4
 ; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    incq %rbx
+; CHECK-NEXT:    leaq 1(%rcx), %rbx
 ; CHECK-NEXT:    testb %al, %al
 ; CHECK-NEXT:    jne .LBB0_1
-; CHECK-NEXT:  # %bb.3: # %bb8split
-; CHECK-NEXT:    decq %rbx
-; CHECK-NEXT:  .LBB0_4: # %bb8
-; CHECK-NEXT:    movq %rbx, %rax
+; CHECK-NEXT:  .LBB0_3: # %bb8
+; CHECK-NEXT:    movq %rcx, %rax
 ; CHECK-NEXT:    popq %rbx
 ; CHECK-NEXT:    retq
 bb:
index b6d0fd5..e857c7f 100644 (file)
@@ -21,10 +21,12 @@ define i64 @blam(%struct.hoge* %start, %struct.hoge* %end, %struct.hoge* %ptr.2)
 ; CHECK-NEXT:    [[EC:%.*]] = icmp eq %struct.hoge* [[IV_NEXT]], [[END:%.*]]
 ; CHECK-NEXT:    br i1 [[EC]], label [[LOOP_2_PH:%.*]], label [[LOOP_1_HEADER]]
 ; CHECK:       loop.2.ph:
+; CHECK-NEXT:    [[IV_NEXT_LCSSA:%.*]] = phi %struct.hoge* [ [[IV_NEXT]], [[LOOP_1_HEADER]] ]
+; CHECK-NEXT:    [[LSR_IV_NEXT6_LCSSA:%.*]] = phi i64 [ [[LSR_IV_NEXT6]], [[LOOP_1_HEADER]] ]
 ; CHECK-NEXT:    br label [[LOOP_2_HEADER:%.*]]
 ; CHECK:       loop.2.header:
-; CHECK-NEXT:    [[LSR_IV2:%.*]] = phi i64 [ [[LSR_IV_NEXT3:%.*]], [[LOOP_2_LATCH:%.*]] ], [ [[LSR_IV_NEXT6]], [[LOOP_2_PH]] ]
-; CHECK-NEXT:    [[IV2:%.*]] = phi %struct.hoge* [ [[IV2_NEXT:%.*]], [[LOOP_2_LATCH]] ], [ [[IV_NEXT]], [[LOOP_2_PH]] ]
+; CHECK-NEXT:    [[LSR_IV2:%.*]] = phi i64 [ [[LSR_IV_NEXT3:%.*]], [[LOOP_2_LATCH:%.*]] ], [ [[LSR_IV_NEXT6_LCSSA]], [[LOOP_2_PH]] ]
+; CHECK-NEXT:    [[IV2:%.*]] = phi %struct.hoge* [ [[IV2_NEXT:%.*]], [[LOOP_2_LATCH]] ], [ [[IV_NEXT_LCSSA]], [[LOOP_2_PH]] ]
 ; CHECK-NEXT:    [[IV24:%.*]] = bitcast %struct.hoge* [[IV2]] to i32*
 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[LSR_IV2]], 12
 ; CHECK-NEXT:    call void @use.i64(i64 [[TMP0]])
index f220103..dc5938f 100644 (file)
@@ -26,9 +26,10 @@ define void @test(ptr %ioptr, i32 %X, ptr %start, ptr %end) {
 ; CHECK-NEXT:    [[EC0:%.*]] = icmp eq ptr [[ADD_PTR94]], [[END:%.*]]
 ; CHECK-NEXT:    br i1 [[EC0]], label [[FOR_BODY37]], label [[FOR_END_LOOPEXIT:%.*]]
 ; CHECK:       for.end.loopexit:
+; CHECK-NEXT:    [[ADD_PTR94_LCSSA:%.*]] = phi ptr [ [[ADD_PTR94]], [[FOR_BODY37]] ]
 ; CHECK-NEXT:    br label [[FOR_END:%.*]]
 ; CHECK:       for.end:
-; CHECK-NEXT:    [[P0R_0_LCSSA:%.*]] = phi ptr [ [[ADD_PTR94]], [[FOR_END_LOOPEXIT]] ]
+; CHECK-NEXT:    [[P0R_0_LCSSA:%.*]] = phi ptr [ [[ADD_PTR94_LCSSA]], [[FOR_END_LOOPEXIT]] ]
 ; CHECK-NEXT:    [[EC1:%.*]] = icmp eq ptr [[P0R_0_LCSSA]], [[END]]
 ; CHECK-NEXT:    br i1 [[EC1]], label [[FOR_BODY15]], label [[FOR_INC133:%.*]]
 ; CHECK:       for.inc133:
index 3c0b904..11c8ae6 100644 (file)
@@ -44,10 +44,11 @@ define void @foo(i64 %N) local_unnamed_addr {
 ; CHECK-NEXT:    [[TOBOOL12:%.*]] = icmp eq i64 [[T2]], 0
 ; CHECK-NEXT:    br i1 [[TOBOOL12]], label [[DO_BODY14_PREHEADER:%.*]], label [[DO_BODY8]]
 ; CHECK:       do.body14.preheader:
+; CHECK-NEXT:    [[INC10_LCSSA:%.*]] = phi i64 [ [[INC10]], [[DO_BODY8]] ]
 ; CHECK-NEXT:    br label [[DO_BODY14:%.*]]
 ; CHECK:       do.body14:
 ; CHECK-NEXT:    [[I_3:%.*]] = phi i64 [ [[INC15:%.*]], [[DO_BODY14]] ], [ 0, [[DO_BODY14_PREHEADER]] ]
-; CHECK-NEXT:    [[J_3:%.*]] = phi i64 [ [[INC16:%.*]], [[DO_BODY14]] ], [ [[INC10]], [[DO_BODY14_PREHEADER]] ]
+; CHECK-NEXT:    [[J_3:%.*]] = phi i64 [ [[INC16:%.*]], [[DO_BODY14]] ], [ [[INC10_LCSSA]], [[DO_BODY14_PREHEADER]] ]
 ; CHECK-NEXT:    tail call void @goo(i64 [[I_3]], i64 [[J_3]])
 ; CHECK-NEXT:    [[INC15]] = add nuw nsw i64 [[I_3]], 1
 ; CHECK-NEXT:    [[INC16]] = add i64 [[J_3]], 1
@@ -55,10 +56,11 @@ define void @foo(i64 %N) local_unnamed_addr {
 ; CHECK-NEXT:    [[TOBOOL18:%.*]] = icmp eq i64 [[T3]], 0
 ; CHECK-NEXT:    br i1 [[TOBOOL18]], label [[DO_BODY20_PREHEADER:%.*]], label [[DO_BODY14]]
 ; CHECK:       do.body20.preheader:
+; CHECK-NEXT:    [[INC16_LCSSA:%.*]] = phi i64 [ [[INC16]], [[DO_BODY14]] ]
 ; CHECK-NEXT:    br label [[DO_BODY20:%.*]]
 ; CHECK:       do.body20:
 ; CHECK-NEXT:    [[I_4:%.*]] = phi i64 [ [[INC21:%.*]], [[DO_BODY20]] ], [ 0, [[DO_BODY20_PREHEADER]] ]
-; CHECK-NEXT:    [[J_4:%.*]] = phi i64 [ [[INC22:%.*]], [[DO_BODY20]] ], [ [[INC16]], [[DO_BODY20_PREHEADER]] ]
+; CHECK-NEXT:    [[J_4:%.*]] = phi i64 [ [[INC22:%.*]], [[DO_BODY20]] ], [ [[INC16_LCSSA]], [[DO_BODY20_PREHEADER]] ]
 ; CHECK-NEXT:    tail call void @goo(i64 [[I_4]], i64 [[J_4]])
 ; CHECK-NEXT:    [[INC21]] = add nuw nsw i64 [[I_4]], 1
 ; CHECK-NEXT:    [[INC22]] = add i64 [[J_4]], 1
@@ -66,10 +68,11 @@ define void @foo(i64 %N) local_unnamed_addr {
 ; CHECK-NEXT:    [[TOBOOL24:%.*]] = icmp eq i64 [[T4]], 0
 ; CHECK-NEXT:    br i1 [[TOBOOL24]], label [[DO_BODY26_PREHEADER:%.*]], label [[DO_BODY20]]
 ; CHECK:       do.body26.preheader:
+; CHECK-NEXT:    [[INC22_LCSSA:%.*]] = phi i64 [ [[INC22]], [[DO_BODY20]] ]
 ; CHECK-NEXT:    br label [[DO_BODY26:%.*]]
 ; CHECK:       do.body26:
 ; CHECK-NEXT:    [[I_5:%.*]] = phi i64 [ [[INC27:%.*]], [[DO_BODY26]] ], [ 0, [[DO_BODY26_PREHEADER]] ]
-; CHECK-NEXT:    [[J_5:%.*]] = phi i64 [ [[INC28:%.*]], [[DO_BODY26]] ], [ [[INC22]], [[DO_BODY26_PREHEADER]] ]
+; CHECK-NEXT:    [[J_5:%.*]] = phi i64 [ [[INC28:%.*]], [[DO_BODY26]] ], [ [[INC22_LCSSA]], [[DO_BODY26_PREHEADER]] ]
 ; CHECK-NEXT:    tail call void @goo(i64 [[I_5]], i64 [[J_5]])
 ; CHECK-NEXT:    [[INC27]] = add nuw nsw i64 [[I_5]], 1
 ; CHECK-NEXT:    [[INC28]] = add nsw i64 [[J_5]], 1
index a7bd527..58f9d7f 100644 (file)
@@ -16,19 +16,18 @@ define dso_local i32 @test1() local_unnamed_addr {
 ; LEGACYPM:       cond.true.i:
 ; LEGACYPM-NEXT:    br label [[DO_BODY_I_I_DO_BODY_I_I_CRIT_EDGE:%.*]]
 ; LEGACYPM:       do.body.i.i.do.body.i.i_crit_edge:
-; LEGACYPM-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[DO_BODY_I_I_DO_BODY_I_I_CRIT_EDGE]] ], [ undef, [[COND_TRUE_I]] ]
-; LEGACYPM-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], 1
 ; LEGACYPM-NEXT:    br i1 true, label [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE:%.*]], label [[DO_BODY_I_I_DO_BODY_I_I_CRIT_EDGE]]
 ; LEGACYPM:       do.body.i.i.rdrand_int.exit.i_crit_edge:
 ; LEGACYPM-NEXT:    br i1 true, label [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE_FOR_END_CRIT_EDGE:%.*]], label [[FOR_INC:%.*]]
 ; LEGACYPM:       do.body.i.i.rdrand_int.exit.i_crit_edge.for.end_crit_edge:
+; LEGACYPM-NEXT:    [[LSR_IV_NEXT_LCSSA_LCSSA:%.*]] = phi i64 [ undef, [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE]] ]
 ; LEGACYPM-NEXT:    br label [[FOR_END:%.*]]
 ; LEGACYPM:       for.inc:
 ; LEGACYPM-NEXT:    br label [[FOR_COND]]
 ; LEGACYPM:       for.endsplit:
 ; LEGACYPM-NEXT:    br label [[FOR_END]]
 ; LEGACYPM:       for.end:
-; LEGACYPM-NEXT:    [[PGOCOUNT_PROMOTED24:%.*]] = phi i64 [ [[LSR_IV_NEXT]], [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE_FOR_END_CRIT_EDGE]] ], [ undef, [[FOR_ENDSPLIT:%.*]] ]
+; LEGACYPM-NEXT:    [[PGOCOUNT_PROMOTED24:%.*]] = phi i64 [ [[LSR_IV_NEXT_LCSSA_LCSSA]], [[DO_BODY_I_I_RDRAND_INT_EXIT_I_CRIT_EDGE_FOR_END_CRIT_EDGE]] ], [ undef, [[FOR_ENDSPLIT:%.*]] ]
 ; LEGACYPM-NEXT:    ret i32 undef
 ;
 ; NEWPM-LABEL: @test1(
index 83def41..9c3698a 100644 (file)
@@ -74,6 +74,7 @@ define void @test(i32 %A, i32 %B, i32 %C) {
 ;
 ; LIMIT-LABEL: @test(
 ; LIMIT-NEXT:  entry:
+; LIMIT-NEXT:    [[TMP0:%.*]] = mul i32 [[C:%.*]], -3
 ; LIMIT-NEXT:    br label [[OUTER_LOOP:%.*]]
 ; LIMIT:       outer_loop:
 ; LIMIT-NEXT:    [[PHI2:%.*]] = phi i32 [ [[A:%.*]], [[ENTRY:%.*]] ], [ 204, [[OUTER_TAIL:%.*]] ]
@@ -81,21 +82,22 @@ define void @test(i32 %A, i32 %B, i32 %C) {
 ; LIMIT-NEXT:    [[PHI4:%.*]] = phi i32 [ [[B:%.*]], [[ENTRY]] ], [ [[I35:%.*]], [[OUTER_TAIL]] ]
 ; LIMIT-NEXT:    br label [[GUARD:%.*]]
 ; LIMIT:       guard:
-; LIMIT-NEXT:    [[LCMP_MOD:%.*]] = icmp eq i32 [[C:%.*]], 0
+; LIMIT-NEXT:    [[LCMP_MOD:%.*]] = icmp eq i32 [[C]], 0
 ; LIMIT-NEXT:    br i1 [[LCMP_MOD]], label [[OUTER_TAIL]], label [[PREHEADER:%.*]]
 ; LIMIT:       preheader:
 ; LIMIT-NEXT:    [[I15:%.*]] = shl i32 [[B]], 1
-; LIMIT-NEXT:    [[TMP0:%.*]] = mul i32 [[PHI2]], -1
-; LIMIT-NEXT:    [[TMP1:%.*]] = mul i32 [[TMP0]], -1
-; LIMIT-NEXT:    [[TMP2:%.*]] = sub i32 [[PHI4]], [[TMP1]]
-; LIMIT-NEXT:    [[TMP3:%.*]] = add i32 [[B]], [[PHI4]]
-; LIMIT-NEXT:    [[TMP4:%.*]] = sub i32 [[TMP3]], [[TMP1]]
-; LIMIT-NEXT:    [[TMP5:%.*]] = sub i32 14, [[TMP4]]
+; LIMIT-NEXT:    [[TMP1:%.*]] = mul i32 [[PHI2]], -1
+; LIMIT-NEXT:    [[TMP2:%.*]] = mul i32 [[TMP1]], -1
+; LIMIT-NEXT:    [[TMP3:%.*]] = sub i32 [[PHI4]], [[TMP2]]
+; LIMIT-NEXT:    [[TMP4:%.*]] = add i32 [[B]], [[PHI4]]
+; LIMIT-NEXT:    [[TMP5:%.*]] = sub i32 [[TMP4]], [[TMP2]]
+; LIMIT-NEXT:    [[TMP6:%.*]] = sub i32 14, [[TMP5]]
+; LIMIT-NEXT:    [[TMP7:%.*]] = add i32 [[TMP0]], [[PHI2]]
 ; LIMIT-NEXT:    br label [[INNER_LOOP:%.*]]
 ; LIMIT:       inner_loop:
-; LIMIT-NEXT:    [[LSR_IV3:%.*]] = phi i32 [ [[LSR_IV_NEXT4:%.*]], [[INNER_LOOP]] ], [ [[TMP5]], [[PREHEADER]] ]
-; LIMIT-NEXT:    [[LSR_IV1:%.*]] = phi i32 [ [[LSR_IV_NEXT2:%.*]], [[INNER_LOOP]] ], [ [[TMP4]], [[PREHEADER]] ]
-; LIMIT-NEXT:    [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[INNER_LOOP]] ], [ [[TMP2]], [[PREHEADER]] ]
+; LIMIT-NEXT:    [[LSR_IV3:%.*]] = phi i32 [ [[LSR_IV_NEXT4:%.*]], [[INNER_LOOP]] ], [ [[TMP6]], [[PREHEADER]] ]
+; LIMIT-NEXT:    [[LSR_IV1:%.*]] = phi i32 [ [[LSR_IV_NEXT2:%.*]], [[INNER_LOOP]] ], [ [[TMP5]], [[PREHEADER]] ]
+; LIMIT-NEXT:    [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[INNER_LOOP]] ], [ [[TMP3]], [[PREHEADER]] ]
 ; LIMIT-NEXT:    [[PHI5:%.*]] = phi i32 [ [[PHI3]], [[PREHEADER]] ], [ [[I30:%.*]], [[INNER_LOOP]] ]
 ; LIMIT-NEXT:    [[PHI6:%.*]] = phi i32 [ [[PHI2]], [[PREHEADER]] ], [ [[I33:%.*]], [[INNER_LOOP]] ]
 ; LIMIT-NEXT:    [[ITER:%.*]] = phi i32 [ [[C]], [[PREHEADER]] ], [ [[ITER_SUB:%.*]], [[INNER_LOOP]] ]
@@ -103,20 +105,20 @@ define void @test(i32 %A, i32 %B, i32 %C) {
 ; LIMIT-NEXT:    [[I18:%.*]] = sub i32 14, [[PHI5]]
 ; LIMIT-NEXT:    [[I19:%.*]] = mul i32 [[I18]], [[C]]
 ; LIMIT-NEXT:    [[FACTOR_PROL:%.*]] = shl i32 [[PHI5]], 1
-; LIMIT-NEXT:    [[TMP6:%.*]] = add i32 [[LSR_IV1]], [[I19]]
-; LIMIT-NEXT:    [[TMP7:%.*]] = add i32 [[TMP6]], [[FACTOR_PROL]]
-; LIMIT-NEXT:    [[TMP8:%.*]] = shl i32 [[TMP7]], 1
-; LIMIT-NEXT:    [[TMP9:%.*]] = add i32 [[LSR_IV]], [[TMP8]]
-; LIMIT-NEXT:    [[TMP10:%.*]] = sub i32 [[LSR_IV3]], [[I19]]
-; LIMIT-NEXT:    [[TMP11:%.*]] = sub i32 [[TMP10]], [[FACTOR_PROL]]
-; LIMIT-NEXT:    [[TMP12:%.*]] = mul i32 [[C]], [[TMP11]]
-; LIMIT-NEXT:    [[TMP13:%.*]] = add i32 [[LSR_IV1]], [[I19]]
-; LIMIT-NEXT:    [[TMP14:%.*]] = add i32 [[TMP13]], [[FACTOR_PROL]]
-; LIMIT-NEXT:    [[TMP15:%.*]] = shl i32 [[TMP14]], 1
-; LIMIT-NEXT:    [[TMP16:%.*]] = add i32 [[TMP12]], [[TMP15]]
-; LIMIT-NEXT:    [[TMP17:%.*]] = add i32 [[LSR_IV]], [[TMP16]]
-; LIMIT-NEXT:    [[I29:%.*]] = mul i32 [[TMP9]], [[C]]
-; LIMIT-NEXT:    [[FACTOR_2_PROL:%.*]] = shl i32 [[TMP17]], 1
+; LIMIT-NEXT:    [[TMP8:%.*]] = add i32 [[LSR_IV1]], [[I19]]
+; LIMIT-NEXT:    [[TMP9:%.*]] = add i32 [[TMP8]], [[FACTOR_PROL]]
+; LIMIT-NEXT:    [[TMP10:%.*]] = shl i32 [[TMP9]], 1
+; LIMIT-NEXT:    [[TMP11:%.*]] = add i32 [[LSR_IV]], [[TMP10]]
+; LIMIT-NEXT:    [[TMP12:%.*]] = sub i32 [[LSR_IV3]], [[I19]]
+; LIMIT-NEXT:    [[TMP13:%.*]] = sub i32 [[TMP12]], [[FACTOR_PROL]]
+; LIMIT-NEXT:    [[TMP14:%.*]] = mul i32 [[C]], [[TMP13]]
+; LIMIT-NEXT:    [[TMP15:%.*]] = add i32 [[LSR_IV1]], [[I19]]
+; LIMIT-NEXT:    [[TMP16:%.*]] = add i32 [[TMP15]], [[FACTOR_PROL]]
+; LIMIT-NEXT:    [[TMP17:%.*]] = shl i32 [[TMP16]], 1
+; LIMIT-NEXT:    [[TMP18:%.*]] = add i32 [[TMP14]], [[TMP17]]
+; LIMIT-NEXT:    [[TMP19:%.*]] = add i32 [[LSR_IV]], [[TMP18]]
+; LIMIT-NEXT:    [[I29:%.*]] = mul i32 [[TMP11]], [[C]]
+; LIMIT-NEXT:    [[FACTOR_2_PROL:%.*]] = shl i32 [[TMP19]], 1
 ; LIMIT-NEXT:    [[I30]] = add i32 [[I17]], [[FACTOR_2_PROL]]
 ; LIMIT-NEXT:    [[I33]] = add i32 [[PHI6]], -3
 ; LIMIT-NEXT:    [[ITER_SUB]] = add i32 [[ITER]], -1
@@ -128,7 +130,7 @@ define void @test(i32 %A, i32 %B, i32 %C) {
 ; LIMIT:       outer_tail.loopexit:
 ; LIMIT-NEXT:    br label [[OUTER_TAIL]]
 ; LIMIT:       outer_tail:
-; LIMIT-NEXT:    [[PHI7:%.*]] = phi i32 [ [[PHI2]], [[GUARD]] ], [ [[I33]], [[OUTER_TAIL_LOOPEXIT]] ]
+; LIMIT-NEXT:    [[PHI7:%.*]] = phi i32 [ [[PHI2]], [[GUARD]] ], [ [[TMP7]], [[OUTER_TAIL_LOOPEXIT]] ]
 ; LIMIT-NEXT:    [[I35]] = sub i32 [[A]], [[PHI7]]
 ; LIMIT-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[I35]], 9876
 ; LIMIT-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[OUTER_LOOP]]
index e8201fc..fbaa595 100644 (file)
@@ -44,6 +44,7 @@ define void @_Z15IntegerToStringjjR7Vector2(i32 %i, i32 %radix, %struct.Vector2*
 ; CHECK-NEXT:    [[LSR_IV_NEXT17]] = add i64 [[LSR_IV16]], 1
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[DO_BODY]], label [[DO_END:%.*]]
 ; CHECK:       do.end:
+; CHECK-NEXT:    [[DOTLCSSA:%.*]] = phi [33 x i16]* [ [[TMP2]], [[DO_BODY]] ]
 ; CHECK-NEXT:    [[XAP_0:%.*]] = inttoptr i64 [[LSR_IV_NEXT17]] to i1*
 ; CHECK-NEXT:    [[CAP_0:%.*]] = ptrtoint i1* [[XAP_0]] to i64
 ; CHECK-NEXT:    [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]]
@@ -62,7 +63,7 @@ define void @_Z15IntegerToStringjjR7Vector2(i32 %i, i32 %radix, %struct.Vector2*
 ; CHECK-NEXT:    [[SCEVGEP1:%.*]] = bitcast i16* [[SCEVGEP]] to i8*
 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
-; CHECK-NEXT:    [[LSR_IV9:%.*]] = phi [33 x i16]* [ [[TMP3:%.*]], [[FOR_BODY]] ], [ [[TMP2]], [[FOR_BODY_LR_PH]] ]
+; CHECK-NEXT:    [[LSR_IV9:%.*]] = phi [33 x i16]* [ [[TMP3:%.*]], [[FOR_BODY]] ], [ [[DOTLCSSA]], [[FOR_BODY_LR_PH]] ]
 ; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_LR_PH]] ]
 ; CHECK-NEXT:    [[LSR_IV911:%.*]] = bitcast [33 x i16]* [[LSR_IV9]] to i16*
 ; CHECK-NEXT:    [[SCEVGEP2:%.*]] = getelementptr i8, i8* [[SCEVGEP1]], i64 [[LSR_IV]]
index 38cfb13..0add19e 100644 (file)
@@ -2,9 +2,6 @@
 ; RUN: opt -S -loop-reduce %s | FileCheck --check-prefixes=LEGACYPM %s
 ; RUN: opt -S -passes=loop-reduce %s | FileCheck --check-prefixes=NEWPM %s
 
-; REQUIRES: asserts
-; XFAIL: *
-
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
@@ -29,13 +26,44 @@ define void @function_0(i32 %val_i32_8, i32 %val_i32_9) {
 ; LEGACYPM-NEXT:    [[LSR_IV_NEXT]] = add i32 [[LSR_IV]], 1
 ; LEGACYPM-NEXT:    br i1 [[VAL_I1_22]], label [[LOOP_4]], label [[BE_6_LOOP_EXIT_7_CRIT_EDGE:%.*]]
 ; LEGACYPM:       loop_exit_7split:
+; LEGACYPM-NEXT:    [[LSR_IV_LCSSA:%.*]] = phi i32 [ [[LSR_IV]], [[LOOP_4]] ]
 ; LEGACYPM-NEXT:    br label [[LOOP_EXIT_7:%.*]]
 ; LEGACYPM:       be_6.loop_exit_7_crit_edge:
+; LEGACYPM-NEXT:    [[LSR_IV_LCSSA1:%.*]] = phi i32 [ [[LSR_IV]], [[BE_6]] ]
 ; LEGACYPM-NEXT:    br label [[LOOP_EXIT_7]]
 ; LEGACYPM:       loop_exit_7:
-; LEGACYPM-NEXT:    [[VAL_I32_24_LCSSA]] = phi i32 [ [[LSR_IV]], [[BE_6_LOOP_EXIT_7_CRIT_EDGE]] ], [ [[LSR_IV]], [[LOOP_EXIT_7SPLIT]] ]
+; LEGACYPM-NEXT:    [[VAL_I32_24_LCSSA]] = phi i32 [ [[LSR_IV_LCSSA1]], [[BE_6_LOOP_EXIT_7_CRIT_EDGE]] ], [ [[LSR_IV_LCSSA]], [[LOOP_EXIT_7SPLIT]] ]
 ; LEGACYPM-NEXT:    br label [[BB_5:%.*]]
 ;
+; NEWPM-LABEL: define void @function_0
+; NEWPM-SAME: (i32 [[VAL_I32_8:%.*]], i32 [[VAL_I32_9:%.*]]) {
+; NEWPM-NEXT:    [[VAL_I1_22:%.*]] = trunc i8 -66 to i1
+; NEWPM-NEXT:    br i1 [[VAL_I1_22]], label [[BB_2_PREHEADER:%.*]], label [[BB_2_PREHEADER]]
+; NEWPM:       bb_2.preheader:
+; NEWPM-NEXT:    br label [[BB_2:%.*]]
+; NEWPM:       bb_2:
+; NEWPM-NEXT:    br label [[PRHDR_LOOP_3:%.*]]
+; NEWPM:       prhdr_loop_3:
+; NEWPM-NEXT:    br label [[LOOP_4:%.*]]
+; NEWPM:       loop_4:
+; NEWPM-NEXT:    [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[BE_6:%.*]] ], [ 7851, [[PRHDR_LOOP_3]] ]
+; NEWPM-NEXT:    br i1 [[VAL_I1_22]], label [[BE_6]], label [[LOOP_EXIT_7SPLIT:%.*]]
+; NEWPM:       bb_5:
+; NEWPM-NEXT:    [[VAL_I32_40:%.*]] = mul i32 [[VAL_I32_9]], [[VAL_I32_24_LCSSA:%.*]]
+; NEWPM-NEXT:    br label [[BB_2]]
+; NEWPM:       be_6:
+; NEWPM-NEXT:    [[LSR_IV_NEXT]] = add i32 [[LSR_IV]], 1
+; NEWPM-NEXT:    br i1 [[VAL_I1_22]], label [[LOOP_4]], label [[BE_6_LOOP_EXIT_7_CRIT_EDGE:%.*]]
+; NEWPM:       loop_exit_7split:
+; NEWPM-NEXT:    [[LSR_IV_LCSSA:%.*]] = phi i32 [ [[LSR_IV]], [[LOOP_4]] ]
+; NEWPM-NEXT:    br label [[LOOP_EXIT_7:%.*]]
+; NEWPM:       be_6.loop_exit_7_crit_edge:
+; NEWPM-NEXT:    [[LSR_IV_LCSSA1:%.*]] = phi i32 [ [[LSR_IV]], [[BE_6]] ]
+; NEWPM-NEXT:    br label [[LOOP_EXIT_7]]
+; NEWPM:       loop_exit_7:
+; NEWPM-NEXT:    [[VAL_I32_24_LCSSA]] = phi i32 [ [[LSR_IV_LCSSA1]], [[BE_6_LOOP_EXIT_7_CRIT_EDGE]] ], [ [[LSR_IV_LCSSA]], [[LOOP_EXIT_7SPLIT]] ]
+; NEWPM-NEXT:    br label [[BB_5:%.*]]
+;
   %val_i1_22 = trunc i8 -66 to i1
   br i1 %val_i1_22, label %bb_2, label %bb_2
 
index a0df907..a9052d5 100644 (file)
@@ -96,10 +96,11 @@ define fastcc void @TransformLine() nounwind {
 ; CHECK-NEXT:    [[P9_PH:%.*]] = phi i32 [ undef, [[BB5_BB6SPLIT_CRIT_EDGE]] ], [ [[I1]], [[BB6SPLITSPLIT]] ]
 ; CHECK-NEXT:    br label [[BB6:%.*]]
 ; CHECK:       loop1.bb6_crit_edge:
+; CHECK-NEXT:    [[I1_LCSSA:%.*]] = phi i32 [ [[I1]], [[LOOP1]] ]
 ; CHECK-NEXT:    br label [[BB6]]
 ; CHECK:       bb6:
 ; CHECK-NEXT:    [[P8:%.*]] = phi i32 [ undef, [[LOOP1_BB6_CRIT_EDGE]] ], [ [[P8_PH]], [[BB6SPLIT]] ]
-; CHECK-NEXT:    [[P9:%.*]] = phi i32 [ [[I1]], [[LOOP1_BB6_CRIT_EDGE]] ], [ [[P9_PH]], [[BB6SPLIT]] ]
+; CHECK-NEXT:    [[P9:%.*]] = phi i32 [ [[I1_LCSSA]], [[LOOP1_BB6_CRIT_EDGE]] ], [ [[P9_PH]], [[BB6SPLIT]] ]
 ; CHECK-NEXT:    unreachable
 ;
 bb: