[llvm-commits] [llvm] r154444 - in /llvm/trunk: lib/Transforms/Instrumentation/ThreadSanitizer.cpp test/Instrumentation/ThreadSanitizer/read_from_global.ll
Kostya Serebryany
kcc at google.com
Tue Apr 10 15:29:18 PDT 2012
Author: kcc
Date: Tue Apr 10 17:29:17 2012
New Revision: 154444
URL: http://llvm.org/viewvc/llvm-project?rev=154444&view=rev
Log:
[tsan] two more compile-time optimizations:
- don't isntrument reads from constant globals.
Saves ~1.5% of instrumented instructions on CPU2006
(counting static instructions, not their execution).
- don't insrument reads from vtable (which is a global constant too).
Saves ~5%.
I did not measure the run-time impact of this,
but it is certainly non-negative.
Added:
llvm/trunk/test/Instrumentation/ThreadSanitizer/read_from_global.ll
Modified:
llvm/trunk/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
Modified: llvm/trunk/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/ThreadSanitizer.cpp?rev=154444&r1=154443&r2=154444&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/ThreadSanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/ThreadSanitizer.cpp Tue Apr 10 17:29:17 2012
@@ -58,6 +58,8 @@
size_t NumOmittedReadsBeforeWrite;
size_t NumAccessesWithBadSize;
size_t NumInstrumentedVtableWrites;
+ size_t NumOmittedReadsFromConstantGlobals;
+ size_t NumOmittedReadsFromVtable;
};
/// ThreadSanitizer: instrument the code in module to find races.
@@ -72,6 +74,7 @@
private:
void choseInstructionsToInstrument(SmallVectorImpl<Instruction*> &Local,
SmallVectorImpl<Instruction*> &All);
+ bool addrPointsToConstantData(Value *Addr);
TargetData *TD;
OwningPtr<FunctionBlackList> BL;
@@ -145,11 +148,44 @@
<< "; vt " << stats.NumInstrumentedVtableWrites
<< "; bs " << stats.NumAccessesWithBadSize
<< "; rbw " << stats.NumOmittedReadsBeforeWrite
+ << "; rcg " << stats.NumOmittedReadsFromConstantGlobals
+ << "; rvt " << stats.NumOmittedReadsFromVtable
<< "\n";
}
return true;
}
+static bool isVtableAccess(Instruction *I) {
+ if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa)) {
+ if (Tag->getNumOperands() < 1) return false;
+ if (MDString *Tag1 = dyn_cast<MDString>(Tag->getOperand(0))) {
+ if (Tag1->getString() == "vtable pointer") return true;
+ }
+ }
+ return false;
+}
+
+bool ThreadSanitizer::addrPointsToConstantData(Value *Addr) {
+ // If this is a GEP, just analyze its pointer operand.
+ if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr))
+ Addr = GEP->getPointerOperand();
+
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) {
+ if (GV->isConstant()) {
+ // Reads from constant globals can not race with any writes.
+ stats.NumOmittedReadsFromConstantGlobals++;
+ return true;
+ }
+ } else if(LoadInst *L = dyn_cast<LoadInst>(Addr)) {
+ if (isVtableAccess(L)) {
+ // Reads from a vtable pointer can not race with any writes.
+ stats.NumOmittedReadsFromVtable++;
+ return true;
+ }
+ }
+ return false;
+}
+
// Instrumenting some of the accesses may be proven redundant.
// Currently handled:
// - read-before-write (within same BB, no calls between)
@@ -173,11 +209,16 @@
WriteTargets.insert(Store->getPointerOperand());
} else {
LoadInst *Load = cast<LoadInst>(I);
- if (WriteTargets.count(Load->getPointerOperand())) {
+ Value *Addr = Load->getPointerOperand();
+ if (WriteTargets.count(Addr)) {
// We will write to this temp, so no reason to analyze the read.
stats.NumOmittedReadsBeforeWrite++;
continue;
}
+ if (addrPointsToConstantData(Addr)) {
+ // Addr points to some constant data -- it can not race with any writes.
+ continue;
+ }
}
All.push_back(I);
}
@@ -236,16 +277,6 @@
return Res;
}
-static bool isVtableAccess(Instruction *I) {
- if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa)) {
- if (Tag->getNumOperands() < 1) return false;
- if (MDString *Tag1 = dyn_cast<MDString>(Tag->getOperand(0))) {
- if (Tag1->getString() == "vtable pointer") return true;
- }
- }
- return false;
-}
-
bool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) {
IRBuilder<> IRB(I);
bool IsWrite = isa<StoreInst>(*I);
Added: llvm/trunk/test/Instrumentation/ThreadSanitizer/read_from_global.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/ThreadSanitizer/read_from_global.ll?rev=154444&view=auto
==============================================================================
--- llvm/trunk/test/Instrumentation/ThreadSanitizer/read_from_global.ll (added)
+++ llvm/trunk/test/Instrumentation/ThreadSanitizer/read_from_global.ll Tue Apr 10 17:29:17 2012
@@ -0,0 +1,61 @@
+; RUN: opt < %s -tsan -S | FileCheck %s
+; Check that tsan does not instrument reads from constant globals.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+
+ at const_global = external constant i32
+define i32 @read_from_const_global() nounwind uwtable readnone {
+entry:
+ %0 = load i32* @const_global, align 4
+ ret i32 %0
+}
+; CHECK: define i32 @read_from_const_global
+; CHECK-NOT: __tsan
+; CHECK: ret i32
+
+ at non_const_global = global i32 0, align 4
+define i32 @read_from_non_const_global() nounwind uwtable readonly {
+entry:
+ %0 = load i32* @non_const_global, align 4
+ ret i32 %0
+}
+
+; CHECK: define i32 @read_from_non_const_global
+; CHECK: __tsan_read
+; CHECK: ret i32
+
+ at const_global_array = external constant [10 x i32]
+define i32 @read_from_const_global_array(i32 %idx) nounwind uwtable readnone {
+entry:
+ %idxprom = sext i32 %idx to i64
+ %arrayidx = getelementptr inbounds [10 x i32]* @const_global_array, i64 0, i64 %idxprom
+ %0 = load i32* %arrayidx, align 4
+ ret i32 %0
+}
+
+; CHECK: define i32 @read_from_const_global_array
+; CHECK-NOT: __tsan
+; CHECK: ret i32
+
+%struct.Foo = type { i32 (...)** }
+define void @call_virtual_func(%struct.Foo* %f) uwtable {
+entry:
+ %0 = bitcast %struct.Foo* %f to void (%struct.Foo*)***
+ %vtable = load void (%struct.Foo*)*** %0, align 8, !tbaa !3
+ %1 = load void (%struct.Foo*)** %vtable, align 8
+ call void %1(%struct.Foo* %f)
+ ret void
+}
+
+; CHECK: define void @call_virtual_func
+; CHECK: __tsan_read
+; CHECK: = load
+; CHECK-NOT: __tsan_read
+; CHECK: = load
+; CHECK: ret void
+
+!0 = metadata !{metadata !"int", metadata !1}
+!1 = metadata !{metadata !"omnipotent char", metadata !2}
+!2 = metadata !{metadata !"Simple C/C++ TBAA", null}
+!3 = metadata !{metadata !"vtable pointer", metadata !2}
+
More information about the llvm-commits
mailing list