Skip to content

Commit f044564

Browse files
authored
[InstCombine] Make backedge check in op of phi transform more precise (#106075)
The op of phi transform wants to prevent moving an operation across a backedge, as this may lead to an infinite combine loop. Currently, this is done using isPotentiallyReachable(). The problem with that is that all blocks inside a loop are reachable from each other. This means that the op of phi transform is effectively completely disabled for code inside loops, even when it's not actually operating on a loop phi (just a phi that happens to be in a loop). Fix this by explicitly computing the backedges inside the function instead. Do this via RPOT, which is a bit more efficient than using FindFunctionBackedges() (which does it without any pre-computed analyses). For irreducible cycles, there may be multiple possible choices of backedge, and this just picks one of them. This is still sufficient to prevent combine loops. This also removes the last use of LoopInfo in InstCombine -- I'll drop the analysis in a followup.
1 parent d2ce9dc commit f044564

File tree

4 files changed

+33
-10
lines changed

4 files changed

+33
-10
lines changed

llvm/include/llvm/Transforms/InstCombine/InstCombiner.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
9494
/// Order of predecessors to canonicalize phi nodes towards.
9595
SmallDenseMap<BasicBlock *, SmallVector<BasicBlock *>, 8> PredOrder;
9696

97+
/// Backedges, used to avoid pushing instructions across backedges in cases
98+
/// where this may result in infinite combine loops. For irreducible loops
99+
/// this picks an arbitrary backedge.
100+
SmallDenseSet<std::pair<const BasicBlock *, const BasicBlock *>, 8> BackEdges;
101+
bool ComputedBackEdges = false;
102+
97103
public:
98104
InstCombiner(InstructionWorklist &Worklist, BuilderTy &Builder,
99105
bool MinimizeSize, AAResults *AA, AssumptionCache &AC,
@@ -359,6 +365,13 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
359365
std::function<void(Instruction *, unsigned, APInt, APInt &)>
360366
SimplifyAndSetOp);
361367

368+
void computeBackEdges();
369+
bool isBackEdge(const BasicBlock *From, const BasicBlock *To) {
370+
if (!ComputedBackEdges)
371+
computeBackEdges();
372+
return BackEdges.contains({From, To});
373+
}
374+
362375
/// Inserts an instruction \p New before instruction \p Old
363376
///
364377
/// Also adds the new instruction to the worklist and returns \p New so that

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,12 +1812,10 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) {
18121812
if (cast<Instruction>(InVal)->getParent() == NonSimplifiedBB)
18131813
return nullptr;
18141814

1815-
// If the incoming non-constant value is reachable from the phis block,
1816-
// we'll push the operation across a loop backedge. This could result in
1815+
// Do not push the operation across a loop backedge. This could result in
18171816
// an infinite combine loop, and is generally non-profitable (especially
18181817
// if the operation was originally outside the loop).
1819-
if (isPotentiallyReachable(PN->getParent(), NonSimplifiedBB, nullptr, &DT,
1820-
LI))
1818+
if (isBackEdge(NonSimplifiedBB, PN->getParent()))
18211819
return nullptr;
18221820
}
18231821

@@ -5390,6 +5388,18 @@ bool InstCombinerImpl::prepareWorklist(Function &F) {
53905388
return MadeIRChange;
53915389
}
53925390

5391+
void InstCombiner::computeBackEdges() {
5392+
// Collect backedges.
5393+
SmallPtrSet<BasicBlock *, 16> Visited;
5394+
for (BasicBlock *BB : RPOT) {
5395+
Visited.insert(BB);
5396+
for (BasicBlock *Succ : successors(BB))
5397+
if (Visited.contains(Succ))
5398+
BackEdges.insert({BB, Succ});
5399+
}
5400+
ComputedBackEdges = true;
5401+
}
5402+
53935403
static bool combineInstructionsOverFunction(
53945404
Function &F, InstructionWorklist &Worklist, AliasAnalysis *AA,
53955405
AssumptionCache &AC, TargetLibraryInfo &TLI, TargetTransformInfo &TTI,

llvm/test/Transforms/InstCombine/phi.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2721,11 +2721,11 @@ define void @phi_op_in_loop(i1 %c, i32 %x) {
27212721
; CHECK: loop:
27222722
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[LOOP_LATCH:%.*]]
27232723
; CHECK: if:
2724+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 1
27242725
; CHECK-NEXT: br label [[LOOP_LATCH]]
27252726
; CHECK: loop.latch:
2726-
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[X:%.*]], [[IF]] ], [ 0, [[LOOP]] ]
2727-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[PHI]], 1
2728-
; CHECK-NEXT: call void @use(i32 [[AND]])
2727+
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[TMP1]], [[IF]] ], [ 0, [[LOOP]] ]
2728+
; CHECK-NEXT: call void @use(i32 [[PHI]])
27292729
; CHECK-NEXT: br label [[LOOP]]
27302730
;
27312731
br label %loop

llvm/test/Transforms/LoopVectorize/induction.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5504,11 +5504,11 @@ define i32 @PR32419(i32 %a, i16 %b) {
55045504
; INTERLEAVE-NEXT: br i1 [[VAR2]], label [[FOR_INC]], label [[FOR_COND:%.*]]
55055505
; INTERLEAVE: for.cond:
55065506
; INTERLEAVE-NEXT: [[VAR3:%.*]] = urem i16 [[B]], [[VAR1]]
5507+
; INTERLEAVE-NEXT: [[TMP50:%.*]] = sext i16 [[VAR3]] to i32
55075508
; INTERLEAVE-NEXT: br label [[FOR_INC]]
55085509
; INTERLEAVE: for.inc:
5509-
; INTERLEAVE-NEXT: [[VAR4:%.*]] = phi i16 [ [[VAR3]], [[FOR_COND]] ], [ 0, [[FOR_BODY]] ]
5510-
; INTERLEAVE-NEXT: [[VAR5:%.*]] = sext i16 [[VAR4]] to i32
5511-
; INTERLEAVE-NEXT: [[VAR6]] = or i32 [[VAR0]], [[VAR5]]
5510+
; INTERLEAVE-NEXT: [[VAR4:%.*]] = phi i32 [ [[TMP50]], [[FOR_COND]] ], [ 0, [[FOR_BODY]] ]
5511+
; INTERLEAVE-NEXT: [[VAR6]] = or i32 [[VAR0]], [[VAR4]]
55125512
; INTERLEAVE-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
55135513
; INTERLEAVE-NEXT: [[COND:%.*]] = icmp eq i32 [[I_NEXT]], 0
55145514
; INTERLEAVE-NEXT: br i1 [[COND]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP49:![0-9]+]]

0 commit comments

Comments
 (0)