[ModRefInfo] Return NoModRef for Must and NoModRef.

Summary:
In ModRefInfo "Must" was introduced to track presence of MustAlias, but we still want to return NoModRef when there is neither Mod or Ref, even when MustAlias is found. Patch has small fixes to ensure this happens.
Minor cleanup to remove nesting for 2 if statements when calling getModRefInfo for 2 ImmutableCallSites.

Reviewers: sanjoy

Subscribers: jlebar, llvm-commits

Differential Revision: https://reviews.llvm.org/D42209

llvm-svn: 322932
This commit is contained in:
Alina Sbirlea 2018-01-19 10:26:40 +00:00
parent 92c61a1032
commit d3b0b1a228
2 changed files with 74 additions and 65 deletions

View File

@ -126,7 +126,7 @@ ModRefInfo AAResults::getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) {
// Early-exit the moment we reach the bottom of the lattice.
if (isNoModRef(Result))
return Result;
return ModRefInfo::NoModRef;
}
return Result;
@ -162,7 +162,7 @@ ModRefInfo AAResults::getModRefInfo(ImmutableCallSite CS,
// Early-exit the moment we reach the bottom of the lattice.
if (isNoModRef(Result))
return Result;
return ModRefInfo::NoModRef;
}
// Try to refine the mod-ref info further using other API entry points to the
@ -224,7 +224,7 @@ ModRefInfo AAResults::getModRefInfo(ImmutableCallSite CS1,
// Early-exit the moment we reach the bottom of the lattice.
if (isNoModRef(Result))
return Result;
return ModRefInfo::NoModRef;
}
// Try to refine the mod-ref info further using other API entry points to the
@ -254,85 +254,91 @@ ModRefInfo AAResults::getModRefInfo(ImmutableCallSite CS1,
// information from CS1's references to the memory referenced by
// CS2's arguments.
if (onlyAccessesArgPointees(CS2B)) {
if (!doesAccessArgPointees(CS2B))
return ModRefInfo::NoModRef;
ModRefInfo R = ModRefInfo::NoModRef;
if (doesAccessArgPointees(CS2B)) {
bool IsMustAlias = true;
for (auto I = CS2.arg_begin(), E = CS2.arg_end(); I != E; ++I) {
const Value *Arg = *I;
if (!Arg->getType()->isPointerTy())
continue;
unsigned CS2ArgIdx = std::distance(CS2.arg_begin(), I);
auto CS2ArgLoc = MemoryLocation::getForArgument(CS2, CS2ArgIdx, TLI);
bool IsMustAlias = true;
for (auto I = CS2.arg_begin(), E = CS2.arg_end(); I != E; ++I) {
const Value *Arg = *I;
if (!Arg->getType()->isPointerTy())
continue;
unsigned CS2ArgIdx = std::distance(CS2.arg_begin(), I);
auto CS2ArgLoc = MemoryLocation::getForArgument(CS2, CS2ArgIdx, TLI);
// ArgModRefCS2 indicates what CS2 might do to CS2ArgLoc, and the
// dependence of CS1 on that location is the inverse:
// - If CS2 modifies location, dependence exists if CS1 reads or writes.
// - If CS2 only reads location, dependence exists if CS1 writes.
ModRefInfo ArgModRefCS2 = getArgModRefInfo(CS2, CS2ArgIdx);
ModRefInfo ArgMask = ModRefInfo::NoModRef;
if (isModSet(ArgModRefCS2))
ArgMask = ModRefInfo::ModRef;
else if (isRefSet(ArgModRefCS2))
ArgMask = ModRefInfo::Mod;
// ArgModRefCS2 indicates what CS2 might do to CS2ArgLoc, and the
// dependence of CS1 on that location is the inverse:
// - If CS2 modifies location, dependence exists if CS1 reads or writes.
// - If CS2 only reads location, dependence exists if CS1 writes.
ModRefInfo ArgModRefCS2 = getArgModRefInfo(CS2, CS2ArgIdx);
ModRefInfo ArgMask = ModRefInfo::NoModRef;
if (isModSet(ArgModRefCS2))
ArgMask = ModRefInfo::ModRef;
else if (isRefSet(ArgModRefCS2))
ArgMask = ModRefInfo::Mod;
// ModRefCS1 indicates what CS1 might do to CS2ArgLoc, and we use
// above ArgMask to update dependence info.
ModRefInfo ModRefCS1 = getModRefInfo(CS1, CS2ArgLoc);
ArgMask = intersectModRef(ArgMask, ModRefCS1);
// ModRefCS1 indicates what CS1 might do to CS2ArgLoc, and we use
// above ArgMask to update dependence info.
ModRefInfo ModRefCS1 = getModRefInfo(CS1, CS2ArgLoc);
ArgMask = intersectModRef(ArgMask, ModRefCS1);
// Conservatively clear IsMustAlias unless only MustAlias is found.
IsMustAlias &= isMustSet(ModRefCS1);
// Conservatively clear IsMustAlias unless only MustAlias is found.
IsMustAlias &= isMustSet(ModRefCS1);
R = intersectModRef(unionModRef(R, ArgMask), Result);
if (R == Result) {
// On early exit, not all args were checked, cannot set Must.
if (I + 1 != E)
IsMustAlias = false;
break;
}
R = intersectModRef(unionModRef(R, ArgMask), Result);
if (R == Result) {
// On early exit, not all args were checked, cannot set Must.
if (I + 1 != E)
IsMustAlias = false;
break;
}
// If Alias found and only MustAlias found above, set Must bit.
R = IsMustAlias ? setMust(R) : clearMust(R);
}
return R;
if (isNoModRef(R))
return ModRefInfo::NoModRef;
// If MustAlias found above, set Must bit.
return IsMustAlias ? setMust(R) : clearMust(R);
}
// If CS1 only accesses memory through arguments, check if CS2 references
// any of the memory referenced by CS1's arguments. If not, return NoModRef.
if (onlyAccessesArgPointees(CS1B)) {
if (!doesAccessArgPointees(CS1B))
return ModRefInfo::NoModRef;
ModRefInfo R = ModRefInfo::NoModRef;
if (doesAccessArgPointees(CS1B)) {
bool IsMustAlias = true;
for (auto I = CS1.arg_begin(), E = CS1.arg_end(); I != E; ++I) {
const Value *Arg = *I;
if (!Arg->getType()->isPointerTy())
continue;
unsigned CS1ArgIdx = std::distance(CS1.arg_begin(), I);
auto CS1ArgLoc = MemoryLocation::getForArgument(CS1, CS1ArgIdx, TLI);
bool IsMustAlias = true;
for (auto I = CS1.arg_begin(), E = CS1.arg_end(); I != E; ++I) {
const Value *Arg = *I;
if (!Arg->getType()->isPointerTy())
continue;
unsigned CS1ArgIdx = std::distance(CS1.arg_begin(), I);
auto CS1ArgLoc = MemoryLocation::getForArgument(CS1, CS1ArgIdx, TLI);
// ArgModRefCS1 indicates what CS1 might do to CS1ArgLoc; if CS1 might
// Mod CS1ArgLoc, 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.
ModRefInfo ArgModRefCS1 = getArgModRefInfo(CS1, CS1ArgIdx);
ModRefInfo ModRefCS2 = getModRefInfo(CS2, CS1ArgLoc);
if ((isModSet(ArgModRefCS1) && isModOrRefSet(ModRefCS2)) ||
(isRefSet(ArgModRefCS1) && isModSet(ModRefCS2)))
R = intersectModRef(unionModRef(R, ArgModRefCS1), Result);
// ArgModRefCS1 indicates what CS1 might do to CS1ArgLoc; if CS1 might
// Mod CS1ArgLoc, 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.
ModRefInfo ArgModRefCS1 = getArgModRefInfo(CS1, CS1ArgIdx);
ModRefInfo ModRefCS2 = getModRefInfo(CS2, CS1ArgLoc);
if ((isModSet(ArgModRefCS1) && isModOrRefSet(ModRefCS2)) ||
(isRefSet(ArgModRefCS1) && isModSet(ModRefCS2)))
R = intersectModRef(unionModRef(R, ArgModRefCS1), Result);
// Conservatively clear IsMustAlias unless only MustAlias is found.
IsMustAlias &= isMustSet(ModRefCS2);
// Conservatively clear IsMustAlias unless only MustAlias is found.
IsMustAlias &= isMustSet(ModRefCS2);
if (R == Result) {
// On early exit, not all args were checked, cannot set Must.
if (I + 1 != E)
IsMustAlias = false;
break;
}
if (R == Result) {
// On early exit, not all args were checked, cannot set Must.
if (I + 1 != E)
IsMustAlias = false;
break;
}
// If Alias found and only MustAlias found above, set Must bit.
R = IsMustAlias ? setMust(R) : clearMust(R);
}
return R;
if (isNoModRef(R))
return ModRefInfo::NoModRef;
// If MustAlias found above, set Must bit.
return IsMustAlias ? setMust(R) : clearMust(R);
}
return Result;

View File

@ -852,8 +852,11 @@ ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS,
IsMustAlias = false;
// Early return if we improved mod ref information
if (!isModAndRefSet(Result))
if (!isModAndRefSet(Result)) {
if (isNoModRef(Result))
return ModRefInfo::NoModRef;
return IsMustAlias ? setMust(Result) : clearMust(Result);
}
}
// If the CallSite is to malloc or calloc, we can assume that it doesn't