Skip to content

Commit ad7f020

Browse files
committed
[InstCombine] Process blocks in RPO
InstComine currently processes blocks in an arbitrary depth-first order. This can break the usual invariant that the operands of an instruction should be simplified before the instruction itself, if uses across basic blocks (particularly inside phi nodes) are involved. This patch switches the initial worklist population to use RPO instead, which will ensure that predecessors are visited before successors (back-edges notwithstanding). This allows us to fold more cases within a single InstCombine iteration, in preparation for D154579. This change by itself is a minor compile-time regression of about 0.1%, which will be more than recovered by switching to single-iteration InstCombine. Differential Revision: https://reviews.llvm.org/D75362
1 parent cf39dea commit ad7f020

File tree

5 files changed

+27
-25
lines changed

5 files changed

+27
-25
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "llvm/ADT/APInt.h"
3737
#include "llvm/ADT/ArrayRef.h"
3838
#include "llvm/ADT/DenseMap.h"
39+
#include "llvm/ADT/PostOrderIterator.h"
3940
#include "llvm/ADT/SmallPtrSet.h"
4041
#include "llvm/ADT/SmallVector.h"
4142
#include "llvm/ADT/Statistic.h"
@@ -4108,31 +4109,29 @@ class AliasScopeTracker {
41084109
}
41094110
};
41104111

4111-
/// Populate the IC worklist from a function, by walking it in depth-first
4112-
/// order and adding all reachable code to the worklist.
4112+
/// Populate the IC worklist from a function, by walking it in reverse
4113+
/// post-order and adding all reachable code to the worklist.
41134114
///
41144115
/// This has a couple of tricks to make the code faster and more powerful. In
41154116
/// particular, we constant fold and DCE instructions as we go, to avoid adding
41164117
/// them to the worklist (this significantly speeds up instcombine on code where
41174118
/// many instructions are dead or constant). Additionally, if we find a branch
41184119
/// whose condition is a known constant, we only visit the reachable successors.
4119-
static bool prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
4120-
const TargetLibraryInfo *TLI,
4121-
InstructionWorklist &ICWorklist) {
4120+
static bool
4121+
prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
4122+
const TargetLibraryInfo *TLI,
4123+
InstructionWorklist &ICWorklist,
4124+
ReversePostOrderTraversal<BasicBlock *> &RPOT) {
41224125
bool MadeIRChange = false;
4123-
SmallPtrSet<BasicBlock *, 32> Visited;
4124-
SmallVector<BasicBlock*, 256> Worklist;
4125-
Worklist.push_back(&F.front());
4126+
SmallPtrSet<BasicBlock *, 32> LiveBlocks;
4127+
LiveBlocks.insert(&F.front());
41264128

41274129
SmallVector<Instruction *, 128> InstrsForInstructionWorklist;
41284130
DenseMap<Constant *, Constant *> FoldedConstants;
41294131
AliasScopeTracker SeenAliasScopes;
41304132

4131-
do {
4132-
BasicBlock *BB = Worklist.pop_back_val();
4133-
4134-
// We have now visited this block! If we've already been here, ignore it.
4135-
if (!Visited.insert(BB).second)
4133+
for (BasicBlock *BB : RPOT) {
4134+
if (!LiveBlocks.count(BB))
41364135
continue;
41374136

41384137
for (Instruction &Inst : llvm::make_early_inc_range(*BB)) {
@@ -4178,8 +4177,8 @@ static bool prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
41784177
}
41794178
}
41804179

4181-
// Recursively visit successors. If this is a branch or switch on a
4182-
// constant, only visit the reachable successor.
4180+
// If this is a branch or switch on a constant, mark only the single
4181+
// live successor. Otherwise assume all successors are live.
41834182
Instruction *TI = BB->getTerminator();
41844183
if (BranchInst *BI = dyn_cast<BranchInst>(TI); BI && BI->isConditional()) {
41854184
if (isa<UndefValue>(BI->getCondition()))
@@ -4188,27 +4187,28 @@ static bool prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
41884187
if (auto *Cond = dyn_cast<ConstantInt>(BI->getCondition())) {
41894188
bool CondVal = Cond->getZExtValue();
41904189
BasicBlock *ReachableBB = BI->getSuccessor(!CondVal);
4191-
Worklist.push_back(ReachableBB);
4190+
LiveBlocks.insert(ReachableBB);
41924191
continue;
41934192
}
41944193
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
41954194
if (isa<UndefValue>(SI->getCondition()))
41964195
// Switch on undef is UB.
41974196
continue;
41984197
if (auto *Cond = dyn_cast<ConstantInt>(SI->getCondition())) {
4199-
Worklist.push_back(SI->findCaseValue(Cond)->getCaseSuccessor());
4198+
LiveBlocks.insert(SI->findCaseValue(Cond)->getCaseSuccessor());
42004199
continue;
42014200
}
42024201
}
42034202

4204-
append_range(Worklist, successors(TI));
4205-
} while (!Worklist.empty());
4203+
for (BasicBlock *SuccBB : successors(TI))
4204+
LiveBlocks.insert(SuccBB);
4205+
}
42064206

