Skip to content

Commit 149241a

Browse files
committed
[Loads] Support dereferenceable assumption with variable size.
Update isDereferenceableAndAlignedPointer to make use of dereferenceable assumptions with variable sizes via SCEV. To do so, factor out the logic to check via an assumption to a helper, and use SE to check if the access size is less than the dereferenceable size.
1 parent f5d467c commit 149241a

File tree

4 files changed

+408
-5
lines changed

4 files changed

+408
-5
lines changed

llvm/include/llvm/Analysis/AssumeBundleQueries.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ LLVM_ABI void fillMapFromAssume(AssumeInst &Assume,
102102
struct RetainedKnowledge {
103103
Attribute::AttrKind AttrKind = Attribute::None;
104104
uint64_t ArgValue = 0;
105+
Value *IRArgValue = nullptr;
105106
Value *WasOn = nullptr;
106107
bool operator==(RetainedKnowledge Other) const {
107108
return AttrKind == Other.AttrKind && WasOn == Other.WasOn &&

llvm/lib/Analysis/AssumeBundleQueries.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ llvm::getKnowledgeFromBundle(AssumeInst &Assume,
114114
};
115115
if (BOI.End - BOI.Begin > ABA_Argument)
116116
Result.ArgValue = GetArgOr1(0);
117+
Result.IRArgValue = getValueFromBundleOpInfo(Assume, BOI, ABA_Argument);
117118
if (Result.AttrKind == Attribute::Alignment)
118119
if (BOI.End - BOI.Begin > ABA_Argument + 1)
119120
Result.ArgValue = MinAlign(Result.ArgValue, GetArgOr1(1));

llvm/lib/Analysis/Loads.cpp

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,35 @@ static bool isAligned(const Value *Base, Align Alignment,
3131
return Base->getPointerAlignment(DL) >= Alignment;
3232
}
3333

34+
static bool isDereferenceableAndAlignedPointerViaAssumption(
35+
const Value *Ptr, Align Alignment,
36+
function_ref<bool(const RetainedKnowledge &RK)> CheckSize,
37+
const DataLayout &DL, const Instruction *CtxI, AssumptionCache *AC,
38+
const DominatorTree *DT) {
39+
if (!CtxI || Ptr->canBeFreed())
40+
return false;
41+
/// Look through assumes to see if both dereferencability and alignment can
42+
/// be proven by an assume if needed.
43+
RetainedKnowledge AlignRK;
44+
RetainedKnowledge DerefRK;
45+
bool IsAligned = Ptr->getPointerAlignment(DL) >= Alignment;
46+
return getKnowledgeForValue(
47+
Ptr, {Attribute::Dereferenceable, Attribute::Alignment}, AC,
48+
[&](RetainedKnowledge RK, Instruction *Assume, auto) {
49+
if (!isValidAssumeForContext(Assume, CtxI, DT))
50+
return false;
51+
if (RK.AttrKind == Attribute::Alignment)
52+
AlignRK = std::max(AlignRK, RK);
53+
if (RK.AttrKind == Attribute::Dereferenceable)
54+
DerefRK = std::max(DerefRK, RK);
55+
IsAligned |= AlignRK && AlignRK.ArgValue >= Alignment.value();
56+
if (IsAligned && DerefRK && CheckSize(DerefRK))
57+
return true; // We have found what we needed so we stop looking
58+
return false; // Other assumes may have better information. so
59+
// keep looking
60+
});
61+
}
62+
3463
/// Test if V is always a pointer to allocated and suitably aligned memory for
3564
/// a simple load or store.
3665
static bool isDereferenceableAndAlignedPointer(
@@ -199,8 +228,12 @@ static bool isDereferenceableAndAlignedPointer(
199228
return true;
200229
}
201230

202-
// If we don't know, assume the worst.
203-
return false;
231+
return isDereferenceableAndAlignedPointerViaAssumption(
232+
V, Alignment,
233+
[Size](const RetainedKnowledge &RK) {
234+
return RK.ArgValue >= Size.getZExtValue();
235+
},
236+
DL, CtxI, AC, DT);
204237
}
205238

206239
bool llvm::isDereferenceableAndAlignedPointer(
@@ -317,8 +350,8 @@ bool llvm::isDereferenceableAndAlignedInLoop(
317350
return false;
318351

319352
const SCEV *MaxBECount =
320-
Predicates ? SE.getPredicatedConstantMaxBackedgeTakenCount(L, *Predicates)
321-
: SE.getConstantMaxBackedgeTakenCount(L);
353+
Predicates ? SE.getPredicatedSymbolicMaxBackedgeTakenCount(L, *Predicates)
354+
: SE.getSymbolicMaxBackedgeTakenCount(L);
322355
const SCEV *BECount = Predicates
323356
? SE.getPredicatedBackedgeTakenCount(L, *Predicates)
324357
: SE.getBackedgeTakenCount(L);
@@ -339,9 +372,11 @@ bool llvm::isDereferenceableAndAlignedInLoop(
339372

340373
Value *Base = nullptr;
341374
APInt AccessSize;
375+
const SCEV *AccessSizeSCEV = nullptr;
342376
if (const SCEVUnknown *NewBase = dyn_cast<SCEVUnknown>(AccessStart)) {
343377
Base = NewBase->getValue();
344378
AccessSize = MaxPtrDiff;
379+
AccessSizeSCEV = PtrDiff;
345380
} else if (auto *MinAdd = dyn_cast<SCEVAddExpr>(AccessStart)) {
346381
if (MinAdd->getNumOperands() != 2)
347382
return false;
@@ -365,12 +400,20 @@ bool llvm::isDereferenceableAndAlignedInLoop(
365400
return false;
366401

367402
AccessSize = MaxPtrDiff + Offset->getAPInt();
403+
AccessSizeSCEV = SE.getAddExpr(PtrDiff, Offset);
368404
Base = NewBase->getValue();
369405
} else
370406
return false;
371407

372408
Instruction *HeaderFirstNonPHI = &*L->getHeader()->getFirstNonPHIIt();
373-
return isDereferenceableAndAlignedPointer(Base, Alignment, AccessSize, DL,
409+
return isDereferenceableAndAlignedPointerViaAssumption(
410+
Base, Alignment,
411+
[&SE, PtrDiff](const RetainedKnowledge &RK) {
412+
return SE.isKnownPredicate(CmpInst::ICMP_ULE, PtrDiff,
413+
SE.getSCEV(RK.IRArgValue));
414+
},
415+
DL, HeaderFirstNonPHI, AC, &DT) ||
416+
isDereferenceableAndAlignedPointer(Base, Alignment, AccessSize, DL,
374417
HeaderFirstNonPHI, AC, &DT);
375418
}
376419

0 commit comments

Comments
 (0)