-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[LV] Compute SCEV for memcheck before unlinking #160326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -575,10 +575,13 @@ LLVM_ABI Loop *cloneLoop(Loop *L, Loop *PL, ValueToValueMapTy &VM, LoopInfo *LI, | |
|
||
/// Add code that checks at runtime if the accessed arrays in \p PointerChecks | ||
/// overlap. Returns the final comparator value or NULL if no check is needed. | ||
/// If \p HoistRuntimeChecks and \p TheLoop has a parent, sets \p | ||
/// AllChecksHoisted when all checks are outer-loop invariant (hoistable). | ||
LLVM_ABI Value * | ||
addRuntimeChecks(Instruction *Loc, Loop *TheLoop, | ||
const SmallVectorImpl<RuntimePointerCheck> &PointerChecks, | ||
SCEVExpander &Expander, bool HoistRuntimeChecks = false); | ||
SCEVExpander &Expander, bool HoistRuntimeChecks, | ||
bool &AllChecksHoisted); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be possible/better to return this together with the runtime check using std::pair<> or somerhing like that? |
||
|
||
LLVM_ABI Value *addDiffRuntimeChecks( | ||
Instruction *Loc, ArrayRef<PointerDiffInfo> Checks, SCEVExpander &Expander, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2038,13 +2038,16 @@ expandBounds(const SmallVectorImpl<RuntimePointerCheck> &PointerChecks, Loop *L, | |
Value *llvm::addRuntimeChecks( | ||
Instruction *Loc, Loop *TheLoop, | ||
const SmallVectorImpl<RuntimePointerCheck> &PointerChecks, | ||
SCEVExpander &Exp, bool HoistRuntimeChecks) { | ||
SCEVExpander &Exp, bool HoistRuntimeChecks, bool &AllChecksHoisted) { | ||
// TODO: Move noalias annotation code from LoopVersioning here and share with LV if possible. | ||
// TODO: Pass RtPtrChecking instead of PointerChecks and SE separately, if possible | ||
auto ExpandedChecks = | ||
expandBounds(PointerChecks, TheLoop, Loc, Exp, HoistRuntimeChecks); | ||
|
||
LLVMContext &Ctx = Loc->getContext(); | ||
auto *SE = Exp.getSE(); | ||
auto *OuterLoop = TheLoop->getParentLoop(); | ||
AllChecksHoisted = HoistRuntimeChecks && OuterLoop != nullptr; | ||
IRBuilder ChkBuilder(Ctx, InstSimplifyFolder(Loc->getDataLayout())); | ||
ChkBuilder.SetInsertPoint(Loc); | ||
// Our instructions might fold to a constant. | ||
|
@@ -2083,6 +2086,20 @@ Value *llvm::addRuntimeChecks( | |
"stride.check"); | ||
IsConflict = ChkBuilder.CreateOr(IsConflict, IsNegativeStride); | ||
} | ||
|
||
if (AllChecksHoisted) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure all these checks are necessary. Can't you just do a single check at the very end before we return from the function, i.e.
|
||
AllChecksHoisted &= SE->isLoopInvariant(SE->getSCEV(A.Start), OuterLoop); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we avoid going from IR value -> SCEV and just check the entries in Constructing SCEVs here for values that may be removed later may leave dangling IR value entries in the SCEV expression cache? |
||
AllChecksHoisted &= SE->isLoopInvariant(SE->getSCEV(B.Start), OuterLoop); | ||
AllChecksHoisted &= SE->isLoopInvariant(SE->getSCEV(A.End), OuterLoop); | ||
AllChecksHoisted &= SE->isLoopInvariant(SE->getSCEV(B.End), OuterLoop); | ||
if (A.StrideToCheck) | ||
AllChecksHoisted &= | ||
SE->isLoopInvariant(SE->getSCEV(A.StrideToCheck), OuterLoop); | ||
if (B.StrideToCheck) | ||
AllChecksHoisted &= | ||
SE->isLoopInvariant(SE->getSCEV(B.StrideToCheck), OuterLoop); | ||
} | ||
|
||
if (MemoryRuntimeCheck) { | ||
IsConflict = | ||
ChkBuilder.CreateOr(MemoryRuntimeCheck, IsConflict, "conflict.rdx"); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1763,6 +1763,10 @@ class GeneratedRTChecks { | |
/// If it is nullptr no memory runtime checks have been generated. | ||
Value *MemRuntimeCheckCond = nullptr; | ||
|
||
/// True if memory checks are outer-loop invariant (hoistable). | ||
/// Used to discount check cost for inner loops. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Perhaps clearer written as 'Used to discount the cost of performing runtime checks for inner loops'? |
||
bool AllChecksHoisted = false; | ||
igogo-x86 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
DominatorTree *DT; | ||
LoopInfo *LI; | ||
TargetTransformInfo *TTI; | ||
|
@@ -1845,7 +1849,8 @@ class GeneratedRTChecks { | |
} else { | ||
MemRuntimeCheckCond = addRuntimeChecks( | ||
MemCheckBlock->getTerminator(), L, RtPtrChecking.getChecks(), | ||
MemCheckExp, VectorizerParams::HoistRuntimeChecks); | ||
MemCheckExp, VectorizerParams::HoistRuntimeChecks, | ||
AllChecksHoisted); | ||
} | ||
assert(MemRuntimeCheckCond && | ||
"no RT checks generated although RtPtrChecking " | ||
|
@@ -1928,13 +1933,11 @@ class GeneratedRTChecks { | |
// the checks will likely be hoisted out and so the effective cost will | ||
// reduce according to the outer loop trip count. | ||
if (OuterLoop) { | ||
ScalarEvolution *SE = MemCheckExp.getSE(); | ||
// TODO: If profitable, we could refine this further by analysing every | ||
// individual memory check, since there could be a mixture of loop | ||
// variant and invariant checks that mean the final condition is | ||
// variant. | ||
const SCEV *Cond = SE->getSCEV(MemRuntimeCheckCond); | ||
if (SE->isLoopInvariant(Cond, OuterLoop)) { | ||
if (AllChecksHoisted) { | ||
// It seems reasonable to assume that we can reduce the effective | ||
// cost of the checks even when we know nothing about the trip | ||
// count. Assume that the outer loop executes at least twice. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Perhaps this should be something like:
What do you think?