Skip to content

Commit 3bbc1ee

Browse files
committed
Reintroduce "[SCCP] Propagate integer range info for parameters in IPSCCP."
This is r315288 & r315294, which were reverted due to stage2 bot failures. Summary: This updates the SCCP solver to use of the ValueElement lattice for parameters, which provides integer range information. The range information is used to remove unneeded icmp instructions. For the following function, f() can be optimized to `ret i32 2` with this change source_filename = "sccp.c" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" ; Function Attrs: norecurse nounwind readnone uwtable define i32 @main() local_unnamed_addr #0 { entry: %call = tail call fastcc i32 @f(i32 1) %call1 = tail call fastcc i32 @f(i32 47) %add3 = add nsw i32 %call, %call1 ret i32 %add3 } ; Function Attrs: noinline norecurse nounwind readnone uwtable define internal fastcc i32 @f(i32 %x) unnamed_addr #1 { entry: %c1 = icmp sle i32 %x, 100 %cmp = icmp sgt i32 %x, 300 %. = select i1 %cmp, i32 1, i32 2 ret i32 %. } attributes #1 = { noinline } Reviewers: davide, sanjoy, efriedma, dberlin Reviewed By: davide, dberlin Subscribers: mcrosier, gberry, mssimpso, dberlin, llvm-commits Differential Revision: https://reviews.llvm.org/D36656 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315593 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 818cdb5 commit 3bbc1ee

File tree

2 files changed

+209
-8
lines changed

2 files changed

+209
-8
lines changed

lib/Transforms/Scalar/SCCP.cpp

Lines changed: 92 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "llvm/Analysis/ConstantFolding.h"
2828
#include "llvm/Analysis/GlobalsModRef.h"
2929
#include "llvm/Analysis/TargetLibraryInfo.h"
30+
#include "llvm/Analysis/ValueLattice.h"
3031
#include "llvm/IR/CallSite.h"
3132
#include "llvm/IR/Constants.h"
3233
#include "llvm/IR/DataLayout.h"
@@ -52,6 +53,8 @@ STATISTIC(NumDeadBlocks , "Number of basic blocks unreachable");
5253
STATISTIC(IPNumInstRemoved, "Number of instructions removed by IPSCCP");
5354
STATISTIC(IPNumArgsElimed ,"Number of arguments constant propagated by IPSCCP");
5455
STATISTIC(IPNumGlobalConst, "Number of globals found to be constant by IPSCCP");
56+
STATISTIC(IPNumRangeInfoUsed, "Number of times constant range info was used by"
57+
"IPSCCP");
5558

5659
namespace {
5760
/// LatticeVal class - This class represents the different lattice values that
@@ -153,6 +156,14 @@ class LatticeVal {
153156
Val.setInt(forcedconstant);
154157
Val.setPointer(V);
155158
}
159+
160+
ValueLatticeElement toValueLattice() const {
161+
if (isOverdefined())
162+
return ValueLatticeElement::getOverdefined();
163+
if (isConstant())
164+
return ValueLatticeElement::get(getConstant());
165+
return ValueLatticeElement();
166+
}
156167
};
157168
} // end anonymous namespace.
158169

@@ -169,6 +180,8 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
169180
const TargetLibraryInfo *TLI;
170181
SmallPtrSet<BasicBlock*, 8> BBExecutable; // The BBs that are executable.
171182
DenseMap<Value*, LatticeVal> ValueState; // The state each value is in.
183+
// The state each parameter is in.
184+
DenseMap<Value *, ValueLatticeElement> ParamState;
172185

173186
/// StructValueState - This maintains ValueState for values that have
174187
/// StructType, for example for formal arguments, calls, insertelement, etc.
@@ -290,10 +303,15 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
290303
return StructValues;
291304
}
292305

293-
LatticeVal getLatticeValueFor(Value *V) const {
294-
DenseMap<Value*, LatticeVal>::const_iterator I = ValueState.find(V);
295-
assert(I != ValueState.end() && "V is not in valuemap!");
296-
return I->second;
306+
ValueLatticeElement getLatticeValueFor(Value *V) {
307+
if (ParamState.count(V) == 0) {
308+
DenseMap<Value *, LatticeVal>::const_iterator I = ValueState.find(V);
309+
assert(I != ValueState.end() &&
310+
"V not found in ValueState nor Paramstate map!");
311+
ParamState[V] = I->second.toValueLattice();
312+
}
313+
314+
return ParamState[V];
297315
}
298316

299317
/// getTrackedRetVals - Get the inferred return value map.
@@ -426,6 +444,15 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
426444
return LV;
427445
}
428446

