160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//===-- ThreadSanitizer.cpp - race detector -------------------------------===// 260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// The LLVM Compiler Infrastructure 460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// This file is distributed under the University of Illinois Open Source 660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// License. See LICENSE.TXT for details. 760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//===----------------------------------------------------------------------===// 960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 1060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// This file is a part of ThreadSanitizer, a race detector. 1160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 1260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// The tool is under development, for the details about previous versions see 1360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// http://code.google.com/p/data-race-test 1460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// 1560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// The instrumentation phase is quite simple: 1660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// - Insert calls to run-time library before every memory access. 1760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// - Optimizations may apply to avoid instrumenting some of the accesses. 1860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// - Insert calls at function entry/exit. 1960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany// The rest is handled by the run-time library. 2060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany//===----------------------------------------------------------------------===// 2160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 2260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#define DEBUG_TYPE "tsan" 2360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 24b5b86d263a651566cb25c0f406f75ceffb771029Kostya Serebryany#include "BlackList.h" 2506cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Function.h" 2606cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/IRBuilder.h" 2706cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Intrinsics.h" 2806cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/LLVMContext.h" 2906cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Metadata.h" 3006cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Module.h" 3106cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Type.h" 322076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany#include "llvm/ADT/SmallSet.h" 3360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/ADT/SmallString.h" 3460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/ADT/SmallVector.h" 352d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany#include "llvm/ADT/Statistic.h" 3660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/ADT/StringExtras.h" 376e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany#include "llvm/Support/CommandLine.h" 3860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Support/Debug.h" 3960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Support/MathExtras.h" 4052eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany#include "llvm/Support/raw_ostream.h" 4160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Target/TargetData.h" 4260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Transforms/Instrumentation.h" 43e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany#include "llvm/Transforms/Utils/BasicBlockUtils.h" 4460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany#include "llvm/Transforms/Utils/ModuleUtils.h" 4560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 4660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanyusing namespace llvm; 4760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 486e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryanystatic cl::opt<std::string> ClBlackListFile("tsan-blacklist", 496e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany cl::desc("Blacklist file"), cl::Hidden); 506e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany 512d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumInstrumentedReads, "Number of instrumented reads"); 522d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumInstrumentedWrites, "Number of instrumented writes"); 531dfe9b52646ce56446ecd3548dbc81068369ef3fAlexey SamsonovSTATISTIC(NumOmittedReadsBeforeWrite, 542d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany "Number of reads ignored due to following writes"); 552d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumAccessesWithBadSize, "Number of accesses with bad size"); 562d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumInstrumentedVtableWrites, "Number of vtable ptr writes"); 572d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumOmittedReadsFromConstantGlobals, 582d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany "Number of reads from constant globals"); 592d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya SerebryanySTATISTIC(NumOmittedReadsFromVtable, "Number of vtable reads"); 602076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany 6160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanynamespace { 622076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany 6360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany/// ThreadSanitizer: instrument the code in module to find races. 6460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanystruct ThreadSanitizer : public FunctionPass { 6560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany ThreadSanitizer(); 66e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const char *getPassName() const; 6760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany bool runOnFunction(Function &F); 6860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany bool doInitialization(Module &M); 6960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany static char ID; // Pass identification, replacement for typeid. 7060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 7160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany private: 72e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany bool instrumentLoadOrStore(Instruction *I); 73e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany bool instrumentAtomic(Instruction *I); 7437cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany void chooseInstructionsToInstrument(SmallVectorImpl<Instruction*> &Local, 7537cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany SmallVectorImpl<Instruction*> &All); 76cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany bool addrPointsToConstantData(Value *Addr); 77e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany int getMemoryAccessFuncIndex(Value *Addr); 782076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany 7960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany TargetData *TD; 80b5b86d263a651566cb25c0f406f75ceffb771029Kostya Serebryany OwningPtr<BlackList> BL; 81e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany IntegerType *OrdTy; 8260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Callbacks to run-time library are computed in doInitialization. 83e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanFuncEntry; 84e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanFuncExit; 8560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Accesses sizes are powers of two: 1, 2, 4, 8, 16. 863eccaa6625a8032bee6b84706cb46ed8eb915acfKostya Serebryany static const size_t kNumberOfAccessSizes = 5; 87e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanRead[kNumberOfAccessSizes]; 88e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanWrite[kNumberOfAccessSizes]; 89e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanAtomicLoad[kNumberOfAccessSizes]; 90e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanAtomicStore[kNumberOfAccessSizes]; 91e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Function *TsanVptrUpdate; 9260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany}; 9360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany} // namespace 9460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 9560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanychar ThreadSanitizer::ID = 0; 9660ebb1947faed42e493179e569c5db0c01d38a2aKostya SerebryanyINITIALIZE_PASS(ThreadSanitizer, "tsan", 9760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany "ThreadSanitizer: detects data races.", 9860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany false, false) 9960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 100e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanyconst char *ThreadSanitizer::getPassName() const { 101e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return "ThreadSanitizer"; 102e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 103e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 10460ebb1947faed42e493179e569c5db0c01d38a2aKostya SerebryanyThreadSanitizer::ThreadSanitizer() 10560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany : FunctionPass(ID), 10660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany TD(NULL) { 10760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany} 10860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 10960ebb1947faed42e493179e569c5db0c01d38a2aKostya SerebryanyFunctionPass *llvm::createThreadSanitizerPass() { 11060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany return new ThreadSanitizer(); 11160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany} 11260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 113e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanystatic Function *checkInterfaceFunction(Constant *FuncOrBitcast) { 114e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (Function *F = dyn_cast<Function>(FuncOrBitcast)) 115e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return F; 116e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany FuncOrBitcast->dump(); 117e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany report_fatal_error("ThreadSanitizer interface function redefined"); 118e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 119e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 12060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanybool ThreadSanitizer::doInitialization(Module &M) { 12160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany TD = getAnalysisIfAvailable<TargetData>(); 12260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany if (!TD) 12360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany return false; 124b5b86d263a651566cb25c0f406f75ceffb771029Kostya Serebryany BL.reset(new BlackList(ClBlackListFile)); 1256e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany 12660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Always insert a call to __tsan_init into the module's CTORs. 12760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRBuilder<> IRB(M.getContext()); 12860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany Value *TsanInit = M.getOrInsertFunction("__tsan_init", 12960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRB.getVoidTy(), NULL); 13060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany appendToGlobalCtors(M, cast<Function>(TsanInit), 0); 13160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 13260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Initialize the callbacks. 133e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanFuncEntry = checkInterfaceFunction(M.getOrInsertFunction( 134e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany "__tsan_func_entry", IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL)); 135e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanFuncExit = checkInterfaceFunction(M.getOrInsertFunction( 136e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany "__tsan_func_exit", IRB.getVoidTy(), NULL)); 137e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany OrdTy = IRB.getInt32Ty(); 1383eccaa6625a8032bee6b84706cb46ed8eb915acfKostya Serebryany for (size_t i = 0; i < kNumberOfAccessSizes; ++i) { 139e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t ByteSize = 1 << i; 140e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t BitSize = ByteSize * 8; 141e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany SmallString<32> ReadName("__tsan_read" + itostr(ByteSize)); 142e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanRead[i] = checkInterfaceFunction(M.getOrInsertFunction( 143e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany ReadName, IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL)); 144e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 145e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany SmallString<32> WriteName("__tsan_write" + itostr(ByteSize)); 146e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanWrite[i] = checkInterfaceFunction(M.getOrInsertFunction( 147e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany WriteName, IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL)); 148e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 149e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *Ty = Type::getIntNTy(M.getContext(), BitSize); 150e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *PtrTy = Ty->getPointerTo(); 151e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany SmallString<32> AtomicLoadName("__tsan_atomic" + itostr(BitSize) + 152e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany "_load"); 153e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanAtomicLoad[i] = checkInterfaceFunction(M.getOrInsertFunction( 154e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany AtomicLoadName, Ty, PtrTy, OrdTy, NULL)); 155e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 156e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany SmallString<32> AtomicStoreName("__tsan_atomic" + itostr(BitSize) + 157e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany "_store"); 158e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanAtomicStore[i] = checkInterfaceFunction(M.getOrInsertFunction( 159e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany AtomicStoreName, IRB.getVoidTy(), PtrTy, Ty, OrdTy, 160e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany NULL)); 16160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany } 162e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TsanVptrUpdate = checkInterfaceFunction(M.getOrInsertFunction( 163e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany "__tsan_vptr_update", IRB.getVoidTy(), IRB.getInt8PtrTy(), 164e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany IRB.getInt8PtrTy(), NULL)); 16560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany return true; 16660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany} 16760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 168cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryanystatic bool isVtableAccess(Instruction *I) { 169cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa)) { 170cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (Tag->getNumOperands() < 1) return false; 171cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (MDString *Tag1 = dyn_cast<MDString>(Tag->getOperand(0))) { 172cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (Tag1->getString() == "vtable pointer") return true; 173cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 174cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 175cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany return false; 176cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany} 177cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany 178cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryanybool ThreadSanitizer::addrPointsToConstantData(Value *Addr) { 179cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany // If this is a GEP, just analyze its pointer operand. 180cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr)) 181cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany Addr = GEP->getPointerOperand(); 182cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany 183cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) { 184cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (GV->isConstant()) { 185cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany // Reads from constant globals can not race with any writes. 1862d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany NumOmittedReadsFromConstantGlobals++; 187cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany return true; 188cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 1891dfe9b52646ce56446ecd3548dbc81068369ef3fAlexey Samsonov } else if (LoadInst *L = dyn_cast<LoadInst>(Addr)) { 190cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (isVtableAccess(L)) { 191cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany // Reads from a vtable pointer can not race with any writes. 1922d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany NumOmittedReadsFromVtable++; 193cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany return true; 194cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 195cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 196cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany return false; 197cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany} 198cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany 1992076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// Instrumenting some of the accesses may be proven redundant. 2002076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// Currently handled: 2012076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// - read-before-write (within same BB, no calls between) 2022076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// 2032076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// We do not handle some of the patterns that should not survive 2042076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// after the classic compiler optimizations. 2052076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// E.g. two reads from the same temp should be eliminated by CSE, 2062076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// two writes should be eliminated by DSE, etc. 2072076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// 2082076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// 'Local' is a vector of insns within the same BB (no calls between). 2092076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany// 'All' is a vector of insns that will be instrumented. 21037cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryanyvoid ThreadSanitizer::chooseInstructionsToInstrument( 2112076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany SmallVectorImpl<Instruction*> &Local, 2122076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany SmallVectorImpl<Instruction*> &All) { 2132076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany SmallSet<Value*, 8> WriteTargets; 2142076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany // Iterate from the end. 2152076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany for (SmallVectorImpl<Instruction*>::reverse_iterator It = Local.rbegin(), 2162076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany E = Local.rend(); It != E; ++It) { 2172076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany Instruction *I = *It; 2182076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany if (StoreInst *Store = dyn_cast<StoreInst>(I)) { 2192076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany WriteTargets.insert(Store->getPointerOperand()); 2202076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany } else { 2212076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany LoadInst *Load = cast<LoadInst>(I); 222cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany Value *Addr = Load->getPointerOperand(); 223cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (WriteTargets.count(Addr)) { 2242076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany // We will write to this temp, so no reason to analyze the read. 2252d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany NumOmittedReadsBeforeWrite++; 2262076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany continue; 2272076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany } 228cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany if (addrPointsToConstantData(Addr)) { 229cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany // Addr points to some constant data -- it can not race with any writes. 230cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany continue; 231cff60c1409e36079b4bc6ecbda84565143bf00afKostya Serebryany } 2322076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany } 2332076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany All.push_back(I); 2342076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany } 2352076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany Local.clear(); 2362076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany} 2372076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany 238e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanystatic bool isAtomic(Instruction *I) { 239e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (LoadInst *LI = dyn_cast<LoadInst>(I)) 240e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return LI->isAtomic() && LI->getSynchScope() == CrossThread; 24137cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany if (StoreInst *SI = dyn_cast<StoreInst>(I)) 242e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return SI->isAtomic() && SI->getSynchScope() == CrossThread; 24337cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany if (isa<AtomicRMWInst>(I)) 244e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return true; 24537cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany if (isa<AtomicCmpXchgInst>(I)) 246e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return true; 24737cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany if (FenceInst *FI = dyn_cast<FenceInst>(I)) 248e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return FI->getSynchScope() == CrossThread; 249e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return false; 250e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 251e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 25260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanybool ThreadSanitizer::runOnFunction(Function &F) { 25360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany if (!TD) return false; 2546e590e3f61b101554f97d6ab257c802c9ec49862Kostya Serebryany if (BL->isIn(F)) return false; 25560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany SmallVector<Instruction*, 8> RetVec; 2562076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany SmallVector<Instruction*, 8> AllLoadsAndStores; 2572076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany SmallVector<Instruction*, 8> LocalLoadsAndStores; 258e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany SmallVector<Instruction*, 8> AtomicAccesses; 25960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany bool Res = false; 26060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany bool HasCalls = false; 26160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 26260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Traverse all instructions, collect loads/stores/returns, check for calls. 26360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany for (Function::iterator FI = F.begin(), FE = F.end(); 26460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany FI != FE; ++FI) { 26560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany BasicBlock &BB = *FI; 26660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany for (BasicBlock::iterator BI = BB.begin(), BE = BB.end(); 26760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany BI != BE; ++BI) { 268e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (isAtomic(BI)) 269e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany AtomicAccesses.push_back(BI); 270e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany else if (isa<LoadInst>(BI) || isa<StoreInst>(BI)) 2712076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany LocalLoadsAndStores.push_back(BI); 27260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany else if (isa<ReturnInst>(BI)) 27360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany RetVec.push_back(BI); 2742076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany else if (isa<CallInst>(BI) || isa<InvokeInst>(BI)) { 27560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany HasCalls = true; 27637cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores); 2772076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany } 27860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany } 27937cb9acac54fdebdb833dc7e2f312d8e3bb33002Kostya Serebryany chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores); 28060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany } 28160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 28260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // We have collected all loads and stores. 28360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // FIXME: many of these accesses do not need to be checked for races 28460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // (e.g. variables that do not escape, etc). 28560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 28660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Instrument memory accesses. 2872076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany for (size_t i = 0, n = AllLoadsAndStores.size(); i < n; ++i) { 2882076af0184bd38185a719ea07cb10a90e8565a89Kostya Serebryany Res |= instrumentLoadOrStore(AllLoadsAndStores[i]); 28960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany } 29060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 291e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany // Instrument atomic memory accesses. 292e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany for (size_t i = 0, n = AtomicAccesses.size(); i < n; ++i) { 293e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Res |= instrumentAtomic(AtomicAccesses[i]); 294e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } 295e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 29660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany // Instrument function entry/exit points if there were instrumented accesses. 29760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany if (Res || HasCalls) { 29860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI()); 29960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany Value *ReturnAddress = IRB.CreateCall( 30060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany Intrinsic::getDeclaration(F.getParent(), Intrinsic::returnaddress), 30160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRB.getInt32(0)); 30260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRB.CreateCall(TsanFuncEntry, ReturnAddress); 30360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany for (size_t i = 0, n = RetVec.size(); i < n; ++i) { 30460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRBuilder<> IRBRet(RetVec[i]); 30560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRBRet.CreateCall(TsanFuncExit); 30660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany } 30752eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany Res = true; 30860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany } 30960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany return Res; 31060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany} 31160ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany 31260ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryanybool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) { 31360ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRBuilder<> IRB(I); 31460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany bool IsWrite = isa<StoreInst>(*I); 31560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany Value *Addr = IsWrite 31660ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany ? cast<StoreInst>(I)->getPointerOperand() 31760ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany : cast<LoadInst>(I)->getPointerOperand(); 318e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany int Idx = getMemoryAccessFuncIndex(Addr); 319e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (Idx < 0) 32060ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany return false; 32152eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany if (IsWrite && isVtableAccess(I)) { 3224a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany DEBUG(dbgs() << " VPTR : " << *I << "\n"); 32352eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany Value *StoredValue = cast<StoreInst>(I)->getValueOperand(); 3244a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany // StoredValue does not necessary have a pointer type. 3254a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany if (isa<IntegerType>(StoredValue->getType())) 3264a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany StoredValue = IRB.CreateIntToPtr(StoredValue, IRB.getInt8PtrTy()); 3274a002ab9c3eb19d33641cf37945a2ed153ee6d77Kostya Serebryany // Call TsanVptrUpdate. 32852eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany IRB.CreateCall2(TsanVptrUpdate, 32952eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()), 33052eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany IRB.CreatePointerCast(StoredValue, IRB.getInt8PtrTy())); 3312d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany NumInstrumentedVtableWrites++; 33252eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany return true; 33352eb699220aa00696b5c4a1a67141a8bcc8a4e68Kostya Serebryany } 33460ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany Value *OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx]; 33560ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy())); 3362d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany if (IsWrite) NumInstrumentedWrites++; 3372d5fdf81dc483e42cfad7ffbfa7492a31bb5ffd2Kostya Serebryany else NumInstrumentedReads++; 33860ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany return true; 33960ebb1947faed42e493179e569c5db0c01d38a2aKostya Serebryany} 340e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 341e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanystatic ConstantInt *createOrdering(IRBuilder<> *IRB, AtomicOrdering ord) { 342e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany uint32_t v = 0; 343e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany switch (ord) { 344e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany case NotAtomic: assert(false); 345e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany case Unordered: // Fall-through. 346e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany case Monotonic: v = 1 << 0; break; 3471dfe9b52646ce56446ecd3548dbc81068369ef3fAlexey Samsonov // case Consume: v = 1 << 1; break; // Not specified yet. 348e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany case Acquire: v = 1 << 2; break; 349e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany case Release: v = 1 << 3; break; 350e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany case AcquireRelease: v = 1 << 4; break; 351e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany case SequentiallyConsistent: v = 1 << 5; break; 352e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } 353e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return IRB->getInt32(v); 354e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 355e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 356e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanybool ThreadSanitizer::instrumentAtomic(Instruction *I) { 357e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany IRBuilder<> IRB(I); 358e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (LoadInst *LI = dyn_cast<LoadInst>(I)) { 359e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Value *Addr = LI->getPointerOperand(); 360e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany int Idx = getMemoryAccessFuncIndex(Addr); 361e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (Idx < 0) 362e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return false; 363e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t ByteSize = 1 << Idx; 364e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t BitSize = ByteSize * 8; 365e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); 366e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *PtrTy = Ty->getPointerTo(); 367e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy), 368e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany createOrdering(&IRB, LI->getOrdering())}; 369e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany CallInst *C = CallInst::Create(TsanAtomicLoad[Idx], 370e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany ArrayRef<Value*>(Args)); 371e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany ReplaceInstWithInst(I, C); 372e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 373e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { 374e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Value *Addr = SI->getPointerOperand(); 375e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany int Idx = getMemoryAccessFuncIndex(Addr); 376e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (Idx < 0) 377e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return false; 378e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t ByteSize = 1 << Idx; 379e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany const size_t BitSize = ByteSize * 8; 380e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); 381e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *PtrTy = Ty->getPointerTo(); 382e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Value *Args[] = {IRB.CreatePointerCast(Addr, PtrTy), 383e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany IRB.CreateIntCast(SI->getValueOperand(), Ty, false), 384e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany createOrdering(&IRB, SI->getOrdering())}; 385e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany CallInst *C = CallInst::Create(TsanAtomicStore[Idx], 386e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany ArrayRef<Value*>(Args)); 387e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany ReplaceInstWithInst(I, C); 388e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } else if (isa<AtomicRMWInst>(I)) { 389e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany // FIXME: Not yet supported. 390e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } else if (isa<AtomicCmpXchgInst>(I)) { 391e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany // FIXME: Not yet supported. 392e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } else if (isa<FenceInst>(I)) { 393e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany // FIXME: Not yet supported. 394e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } 395e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return true; 396e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 397e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany 398e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryanyint ThreadSanitizer::getMemoryAccessFuncIndex(Value *Addr) { 399e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *OrigPtrTy = Addr->getType(); 400e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType(); 401e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany assert(OrigTy->isSized()); 402e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany uint32_t TypeSize = TD->getTypeStoreSizeInBits(OrigTy); 403e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany if (TypeSize != 8 && TypeSize != 16 && 404e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany TypeSize != 32 && TypeSize != 64 && TypeSize != 128) { 405e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany NumAccessesWithBadSize++; 406e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany // Ignore all unusual sizes. 407e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return -1; 408e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany } 409e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany size_t Idx = CountTrailingZeros_32(TypeSize / 8); 410e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany assert(Idx < kNumberOfAccessSizes); 411e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany return Idx; 412e507922779b0d0d9ed3c159306174b4e191d119aKostya Serebryany} 413