diff options
author | David Majnemer <david.majnemer@gmail.com> | 2016-05-26 17:36:22 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2016-05-26 17:36:22 +0000 |
commit | 7f32420ed520ae6298900e8a50109c265c4dba85 (patch) | |
tree | 290bb48234b9f84f2101b6fd8dced8e6e372ec41 /llvm/lib | |
parent | 686c70c3dc951d6f4b9c09197171f10ac25189f6 (diff) | |
download | bcm5719-llvm-7f32420ed520ae6298900e8a50109c265c4dba85.tar.gz bcm5719-llvm-7f32420ed520ae6298900e8a50109c265c4dba85.zip |
[CaptureTracking] Volatile operations capture their memory location
The memory location that corresponds to a volatile operation is very
special. They are observed by the machine in ways which we cannot
reason about.
Differential Revision: http://reviews.llvm.org/D20555
llvm-svn: 270879
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/CaptureTracking.cpp | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/llvm/lib/Analysis/CaptureTracking.cpp b/llvm/lib/Analysis/CaptureTracking.cpp index 5997975085b..9862c3c9c27 100644 --- a/llvm/lib/Analysis/CaptureTracking.cpp +++ b/llvm/lib/Analysis/CaptureTracking.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" using namespace llvm; @@ -242,6 +243,13 @@ void llvm::PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker) { if (CS.onlyReadsMemory() && CS.doesNotThrow() && I->getType()->isVoidTy()) break; + // Volatile operations effectively capture the memory location that they + // load and store to. + if (auto *MI = dyn_cast<MemIntrinsic>(I)) + if (MI->isVolatile()) + if (Tracker->captured(U)) + return; + // Not captured if only passed via 'nocapture' arguments. Note that // calling a function pointer does not in itself cause the pointer to // be captured. This is a subtle point considering that (for example) @@ -259,29 +267,46 @@ void llvm::PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker) { break; } case Instruction::Load: - // Loading from a pointer does not cause it to be captured. + // Volatile loads make the address observable. + if (cast<LoadInst>(I)->isVolatile()) + if (Tracker->captured(U)) + return; break; case Instruction::VAArg: // "va-arg" from a pointer does not cause it to be captured. break; case Instruction::Store: - if (V == I->getOperand(0)) // Stored the pointer - conservatively assume it may be captured. + // Volatile stores make the address observable. + if (V == I->getOperand(0) || cast<StoreInst>(I)->isVolatile()) if (Tracker->captured(U)) return; - // Storing to the pointee does not cause the pointer to be captured. break; - case Instruction::AtomicRMW: - case Instruction::AtomicCmpXchg: - // atomicrmw and cmpxchg conceptually include both a load and store from - // the same location. As with a store, the location being accessed is - // not captured, but the value being stored is. (For cmpxchg, we - // probably don't need to capture the original comparison value, but for - // the moment, let's be conservative.) - if (V != I->getOperand(0)) + case Instruction::AtomicRMW: { + // atomicrmw conceptually includes both a load and store from + // the same location. + // As with a store, the location being accessed is not captured, + // but the value being stored is. + // Volatile stores make the address observable. + auto *ARMWI = cast<AtomicRMWInst>(I); + if (ARMWI->getValOperand() == V || ARMWI->isVolatile()) if (Tracker->captured(U)) return; break; + } + case Instruction::AtomicCmpXchg: { + // cmpxchg conceptually includes both a load and store from + // the same location. + // As with a store, the location being accessed is not captured, + // but the value being stored is. + // Volatile stores make the address observable. + auto *ACXI = cast<AtomicCmpXchgInst>(I); + if (ACXI->getCompareOperand() == V || ACXI->getNewValOperand() == V || + ACXI->isVolatile()) + if (Tracker->captured(U)) + return; + break; + } case Instruction::BitCast: case Instruction::GetElementPtr: case Instruction::PHI: |