diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 3f7dcb36cf698..5570d356149dc 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -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(); diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index ee5ba61a295cf..d7ab02f373cf1 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -855,6 +855,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option 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 diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index f463f258ad550..7951b3be0e573 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -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)) diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index d88e01f6e495f..296a6b40e54fc 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -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); diff --git a/src/test/run-pass/intrinsic-assume.rs b/src/test/run-pass/intrinsic-assume.rs new file mode 100644 index 0000000000000..abf9b94c59d8a --- /dev/null +++ b/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 or the MIT license +// , 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); +} +