Skip to content

Commit 90c738e

Browse files
vitalybukanikic
andauthored
[IR] Introduce llvm.allow.{runtime,ubsan}.check() (#84850)
The goal is to have ability to change logic compile time based on PGO data. Our primary application is removing UBSAN checks from hot code. Then we'd like to use this for libc++ hardening and regular debug asserts. Previous attempt is #84214. Benefits from special intrinsic vs #84214: 1. Resulting binary is 3% faster than removing traps (on "test-suite/MultiSource/Benchmarks" with PGO+ThinLTO) 2. Intrinsic can be used from source code to change behavior from C/C++ program. E.g. enabling asserts in cold code. 3. Easier to match basic blocks. RFC: https://discourse.llvm.org/t/rfc-add-llvm-experimental-hot-intrinsic-or-llvm-hot/77641 --------- Co-authored-by: Nikita Popov <[email protected]>
1 parent 70deb7b commit 90c738e

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

llvm/docs/LangRef.rst

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27839,6 +27839,120 @@ constant `true`. However it is always correct to replace
2783927839
it with any other `i1` value. Any pass can
2784027840
freely do it if it can benefit from non-default lowering.
2784127841

27842+
'``llvm.allow.ubsan.check``' Intrinsic
27843+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27844+
27845+
Syntax:
27846+
"""""""
27847+
27848+
::
27849+
27850+
declare i1 @llvm.allow.ubsan.check(i8 immarg %kind)
27851+
27852+
Overview:
27853+
"""""""""
27854+
27855+
This intrinsic returns ``true`` if and only if the compiler opted to enable the
27856+
ubsan check in the current basic block.
27857+
27858+
Rules to allow ubsan checks are not part of the intrinsic declaration, and
27859+
controlled by compiler options.
27860+
27861+
This intrinsic is the ubsan specific version of ``@llvm.allow.runtime.check()``.
27862+
27863+
Arguments:
27864+
""""""""""
27865+
27866+
An integer describing the kind of ubsan check guarded by the intrinsic.
27867+
27868+
Semantics:
27869+
""""""""""
27870+
27871+
The intrinsic ``@llvm.allow.ubsan.check()`` returns either ``true`` or
27872+
``false``, depending on compiler options.
27873+
27874+
For each evaluation of a call to this intrinsic, the program must be valid and
27875+
correct both if it returns ``true`` and if it returns ``false``.
27876+
27877+
When used in a branch condition, it selects one of the two paths:
27878+
27879+
* `true``: Executes the UBSan check and reports any failures.
27880+
27881+
* `false`: Bypasses the check, assuming it always succeeds.
27882+
27883+
Example:
27884+
27885+
.. code-block:: text
27886+
27887+
%allow = call i1 @llvm.allow.ubsan.check(i8 5)
27888+
%not.allow = xor i1 %allow, true
27889+
%cond = or i1 %ubcheck, %not.allow
27890+
br i1 %cond, label %cont, label %trap
27891+
27892+
cont:
27893+
; Proceed
27894+
27895+
trap:
27896+
call void @llvm.ubsantrap(i8 5)
27897+
unreachable
27898+
27899+
27900+
'``llvm.allow.runtime.check``' Intrinsic
27901+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27902+
27903+
Syntax:
27904+
"""""""
27905+
27906+
::
27907+
27908+
declare i1 @llvm.allow.runtime.check(metadata %kind)
27909+
27910+
Overview:
27911+
"""""""""
27912+
27913+
This intrinsic returns ``true`` if and only if the compiler opted to enable
27914+
runtime checks in the current basic block.
27915+
27916+
Rules to allow runtime checks are not part of the intrinsic declaration, and
27917+
controlled by compiler options.
27918+
27919+
This intrinsic is non-ubsan specific version of ``@llvm.allow.ubsan.check()``.
27920+
27921+
Arguments:
27922+
""""""""""
27923+
27924+
A string identifying the kind of runtime check guarded by the intrinsic. The
27925+
string can be used to control rules to allow checks.
27926+
27927+
Semantics:
27928+
""""""""""
27929+
27930+
The intrinsic ``@llvm.allow.runtime.check()`` returns either ``true`` or
27931+
``false``, depending on compiler options.
27932+
27933+
For each evaluation of a call to this intrinsic, the program must be valid and
27934+
correct both if it returns ``true`` and if it returns ``false``.
27935+
27936+
When used in a branch condition, it allows us to choose between
27937+
two alternative correct solutions for the same problem.
27938+
27939+
If the intrinsic is evaluated as ``true``, program should execute a guarded
27940+
check. If the intrinsic is evaluated as ``false``, the program should avoid any
27941+
unnecessary checks.
27942+
27943+
Example:
27944+
27945+
.. code-block:: text
27946+
27947+
%allow = call i1 @llvm.allow.runtime.check(metadata !"my_check")
27948+
br i1 %allow, label %fast_path, label %slow_path
27949+
27950+
fast_path:
27951+
; Omit diagnostics.
27952+
27953+
slow_path:
27954+
; Additional diagnostics.
27955+
2784227956

2784327957
'``llvm.load.relative``' Intrinsic
2784427958
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,16 @@ def int_debugtrap : Intrinsic<[]>,
17311731
def int_ubsantrap : Intrinsic<[], [llvm_i8_ty],
17321732
[IntrNoReturn, IntrCold, ImmArg<ArgIndex<0>>]>;
17331733

1734+
// Return true if ubsan check is allowed.
1735+
def int_allow_ubsan_check : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i8_ty],
1736+
[IntrInaccessibleMemOnly, IntrWriteMem, ImmArg<ArgIndex<0>>, NoUndef<RetIndex>]>,
1737+
ClangBuiltin<"__builtin_allow_ubsan_check">;
1738+
1739+
// Return true if runtime check is allowed.
1740+
def int_allow_runtime_check : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_metadata_ty],
1741+
[IntrInaccessibleMemOnly, IntrWriteMem, NoUndef<RetIndex>]>,
1742+
ClangBuiltin<"__builtin_allow_runtime_check">;
1743+
17341744
// Support for dynamic deoptimization (or de-specialization)
17351745
def int_experimental_deoptimize : Intrinsic<[llvm_any_ty], [llvm_vararg_ty],
17361746
[Throws]>;

0 commit comments

Comments
 (0)