/// Return true if this instruction may throw an exception.
bool mayThrow() const;
+ /// Return true if this instruction behaves like a memory fence: it can load
+ /// or store to memory location without being given a memory location.
+ bool isFenceLike() const {
+ switch (getOpcode()) {
+ default:
+ return false;
+ // This list should be kept in sync with the list in mayWriteToMemory for
+ // all opcodes which don't have a memory location.
+ case Instruction::Fence:
+ case Instruction::CatchPad:
+ case Instruction::CatchRet:
+ case Instruction::Call:
+ case Instruction::Invoke:
+ return true;
+ }
+ }
+
/// Return true if the instruction may have side effects.
///
/// Note that this does not consider malloc and alloca to have side
if (auto CS = ImmutableCallSite(I)) {
// Check if the two calls modify the same memory
return getModRefInfo(CS, Call);
+ } else if (I->isFenceLike()) {
+ // If this is a fence, just return MRI_ModRef.
+ return MRI_ModRef;
} else {
// Otherwise, check if the call modifies or references the
// location this memory access defines. The best we can say
// Conservatively, fences are always clobbers, so don't perform the walk if we
// hit a fence.
- if (isa<FenceInst>(I))
+ if (!ImmutableCallSite(I) && I->isFenceLike())
return StartingUseOrDef;
UpwardsMemoryQuery Q;
// access, since we only map BB's to PHI's. So, this must be a use or def.
auto *StartingAccess = cast<MemoryUseOrDef>(MSSA->getMemoryAccess(I));
- // We can't sanely do anything with a FenceInst, they conservatively
+ bool IsCall = bool(ImmutableCallSite(I));
+
+ // We can't sanely do anything with a fences, they conservatively
// clobber all memory, and have no locations to get pointers from to
- // try to disambiguate
- if (isa<FenceInst>(I))
+ // try to disambiguate.
+ if (!IsCall && I->isFenceLike())
return StartingAccess;
UpwardsMemoryQuery Q;
Q.OriginalAccess = StartingAccess;
- Q.IsCall = bool(ImmutableCallSite(I));
+ Q.IsCall = IsCall;
if (!Q.IsCall)
Q.StartingLoc = MemoryLocation::get(I);
Q.Inst = I;