mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[tsan] Do not instrument reads/writes to instruction profile counters.
We have known races on profile counters, which can be reproduced by enabling -fsanitize=thread and -fprofile-instr-generate simultaneously on a multi-threaded program. This patch avoids reporting those races by not instrumenting the reads and writes coming from the instruction profiler. llvm-svn: 264805
This commit is contained in:
parent
a6e8668e11
commit
83e4032a41
@ -36,6 +36,7 @@
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
@ -243,6 +244,24 @@ static bool isVtableAccess(Instruction *I) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do not instrument known races/"benign races" that come from compiler
|
||||
// instrumentatin. The user has no way of suppressing them.
|
||||
bool shouldInstrumentReadWriteFromAddress(Value *Addr) {
|
||||
// Peel off GEPs and BitCasts.
|
||||
Addr = Addr->stripInBoundsOffsets();
|
||||
|
||||
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) {
|
||||
if (GV->hasSection()) {
|
||||
StringRef SectionName = GV->getSection();
|
||||
// Check if the global is in the PGO counters section.
|
||||
if (SectionName.endswith(getInstrProfCountersSectionName(
|
||||
/*AddSegment=*/false)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThreadSanitizer::addrPointsToConstantData(Value *Addr) {
|
||||
// If this is a GEP, just analyze its pointer operand.
|
||||
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr))
|
||||
@ -285,10 +304,15 @@ void ThreadSanitizer::chooseInstructionsToInstrument(
|
||||
E = Local.rend(); It != E; ++It) {
|
||||
Instruction *I = *It;
|
||||
if (StoreInst *Store = dyn_cast<StoreInst>(I)) {
|
||||
WriteTargets.insert(Store->getPointerOperand());
|
||||
Value *Addr = Store->getPointerOperand();
|
||||
if (!shouldInstrumentReadWriteFromAddress(Addr))
|
||||
continue;
|
||||
WriteTargets.insert(Addr);
|
||||
} else {
|
||||
LoadInst *Load = cast<LoadInst>(I);
|
||||
Value *Addr = Load->getPointerOperand();
|
||||
if (!shouldInstrumentReadWriteFromAddress(Addr))
|
||||
continue;
|
||||
if (WriteTargets.count(Addr)) {
|
||||
// We will write to this temp, so no reason to analyze the read.
|
||||
NumOmittedReadsBeforeWrite++;
|
||||
|
@ -0,0 +1,33 @@
|
||||
; This test checks that we are not instrumenting unwanted acesses to globals:
|
||||
; - Instruction profiler counter instrumentation has known intended races.
|
||||
;
|
||||
; RUN: opt < %s -tsan -S | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.9"
|
||||
|
||||
@__profc_test_gep = private global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
@__profc_test_bitcast = private global [2 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
@__profc_test_bitcast_foo = private global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
|
||||
define i32 @test_gep() sanitize_thread {
|
||||
entry:
|
||||
%pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test_gep, i64 0, i64 0)
|
||||
%0 = add i64 %pgocount, 1
|
||||
store i64 %0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test_gep, i64 0, i64 0)
|
||||
ret i32 1
|
||||
}
|
||||
|
||||
define i32 @test_bitcast() sanitize_thread {
|
||||
entry:
|
||||
%0 = load <2 x i64>, <2 x i64>* bitcast ([2 x i64]* @__profc_test_bitcast to <2 x i64>*), align 8
|
||||
%.promoted5 = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test_bitcast_foo, i64 0, i64 0), align 8
|
||||
%1 = add i64 %.promoted5, 10
|
||||
%2 = add <2 x i64> %0, <i64 1, i64 10>
|
||||
store <2 x i64> %2, <2 x i64>* bitcast ([2 x i64]* @__profc_test_bitcast to <2 x i64>*), align 8
|
||||
store i64 %1, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test_bitcast_foo, i64 0, i64 0), align 8
|
||||
ret i32 undef
|
||||
}
|
||||
|
||||
; CHECK-NOT: {{call void @__tsan_write}}
|
||||
; CHECK: __tsan_init
|
Loading…
x
Reference in New Issue
Block a user