mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-24 23:28:41 +00:00
Improve BasicAA CS-CS queries (redux)
This reverts, "r213024 - Revert r212572 "improve BasicAA CS-CS queries", it causes PR20303." with a fix for the bug in pr20303. As it turned out, the relevant code was both wrong and over-conservative (because, as with the code it replaced, it would return the overall ModRef mask even if just Ref had been implied by the argument aliasing results). Hopefully, this correctly fixes both problems. Thanks to Nick Lewycky for reducing the test case for pr20303 (which I've cleaned up a little and added in DSE's test directory). The BasicAA test has also been updated to check for this error. Original commit message: BasicAA contains knowledge of certain intrinsics, such as memcpy and memset, and uses that information to form more-accurate answers to CallSite vs. Loc ModRef queries. Unfortunately, it did not use this information when answering CallSite vs. CallSite queries. Generically, when an intrinsic takes one or more pointers and the intrinsic is marked only to read/write from its arguments, the offset/size is unknown. As a result, the generic code that answers CallSite vs. CallSite (and CallSite vs. Loc) queries in AA uses UnknownSize when forming Locs from an intrinsic's arguments. While BasicAA's CallSite vs. Loc override could use more-accurate size information for some intrinsics, it did not do the same for CallSite vs. CallSite queries. This change refactors the intrinsic-specific logic in BasicAA into a generic AA query function: getArgLocation, which is overridden by BasicAA to supply the intrinsic-specific knowledge, and used by AA's generic implementation. This allows the intrinsic-specific knowledge to be used by both CallSite vs. Loc and CallSite vs. CallSite queries, and simplifies the BasicAA implementation. Currently, only one function, Mac's memset_pattern16, is handled by BasicAA (all the rest are intrinsics). As a side-effect of this refactoring, BasicAA's getModRefBehavior override now also returns OnlyAccessesArgumentPointees for this function (which is an improvement). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213219 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -60,6 +60,13 @@ bool AliasAnalysis::pointsToConstantMemory(const Location &Loc,
|
||||
return AA->pointsToConstantMemory(Loc, OrLocal);
|
||||
}
|
||||
|
||||
AliasAnalysis::Location
|
||||
AliasAnalysis::getArgLocation(ImmutableCallSite CS, unsigned ArgIdx,
|
||||
AliasAnalysis::ModRefResult &Mask) {
|
||||
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
|
||||
return AA->getArgLocation(CS, ArgIdx, Mask);
|
||||
}
|
||||
|
||||
void AliasAnalysis::deleteValue(Value *V) {
|
||||
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
|
||||
AA->deleteValue(V);
|
||||
@@ -91,22 +98,26 @@ AliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
|
||||
if (onlyAccessesArgPointees(MRB)) {
|
||||
bool doesAlias = false;
|
||||
ModRefResult AllArgsMask = NoModRef;
|
||||
if (doesAccessArgPointees(MRB)) {
|
||||
MDNode *CSTag = CS.getInstruction()->getMetadata(LLVMContext::MD_tbaa);
|
||||
for (ImmutableCallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
|
||||
AI != AE; ++AI) {
|
||||
const Value *Arg = *AI;
|
||||
if (!Arg->getType()->isPointerTy())
|
||||
continue;
|
||||
Location CSLoc(Arg, UnknownSize, CSTag);
|
||||
ModRefResult ArgMask;
|
||||
Location CSLoc =
|
||||
getArgLocation(CS, (unsigned) std::distance(CS.arg_begin(), AI),
|
||||
ArgMask);
|
||||
if (!isNoAlias(CSLoc, Loc)) {
|
||||
doesAlias = true;
|
||||
break;
|
||||
AllArgsMask = ModRefResult(AllArgsMask | ArgMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!doesAlias)
|
||||
return NoModRef;
|
||||
Mask = ModRefResult(Mask & AllArgsMask);
|
||||
}
|
||||
|
||||
// If Loc is a constant memory location, the call definitely could not
|
||||
@@ -150,14 +161,23 @@ AliasAnalysis::getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) {
|
||||
if (onlyAccessesArgPointees(CS2B)) {
|
||||
AliasAnalysis::ModRefResult R = NoModRef;
|
||||
if (doesAccessArgPointees(CS2B)) {
|
||||
MDNode *CS2Tag = CS2.getInstruction()->getMetadata(LLVMContext::MD_tbaa);
|
||||
for (ImmutableCallSite::arg_iterator
|
||||
I = CS2.arg_begin(), E = CS2.arg_end(); I != E; ++I) {
|
||||
const Value *Arg = *I;
|
||||
if (!Arg->getType()->isPointerTy())
|
||||
continue;
|
||||
Location CS2Loc(Arg, UnknownSize, CS2Tag);
|
||||
R = ModRefResult((R | getModRefInfo(CS1, CS2Loc)) & Mask);
|
||||
ModRefResult ArgMask;
|
||||
Location CS2Loc =
|
||||
getArgLocation(CS2, (unsigned) std::distance(CS2.arg_begin(), I),
|
||||
ArgMask);
|
||||
// ArgMask indicates what CS2 might do to CS2Loc, and the dependence of
|
||||
// CS1 on that location is the inverse.
|
||||
if (ArgMask == Mod)
|
||||
ArgMask = ModRef;
|
||||
else if (ArgMask == Ref)
|
||||
ArgMask = Mod;
|
||||
|
||||
R = ModRefResult((R | (getModRefInfo(CS1, CS2Loc) & ArgMask)) & Mask);
|
||||
if (R == Mask)
|
||||
break;
|
||||
}
|
||||
@@ -170,21 +190,28 @@ AliasAnalysis::getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) {
|
||||
if (onlyAccessesArgPointees(CS1B)) {
|
||||
AliasAnalysis::ModRefResult R = NoModRef;
|
||||
if (doesAccessArgPointees(CS1B)) {
|
||||
MDNode *CS1Tag = CS1.getInstruction()->getMetadata(LLVMContext::MD_tbaa);
|
||||
for (ImmutableCallSite::arg_iterator
|
||||
I = CS1.arg_begin(), E = CS1.arg_end(); I != E; ++I) {
|
||||
const Value *Arg = *I;
|
||||
if (!Arg->getType()->isPointerTy())
|
||||
continue;
|
||||
Location CS1Loc(Arg, UnknownSize, CS1Tag);
|
||||
if (getModRefInfo(CS2, CS1Loc) != NoModRef) {
|
||||
R = Mask;
|
||||
ModRefResult ArgMask;
|
||||
Location CS1Loc =
|
||||
getArgLocation(CS1, (unsigned) std::distance(CS1.arg_begin(), I),
|
||||
ArgMask);
|
||||
// ArgMask indicates what CS1 might do to CS1Loc; if CS1 might Mod
|
||||
// CS1Loc, then we care about either a Mod or a Ref by CS2. If CS1
|
||||
// might Ref, then we care only about a Mod by CS2.
|
||||
ModRefResult ArgR = getModRefInfo(CS2, CS1Loc);
|
||||
if (((ArgMask & Mod) != NoModRef && (ArgR & ModRef) != NoModRef) ||
|
||||
((ArgMask & Ref) != NoModRef && (ArgR & Mod) != NoModRef))
|
||||
R = ModRefResult((R | ArgMask) & Mask);
|
||||
|
||||
if (R == Mask)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (R == NoModRef)
|
||||
return R;
|
||||
return R;
|
||||
}
|
||||
|
||||
// If this is the end of the chain, don't forward.
|
||||
|
Reference in New Issue
Block a user