Skip to content

Commit

Permalink
Add assume intrinsic
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
veddan committed Oct 15, 2014
1 parent e4761c8 commit 0525bb7
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/libcore/intrinsics.rs
Expand Up @@ -256,6 +256,13 @@ extern "rust-intrinsic" {
/// NB: This is very different from the `unreachable!()` macro!
pub fn unreachable() -> !;

/// Inform the optimizer that a condition is always true.
/// If the condition is false, the behavior is undefined.
///
/// No code is generated for this intrisic.
#[cfg(not(stage0))]
pub fn assume(b: bool);

/// Execute a breakpoint trap, for inspection by a debugger.
pub fn breakpoint();

Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/trans/context.rs
Expand Up @@ -855,6 +855,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
ifn!("llvm.lifetime.end" fn(t_i64, i8p) -> void);

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

// Some intrinsics were introduced in later versions of LLVM, but they have
// fallbacks in libc or libm and such. Currently, all of these intrinsics
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/trans/intrinsic.rs
Expand Up @@ -81,6 +81,7 @@ pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Opti
"bswap16" => "llvm.bswap.i16",
"bswap32" => "llvm.bswap.i32",
"bswap64" => "llvm.bswap.i64",
"assume" => "llvm.assume",
_ => return None
};
Some(ccx.get_intrinsic(&name))
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/typeck/check/mod.rs
Expand Up @@ -5754,6 +5754,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {

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

"assume" => (0, vec![ty::mk_bool()], ty::mk_nil()),

ref other => {
span_err!(tcx.sess, it.span, E0093,
"unrecognized intrinsic function: `{}`", *other);
Expand Down
25 changes: 25 additions & 0 deletions src/test/run-pass/intrinsic-assume.rs
@@ -0,0 +1,25 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::intrinsics::assume;

unsafe fn f(x: i32) -> i32 {
assume(x == 34);
match x {
34 => 42,
_ => 30
}
}

fn main() {
let x = unsafe { f(34) };
assert_eq!(x, 42);
}

0 comments on commit 0525bb7

Please sign in to comment.