Skip to content

Commit 630a697

Browse files
authored
Merge pull request #17100 from devincoughlin/tsan-exclusivity-interaction
2 parents 5f8c139 + be60d9b commit 630a697

File tree

7 files changed

+72
-32
lines changed

7 files changed

+72
-32
lines changed

include/swift/SIL/InstructionUtils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ bool isIncidentalUse(SILInstruction *user);
111111
/// only used in recognizable patterns without otherwise "escaping".
112112
bool onlyAffectsRefCount(SILInstruction *user);
113113

114+
/// Return true when the instruction represents added instrumentation for
115+
/// run-time sanitizers.
116+
bool isSanitizerInstrumentation(SILInstruction *Instruction);
117+
114118
/// If V is a convert_function or convert_escape_to_noescape return its operand
115119
/// recursively.
116120
SILValue stripConvertFunctions(SILValue V);

lib/SIL/InstructionUtils.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,18 @@ bool swift::onlyAffectsRefCount(SILInstruction *user) {
299299
}
300300
}
301301

302+
bool swift::isSanitizerInstrumentation(SILInstruction *Instruction) {
303+
auto *BI = dyn_cast<BuiltinInst>(Instruction);
304+
if (!BI)
305+
return false;
306+
307+
Identifier Name = BI->getName();
308+
if (Name == BI->getModule().getASTContext().getIdentifier("tsanInoutAccess"))
309+
return true;
310+
311+
return false;
312+
}
313+
302314
SILValue swift::stripConvertFunctions(SILValue V) {
303315
while (true) {
304316
if (auto CFI = dyn_cast<ConvertFunctionInst>(V)) {

lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#define DEBUG_TYPE "sil-access-summary-analysis"
14+
#include "swift/SIL/InstructionUtils.h"
1415
#include "swift/SIL/SILArgument.h"
1516
#include "swift/SILOptimizer/Analysis/AccessSummaryAnalysis.h"
1617
#include "swift/SILOptimizer/Analysis/FunctionOrder.h"
@@ -489,6 +490,12 @@ getSingleAddressProjectionUser(SingleValueInstruction *I) {
489490
if (isa<BeginAccessInst>(I) && isa<EndAccessInst>(User))
490491
continue;
491492

493+
// Ignore sanitizer instrumentation when looking for a single projection
494+
// user. This ensures that we're able to find a single projection subpath
495+
// even when sanitization is enabled.
496+
if (isSanitizerInstrumentation(User))
497+
continue;
498+
492499
// We have more than a single user so bail.
493500
if (SingleUser)
494501
return std::make_pair(nullptr, 0);

lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -683,21 +683,6 @@ static SILValue getAccessedPointer(SILValue Pointer) {
683683
return Pointer;
684684
}
685685

686-
/// Returns true when the instruction represents added instrumentation for
687-
/// run-time sanitizers.
688-
static bool isSanitizerInstrumentation(SILInstruction *Instruction,
689-
ASTContext &Ctx) {
690-
auto *BI = dyn_cast<BuiltinInst>(Instruction);
691-
if (!BI)
692-
return false;
693-
694-
Identifier Name = BI->getName();
695-
if (Name == Ctx.getIdentifier("tsanInoutAccess"))
696-
return true;
697-
698-
return false;
699-
}
700-
701686
void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
702687
assert(Pointer->getType().isAddress() &&
703688
"Walked through the pointer to the value?");
@@ -954,7 +939,7 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
954939

955940
// Sanitizer instrumentation is not user visible, so it should not
956941
// count as a use and must not affect compile-time diagnostics.
957-
if (isSanitizerInstrumentation(User, Module.getASTContext()))
942+
if (isSanitizerInstrumentation(User))
958943
continue;
959944

960945
// Otherwise, the use is something complicated, it escapes.

lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define DEBUG_TYPE "definite-init"
1414
#include "PMOMemoryUseCollector.h"
1515
#include "swift/AST/Expr.h"
16+
#include "swift/SIL/InstructionUtils.h"
1617
#include "swift/SIL/SILArgument.h"
1718
#include "swift/SIL/SILBuilder.h"
1819
#include "llvm/ADT/StringExtras.h"
@@ -364,21 +365,6 @@ bool ElementUseCollector::collectContainerUses(AllocBoxInst *ABI) {
364365
return true;
365366
}
366367

367-
// Returns true when the instruction represents added instrumentation for
368-
/// run-time sanitizers.
369-
static bool isSanitizerInstrumentation(SILInstruction *Instruction,
370-
ASTContext &Ctx) {
371-
auto *BI = dyn_cast<BuiltinInst>(Instruction);
372-
if (!BI)
373-
return false;
374-
375-
Identifier Name = BI->getName();
376-
if (Name == Ctx.getIdentifier("tsanInoutAccess"))
377-
return true;
378-
379-
return false;
380-
}
381-
382368
bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
383369
assert(Pointer->getType().isAddress() &&
384370
"Walked through the pointer to the value?");
@@ -630,7 +616,7 @@ bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
630616

631617
// Sanitizer instrumentation is not user visible, so it should not
632618
// count as a use and must not affect compile-time diagnostics.
633-
if (isSanitizerInstrumentation(User, Module.getASTContext()))
619+
if (isSanitizerInstrumentation(User))
634620
continue;
635621

636622
// Otherwise, the use is something complicated, it escapes.

test/SILOptimizer/access_summary_analysis.sil

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,24 @@ bb0(%0 : @trivial $*StructWithStoredProperties):
174174
return %7 : $()
175175
}
176176

177+
// CHECK-LABEL: @accessSeparateStoredPropertiesOfSameCaptureWithTSanInstrumentation
178+
// CHECK-NEXT: ([.f modify, .g read])
179+
sil private @accessSeparateStoredPropertiesOfSameCaptureWithTSanInstrumentation : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
180+
bb0(%0 : @trivial $*StructWithStoredProperties):
181+
%1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
182+
%2 = builtin "tsanInoutAccess"(%1 : $*StructWithStoredProperties) : $()
183+
%3 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
184+
%4 = builtin "tsanInoutAccess"(%3 : $*Int) : $()
185+
end_access %1 : $*StructWithStoredProperties
186+
%6 = begin_access [read] [unknown] %0: $*StructWithStoredProperties
187+
%7 = builtin "tsanInoutAccess"(%6 : $*StructWithStoredProperties) : $()
188+
%8 = struct_element_addr %6 : $*StructWithStoredProperties, #StructWithStoredProperties.g
189+
%9 = builtin "tsanInoutAccess"(%8 : $*Int) : $()
190+
end_access %6 : $*StructWithStoredProperties
191+
%11 = tuple ()
192+
return %11 : $()
193+
}
194+
177195
// CHECK-LABEL: @addressToPointerOfStructElementAddr
178196
// CHECK-NEXT: ([])
179197
// This mirrors the code pattern for materializeForSet on a struct stored
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-swift-frontend -enforce-exclusivity=checked -sanitize=thread -emit-sil -primary-file %s -o /dev/null -verify
2+
// REQUIRES: tsan_runtime
3+
4+
5+
struct OtherStruct {
6+
mutating
7+
func mutableTakingClosure(_ c: () -> Void) { }
8+
}
9+
10+
struct StructAndInt {
11+
var s = OtherStruct()
12+
var f = 42
13+
}
14+
15+
func testStoredPropertyRelaxationInClosure() {
16+
var l = StructAndInt()
17+
l.s.mutableTakingClosure {
18+
_ = l.f // no-diagnostic
19+
}
20+
}
21+
22+
func takesInouts(_ p1: inout Int, _ p2: inout OtherStruct) { }
23+
24+
func testStoredPropertyRelaxationInInout() {
25+
var l = StructAndInt()
26+
takesInouts(&l.f, &l.s) // no-diagnostic
27+
}
28+

0 commit comments

Comments
 (0)