diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h index e9ea6c6d86c34..c9d48088ab899 100644 --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -5310,6 +5310,10 @@ class AddrSpaceCastInst : public CastInst { } }; +//===----------------------------------------------------------------------===// +// Helper functions +//===----------------------------------------------------------------------===// + /// A helper function that returns the pointer operand of a load or store /// instruction. Returns nullptr if not load or store. inline const Value *getLoadStorePointerOperand(const Value *V) { @@ -5365,6 +5369,24 @@ inline Type *getLoadStoreType(Value *I) { return cast(I)->getValueOperand()->getType(); } +/// A helper function that returns an atomic operation's sync scope; returns +/// None if it is not an atomic operation. +inline Optional getAtomicSyncScopeID(const Instruction *I) { + if (!I->isAtomic()) + return None; + if (auto *AI = dyn_cast(I)) + return AI->getSyncScopeID(); + if (auto *AI = dyn_cast(I)) + return AI->getSyncScopeID(); + if (auto *AI = dyn_cast(I)) + return AI->getSyncScopeID(); + if (auto *AI = dyn_cast(I)) + return AI->getSyncScopeID(); + if (auto *AI = dyn_cast(I)) + return AI->getSyncScopeID(); + llvm_unreachable("unhandled atomic operation"); +} + //===----------------------------------------------------------------------===// // FreezeInst Class //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp index cd1e8541c40fb..ade0316f5a4e2 100644 --- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp @@ -526,19 +526,14 @@ void ThreadSanitizer::chooseInstructionsToInstrument( Local.clear(); } -static bool isAtomic(Instruction *I) { +static bool isTsanAtomic(const Instruction *I) { // TODO: Ask TTI whether synchronization scope is between threads. - if (LoadInst *LI = dyn_cast(I)) - return LI->isAtomic() && LI->getSyncScopeID() != SyncScope::SingleThread; - if (StoreInst *SI = dyn_cast(I)) - return SI->isAtomic() && SI->getSyncScopeID() != SyncScope::SingleThread; - if (isa(I)) - return true; - if (isa(I)) - return true; - if (isa(I)) - return true; - return false; + auto SSID = getAtomicSyncScopeID(I); + if (!SSID.hasValue()) + return false; + if (isa(I) || isa(I)) + return SSID.getValue() != SyncScope::SingleThread; + return true; } void ThreadSanitizer::InsertRuntimeIgnores(Function &F) { @@ -580,7 +575,7 @@ bool ThreadSanitizer::sanitizeFunction(Function &F, // Traverse all instructions, collect loads/stores/returns, check for calls. for (auto &BB : F) { for (auto &Inst : BB) { - if (isAtomic(&Inst)) + if (isTsanAtomic(&Inst)) AtomicAccesses.push_back(&Inst); else if (isa(Inst) || isa(Inst)) LocalLoadsAndStores.push_back(&Inst);