diff --git a/llvm/lib/Transforms/Utils/LCSSA.cpp b/llvm/lib/Transforms/Utils/LCSSA.cpp --- a/llvm/lib/Transforms/Utils/LCSSA.cpp +++ b/llvm/lib/Transforms/Utils/LCSSA.cpp @@ -161,27 +161,42 @@ // If we already inserted something for this BB, don't reprocess it. if (SSAUpdate.HasValueForBlock(ExitBB)) continue; + + PHINode *PN = nullptr; + // If ExitBB already contains a phi with a constant incoming value, re-use + // it instead of creating a new phi. + for (PHINode &ExistingPN : ExitBB->phis()) { + if (ExistingPN.hasConstantValue() == I) { + PN = &ExistingPN; + // LCSSA construction code assumes the phi to be the first in the + // block. + PN->moveBefore(&ExitBB->front()); + break; + } + } Builder.SetInsertPoint(&ExitBB->front()); - PHINode *PN = Builder.CreatePHI(I->getType(), PredCache.size(ExitBB), - I->getName() + ".lcssa"); - // Get the debug location from the original instruction. - PN->setDebugLoc(I->getDebugLoc()); - - // Add inputs from inside the loop for this PHI. This is valid - // because `I` dominates `ExitBB` (checked above). This implies - // that every incoming block/edge is dominated by `I` as well, - // i.e. we can add uses of `I` to those incoming edges/append to the incoming - // blocks without violating the SSA dominance property. - for (BasicBlock *Pred : PredCache.get(ExitBB)) { - PN->addIncoming(I, Pred); - - // If the exit block has a predecessor not within the loop, arrange for - // the incoming value use corresponding to that predecessor to be - // rewritten in terms of a different LCSSA PHI. - if (!L->contains(Pred)) - UsesToRewrite.push_back( - &PN->getOperandUse(PN->getOperandNumForIncomingValue( - PN->getNumIncomingValues() - 1))); + if (!PN) { + PN = Builder.CreatePHI(I->getType(), PredCache.size(ExitBB), + I->getName() + ".lcssa"); + // Get the debug location from the original instruction. + PN->setDebugLoc(I->getDebugLoc()); + + // Add inputs from inside the loop for this PHI. This is valid + // because `I` dominates `ExitBB` (checked above). This implies + // that every incoming block/edge is dominated by `I` as well, + // i.e. we can add uses of `I` to those incoming edges/append to the + // incoming blocks without violating the SSA dominance property. + for (BasicBlock *Pred : PredCache.get(ExitBB)) { + PN->addIncoming(I, Pred); + } + + for (unsigned I = 0, E = PN->getNumIncomingValues(); I != E; ++I) { + // If the exit block has a predecessor not within the loop, arrange + // for the incoming value use corresponding to that predecessor to be + // rewritten in terms of a different LCSSA PHI. + if (!L->contains(PN->getIncomingBlock(I))) + UsesToRewrite.push_back(&PN->getOperandUse(I)); + } } AddedPHIs.push_back(PN); diff --git a/llvm/test/Transforms/IndVarSimplify/lcssa-preservation.ll b/llvm/test/Transforms/IndVarSimplify/lcssa-preservation.ll --- a/llvm/test/Transforms/IndVarSimplify/lcssa-preservation.ll +++ b/llvm/test/Transforms/IndVarSimplify/lcssa-preservation.ll @@ -86,3 +86,59 @@ %res.lcssa2 = phi i64 [ %res.lcssa, %loop1.latch ] ret i64 %res.lcssa2 } + +; Check that it does not crash because the incoming values of an LCSSA phi are +; equal. +define void @pr57000(i64 %a) { +; CHECK-LABEL: @pr57000( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP_1_OUTER:%.*]] +; CHECK: loop.1.loopexit: +; CHECK-NEXT: br label [[LOOP_1_OUTER]] +; CHECK: loop.1.outer: +; CHECK-NEXT: br label [[LOOP_1:%.*]] +; CHECK: loop.1: +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i64 [[A:%.*]], 2546175499358690212 +; CHECK-NEXT: [[CMP_EXT:%.*]] = zext i1 [[CMP]] to i8 +; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_1]], label [[LOOP_2_HEADER_PREHEADER:%.*]] +; CHECK: loop.2.header.preheader: +; CHECK-NEXT: [[CMP_LCSSA:%.*]] = phi i1 [ [[CMP]], [[LOOP_1]] ] +; CHECK-NEXT: [[CMP_EXT_LCSSA:%.*]] = phi i8 [ [[CMP_EXT]], [[LOOP_1]] ] +; CHECK-NEXT: br label [[LOOP_2_HEADER_OUTER:%.*]] +; CHECK: loop.2.header.outer: +; CHECK-NEXT: br label [[LOOP_2_HEADER:%.*]] +; CHECK: loop.2.header: +; CHECK-NEXT: switch i8 [[CMP_EXT_LCSSA]], label [[LOOP_1_LOOPEXIT:%.*]] [ +; CHECK-NEXT: i8 -1, label [[LOOP_2_LATCH:%.*]] +; CHECK-NEXT: i8 1, label [[LOOP_2_LATCH]] +; CHECK-NEXT: i8 4, label [[LOOP_2_HEADER]] +; CHECK-NEXT: ] +; CHECK: loop.2.latch: +; CHECK-NEXT: [[CMP_TRUNC_LCSSA1:%.*]] = phi i1 [ [[CMP_LCSSA]], [[LOOP_2_HEADER]] ], [ [[CMP_LCSSA]], [[LOOP_2_HEADER]] ] +; CHECK-NEXT: call void @use(i1 [[CMP_TRUNC_LCSSA1]]) +; CHECK-NEXT: br label [[LOOP_2_HEADER_OUTER]] +; +entry: + br label %loop.1 + +loop.1: + %p.1 = phi i1 [ 0 , %entry ], [ %p.1, %loop.1 ], [ %p.2, %loop.2.header ] + %cmp = icmp sle i64 %a, 2546175499358690212 + %cmp.ext = zext i1 %cmp to i8 + br i1 %cmp, label %loop.1, label %loop.2.header + +loop.2.header: + %p.2 = phi i1 [ %p.1, %loop.1 ], [ %p.2, %loop.2.header ], [ %cmp, %loop.2.latch ] + %cmp.trunc = trunc i8 %cmp.ext to i1 + switch i8 %cmp.ext, label %loop.1 [ + i8 -1, label %loop.2.latch + i8 1, label %loop.2.latch + i8 4, label %loop.2.header + ] + +loop.2.latch: + call void @use(i1 %cmp.trunc) + br label %loop.2.header +} + +declare void @use(i1) diff --git a/llvm/test/Transforms/LoopUnroll/rebuild_lcssa.ll b/llvm/test/Transforms/LoopUnroll/rebuild_lcssa.ll --- a/llvm/test/Transforms/LoopUnroll/rebuild_lcssa.ll +++ b/llvm/test/Transforms/LoopUnroll/rebuild_lcssa.ll @@ -246,7 +246,6 @@ ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA]], [[INNER3]] ], [ [[A]], [[INNER2_INDIRECT_EXIT]] ] ; CHECK-NEXT: br i1 true, label [[OUTER_LATCH_LOOPEXIT:%.*]], label [[INNER3]] ; CHECK: outer_latch.loopexit: -; CHECK-NEXT: [[A_LCSSA_LCSSA2:%.*]] = phi i32 [ [[A_LCSSA]], [[INNER3]] ] ; CHECK-NEXT: [[A_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_LCSSA]], [[INNER3]] ] ; CHECK-NEXT: br label [[OUTER_LATCH:%.*]] ; CHECK: outer_latch: diff --git a/llvm/test/Transforms/LoopVectorize/create-induction-resume.ll b/llvm/test/Transforms/LoopVectorize/create-induction-resume.ll --- a/llvm/test/Transforms/LoopVectorize/create-induction-resume.ll +++ b/llvm/test/Transforms/LoopVectorize/create-induction-resume.ll @@ -29,7 +29,6 @@ ; CHECK: L1.early.exit: ; CHECK-NEXT: ret void ; CHECK: L1.exit: -; CHECK-NEXT: [[INDUCTION_IV_LCSSA3:%.*]] = phi i32 [ [[INDUCTION_IV]], [[L1_BACKEDGE]] ] ; CHECK-NEXT: [[INDUCTION_IV_LCSSA1:%.*]] = phi i32 [ [[INDUCTION_IV]], [[L1_BACKEDGE]] ] ; CHECK-NEXT: [[L1_EXIT_VAL:%.*]] = phi i32 [ [[L1_SUM_NEXT]], [[L1_BACKEDGE]] ] ; CHECK-NEXT: br label [[L2_HEADER:%.*]] diff --git a/llvm/test/Transforms/LoopVectorize/skeleton-lcssa-crash.ll b/llvm/test/Transforms/LoopVectorize/skeleton-lcssa-crash.ll --- a/llvm/test/Transforms/LoopVectorize/skeleton-lcssa-crash.ll +++ b/llvm/test/Transforms/LoopVectorize/skeleton-lcssa-crash.ll @@ -23,7 +23,6 @@ ; CHECK-NEXT: [[C_3:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C_3]], label [[LOOP_3_PREHEADER:%.*]], label [[INNER_LATCH:%.*]] ; CHECK: loop.3.preheader: -; CHECK-NEXT: [[L_1_LCSSA7:%.*]] = phi ptr [ [[L_1]], [[INNER_BB]] ] ; CHECK-NEXT: [[L_1_LCSSA:%.*]] = phi ptr [ [[L_1]], [[INNER_BB]] ] ; CHECK-NEXT: [[L_2_LCSSA:%.*]] = phi ptr [ [[L_2]], [[INNER_BB]] ] ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N:%.*]], 1 @@ -34,7 +33,7 @@ ; CHECK-NEXT: [[UGLYGEP3:%.*]] = getelementptr i8, ptr [[L_1_LCSSA]], i64 2 ; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[N]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 4 -; CHECK-NEXT: [[UGLYGEP6:%.*]] = getelementptr i8, ptr [[L_1_LCSSA7]], i64 [[TMP2]] +; CHECK-NEXT: [[UGLYGEP6:%.*]] = getelementptr i8, ptr [[L_1_LCSSA]], i64 [[TMP2]] ; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[L_2_LCSSA]], [[UGLYGEP6]] ; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[UGLYGEP3]], [[UGLYGEP]] ; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]] @@ -141,14 +140,13 @@ ; CHECK-NEXT: [[INDVAR_NEXT]] = add i32 [[INDVAR]], 1 ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_2]], label [[LOOP_3_PH:%.*]] ; CHECK: loop.3.ph: -; CHECK-NEXT: [[INDVAR_LCSSA1:%.*]] = phi i32 [ [[INDVAR]], [[LOOP_2]] ] ; CHECK-NEXT: [[INDVAR_LCSSA:%.*]] = phi i32 [ [[INDVAR]], [[LOOP_2]] ] ; CHECK-NEXT: [[IV_1_LCSSA:%.*]] = phi i64 [ [[IV_1]], [[LOOP_2]] ] ; CHECK-NEXT: [[TMP0:%.*]] = and i64 [[IV_1_LCSSA]], 4294967295 -; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[INDVAR_LCSSA1]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[INDVAR_LCSSA]], -1 ; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1000 -; CHECK-NEXT: [[SMIN2:%.*]] = call i32 @llvm.smin.i32(i32 [[TMP2]], i32 1) -; CHECK-NEXT: [[TMP3:%.*]] = sub i32 [[TMP2]], [[SMIN2]] +; CHECK-NEXT: [[SMIN1:%.*]] = call i32 @llvm.smin.i32(i32 [[TMP2]], i32 1) +; CHECK-NEXT: [[TMP3:%.*]] = sub i32 [[TMP2]], [[SMIN1]] ; CHECK-NEXT: [[TMP4:%.*]] = zext i32 [[TMP3]] to i64 ; CHECK-NEXT: [[TMP5:%.*]] = add nuw nsw i64 [[TMP4]], 1 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP5]], 2