Skip to content

Commit d77b476

Browse files
committed
tsan: avoid extra call indirection in unaligned access functions
Currently unaligned access functions are defined in tsan_interface.cpp and do a real call to MemoryAccess. This means we have a real call and no read/write constant propagation. Unaligned memory access can be quite hot for some programs (observed on some compression algorithms with ~90% of unaligned accesses). Move them to tsan_interface_inl.h to avoid the additional call and enable constant propagation. Also reorder the actual store and memory access handling for __sanitizer_unaligned_store callbacks to enable tail calling in MemoryAccess. Depends on D107282. Reviewed By: vitalybuka, melver Differential Revision: https://reviews.llvm.org/D107283
1 parent 6939689 commit d77b476

File tree

2 files changed

+71
-64
lines changed

2 files changed

+71
-64
lines changed

compiler-rt/lib/tsan/rtl/tsan_interface.cpp

Lines changed: 8 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -59,77 +59,21 @@ void __tsan_write16_pc(void *addr, void *pc) {
5959

6060
// __tsan_unaligned_read/write calls are emitted by compiler.
6161

62-
void __tsan_unaligned_read2(const void *addr) {
63-
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessRead);
64-
}
65-
66-
void __tsan_unaligned_read4(const void *addr) {
67-
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessRead);
68-
}
69-
70-
void __tsan_unaligned_read8(const void *addr) {
71-
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessRead);
72-
}
73-
7462
void __tsan_unaligned_read16(const void *addr) {
75-
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 16, kAccessRead);
76-
}
77-
78-
void __tsan_unaligned_write2(void *addr) {
79-
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessWrite);
80-
}
81-
82-
void __tsan_unaligned_write4(void *addr) {
83-
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessWrite);
84-
}
85-
86-
void __tsan_unaligned_write8(void *addr) {
87-
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessWrite);
63+
uptr pc = CALLERPC;
64+
ThreadState *thr = cur_thread();
65+
UnalignedMemoryAccess(thr, pc, (uptr)addr, 8, kAccessRead);
66+
UnalignedMemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessRead);
8867
}
8968

9069
void __tsan_unaligned_write16(void *addr) {
91-
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 16, kAccessWrite);
70+
uptr pc = CALLERPC;
71+
ThreadState *thr = cur_thread();
72+
UnalignedMemoryAccess(thr, pc, (uptr)addr, 8, kAccessWrite);
73+
UnalignedMemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessWrite);
9274
}
9375

94-
// __sanitizer_unaligned_load/store are for user instrumentation.
95-
9676
extern "C" {
97-
SANITIZER_INTERFACE_ATTRIBUTE
98-
u16 __sanitizer_unaligned_load16(const uu16 *addr) {
99-
__tsan_unaligned_read2(addr);
100-
return *addr;
101-
}
102-
103-
SANITIZER_INTERFACE_ATTRIBUTE
104-
u32 __sanitizer_unaligned_load32(const uu32 *addr) {
105-
__tsan_unaligned_read4(addr);
106-
return *addr;
107-
}
108-
109-
SANITIZER_INTERFACE_ATTRIBUTE
110-
u64 __sanitizer_unaligned_load64(const uu64 *addr) {
111-
__tsan_unaligned_read8(addr);
112-
return *addr;
113-
}
114-
115-
SANITIZER_INTERFACE_ATTRIBUTE
116-
void __sanitizer_unaligned_store16(uu16 *addr, u16 v) {
117-
__tsan_unaligned_write2(addr);
118-
*addr = v;
119-
}
120-
121-
SANITIZER_INTERFACE_ATTRIBUTE
122-
void __sanitizer_unaligned_store32(uu32 *addr, u32 v) {
123-
__tsan_unaligned_write4(addr);
124-
*addr = v;
125-
}
126-
127-
SANITIZER_INTERFACE_ATTRIBUTE
128-
void __sanitizer_unaligned_store64(uu64 *addr, u64 v) {
129-
__tsan_unaligned_write8(addr);
130-
*addr = v;
131-
}
132-
13377
SANITIZER_INTERFACE_ATTRIBUTE
13478
void *__tsan_get_current_fiber() {
13579
return cur_thread();

compiler-rt/lib/tsan/rtl/tsan_interface_inl.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,69 @@ void __tsan_write8_pc(void *addr, void *pc) {
8282
MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 8, kAccessWrite);
8383
}
8484

85+
ALWAYS_INLINE USED void __tsan_unaligned_read2(const void *addr) {
86+
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessRead);
87+
}
88+
89+
ALWAYS_INLINE USED void __tsan_unaligned_read4(const void *addr) {
90+
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessRead);
91+
}
92+
93+
ALWAYS_INLINE USED void __tsan_unaligned_read8(const void *addr) {
94+
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessRead);
95+
}
96+
97+
ALWAYS_INLINE USED void __tsan_unaligned_write2(void *addr) {
98+
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessWrite);
99+
}
100+
101+
ALWAYS_INLINE USED void __tsan_unaligned_write4(void *addr) {
102+
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessWrite);
103+
}
104+
105+
ALWAYS_INLINE USED void __tsan_unaligned_write8(void *addr) {
106+
UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessWrite);
107+
}
108+
109+
extern "C" {
110+
// __sanitizer_unaligned_load/store are for user instrumentation.
111+
SANITIZER_INTERFACE_ATTRIBUTE
112+
u16 __sanitizer_unaligned_load16(const uu16 *addr) {
113+
__tsan_unaligned_read2(addr);
114+
return *addr;
115+
}
116+
117+
SANITIZER_INTERFACE_ATTRIBUTE
118+
u32 __sanitizer_unaligned_load32(const uu32 *addr) {
119+
__tsan_unaligned_read4(addr);
120+
return *addr;
121+
}
122+
123+
SANITIZER_INTERFACE_ATTRIBUTE
124+
u64 __sanitizer_unaligned_load64(const uu64 *addr) {
125+
__tsan_unaligned_read8(addr);
126+
return *addr;
127+
}
128+
129+
SANITIZER_INTERFACE_ATTRIBUTE
130+
void __sanitizer_unaligned_store16(uu16 *addr, u16 v) {
131+
*addr = v;
132+
__tsan_unaligned_write2(addr);
133+
}
134+
135+
SANITIZER_INTERFACE_ATTRIBUTE
136+
void __sanitizer_unaligned_store32(uu32 *addr, u32 v) {
137+
*addr = v;
138+
__tsan_unaligned_write4(addr);
139+
}
140+
141+
SANITIZER_INTERFACE_ATTRIBUTE
142+
void __sanitizer_unaligned_store64(uu64 *addr, u64 v) {
143+
*addr = v;
144+
__tsan_unaligned_write8(addr);
145+
}
146+
}
147+
85148
void __tsan_vptr_update(void **vptr_p, void *new_val) {
86149
if (*vptr_p == new_val)
87150
return;

0 commit comments

Comments
 (0)