diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -5310,6 +5310,10 @@ } }; +//===----------------------------------------------------------------------===// +// 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 @@ 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 --- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp @@ -526,19 +526,14 @@ 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 @@ // 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);