42074207
// Remove instructions inside unreachable blocks. This prevents the
42084208
// instcombine code from having to deal with some bad special cases, and
42094209
// reduces use counts of instructions.
42104210
for (BasicBlock &BB : F) {
4211-
if (Visited.count(&BB))
4211+
if (LiveBlocks.count(&BB))
42124212
continue;
42134213

42144214
unsigned NumDeadInstInBB;
@@ -4262,6 +4262,8 @@ static bool combineInstructionsOverFunction(
42624262
AC.registerAssumption(Assume);
42634263
}));
42644264

4265+
ReversePostOrderTraversal<BasicBlock *> RPOT(&F.front());
4266+
42654267
// Lower dbg.declare intrinsics otherwise their value may be clobbered
42664268
// by instcombiner.
42674269
bool MadeIRChange = false;
@@ -4290,7 +4292,7 @@ static bool combineInstructionsOverFunction(
42904292
LLVM_DEBUG(dbgs() << "\n\nINSTCOMBINE ITERATION #" << Iteration << " on "
42914293
<< F.getName() << "\n");
42924294

4293-
MadeIRChange |= prepareICWorklistFromFunction(F, DL, &TLI, Worklist);
4295+
MadeIRChange |= prepareICWorklistFromFunction(F, DL, &TLI, Worklist, RPOT);
42944296

42954297
InstCombinerImpl IC(Worklist, Builder, F.hasMinSize(), AA, AC, TLI, TTI, DT,
42964298
ORE, BFI, PSI, DL, LI);

llvm/test/Transforms/InstCombine/oss_fuzz_32759.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ define i1 @oss_fuzz_32759(i1 %y, i1 %c1) {
99
; CHECK: cond.true:
1010
; CHECK-NEXT: br label [[END]]
1111
; CHECK: end:
12-
; CHECK-NEXT: ret i1 [[C1]]
12+
; CHECK-NEXT: ret i1 false
1313
;
1414
entry:
1515
br i1 %c1, label %cond.true, label %end

llvm/test/Transforms/InstCombine/pr44245.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,9 @@ define void @test_2(i1 %c) local_unnamed_addr {
157157
; CHECK: cond.true133:
158158
; CHECK-NEXT: br label [[COND_END144:%.*]]
159159
; CHECK: cond.false138:
160-
; CHECK-NEXT: store i1 true, ptr poison, align 1
161160
; CHECK-NEXT: br label [[COND_END144]]
162161
; CHECK: cond.end144:
162+
; CHECK-NEXT: store i1 true, ptr poison, align 1
163163
; CHECK-NEXT: br label [[WHILE_COND]]
164164
;
165165
entry:

llvm/test/Transforms/InstCombine/select.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ define void @test64(i32 %p, i16 %b, i1 %c1) noreturn {
960960
; CHECK: lor.rhs:
961961
; CHECK-NEXT: br label [[LOR_END]]
962962
; CHECK: lor.end:
963-
; CHECK-NEXT: br i1 true, label [[COND_END17:%.*]], label [[COND_FALSE16:%.*]]
963+
; CHECK-NEXT: br i1 poison, label [[COND_END17:%.*]], label [[COND_FALSE16:%.*]]
964964
; CHECK: cond.false16:
965965
; CHECK-NEXT: br label [[COND_END17]]
966966
; CHECK: cond.end17:

llvm/test/Transforms/InstCombine/store.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
2+
; RUN: opt < %s -passes=instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s
33

44
; FIXME: This is technically incorrect because it might overwrite a poison
55
; value. Stop folding it once #52930 is resolved.

0 commit comments

Comments
 (0)