[clang] [llvm] [TySan][Clang] Add clang flag to use tysan outlined instrumentation a… (PR #166170)
Matthew Nagy via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 13 05:57:59 PST 2025
https://github.com/gbMattN updated https://github.com/llvm/llvm-project/pull/166170
>From 95c5ff34c043680cbf85d7baf3e73ef7680e5854 Mon Sep 17 00:00:00 2001
From: gbMattN <matthew.nagy at sony.com>
Date: Fri, 31 Oct 2025 21:02:34 +0000
Subject: [PATCH 1/4] [TySan][Clang] Add clang flag to use tysan outlined
instrumentation and update docs
---
clang/docs/TypeSanitizer.rst | 27 ++++++++++++++++---
clang/docs/UsersManual.rst | 9 +++++++
clang/include/clang/Driver/SanitizerArgs.h | 2 ++
clang/include/clang/Options/Options.td | 12 +++++++++
clang/lib/Driver/SanitizerArgs.cpp | 20 ++++++++++++++
clang/test/CodeGen/sanitize-type-outlined.cpp | 23 ++++++++++++++++
6 files changed, 90 insertions(+), 3 deletions(-)
create mode 100644 clang/test/CodeGen/sanitize-type-outlined.cpp
diff --git a/clang/docs/TypeSanitizer.rst b/clang/docs/TypeSanitizer.rst
index 3c683a6c24bb4..6420d9e1d0ebd 100644
--- a/clang/docs/TypeSanitizer.rst
+++ b/clang/docs/TypeSanitizer.rst
@@ -20,9 +20,13 @@ code is build with ``-fno-strict-aliasing``, sacrificing performance.
TypeSanitizer is built to catch when these strict aliasing rules have been violated, helping
users find where such bugs originate in their code despite the code looking valid at first glance.
-As TypeSanitizer is still experimental, it can currently have a large impact on runtime speed,
-memory use, and code size. It also has a large compile-time overhead. Work is being done to
-reduce these impacts.
+Typical memory overhead introduced by TypeSanitizer is about **8x**. Runtime slowdown varies greatly
+depending on how often the instrumented code relies on type aliasing. In the best case slowdown is
+**2x-3x**.
+
+The compiler instrumentation also has an impact on code size and compilation overhead. There is an
+experimental :ref:`instrumentation outlining option<outlining_flag>` which can greatly reduce this
+but this may decrease runtime performance.
The TypeSanitizer Algorithm
===========================
@@ -128,6 +132,23 @@ references to LLVM IR specific terms.
Sanitizer features
==================
+.. _outlining_flag:
+
+Instrumentation code outlining
+------------------------------
+
+By default TypeSanitizer inlines the instrumentation code. This leads to increased
+binary size and compilation time. Using the clang flag
+``-fsanitize-type-outline-instrumentation`` (default: ``false``)
+forces all code instrumentation to be outlined. This reduces the size of the
+generated code and reduces compile-time overhead, but it also reduces runtime
+performance.
+
+This outlined instrumentation is new. If you wish to verify that the outlined instrumentation
+is behaving in the same way as the inline instrumentation, you can force TypeSanitizer
+to use both types of instrumentation. You can use the clang flag
+``-fsanitize-type-verify-outlined-instrumentation`` (default: ``false``) to do this.
+
``__has_feature(type_sanitizer)``
------------------------------------
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index fb22ad3c90af4..04da152bd0aff 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -2277,6 +2277,15 @@ are listed below.
See :doc: `AddressSanitizer` for more details.
+.. option:: -f[no-]sanitize-type-outline-instrumentation
+
+ Controls how type sanitizer code is generated. If enabled will always use
+ a function call instead of inlining the code. Turning this option on may
+ reduce the binary size and compilation overhead, but might result in a worse
+ run-time performance.
+
+ See :doc: `TypeSanitizer` for more details.
+
.. option:: -f[no-]sanitize-stats
Enable simple statistics gathering for the enabled sanitizers.
diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h
index eea7897e96afd..29569bcf7fa25 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -67,6 +67,8 @@ class SanitizerArgs {
bool TsanFuncEntryExit = true;
bool TsanAtomics = true;
bool MinimalRuntime = false;
+ bool TysanOutlineInstrumentation = false;
+ bool TysanVerifyOutlinedInstrumentation = false;
// True if cross-dso CFI support if provided by the system (i.e. Android).
bool ImplicitCfiRuntime = false;
bool NeedsMemProfRt = false;
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 2f7434d8afe11..1890f46ec5893 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2459,6 +2459,18 @@ def fsanitize_address_outline_instrumentation : Flag<["-"], "fsanitize-address-o
def fno_sanitize_address_outline_instrumentation : Flag<["-"], "fno-sanitize-address-outline-instrumentation">,
Group<f_clang_Group>,
HelpText<"Use default code inlining logic for the address sanitizer">;
+def fsanitize_type_outline_instrumentation : Flag<["-"], "fsanitize-type-outline-instrumentation">,
+ Group<f_clang_Group>,
+ HelpText<"Always generate function calls for type sanitizer instrumentation">;
+def fno_sanitize_type_outline_instrumentation : Flag<["-"], "fno-sanitize-type-outline-instrumentation">,
+ Group<f_clang_Group>,
+ HelpText<"Use default code inlining logic for the type sanitizer">;
+def fsanitize_type_verify_outlined_instrumentation : Flag<["-"], "fsanitize_type_verify_outlined_instrumentation">,
+ Group<f_clang_Group>,
+ HelpText<"Use both inlined and outlined instrumentation for type sanitizer to verify equivilence">;
+def fno_sanitize_type_verify_outlined_instrumentation : Flag<["-"], "fno_sanitize_type_verify_outlined_instrumentation">,
+ Group<f_clang_Group>,
+ HelpText<"Don't use both inlined and outlined instrumentation for type sanitizer to verify equivilence">;
defm sanitize_stable_abi
: OptInCC1FFlag<"sanitize-stable-abi", "Stable ", "Conventional ",
"ABI instrumentation for sanitizer runtime. Default: Conventional">;
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 420c4cddbc8dd..efd050373b991 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -1176,6 +1176,17 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
options::OPT_fno_sanitize_alloc_token_extended, AllocTokenExtended);
}
+ if (AllAddedKinds & SanitizerKind::Type) {
+ TysanOutlineInstrumentation =
+ Args.hasFlag(options::OPT_fsanitize_type_outline_instrumentation,
+ options::OPT_fno_sanitize_type_outline_instrumentation,
+ TysanOutlineInstrumentation);
+ TysanVerifyOutlinedInstrumentation = Args.hasFlag(
+ options::OPT_fsanitize_type_verify_outlined_instrumentation,
+ options::OPT_fno_sanitize_type_verify_outlined_instrumentation,
+ TysanVerifyOutlinedInstrumentation);
+ }
+
LinkRuntimes = Args.hasFlag(options::OPT_fsanitize_link_runtime,
options::OPT_fno_sanitize_link_runtime,
!Args.hasArg(options::OPT_r));
@@ -1500,6 +1511,15 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
}
+ if (TysanOutlineInstrumentation || TysanVerifyOutlinedInstrumentation) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-tysan-outline-instrumentation");
+ }
+ if (TysanVerifyOutlinedInstrumentation) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-tysan-verify-outlined-instrumentation");
+ }
+
// When emitting Stable ABI instrumentation, force outlining calls and avoid
// inlining shadow memory poisoning. While this is a big performance burden
// for now it allows full abstraction from implementation details.
diff --git a/clang/test/CodeGen/sanitize-type-outlined.cpp b/clang/test/CodeGen/sanitize-type-outlined.cpp
new file mode 100644
index 0000000000000..3c22f15c93d94
--- /dev/null
+++ b/clang/test/CodeGen/sanitize-type-outlined.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
+// RUN: | FileCheck %s --check-prefixes=CHECK-NO-OUTLINE
+// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
+// RUN: -fsanitize-type-outline-instrumentation \
+// RUN: | FileCheck %s --check-prefixes=CHECK-OUTLINE
+
+// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
+// RUN: -fsanitize-type-outline-instrumentation \
+// RUN: -fsanitize-type-verify-outlined-instrumentation \
+// RUN: | FileCheck %s --check-prefixes=CHECK-OUTLINE-VERIFY
+// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
+// RUN: -fsanitize-type-verify-outlined-instrumentation \
+// RUN: | FileCheck %s --check-prefixes=CHECK-VERIFY
+
+// CHECK-NO-OUTLINE-NOT: call{{.*}}@__tysan_instrument_mem_inst
+// CHECK-OUTLINE: call{{.*}}@__tysan_instrument_mem_inst
+// CHECK-OUTLINE-VERIFY: call{{.*}}@__tysan_instrument_mem_inst
+// CHECK-VERIFY: call{{.*}}@__tysan_instrument_mem_inst
+
+float alias(int *ptr){
+ float *aliasedPtr = (float *)ptr;
+ return *aliasedPtr;
+}
>From d9dc8be807a7fd79f085ceb2e650ef0d8b30f333 Mon Sep 17 00:00:00 2001
From: gbMattN <matthew.nagy at sony.com>
Date: Mon, 3 Nov 2025 15:06:23 +0000
Subject: [PATCH 2/4] Fix typo in Option.td
---
clang/include/clang/Options/Options.td | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 1890f46ec5893..893ebe918f7cd 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2465,10 +2465,10 @@ def fsanitize_type_outline_instrumentation : Flag<["-"], "fsanitize-type-outline
def fno_sanitize_type_outline_instrumentation : Flag<["-"], "fno-sanitize-type-outline-instrumentation">,
Group<f_clang_Group>,
HelpText<"Use default code inlining logic for the type sanitizer">;
-def fsanitize_type_verify_outlined_instrumentation : Flag<["-"], "fsanitize_type_verify_outlined_instrumentation">,
+def fsanitize_type_verify_outlined_instrumentation : Flag<["-"], "fsanitize-type-verify-outlined-instrumentation">,
Group<f_clang_Group>,
HelpText<"Use both inlined and outlined instrumentation for type sanitizer to verify equivilence">;
-def fno_sanitize_type_verify_outlined_instrumentation : Flag<["-"], "fno_sanitize_type_verify_outlined_instrumentation">,
+def fno_sanitize_type_verify_outlined_instrumentation : Flag<["-"], "fno_sanitize-type-verify-outlined-instrumentation">,
Group<f_clang_Group>,
HelpText<"Don't use both inlined and outlined instrumentation for type sanitizer to verify equivilence">;
defm sanitize_stable_abi
>From 9ff2fb9ae3b11521f67eea963a690195b76a0b05 Mon Sep 17 00:00:00 2001
From: gbMattN <matthew.nagy at sony.com>
Date: Mon, 3 Nov 2025 15:33:54 +0000
Subject: [PATCH 3/4] Windows doesnt support tysan so unsupport in the test
---
clang/test/CodeGen/sanitize-type-outlined.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/test/CodeGen/sanitize-type-outlined.cpp b/clang/test/CodeGen/sanitize-type-outlined.cpp
index 3c22f15c93d94..de21b903621fc 100644
--- a/clang/test/CodeGen/sanitize-type-outlined.cpp
+++ b/clang/test/CodeGen/sanitize-type-outlined.cpp
@@ -1,3 +1,5 @@
+// UNSUPPORTED: target={{.*}}-windows-{{.*}}
+
// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
// RUN: | FileCheck %s --check-prefixes=CHECK-NO-OUTLINE
// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
>From 709c21812cad47621106beac5085b467e88d0925 Mon Sep 17 00:00:00 2001
From: gbMattN <matthew.nagy at sony.com>
Date: Thu, 13 Nov 2025 13:54:30 +0000
Subject: [PATCH 4/4] Switch outlining to default, remove verification focused
flag changes
---
clang/docs/TypeSanitizer.rst | 5 -----
clang/include/clang/Driver/SanitizerArgs.h | 1 -
clang/include/clang/Options/Options.td | 6 ------
clang/lib/Driver/SanitizerArgs.cpp | 10 +---------
clang/test/CodeGen/sanitize-type-outlined.cpp | 10 ----------
llvm/lib/Transforms/Instrumentation/TypeSanitizer.cpp | 2 +-
6 files changed, 2 insertions(+), 32 deletions(-)
diff --git a/clang/docs/TypeSanitizer.rst b/clang/docs/TypeSanitizer.rst
index 6420d9e1d0ebd..07af5d6f605b4 100644
--- a/clang/docs/TypeSanitizer.rst
+++ b/clang/docs/TypeSanitizer.rst
@@ -144,11 +144,6 @@ forces all code instrumentation to be outlined. This reduces the size of the
generated code and reduces compile-time overhead, but it also reduces runtime
performance.
-This outlined instrumentation is new. If you wish to verify that the outlined instrumentation
-is behaving in the same way as the inline instrumentation, you can force TypeSanitizer
-to use both types of instrumentation. You can use the clang flag
-``-fsanitize-type-verify-outlined-instrumentation`` (default: ``false``) to do this.
-
``__has_feature(type_sanitizer)``
------------------------------------
diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h
index 29569bcf7fa25..4803ddecc6b9d 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -68,7 +68,6 @@ class SanitizerArgs {
bool TsanAtomics = true;
bool MinimalRuntime = false;
bool TysanOutlineInstrumentation = false;
- bool TysanVerifyOutlinedInstrumentation = false;
// True if cross-dso CFI support if provided by the system (i.e. Android).
bool ImplicitCfiRuntime = false;
bool NeedsMemProfRt = false;
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 893ebe918f7cd..c8cfee88e94a9 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2465,12 +2465,6 @@ def fsanitize_type_outline_instrumentation : Flag<["-"], "fsanitize-type-outline
def fno_sanitize_type_outline_instrumentation : Flag<["-"], "fno-sanitize-type-outline-instrumentation">,
Group<f_clang_Group>,
HelpText<"Use default code inlining logic for the type sanitizer">;
-def fsanitize_type_verify_outlined_instrumentation : Flag<["-"], "fsanitize-type-verify-outlined-instrumentation">,
- Group<f_clang_Group>,
- HelpText<"Use both inlined and outlined instrumentation for type sanitizer to verify equivilence">;
-def fno_sanitize_type_verify_outlined_instrumentation : Flag<["-"], "fno_sanitize-type-verify-outlined-instrumentation">,
- Group<f_clang_Group>,
- HelpText<"Don't use both inlined and outlined instrumentation for type sanitizer to verify equivilence">;
defm sanitize_stable_abi
: OptInCC1FFlag<"sanitize-stable-abi", "Stable ", "Conventional ",
"ABI instrumentation for sanitizer runtime. Default: Conventional">;
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index efd050373b991..42acc0c6c64ec 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -1181,10 +1181,6 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
Args.hasFlag(options::OPT_fsanitize_type_outline_instrumentation,
options::OPT_fno_sanitize_type_outline_instrumentation,
TysanOutlineInstrumentation);
- TysanVerifyOutlinedInstrumentation = Args.hasFlag(
- options::OPT_fsanitize_type_verify_outlined_instrumentation,
- options::OPT_fno_sanitize_type_verify_outlined_instrumentation,
- TysanVerifyOutlinedInstrumentation);
}
LinkRuntimes = Args.hasFlag(options::OPT_fsanitize_link_runtime,
@@ -1511,14 +1507,10 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
}
- if (TysanOutlineInstrumentation || TysanVerifyOutlinedInstrumentation) {
+ if (TysanOutlineInstrumentation) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-tysan-outline-instrumentation");
}
- if (TysanVerifyOutlinedInstrumentation) {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-tysan-verify-outlined-instrumentation");
- }
// When emitting Stable ABI instrumentation, force outlining calls and avoid
// inlining shadow memory poisoning. While this is a big performance burden
diff --git a/clang/test/CodeGen/sanitize-type-outlined.cpp b/clang/test/CodeGen/sanitize-type-outlined.cpp
index de21b903621fc..57b66fb626f51 100644
--- a/clang/test/CodeGen/sanitize-type-outlined.cpp
+++ b/clang/test/CodeGen/sanitize-type-outlined.cpp
@@ -6,18 +6,8 @@
// RUN: -fsanitize-type-outline-instrumentation \
// RUN: | FileCheck %s --check-prefixes=CHECK-OUTLINE
-// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
-// RUN: -fsanitize-type-outline-instrumentation \
-// RUN: -fsanitize-type-verify-outlined-instrumentation \
-// RUN: | FileCheck %s --check-prefixes=CHECK-OUTLINE-VERIFY
-// RUN: %clang -S -fsanitize=type -emit-llvm -o - -fsanitize=type %s \
-// RUN: -fsanitize-type-verify-outlined-instrumentation \
-// RUN: | FileCheck %s --check-prefixes=CHECK-VERIFY
-
// CHECK-NO-OUTLINE-NOT: call{{.*}}@__tysan_instrument_mem_inst
// CHECK-OUTLINE: call{{.*}}@__tysan_instrument_mem_inst
-// CHECK-OUTLINE-VERIFY: call{{.*}}@__tysan_instrument_mem_inst
-// CHECK-VERIFY: call{{.*}}@__tysan_instrument_mem_inst
float alias(int *ptr){
float *aliasedPtr = (float *)ptr;
diff --git a/llvm/lib/Transforms/Instrumentation/TypeSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/TypeSanitizer.cpp
index 87eba5f2c5242..1c91d833ea616 100644
--- a/llvm/lib/Transforms/Instrumentation/TypeSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/TypeSanitizer.cpp
@@ -62,7 +62,7 @@ static cl::opt<bool> ClOutlineInstrumentation(
"tysan-outline-instrumentation",
cl::desc("Uses function calls for all TySan instrumentation, reducing "
"ELF size"),
- cl::Hidden, cl::init(false));
+ cl::Hidden, cl::init(true));
static cl::opt<bool> ClVerifyOutlinedInstrumentation(
"tysan-verify-outlined-instrumentation",
More information about the cfe-commits
mailing list