Skip to content

Commit 4ab87ff

Browse files
authored
[SCCP] Enable PredicateInfo for non-interprocedural SCCP (#153003)
SCCP can use PredicateInfo to constrain ranges based on assume and branch conditions. Currently, this is only enabled during IPSCCP. This enables it for SCCP as well, which runs after functions have already been simplified, while IPSCCP runs pre-inline. To a large degree, CVP already handles range-based optimizations, but SCCP is more reliable for the cases it can handle. In particular, SCCP works reliably inside loops, which is something that CVP struggles with due to LVI cycles. I have made various optimizations to make PredicateInfo more efficient, but unfortunately this still has significant compile-time cost (around 0.1-0.2%).
1 parent fb8ee3a commit 4ab87ff

File tree

6 files changed

+133
-256
lines changed

6 files changed

+133
-256
lines changed

llvm/lib/Transforms/Scalar/SCCP.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/ADT/SmallPtrSet.h"
2121
#include "llvm/ADT/SmallVector.h"
2222
#include "llvm/ADT/Statistic.h"
23+
#include "llvm/Analysis/AssumptionCache.h"
2324
#include "llvm/Analysis/DomTreeUpdater.h"
2425
#include "llvm/Analysis/GlobalsModRef.h"
2526
#include "llvm/Analysis/TargetLibraryInfo.h"
@@ -31,6 +32,7 @@
3132
#include "llvm/IR/InstrTypes.h"
3233
#include "llvm/IR/Instruction.h"
3334
#include "llvm/IR/Instructions.h"
35+
#include "llvm/IR/IntrinsicInst.h"
3436
#include "llvm/IR/PassManager.h"
3537
#include "llvm/IR/Type.h"
3638
#include "llvm/IR/Value.h"
@@ -53,12 +55,15 @@ STATISTIC(NumInstReplaced,
5355
// runSCCP() - Run the Sparse Conditional Constant Propagation algorithm,
5456
// and return true if the function was modified.
5557
static bool runSCCP(Function &F, const DataLayout &DL,
56-
const TargetLibraryInfo *TLI, DomTreeUpdater &DTU) {
58+
const TargetLibraryInfo *TLI, DominatorTree &DT,
59+
AssumptionCache &AC) {
5760
LLVM_DEBUG(dbgs() << "SCCP on function '" << F.getName() << "'\n");
5861
SCCPSolver Solver(
5962
DL, [TLI](Function &F) -> const TargetLibraryInfo & { return *TLI; },
6063
F.getContext());
6164

65+
Solver.addPredicateInfo(F, DT, AC);
66+
6267
// While we don't do any actual inter-procedural analysis, still track
6368
// return values so we can infer attributes.
6469
if (canTrackReturnsInterprocedurally(&F))
@@ -101,6 +106,7 @@ static bool runSCCP(Function &F, const DataLayout &DL,
101106
}
102107

103108
// Remove unreachable blocks and non-feasible edges.
109+
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
104110
for (BasicBlock *DeadBB : BlocksToErase)
105111
NumInstRemoved += changeToUnreachable(&*DeadBB->getFirstNonPHIIt(),
106112
/*PreserveLCSSA=*/false, &DTU);
@@ -113,6 +119,8 @@ static bool runSCCP(Function &F, const DataLayout &DL,
113119
if (!DeadBB->hasAddressTaken())
114120
DTU.deleteBB(DeadBB);
115121

122+
Solver.removeSSACopies(F);
123+
116124
Solver.inferReturnAttributes();
117125

118126
return MadeChanges;
@@ -121,9 +129,9 @@ static bool runSCCP(Function &F, const DataLayout &DL,
121129
PreservedAnalyses SCCPPass::run(Function &F, FunctionAnalysisManager &AM) {
122130
const DataLayout &DL = F.getDataLayout();
123131
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
124-
auto *DT = AM.getCachedResult<DominatorTreeAnalysis>(F);
125-
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
126-
if (!runSCCP(F, DL, &TLI, DTU))
132+
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
133+
auto &AC = AM.getResult<AssumptionAnalysis>(F);
134+
if (!runSCCP(F, DL, &TLI, DT, AC))
127135
return PreservedAnalyses::all();
128136

129137
auto PA = PreservedAnalyses();

llvm/test/Transforms/PhaseOrdering/deletion-of-loops-that-became-side-effect-free.ll

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -96,35 +96,10 @@ while.end:
9696
}
9797

9898
define dso_local zeroext i1 @is_not_empty_variant3(ptr %p) {
99-
; O3-LABEL: @is_not_empty_variant3(
100-
; O3-NEXT: entry:
101-
; O3-NEXT: [[TOBOOL_NOT4_I:%.*]] = icmp ne ptr [[P:%.*]], null
102-
; O3-NEXT: ret i1 [[TOBOOL_NOT4_I]]
103-
;
104-
; O2-LABEL: @is_not_empty_variant3(
105-
; O2-NEXT: entry:
106-
; O2-NEXT: [[TOBOOL_NOT4_I:%.*]] = icmp ne ptr [[P:%.*]], null
107-
; O2-NEXT: ret i1 [[TOBOOL_NOT4_I]]
108-
;
109-
; O1-LABEL: @is_not_empty_variant3(
110-
; O1-NEXT: entry:
111-
; O1-NEXT: [[TOBOOL_NOT4_I:%.*]] = icmp eq ptr [[P:%.*]], null
112-
; O1-NEXT: br i1 [[TOBOOL_NOT4_I]], label [[COUNT_NODES_VARIANT3_EXIT:%.*]], label [[WHILE_BODY_I:%.*]]
113-
; O1: while.body.i:
114-
; O1-NEXT: [[SIZE_06_I:%.*]] = phi i64 [ [[INC_I:%.*]], [[WHILE_BODY_I]] ], [ 0, [[ENTRY:%.*]] ]
115-
; O1-NEXT: [[P_ADDR_05_I:%.*]] = phi ptr [ [[TMP0:%.*]], [[WHILE_BODY_I]] ], [ [[P]], [[ENTRY]] ]
116-
; O1-NEXT: [[CMP_I:%.*]] = icmp ne i64 [[SIZE_06_I]], -1
117-
; O1-NEXT: call void @llvm.assume(i1 [[CMP_I]])
118-
; O1-NEXT: [[TMP0]] = load ptr, ptr [[P_ADDR_05_I]], align 8
119-
; O1-NEXT: [[INC_I]] = add i64 [[SIZE_06_I]], 1
120-
; O1-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq ptr [[TMP0]], null
121-
; O1-NEXT: br i1 [[TOBOOL_NOT_I]], label [[COUNT_NODES_VARIANT3_EXIT_LOOPEXIT:%.*]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP0:![0-9]+]]
122-
; O1: count_nodes_variant3.exit.loopexit:
123-
; O1-NEXT: [[PHI_CMP:%.*]] = icmp ne i64 [[INC_I]], 0
124-
; O1-NEXT: br label [[COUNT_NODES_VARIANT3_EXIT]]
125-
; O1: count_nodes_variant3.exit:
126-
; O1-NEXT: [[SIZE_0_LCSSA_I:%.*]] = phi i1 [ false, [[ENTRY]] ], [ [[PHI_CMP]], [[COUNT_NODES_VARIANT3_EXIT_LOOPEXIT]] ]
127-
; O1-NEXT: ret i1 [[SIZE_0_LCSSA_I]]
99+
; ALL-LABEL: @is_not_empty_variant3(
100+
; ALL-NEXT: entry:
101+
; ALL-NEXT: [[TOBOOL_NOT4_I:%.*]] = icmp ne ptr [[P:%.*]], null
102+
; ALL-NEXT: ret i1 [[TOBOOL_NOT4_I]]
128103
;
129104
entry:
130105
%p.addr = alloca ptr, align 8
@@ -182,3 +157,7 @@ declare void @llvm.assume(i1 noundef)
182157
!1 = !{!"llvm.loop.mustprogress"}
183158
!2 = distinct !{!2, !1}
184159
!3 = distinct !{!3, !1}
160+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
161+
; O1: {{.*}}
162+
; O2: {{.*}}
163+
; O3: {{.*}}

llvm/test/Transforms/SCCP/pr27712.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
; RUN: opt -passes=sccp -S < %s | FileCheck %s
33

44
define i32 @main() {
5-
; CHECK-LABEL: define i32 @main() {
5+
; CHECK-LABEL: define range(i32 33554432, 0) i32 @main() {
66
; CHECK-NEXT: [[ENTRY:.*]]:
77
; CHECK-NEXT: br label %[[LBL_1154:.*]]
88
; CHECK: [[LBL_1154]]:

llvm/test/Transforms/SCCP/sccptest.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ define i32 @test2(i32 %i0, i32 %j0) {
4343
; CHECK: BB4:
4444
; CHECK-NEXT: ret i32 1
4545
; CHECK: BB5:
46-
; CHECK-NEXT: [[K3]] = add i32 [[K2]], 1
46+
; CHECK-NEXT: [[K3]] = add nsw i32 [[K2]], 1
4747
; CHECK-NEXT: br label [[BB7]]
4848
; CHECK: BB7:
4949
; CHECK-NEXT: br label [[BB2]]

llvm/test/Transforms/SCCP/undef-resolve.ll

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ define i32 @test2() nounwind readnone ssp {
3333
; CHECK: control.outer.outer.split.us:
3434
; CHECK-NEXT: br label [[CONTROL_OUTER_US:%.*]]
3535
; CHECK: control.outer.us:
36-
; CHECK-NEXT: [[A_0_PH_US:%.*]] = phi i32 [ [[SWITCHCOND_0_US:%.*]], [[BB3_US:%.*]] ], [ 4, [[CONTROL_OUTER_OUTER_SPLIT_US]] ]
36+
; CHECK-NEXT: [[A_0_PH_US:%.*]] = phi i32 [ 3, [[BB3_US:%.*]] ], [ 4, [[CONTROL_OUTER_OUTER_SPLIT_US]] ]
3737
; CHECK-NEXT: [[SWITCHCOND_0_PH_US:%.*]] = phi i32 [ [[A_0_PH_US]], [[BB3_US]] ], [ [[SWITCHCOND_0_PH_PH]], [[CONTROL_OUTER_OUTER_SPLIT_US]] ]
3838
; CHECK-NEXT: br label [[CONTROL_US:%.*]]
3939
; CHECK: bb3.us:
4040
; CHECK-NEXT: br label [[CONTROL_OUTER_US]]
4141
; CHECK: bb0.us:
4242
; CHECK-NEXT: br label [[CONTROL_US]]
4343
; CHECK: control.us:
44-
; CHECK-NEXT: [[SWITCHCOND_0_US]] = phi i32 [ [[A_0_PH_US]], [[BB0_US:%.*]] ], [ [[SWITCHCOND_0_PH_US]], [[CONTROL_OUTER_US]] ]
44+
; CHECK-NEXT: [[SWITCHCOND_0_US:%.*]] = phi i32 [ [[A_0_PH_US]], [[BB0_US:%.*]] ], [ [[SWITCHCOND_0_PH_US]], [[CONTROL_OUTER_US]] ]
4545
; CHECK-NEXT: switch i32 [[SWITCHCOND_0_US]], label [[CONTROL_OUTER_LOOPEXIT_US_LCSSA_US:%.*]] [
4646
; CHECK-NEXT: i32 0, label [[BB0_US]]
4747
; CHECK-NEXT: i32 1, label [[BB1_US_LCSSA_US:%.*]]
@@ -55,7 +55,7 @@ define i32 @test2() nounwind readnone ssp {
5555
; CHECK: bb4.us-lcssa.us:
5656
; CHECK-NEXT: br label [[BB4:%.*]]
5757
; CHECK: control.outer:
58-
; CHECK-NEXT: [[A_0_PH:%.*]] = phi i32 [ [[NEXTID17:%.*]], [[BB3:%.*]] ], [ 4, [[CONTROL_OUTER_OUTER_CONTROL_OUTER_OUTER_SPLIT_CRIT_EDGE]] ]
58+
; CHECK-NEXT: [[A_0_PH:%.*]] = phi i32 [ 1, [[BB3:%.*]] ], [ 4, [[CONTROL_OUTER_OUTER_CONTROL_OUTER_OUTER_SPLIT_CRIT_EDGE]] ]
5959
; CHECK-NEXT: [[SWITCHCOND_0_PH:%.*]] = phi i32 [ 0, [[BB3]] ], [ [[SWITCHCOND_0_PH_PH]], [[CONTROL_OUTER_OUTER_CONTROL_OUTER_OUTER_SPLIT_CRIT_EDGE]] ]
6060
; CHECK-NEXT: br label [[CONTROL:%.*]]
6161
; CHECK: control:
@@ -74,7 +74,6 @@ define i32 @test2() nounwind readnone ssp {
7474
; CHECK-NEXT: [[I_0_PH_PH_BE]] = phi i32 [ 1, [[BB4]] ], [ 0, [[CONTROL_OUTER_LOOPEXIT]] ]
7575
; CHECK-NEXT: br label [[CONTROL_OUTER_OUTER]]
7676
; CHECK: bb3:
77-
; CHECK-NEXT: [[NEXTID17]] = add i32 [[SWITCHCOND_0]], -2
7877
; CHECK-NEXT: br label [[CONTROL_OUTER]]
7978
; CHECK: bb0:
8079
; CHECK-NEXT: br label [[CONTROL]]

0 commit comments

Comments
 (0)