Skip to content

Commit e82b5b5

Browse files
committed
[ConstraintElimination] Add Decomposition struct (NFCI)
Replace the vector of DecompEntry with a struct that stores the constant offset separately. I think this is cleaner than giving the first element special handling. This probably also fixes some potential ubsan errors by more consistently using addWithOverflow/multiplyWithOverflow.
1 parent 30982a5 commit e82b5b5

File tree

1 file changed

+76
-61
lines changed

1 file changed

+76
-61
lines changed

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 76 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,20 @@ DEBUG_COUNTER(EliminatedCounter, "conds-eliminated",
4848
static int64_t MaxConstraintValue = std::numeric_limits<int64_t>::max();
4949
static int64_t MinSignedConstraintValue = std::numeric_limits<int64_t>::min();
5050

51+
// A helper to multiply 2 signed integers where overflowing is allowed.
52+
static int64_t multiplyWithOverflow(int64_t A, int64_t B) {
53+
int64_t Result;
54+
MulOverflow(A, B, Result);
55+
return Result;
56+
}
57+
58+
// A helper to add 2 signed integers where overflowing is allowed.
59+
static int64_t addWithOverflow(int64_t A, int64_t B) {
60+
int64_t Result;
61+
AddOverflow(A, B, Result);
62+
return Result;
63+
}
64+
5165
namespace {
5266

5367
class ConstraintInfo;
@@ -178,42 +192,55 @@ struct DecompEntry {
178192
IsKnownPositive(IsKnownPositive) {}
179193
};
180194

195+
/// Represents an Offset + Coefficient1 * Variable1 + ... decomposition.
196+
struct Decomposition {
197+
int64_t Offset = 0;
198+
SmallVector<DecompEntry, 3> Vars;
199+
200+
Decomposition(int64_t Offset) : Offset(Offset) {}
201+
Decomposition(Value *V, bool IsKnownPositive = false) {
202+
Vars.emplace_back(1, V, IsKnownPositive);
203+
}
204+
Decomposition(int64_t Offset, ArrayRef<DecompEntry> Vars)
205+
: Offset(Offset), Vars(Vars) {}
206+
207+
void add(int64_t OtherOffset) {
208+
Offset = addWithOverflow(Offset, OtherOffset);
209+
}
210+
211+
void add(const Decomposition &Other) {
212+
add(Other.Offset);
213+
append_range(Vars, Other.Vars);
214+
}
215+
216+
void mul(int64_t Factor) {
217+
Offset = multiplyWithOverflow(Offset, Factor);
218+
for (auto &Var : Vars)
219+
Var.Coefficient = multiplyWithOverflow(Var.Coefficient, Factor);
220+
}
221+
};
222+
181223
} // namespace
182224

183-
static SmallVector<DecompEntry, 4>
184-
decompose(Value *V, SmallVector<PreconditionTy, 4> &Preconditions,
185-
bool IsSigned, const DataLayout &DL);
225+
static Decomposition decompose(Value *V,
226+
SmallVector<PreconditionTy, 4> &Preconditions,
227+
bool IsSigned, const DataLayout &DL);
186228

187229
static bool canUseSExt(ConstantInt *CI) {
188230
const APInt &Val = CI->getValue();
189231
return Val.sgt(MinSignedConstraintValue) && Val.slt(MaxConstraintValue);
190232
}
191233

192-
// A helper to multiply 2 signed integers where overflowing is allowed.
193-
static int64_t multiplyWithOverflow(int64_t A, int64_t B) {
194-
int64_t Result;
195-
MulOverflow(A, B, Result);
196-
return Result;
197-
}
198-
199-
// A helper to add 2 signed integers where overflowing is allowed.
200-
static int64_t addWithOverflow(int64_t A, int64_t B) {
201-
int64_t Result;
202-
AddOverflow(A, B, Result);
203-
return Result;
204-
}
205-
206-
static SmallVector<DecompEntry, 4>
207-
decomposeGEP(GetElementPtrInst &GEP,
208-
SmallVector<PreconditionTy, 4> &Preconditions, bool IsSigned,
209-
const DataLayout &DL) {
234+
static Decomposition decomposeGEP(GetElementPtrInst &GEP,
235+
SmallVector<PreconditionTy, 4> &Preconditions,
236+
bool IsSigned, const DataLayout &DL) {
210237
// Do not reason about pointers where the index size is larger than 64 bits,
211238
// as the coefficients used to encode constraints are 64 bit integers.
212239
if (DL.getIndexTypeSizeInBits(GEP.getPointerOperand()->getType()) > 64)
213-
return {{0, nullptr}, {1, &GEP}};
240+
return &GEP;
214241

215242
if (!GEP.isInBounds())
216-
return {{0, nullptr}, {1, &GEP}};
243+
return &GEP;
217244

218245
// Handle the (gep (gep ....), C) case by incrementing the constant
219246
// coefficient of the inner GEP, if C is a constant.
@@ -226,13 +253,11 @@ decomposeGEP(GetElementPtrInst &GEP,
226253
auto GTI = gep_type_begin(GEP);
227254
// Bail out for scalable vectors for now.
228255
if (isa<ScalableVectorType>(GTI.getIndexedType()))
229-
return {{0, nullptr}, {1, &GEP}};
256+
return &GEP;
230257
int64_t Scale = static_cast<int64_t>(
231258
DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize());
232259

233-
Result[0].Coefficient =
234-
addWithOverflow(Result[0].Coefficient,
235-
multiplyWithOverflow(Scale, Offset.getSExtValue()));
260+
Result.add(multiplyWithOverflow(Scale, Offset.getSExtValue()));
236261
if (Offset.isNegative()) {
237262
// Add pre-condition ensuring the GEP is increasing monotonically and
238263
// can be de-composed.
@@ -244,16 +269,15 @@ decomposeGEP(GetElementPtrInst &GEP,
244269
return Result;
245270
}
246271

247-
SmallVector<DecompEntry, 4> Result = {{0, nullptr},
248-
{1, GEP.getPointerOperand()}};
272+
Decomposition Result = GEP.getPointerOperand();
249273
gep_type_iterator GTI = gep_type_begin(GEP);
250274
for (User::const_op_iterator I = GEP.op_begin() + 1, E = GEP.op_end(); I != E;
251275
++I, ++GTI) {
252276
Value *Index = *I;
253277

254278
// Bail out for scalable vectors for now.
255279
if (isa<ScalableVectorType>(GTI.getIndexedType()))
256-
return {{0, nullptr}, {1, &GEP}};
280+
return &GEP;
257281

258282
// Struct indices must be constants (and reference an existing field). Add
259283
// them to the constant factor.
@@ -264,20 +288,16 @@ decomposeGEP(GetElementPtrInst &GEP,
264288
continue;
265289

266290
// Add offset to constant factor.
267-
Result[0].Coefficient = addWithOverflow(
268-
Result[0].Coefficient,
269-
int64_t(DL.getStructLayout(STy)->getElementOffset(FieldNo)));
291+
Result.add(int64_t(DL.getStructLayout(STy)->getElementOffset(FieldNo)));
270292
continue;
271293
}
272294

273295
// For an array/pointer, add the element offset, explicitly scaled.
274296
unsigned Scale = DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize();
275297

276298
auto IdxResult = decompose(Index, Preconditions, IsSigned, DL);
277-
for (auto &KV : IdxResult)
278-
KV.Coefficient = multiplyWithOverflow(KV.Coefficient, Scale);
279-
Result[0].Coefficient += IdxResult[0].Coefficient;
280-
append_range(Result, ArrayRef<DecompEntry>(IdxResult).drop_front());
299+
IdxResult.mul(Scale);
300+
Result.add(IdxResult);
281301

282302
// If Op0 is signed non-negative, the GEP is increasing monotonically and
283303
// can be de-composed.
@@ -292,38 +312,36 @@ decomposeGEP(GetElementPtrInst &GEP,
292312
// } where Coefficient * Variable. The sum of the pairs equals \p V. The first
293313
// pair is the constant-factor and X must be nullptr. If the expression cannot
294314
// be decomposed, returns an empty vector.
295-
static SmallVector<DecompEntry, 4>
296-
decompose(Value *V, SmallVector<PreconditionTy, 4> &Preconditions,
297-
bool IsSigned, const DataLayout &DL) {
315+
static Decomposition decompose(Value *V,
316+
SmallVector<PreconditionTy, 4> &Preconditions,
317+
bool IsSigned, const DataLayout &DL) {
298318

299-
auto MergeResults = [&Preconditions, IsSigned,
300-
&DL](Value *A, Value *B,
301-
bool IsSignedB) -> SmallVector<DecompEntry, 4> {
319+
auto MergeResults = [&Preconditions, IsSigned, &DL](Value *A, Value *B,
320+
bool IsSignedB) {
302321
auto ResA = decompose(A, Preconditions, IsSigned, DL);
303322
auto ResB = decompose(B, Preconditions, IsSignedB, DL);
304-
ResA[0].Coefficient += ResB[0].Coefficient;
305-
append_range(ResA, drop_begin(ResB));
323+
ResA.add(ResB);
306324
return ResA;
307325
};
308326

309327
// Decompose \p V used with a signed predicate.
310328
if (IsSigned) {
311329
if (auto *CI = dyn_cast<ConstantInt>(V)) {
312330
if (canUseSExt(CI))
313-
return {{CI->getSExtValue(), nullptr}};
331+
return CI->getSExtValue();
314332
}
315333
Value *Op0;
316334
Value *Op1;
317335
if (match(V, m_NSWAdd(m_Value(Op0), m_Value(Op1))))
318336
return MergeResults(Op0, Op1, IsSigned);
319337

320-
return {{0, nullptr}, {1, V}};
338+
return V;
321339
}
322340

323341
if (auto *CI = dyn_cast<ConstantInt>(V)) {
324342
if (CI->uge(MaxConstraintValue))
325-
return {{0, nullptr}, {1, V}};
326-
return {{int64_t(CI->getZExtValue()), nullptr}};
343+
return V;
344+
return int64_t(CI->getZExtValue());
327345
}
328346

329347
if (auto *GEP = dyn_cast<GetElementPtrInst>(V))
@@ -363,25 +381,23 @@ decompose(Value *V, SmallVector<PreconditionTy, 4> &Preconditions,
363381
if (match(V, m_NUWShl(m_Value(Op1), m_ConstantInt(CI))) && canUseSExt(CI)) {
364382
int64_t Mult = int64_t(std::pow(int64_t(2), CI->getSExtValue()));
365383
auto Result = decompose(Op1, Preconditions, IsSigned, DL);
366-
for (auto &KV : Result)
367-
KV.Coefficient *= Mult;
384+
Result.mul(Mult);
368385
return Result;
369386
}
370387

371388
if (match(V, m_NUWMul(m_Value(Op1), m_ConstantInt(CI))) && canUseSExt(CI) &&
372389
(!CI->isNegative())) {
373390
auto Result = decompose(Op1, Preconditions, IsSigned, DL);
374-
for (auto &KV : Result)
375-
KV.Coefficient *= CI->getSExtValue();
391+
Result.mul(CI->getSExtValue());
376392
return Result;
377393
}
378394

379395
if (match(V, m_NUWSub(m_Value(Op0), m_ConstantInt(CI))) && canUseSExt(CI))
380-
return {{-1 * CI->getSExtValue(), nullptr}, {1, Op0}};
396+
return {-1 * CI->getSExtValue(), {{1, Op0}}};
381397
if (match(V, m_NUWSub(m_Value(Op0), m_Value(Op1))))
382-
return {{0, nullptr}, {1, Op0}, {-1, Op1}};
398+
return {0, {{1, Op0}, {-1, Op1}}};
383399

384-
return {{0, nullptr}, {1, V, IsKnownPositive}};
400+
return {V, IsKnownPositive};
385401
}
386402

387403
ConstraintTy
@@ -429,13 +445,12 @@ ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
429445
Preconditions, IsSigned, DL);
430446
auto BDec = decompose(Op1->stripPointerCastsSameRepresentation(),
431447
Preconditions, IsSigned, DL);
432-
int64_t Offset1 = ADec[0].Coefficient;
433-
int64_t Offset2 = BDec[0].Coefficient;
448+
int64_t Offset1 = ADec.Offset;
449+
int64_t Offset2 = BDec.Offset;
434450
Offset1 *= -1;
435451

436-
// Create iterator ranges that skip the constant-factor.
437-
auto VariablesA = llvm::drop_begin(ADec);
438-
auto VariablesB = llvm::drop_begin(BDec);
452+
auto &VariablesA = ADec.Vars;
453+
auto &VariablesB = BDec.Vars;
439454

440455
// First try to look up \p V in Value2Index and NewVariables. Otherwise add a
441456
// new entry to NewVariables.

0 commit comments

Comments
 (0)