Skip to content

Commit 0525bb7

Browse files
committed
Add assume intrinsic
Adds an `assume` intrinsic that gets translated to llvm.assume. It is used on a boolean expression and allows the optimizer to assume that the expression is true. This implements #18051.
1 parent e4761c8 commit 0525bb7

File tree

5 files changed

+36
-0
lines changed

5 files changed

+36
-0
lines changed

src/libcore/intrinsics.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,13 @@ extern "rust-intrinsic" {
256256
/// NB: This is very different from the `unreachable!()` macro!
257257
pub fn unreachable() -> !;
258258

259+
/// Inform the optimizer that a condition is always true.
260+
/// If the condition is false, the behavior is undefined.
261+
///
262+
/// No code is generated for this intrisic.
263+
#[cfg(not(stage0))]
264+
pub fn assume(b: bool);
265+
259266
/// Execute a breakpoint trap, for inspection by a debugger.
260267
pub fn breakpoint();
261268

src/librustc/middle/trans/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
855855
ifn!("llvm.lifetime.end" fn(t_i64, i8p) -> void);
856856

857857
ifn!("llvm.expect.i1" fn(i1, i1) -> i1);
858+
ifn!("llvm.assume" fn(i1) -> void);
858859

859860
// Some intrinsics were introduced in later versions of LLVM, but they have
860861
// fallbacks in libc or libm and such. Currently, all of these intrinsics

src/librustc/middle/trans/intrinsic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Opti
8181
"bswap16" => "llvm.bswap.i16",
8282
"bswap32" => "llvm.bswap.i32",
8383
"bswap64" => "llvm.bswap.i64",
84+
"assume" => "llvm.assume",
8485
_ => return None
8586
};
8687
Some(ccx.get_intrinsic(&name))

src/librustc/middle/typeck/check/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5754,6 +5754,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
57545754

57555755
"return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
57565756

5757+
"assume" => (0, vec![ty::mk_bool()], ty::mk_nil()),
5758+
57575759
ref other => {
57585760
span_err!(tcx.sess, it.span, E0093,
57595761
"unrecognized intrinsic function: `{}`", *other);

src/test/run-pass/intrinsic-assume.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::intrinsics::assume;
12+
13+
unsafe fn f(x: i32) -> i32 {
14+
assume(x == 34);
15+
match x {
16+
34 => 42,
17+
_ => 30
18+
}
19+
}
20+
21+
fn main() {
22+
let x = unsafe { f(34) };
23+
assert_eq!(x, 42);
24+
}
25+

0 commit comments

Comments
 (0)