20
20
#include " llvm/Analysis/ValueLatticeUtils.h"
21
21
#include " llvm/Analysis/ValueTracking.h"
22
22
#include " llvm/IR/InstVisitor.h"
23
+ #include " llvm/IR/PatternMatch.h"
23
24
#include " llvm/Support/Casting.h"
24
25
#include " llvm/Support/Debug.h"
25
26
#include " llvm/Support/ErrorHandling.h"
30
31
#include < vector>
31
32
32
33
using namespace llvm ;
34
+ using namespace PatternMatch ;
33
35
34
36
#define DEBUG_TYPE " sccp"
35
37
@@ -83,20 +85,28 @@ bool SCCPSolver::tryToReplaceWithConstant(Value *V) {
83
85
return true ;
84
86
}
85
87
88
+ // / Helper for getting ranges from \p Solver. Instructions inserted during
89
+ // / simplification are unavailable in the solver, so we return a full range for
90
+ // / them.
91
+ static ConstantRange getRange (Value *Op, SCCPSolver &Solver,
92
+ const SmallPtrSetImpl<Value *> &InsertedValues) {
93
+ if (auto *Const = dyn_cast<Constant>(Op))
94
+ return Const->toConstantRange ();
95
+ if (InsertedValues.contains (Op)) {
96
+ unsigned Bitwidth = Op->getType ()->getScalarSizeInBits ();
97
+ return ConstantRange::getFull (Bitwidth);
98
+ }
99
+ return Solver.getLatticeValueFor (Op).asConstantRange (Op->getType (),
100
+ /* UndefAllowed=*/ false );
101
+ }
102
+
86
103
// / Try to use \p Inst's value range from \p Solver to infer the NUW flag.
87
104
static bool refineInstruction (SCCPSolver &Solver,
88
105
const SmallPtrSetImpl<Value *> &InsertedValues,
89
106
Instruction &Inst) {
90
107
bool Changed = false ;
91
108
auto GetRange = [&Solver, &InsertedValues](Value *Op) {
92
- if (auto *Const = dyn_cast<Constant>(Op))
93
- return Const->toConstantRange ();
94
- if (InsertedValues.contains (Op)) {
95
- unsigned Bitwidth = Op->getType ()->getScalarSizeInBits ();
96
- return ConstantRange::getFull (Bitwidth);
97
- }
98
- return Solver.getLatticeValueFor (Op).asConstantRange (
99
- Op->getType (), /* UndefAllowed=*/ false );
109
+ return getRange (Op, Solver, InsertedValues);
100
110
};
101
111
102
112
if (isa<OverflowingBinaryOperator>(Inst)) {
@@ -167,16 +177,8 @@ static bool replaceSignedInst(SCCPSolver &Solver,
167
177
SmallPtrSetImpl<Value *> &InsertedValues,
168
178
Instruction &Inst) {
169
179
// Determine if a signed value is known to be >= 0.
170
- auto isNonNegative = [&Solver](Value *V) {
171
- // If this value was constant-folded, it may not have a solver entry.
172
- // Handle integers. Otherwise, return false.
173
- if (auto *C = dyn_cast<Constant>(V)) {
174
- auto *CInt = dyn_cast<ConstantInt>(C);
175
- return CInt && !CInt->isNegative ();
176
- }
177
- const ValueLatticeElement &IV = Solver.getLatticeValueFor (V);
178
- return IV.isConstantRange (/* UndefAllowed=*/ false ) &&
179
- IV.getConstantRange ().isAllNonNegative ();
180
+ auto isNonNegative = [&Solver, &InsertedValues](Value *V) {
181
+ return getRange (V, Solver, InsertedValues).isAllNonNegative ();
180
182
};
181
183
182
184
Instruction *NewInst = nullptr ;
@@ -185,7 +187,7 @@ static bool replaceSignedInst(SCCPSolver &Solver,
185
187
case Instruction::SExt: {
186
188
// If the source value is not negative, this is a zext/uitofp.
187
189
Value *Op0 = Inst.getOperand (0 );
188
- if (InsertedValues. count (Op0) || !isNonNegative (Op0))
190
+ if (!isNonNegative (Op0))
189
191
return false ;
190
192
NewInst = CastInst::Create (Inst.getOpcode () == Instruction::SExt
191
193
? Instruction::ZExt
@@ -197,7 +199,7 @@ static bool replaceSignedInst(SCCPSolver &Solver,
197
199
case Instruction::AShr: {
198
200
// If the shifted value is not negative, this is a logical shift right.
199
201
Value *Op0 = Inst.getOperand (0 );
200
- if (InsertedValues. count (Op0) || !isNonNegative (Op0))
202
+ if (!isNonNegative (Op0))
201
203
return false ;
202
204
NewInst = BinaryOperator::CreateLShr (Op0, Inst.getOperand (1 ), " " , Inst.getIterator ());
203
205
NewInst->setIsExact (Inst.isExact ());
@@ -207,8 +209,7 @@ static bool replaceSignedInst(SCCPSolver &Solver,
207
209
case Instruction::SRem: {
208
210
// If both operands are not negative, this is the same as udiv/urem.
209
211
Value *Op0 = Inst.getOperand (0 ), *Op1 = Inst.getOperand (1 );
210
- if (InsertedValues.count (Op0) || InsertedValues.count (Op1) ||
211
- !isNonNegative (Op0) || !isNonNegative (Op1))
212
+ if (!isNonNegative (Op0) || !isNonNegative (Op1))
212
213
return false ;
213
214
auto NewOpcode = Inst.getOpcode () == Instruction::SDiv ? Instruction::UDiv
214
215
: Instruction::URem;
@@ -232,6 +233,26 @@ static bool replaceSignedInst(SCCPSolver &Solver,
232
233
return true ;
233
234
}
234
235
236
+ // / Try to use \p Inst's value range from \p Solver to simplify it.
237
+ static Value *simplifyInstruction (SCCPSolver &Solver,
238
+ SmallPtrSetImpl<Value *> &InsertedValues,
239
+ Instruction &Inst) {
240
+ auto GetRange = [&Solver, &InsertedValues](Value *Op) {
241
+ return getRange (Op, Solver, InsertedValues);
242
+ };
243
+
244
+ Value *X;
245
+ const APInt *RHSC;
246
+ // Remove masking operations.
247
+ if (match (&Inst, m_And (m_Value (X), m_LowBitMask (RHSC)))) {
248
+ ConstantRange LRange = GetRange (Inst.getOperand (0 ));
249
+ if (LRange.getUnsignedMax ().ule (*RHSC))
250
+ return X;
251
+ }
252
+
253
+ return nullptr ;
254
+ }
255
+
235
256
bool SCCPSolver::simplifyInstsInBlock (BasicBlock &BB,
236
257
SmallPtrSetImpl<Value *> &InsertedValues,
237
258
Statistic &InstRemovedStat,
@@ -251,6 +272,11 @@ bool SCCPSolver::simplifyInstsInBlock(BasicBlock &BB,
251
272
++InstReplacedStat;
252
273
} else if (refineInstruction (*this , InsertedValues, Inst)) {
253
274
MadeChanges = true ;
275
+ } else if (auto *V = simplifyInstruction (*this , InsertedValues, Inst)) {
276
+ Inst.replaceAllUsesWith (V);
277
+ Inst.eraseFromParent ();
278
+ ++InstRemovedStat;
279
+ MadeChanges = true ;
254
280
}
255
281
}
256
282
return MadeChanges;
0 commit comments