447+
ValueLatticeElement &getParamState(Value *V) {
448+
assert(!V->getType()->isStructTy() && "Should use getStructValueState");
449+
450+
if (ParamState.count(V) == 0)
451+
ParamState[V] = getValueState(V).toValueLattice();
452+
453+
return ParamState[V];
454+
}
455+
429456
/// getStructValueState - Return the LatticeVal object that corresponds to the
430457
/// value/field pair. This function handles the case when the value hasn't
431458
/// been seen yet by properly seeding constants etc.
@@ -1162,6 +1189,9 @@ void SCCPSolver::visitCallSite(CallSite CS) {
11621189
mergeInValue(getStructValueState(&*AI, i), &*AI, CallArg);
11631190
}
11641191
} else {
1192+
// Most other parts of the Solver still only use the simpler value
1193+
// lattice, so we propagate changes for parameters to both lattices.
1194+
getParamState(&*AI).mergeIn(getValueState(*CAI).toValueLattice(), DL);
11651195
mergeInValue(&*AI, getValueState(*CAI));
11661196
}
11671197
}
@@ -1557,6 +1587,46 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
15571587
return false;
15581588
}
15591589

1590+
static bool tryToReplaceWithConstantRange(SCCPSolver &Solver, Value *V) {
1591+
bool Changed = false;
1592+
if (!V->getType()->isIntegerTy())
1593+
return false;
1594+
1595+
const ValueLatticeElement &IV = Solver.getLatticeValueFor(V);
1596+
if (IV.isOverdefined())
1597+
return false;
1598+
1599+
// Currently we only use range information for integer values.
1600+
if (!(V->getType()->isIntegerTy() && IV.isConstantRange()))
1601+
return false;
1602+
1603+
for (auto UI = V->uses().begin(), E = V->uses().end(); UI != E;) {
1604+
// Advance the iterator here, as we might remove the current use.
1605+
const Use &U = *UI++;
1606+
auto *Icmp = dyn_cast<ICmpInst>(U.getUser());
1607+
if (!Icmp)
1608+
continue;
1609+
1610+
auto A = Solver.getLatticeValueFor(Icmp->getOperand(0));
1611+
auto B = Solver.getLatticeValueFor(Icmp->getOperand(1));
1612+
Constant *C = nullptr;
1613+
if (A.satisfiesPredicate(Icmp->getPredicate(), B))
1614+
C = ConstantInt::getTrue(Icmp->getType());
1615+
else if (A.satisfiesPredicate(Icmp->getInversePredicate(), B))
1616+
C = ConstantInt::getFalse(Icmp->getType());
1617+
1618+
if (C) {
1619+
Icmp->replaceAllUsesWith(C);
1620+
DEBUG(dbgs() << "Replacing " << *Icmp << " with " << *C
1621+
<< ", because of range information " << A << " " << B
1622+
<< "\n");
1623+
Icmp->eraseFromParent();
1624+
Changed = true;
1625+
}
1626+
}
1627+
return Changed;
1628+
}
1629+
15601630
static bool tryToReplaceWithConstant(SCCPSolver &Solver, Value *V) {
15611631
Constant *Const = nullptr;
15621632
if (V->getType()->isStructTy()) {
@@ -1573,10 +1643,19 @@ static bool tryToReplaceWithConstant(SCCPSolver &Solver, Value *V) {
15731643
}
15741644
Const = ConstantStruct::get(ST, ConstVals);
15751645
} else {
1576-
LatticeVal IV = Solver.getLatticeValueFor(V);
1646+
const ValueLatticeElement &IV = Solver.getLatticeValueFor(V);
15771647
if (IV.isOverdefined())
15781648
return false;
1579-
Const = IV.isConstant() ? IV.getConstant() : UndefValue::get(V->getType());
1649+
1650+
if (IV.isConstantRange()) {
1651+
if (IV.getConstantRange().isSingleElement())
1652+
Const =
1653+
ConstantInt::get(V->getType(), IV.asConstantInteger().getValue());
1654+
else
1655+
return false;
1656+
} else
1657+
Const =
1658+
IV.isConstant() ? IV.getConstant() : UndefValue::get(V->getType());
15801659
}
15811660
assert(Const && "Constant is nullptr here!");
15821661
DEBUG(dbgs() << " Constant: " << *Const << " = " << *V << '\n');
@@ -1816,12 +1895,17 @@ static bool runIPSCCP(Module &M, const DataLayout &DL,
18161895
if (F.isDeclaration())
18171896
continue;
18181897

1819-
if (Solver.isBlockExecutable(&F.front()))
1898+
if (Solver.isBlockExecutable(&F.front())) {
18201899
for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); AI != E;
1821-
++AI)
1900+
++AI) {
18221901
if (!AI->use_empty() && tryToReplaceWithConstant(Solver, &*AI))
18231902
++IPNumArgsElimed;
18241903

1904+
if (!AI->use_empty() && tryToReplaceWithConstantRange(Solver, &*AI))
1905+
++IPNumRangeInfoUsed;
1906+
}
1907+
}
1908+
18251909
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
18261910
if (!Solver.isBlockExecutable(&*BB)) {
18271911
DEBUG(dbgs() << " BasicBlock Dead:" << *BB);
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
; RUN: opt < %s -ipsccp -S | FileCheck %s
2+
3+
; Constant range for %a is [1, 48) and for %b is [301, 1000)
4+
; CHECK-LABEL: f1
5+
; CHECK-NOT: icmp
6+
; CHECK: %a.1 = select i1 false, i32 1, i32 2
7+
; CHECK: %b.1 = select i1 true, i32 1, i32 2
8+
; CHECK: %a.2 = select i1 false, i32 1, i32 2
9+
; CHECK: %b.2 = select i1 true, i32 1, i32 2
10+
define internal i32 @f1(i32 %a, i32 %b) {
11+
entry:
12+
%cmp.a = icmp sgt i32 %a, 300
13+
%cmp.b = icmp sgt i32 %b, 300
14+
%cmp.a2 = icmp ugt i32 %a, 300
15+
%cmp.b2 = icmp ugt i32 %b, 300
16+
17+
%a.1 = select i1 %cmp.a, i32 1, i32 2
18+
%b.1 = select i1 %cmp.b, i32 1, i32 2
19+
%a.2 = select i1 %cmp.a2, i32 1, i32 2
20+
%b.2 = select i1 %cmp.b2, i32 1, i32 2
21+
%res1 = add i32 %a.1, %b.1
22+
%res2 = add i32 %a.2, %b.2
23+
%res3 = add i32 %res1, %res2
24+
ret i32 %res3
25+
}
26+
27+
; Constant range for %x is [47, 302)
28+
; CHECK-LABEL: f2
29+
; CHECK: %cmp = icmp sgt i32 %x, 300
30+
; CHECK: %res1 = select i1 %cmp, i32 1, i32 2
31+
; CHECK-NEXT: %res2 = select i1 true, i32 3, i32 4
32+
; CHECK-NEXT: %res3 = select i1 true, i32 5, i32 6
33+
; CHECK-NEXT: %res4 = select i1 %cmp4, i32 3, i32 4
34+
; CHECK-NEXT: %res5 = select i1 true, i32 5, i32 6
35+
define internal i32 @f2(i32 %x) {
36+
entry:
37+
%cmp = icmp sgt i32 %x, 300
38+
%cmp2 = icmp ne i32 %x, 10
39+
%cmp3 = icmp sge i32 %x, 47
40+
%cmp4 = icmp ugt i32 %x, 300
41+
%cmp5 = icmp uge i32 %x, 47
42+
%res1 = select i1 %cmp, i32 1, i32 2
43+
%res2 = select i1 %cmp2, i32 3, i32 4
44+
%res3 = select i1 %cmp3, i32 5, i32 6
45+
%res4 = select i1 %cmp4, i32 3, i32 4
46+
%res5 = select i1 %cmp5, i32 5, i32 6
47+
48+
%res6 = add i32 %res1, %res2
49+
%res7 = add i32 %res3, %res4
50+
%res = add i32 %res6, %res5
51+
ret i32 %res
52+
}
53+
54+
define i32 @caller1() {
55+
entry:
56+
%call1 = tail call i32 @f1(i32 1, i32 301)
57+
%call2 = tail call i32 @f1(i32 47, i32 999)
58+
%call3 = tail call i32 @f2(i32 47)
59+
%call4 = tail call i32 @f2(i32 301)
60+
%res = add nsw i32 %call1, %call2
61+
%res.1 = add nsw i32 %res, %call3
62+
%res.2 = add nsw i32 %res.1, %call4
63+
ret i32 %res.2
64+
}
65+
66+
; x is overdefined, because constant ranges are only used for parameter
67+
; values.
68+
; CHECK-LABEL: f3
69+
; CHECK: %cmp = icmp sgt i32 %x, 300
70+
; CHECK: %res = select i1 %cmp, i32 1, i32 2
71+
; CHECK: ret i32 %res
72+
define internal i32 @f3(i32 %x) {
73+
entry:
74+
%cmp = icmp sgt i32 %x, 300
75+
%res = select i1 %cmp, i32 1, i32 2
76+
ret i32 %res
77+
}
78+
79+
; The phi node could be converted in a ConstantRange.
80+
define i32 @caller2(i1 %cmp) {
81+
entry:
82+
br i1 %cmp, label %if.true, label %end
83+
84+
if.true:
85+
br label %end
86+
87+
end:
88+
%res = phi i32 [ 0, %entry], [ 1, %if.true ]
89+
%call1 = tail call i32 @f3(i32 %res)
90+
ret i32 %call1
91+
}
92+
93+
; CHECK-LABEL: f4
94+
; CHECK: %cmp = icmp sgt i32 %x, 300
95+
; CHECK: %res = select i1 %cmp, i32 1, i32 2
96+
; CHECK: ret i32 %res
97+
define internal i32 @f4(i32 %x) {
98+
entry:
99+
%cmp = icmp sgt i32 %x, 300
100+
%res = select i1 %cmp, i32 1, i32 2
101+
ret i32 %res
102+
}
103+
104+
; ICmp could introduce bounds on ConstantRanges.
105+
define i32 @caller3(i32 %x) {
106+
entry:
107+
%cmp = icmp sgt i32 %x, 300
108+
br i1 %cmp, label %if.true, label %end
109+
110+
if.true:
111+
%x.1 = tail call i32 @f4(i32 %x)
112+
br label %end
113+
114+
end:
115+
%res = phi i32 [ 0, %entry], [ %x.1, %if.true ]
116+
ret i32 %res
117+
}

0 commit comments

Comments
 (0)