From f379d232c8c3c66391379c06491515d9555668e1 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 20 Mar 2024 19:58:58 -0700 Subject: =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20changes=20to?= =?UTF-8?q?=20main=20this=20commit=20is=20based=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 [skip ci] --- llvm/docs/LangRef.rst | 115 +++++++++++++++++++++ .../llvm/Analysis/TargetTransformInfoImpl.h | 2 + llvm/include/llvm/IR/Intrinsics.td | 10 ++ llvm/lib/Analysis/AliasSetTracker.cpp | 2 + llvm/lib/Analysis/MemorySSA.cpp | 4 + llvm/lib/CodeGen/CodeGenPrepare.cpp | 4 +- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 5 + llvm/lib/CodeGen/IntrinsicLowering.cpp | 5 + llvm/lib/CodeGen/SelectionDAG/FastISel.cpp | 4 + .../CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 5 + llvm/test/Analysis/AliasSet/intrinsics.ll | 30 ++++++ .../CostModel/free-intrinsics-datalayout.ll | 6 ++ .../Analysis/CostModel/free-intrinsics-no_info.ll | 6 ++ llvm/test/Analysis/MemorySSA/allow-check.ll | 29 ++++++ llvm/test/CodeGen/AArch64/allow-check.ll | 30 ++++++ llvm/test/CodeGen/AMDGPU/allow-check.ll | 30 ++++++ llvm/test/CodeGen/Generic/allow-check.ll | 23 +++++ llvm/test/CodeGen/RISCV/allow-check.ll | 31 ++++++ llvm/test/CodeGen/X86/allow-check.ll | 28 +++++ 19 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Analysis/MemorySSA/allow-check.ll create mode 100644 llvm/test/CodeGen/AArch64/allow-check.ll create mode 100644 llvm/test/CodeGen/AMDGPU/allow-check.ll create mode 100644 llvm/test/CodeGen/Generic/allow-check.ll create mode 100644 llvm/test/CodeGen/RISCV/allow-check.ll create mode 100644 llvm/test/CodeGen/X86/allow-check.ll diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 8bc1cab..773eb75 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -27696,6 +27696,121 @@ constant `true`. However it is always correct to replace it with any other `i1` value. Any pass can freely do it if it can benefit from non-default lowering. +'``llvm.allow.ubsan.check``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i1 @llvm.allow.ubsan.check(i8 immarg %kind) + +Overview: +""""""""" + +This intrinsic returns ``true`` if and only if the compiler opted to enable the +ubsan check in the current basic block. + +Rules to allow ubsan checks are not part of the intrinsic declaration, and +controlled by compiler options. + +This intrinsic is the ubsan specific version of ``@llvm.allow.runtime.check()``. + +Arguments: +"""""""""" + +An integer describing the kind of ubsan check guarded by the intrinsic. + +Semantics: +"""""""""" + +The intrinsic ``@llvm.allow.ubsan.check()`` returns either ``true`` or +``false``, depending on compiler options. + +For each evaluation of a call to this intrinsic, the program must be valid and +correct both if it returns ``true`` and if it returns ``false``. + +When used in a branch condition, it allows us to choose between +two alternative correct solutions for the same problem. + +If the intrinsic is evaluated as ``true``, program must check ubsan condition, +and report if needed. If the intrinsic is evaluated as ``false``, program must +avoid checking ubsan condition and assume it passed. + +Example: + +.. code-block:: text + + %allow = call i1 @llvm.allow.ubsan.check(i8 5) + %not.allow = xor i1 %allow, true + %cond = or i1 %ubcheck, %not.allow + br i1 %cond, label %cont, label %trap + + cont: + ; Proceed + + trap: + call void @llvm.ubsantrap(i8 5) + unreachable + + +'``llvm.allow.runtime.check``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i1 @llvm.allow.runtime.check(metadata %kind) + +Overview: +""""""""" + +This intrinsic returns ``true`` if and only if the compiler opted to enable +runtime checks in the current basic block. + +Rules to allow runtime checks are not part of the intrinsic declaration, and +controlled by compiler options. + +This intrinsic is non-ubsan specific version of ``@llvm.allow.ubsan.check()``. + +Arguments: +"""""""""" + +A string identifying the kind of runtime check guarded by the intrinsic. The +string can be used to control rules to allow checks. + +Semantics: +"""""""""" + +The intrinsic ``@llvm.allow.ubsan.check()`` returns either ``true`` or +``false``, depending on compiler options. + +For each evaluation of a call to this intrinsic, the program must be valid and +correct both if it returns ``true`` and if it returns ``false``. + +When used in a branch condition, it allows us to choose between +two alternative correct solutions for the same problem. + +If the intrinsic is evaluated as ``true``, program should execute a guarded +checks. If the intrinsic is evaluated as ``false``, the program should avoid any +unnecessary checks. + +Example: + +.. code-block:: text + + %allow = call i1 @llvm.allow.runtime.check(metadata !"my_check") + br i1 %allow, label %fast_path, label %slow_path + + fast_path: + ; Omit diagnostics. + + slow_path: + ; Additional diagnostics. + '``llvm.load.relative``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h index 7c47d3c..63c2ef8 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -714,6 +714,8 @@ public: switch (ICA.getID()) { default: break; + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: case Intrinsic::annotation: case Intrinsic::assume: case Intrinsic::sideeffect: diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 091f9b38..c0c4470 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1728,6 +1728,16 @@ def int_debugtrap : Intrinsic<[]>, def int_ubsantrap : Intrinsic<[], [llvm_i8_ty], [IntrNoReturn, IntrCold, ImmArg>]>; +// Return true if ubsan check is allowed. +def int_allow_ubsan_check : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i8_ty], + [IntrInaccessibleMemOnly, IntrWriteMem, ImmArg>, NoUndef]>, + ClangBuiltin<"__builtin_allow_ubsan_check">; + +// Return true if runtime check is allowed. +def int_allow_runtime_check : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_metadata_ty], + [IntrInaccessibleMemOnly, IntrWriteMem, NoUndef]>, + ClangBuiltin<"__builtin_allow_runtime_check">; + // Support for dynamic deoptimization (or de-specialization) def int_experimental_deoptimize : Intrinsic<[llvm_any_ty], [llvm_vararg_ty], [Throws]>; diff --git a/llvm/lib/Analysis/AliasSetTracker.cpp b/llvm/lib/Analysis/AliasSetTracker.cpp index 59bb40c..32e545d 100644 --- a/llvm/lib/Analysis/AliasSetTracker.cpp +++ b/llvm/lib/Analysis/AliasSetTracker.cpp @@ -354,6 +354,8 @@ void AliasSetTracker::addUnknown(Instruction *Inst) { default: break; // FIXME: Add lifetime/invariant intrinsics (See: PR30807). + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: case Intrinsic::assume: case Intrinsic::experimental_noalias_scope_decl: case Intrinsic::sideeffect: diff --git a/llvm/lib/Analysis/MemorySSA.cpp b/llvm/lib/Analysis/MemorySSA.cpp index 82a6c47..49450d8 100644 --- a/llvm/lib/Analysis/MemorySSA.cpp +++ b/llvm/lib/Analysis/MemorySSA.cpp @@ -292,6 +292,8 @@ instructionClobbersQuery(const MemoryDef *MD, const MemoryLocation &UseLoc, // clobbers where they don't really exist at all. Please see D43269 for // context. switch (II->getIntrinsicID()) { + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: case Intrinsic::invariant_start: case Intrinsic::invariant_end: case Intrinsic::assume: @@ -1725,6 +1727,8 @@ MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I, switch (II->getIntrinsicID()) { default: break; + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: case Intrinsic::assume: case Intrinsic::experimental_noalias_scope_decl: case Intrinsic::pseudoprobe: diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 9f99bb7..e657872 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -2462,8 +2462,10 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, ModifyDT &ModifiedDT) { break; case Intrinsic::assume: llvm_unreachable("llvm.assume should have been removed already"); + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: case Intrinsic::experimental_widenable_condition: { - // Give up on future widening oppurtunties so that we can fold away dead + // Give up on future widening opportunities so that we can fold away dead // paths and merge blocks before going into block-local instruction // selection. if (II->use_empty()) { diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 757af3b..0811c56 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2475,6 +2475,11 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, Info.OrigRet = {Register(), Type::getVoidTy(CI.getContext()), 0}; return CLI->lowerCall(MIRBuilder, Info); } + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: + MIRBuilder.buildCopy(getOrCreateVReg(CI), + getOrCreateVReg(*ConstantInt::getTrue(CI.getType()))); + return true; case Intrinsic::amdgcn_cs_chain: return translateCallBase(CI, MIRBuilder); case Intrinsic::fptrunc_round: { diff --git a/llvm/lib/CodeGen/IntrinsicLowering.cpp b/llvm/lib/CodeGen/IntrinsicLowering.cpp index 09d282d..45fba43 100644 --- a/llvm/lib/CodeGen/IntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/IntrinsicLowering.cpp @@ -243,6 +243,11 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { break; } + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: + CI->replaceAllUsesWith(ConstantInt::getTrue(CI->getType())); + return; + case Intrinsic::ctpop: CI->replaceAllUsesWith(LowerCTPOP(Context, CI->getArgOperand(0), CI)); break; diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index 27b8472..ce5a7ea 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1452,6 +1452,10 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) { case Intrinsic::is_constant: llvm_unreachable("llvm.is.constant.* should have been lowered already"); + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: + llvm_unreachable("llvm.*.check should have been lowered already"); + case Intrinsic::launder_invariant_group: case Intrinsic::strip_invariant_group: case Intrinsic::expect: { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 2d63774..51c9af6 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7322,6 +7322,11 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, return; } + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: + setValue(&I, getValue(ConstantInt::getTrue(I.getType()))); + return; + case Intrinsic::uadd_with_overflow: case Intrinsic::sadd_with_overflow: case Intrinsic::usub_with_overflow: diff --git a/llvm/test/Analysis/AliasSet/intrinsics.ll b/llvm/test/Analysis/AliasSet/intrinsics.ll index 678d6d2..0dc802c 100644 --- a/llvm/test/Analysis/AliasSet/intrinsics.ll +++ b/llvm/test/Analysis/AliasSet/intrinsics.ll @@ -74,6 +74,36 @@ entry: ret void } +; CHECK: Alias sets for function 'test_runtime': +; CHECK: Alias Set Tracker: 2 alias sets for 2 pointer values. +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %a, LocationSize::precise(1)) +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %b, LocationSize::precise(1)) +define i1 @test_runtime() local_unnamed_addr { +entry: + %a = alloca i8, align 1 + %b = alloca i8, align 1 + store i8 1, ptr %a, align 1 + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + store i8 1, ptr %b, align 1 + ret i1 %allow +} + +; CHECK: Alias sets for function 'test_ubsan': +; CHECK: Alias Set Tracker: 2 alias sets for 2 pointer values. +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %a, LocationSize::precise(1)) +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %b, LocationSize::precise(1)) +define i1 @test_ubsan() local_unnamed_addr { +entry: + %a = alloca i8, align 1 + %b = alloca i8, align 1 + store i8 1, ptr %a, align 1 + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + store i8 1, ptr %b, align 1 + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) +declare i1 @llvm.allow.runtime.check(metadata) declare void @llvm.assume(i1) declare void @llvm.experimental.guard(i1, ...) declare void @llvm.experimental.noalias.scope.decl(metadata) diff --git a/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll b/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll index 4ebb1e3..09fbd68 100644 --- a/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll +++ b/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll @@ -25,6 +25,8 @@ define i32 @trivially_free() { ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; @@ -45,6 +47,8 @@ define i32 @trivially_free() { ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; @@ -65,6 +69,8 @@ define i32 @trivially_free() { call void @llvm.lifetime.end.p0(i64 1, ptr undef) %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 1, i1 1, i1 1) %a6 = call ptr @llvm.ptr.annotation.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) + %a7 = call i1 @llvm.allow.ubsan.check(i8 123) + %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") call void @llvm.var.annotation(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ret i32 undef } diff --git a/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll b/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll index 5d47e48..3e78c62 100644 --- a/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll +++ b/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll @@ -24,6 +24,8 @@ define i32 @trivially_free() { ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; ; CHECK-THROUGHPUT-LABEL: 'trivially_free' @@ -44,6 +46,8 @@ define i32 @trivially_free() { ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %a0 = call i32 @llvm.annotation.i32(i32 undef, ptr undef, ptr undef, i32 undef) @@ -64,6 +68,8 @@ define i32 @trivially_free() { %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 1, i1 1, i1 1) %a6 = call ptr @llvm.ptr.annotation.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) call void @llvm.var.annotation(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) + %a7 = call i1 @llvm.allow.ubsan.check(i8 123) + %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") ret i32 undef } diff --git a/llvm/test/Analysis/MemorySSA/allow-check.ll b/llvm/test/Analysis/MemorySSA/allow-check.ll new file mode 100644 index 0000000..dcdad00 --- /dev/null +++ b/llvm/test/Analysis/MemorySSA/allow-check.ll @@ -0,0 +1,29 @@ +; RUN: opt -aa-pipeline=basic-aa -passes='print,verify' -disable-output < %s 2>&1 | FileCheck %s --implicit-check-not=MemoryDef +; +; Ensures that allow.*.check are treated as not reading or writing memory. + +target triple = "aarch64-linux" + +define i1 @test_runtime(ptr %a) local_unnamed_addr { +entry: +; CHECK: 1 = MemoryDef(liveOnEntry) + store i32 4, ptr %a, align 4 + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + %0 = load i32, ptr %a, align 4 +; CHECK: MemoryUse(1) + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) + +define i1 @test_ubsan(ptr %a) local_unnamed_addr { +entry: +; CHECK: 1 = MemoryDef(liveOnEntry) + store i32 4, ptr %a, align 4 + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + %0 = load i32, ptr %a, align 4 +; CHECK: MemoryUse(1) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) diff --git a/llvm/test/CodeGen/AArch64/allow-check.ll b/llvm/test/CodeGen/AArch64/allow-check.ll new file mode 100644 index 0000000..c315b21 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/allow-check.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=aarch64 | FileCheck %s +; RUN: llc < %s -mtriple=aarch64 -global-isel | FileCheck %s +; RUN: llc < %s -mtriple=aarch64 -fast-isel | FileCheck %s + +target triple = "aarch64-linux" + +define i1 @test_runtime() local_unnamed_addr { +; CHECK-LABEL: test_runtime: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, #1 // =0x1 +; CHECK-NEXT: ret +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) nounwind + +define i1 @test_ubsan() local_unnamed_addr { +; CHECK-LABEL: test_ubsan: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, #1 // =0x1 +; CHECK-NEXT: ret +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) nounwind diff --git a/llvm/test/CodeGen/AMDGPU/allow-check.ll b/llvm/test/CodeGen/AMDGPU/allow-check.ll new file mode 100644 index 0000000..db6cdc3 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/allow-check.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=amdgcn-amd-mesa3d | FileCheck %s +; RUN: llc < %s -mtriple=amdgcn-amd-mesa3d -global-isel | FileCheck %s +; RUN: llc < %s -mtriple=amdgcn-amd-mesa3d -fast-isel | FileCheck %s + +define i1 @test_runtime() local_unnamed_addr { +; CHECK-LABEL: test_runtime: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_mov_b32_e32 v0, 1 +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) nounwind + +define i1 @test_ubsan() local_unnamed_addr { +; CHECK-LABEL: test_ubsan: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_mov_b32_e32 v0, 1 +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) nounwind diff --git a/llvm/test/CodeGen/Generic/allow-check.ll b/llvm/test/CodeGen/Generic/allow-check.ll new file mode 100644 index 0000000..88412f5 --- /dev/null +++ b/llvm/test/CodeGen/Generic/allow-check.ll @@ -0,0 +1,23 @@ +; RUN: llc < %s -O3 +; RUN: llc < %s -O3 -global-isel +; RUN: llc < %s -O3 -fast-isel + +; RUN: llc < %s -O0 +; RUN: llc < %s -O0 -global-isel +; RUN: llc < %s -O0 -fast-isel + +define i1 @test_runtime() local_unnamed_addr { +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) nounwind + +define i1 @test_ubsan() local_unnamed_addr { +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) nounwind diff --git a/llvm/test/CodeGen/RISCV/allow-check.ll b/llvm/test/CodeGen/RISCV/allow-check.ll new file mode 100644 index 0000000..2ac6370 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/allow-check.ll @@ -0,0 +1,31 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=riscv32 | FileCheck %s +; RUN: llc < %s -mtriple=riscv64 | FileCheck %s +; RUN: llc < %s -mtriple=riscv32 -global-isel | FileCheck %s +; RUN: llc < %s -mtriple=riscv64 -global-isel | FileCheck %s +; RUN: llc < %s -mtriple=riscv32 -fast-isel=true | FileCheck %s +; RUN: llc < %s -mtriple=riscv64 -fast-isel=true | FileCheck %s + +define i1 @test_runtime() local_unnamed_addr { +; CHECK-LABEL: test_runtime: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: li a0, 1 +; CHECK-NEXT: ret +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) nounwind + +define i1 @test_ubsan() local_unnamed_addr { +; CHECK-LABEL: test_ubsan: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: li a0, 1 +; CHECK-NEXT: ret +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) nounwind diff --git a/llvm/test/CodeGen/X86/allow-check.ll b/llvm/test/CodeGen/X86/allow-check.ll new file mode 100644 index 0000000..3f0bb18 --- /dev/null +++ b/llvm/test/CodeGen/X86/allow-check.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=x86_64 | FileCheck %s +; RUN: llc < %s -mtriple=x86_64 -global-isel | FileCheck %s +; RUN: llc < %s -mtriple=x86_64 -fast-isel | FileCheck %s + +define i1 @test_runtime() local_unnamed_addr { +; CHECK-LABEL: test_runtime: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movb $1, %al +; CHECK-NEXT: retq +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) nounwind + +define i1 @test_ubsan() local_unnamed_addr { +; CHECK-LABEL: test_ubsan: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movb $1, %al +; CHECK-NEXT: retq +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) nounwind -- cgit v1.1