From ee041f8e9c0a9c04d413ea6171481724eb77aac2 Mon Sep 17 00:00:00 2001 From: DianQK Date: Fri, 5 Jul 2024 22:04:22 +0800 Subject: [PATCH] Emit `assume(false)` as `store i1 true, ptr poison, align 1` Store to poison is the canonical form for non-terminator unreachable. --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 15 ++++++++++++++- tests/codegen/assume-false.rs | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/codegen/assume-false.rs diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 68c3d47e826bf..10498b996fa35 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -566,7 +566,20 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { } fn assume(&mut self, val: Self::Value) { - self.call_intrinsic("llvm.assume", &[val]); + match self.const_to_opt_uint(val) { + Some(0) => { + // See https://github.com/llvm/llvm-project/blob/1347b9a3aa671d610e812579ab5e5f05870586cf/llvm/docs/Frontend/PerformanceTips.rst?plain=1#L204-L211. + self.store( + self.const_bool(true), + self.const_poison(self.type_ptr()), + self.tcx().data_layout.i1_align.abi, + ); + } + Some(_) => {} + None => { + self.call_intrinsic("llvm.assume", &[val]); + } + } } fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value { diff --git a/tests/codegen/assume-false.rs b/tests/codegen/assume-false.rs new file mode 100644 index 0000000000000..cc82ca5bdbbe3 --- /dev/null +++ b/tests/codegen/assume-false.rs @@ -0,0 +1,14 @@ +//@ compile-flags: -Cno-prepopulate-passes -Zmir-opt-level=0 -O -Zinline-mir + +#![crate_type = "lib"] + +#[no_mangle] +pub fn unwrap_unchecked(x: Option) -> i32 { + // CHECK-LABEL: define{{.*}} i32 @unwrap_unchecked + // CHECK-NOT: call void @llvm.assume(i1 false) + // CHECK: store i1 true, ptr poison, align 1 + // CHECK-NOT: call void @llvm.assume(i1 false) + // CHECK: ret + // CHECK } + unsafe { x.unwrap_unchecked() } +}