diff options
| author | bors <bors@rust-lang.org> | 2014-10-25 00:32:07 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-10-25 00:32:07 +0000 |
| commit | 172b59abe510dde5826fec24377f208a19418c04 (patch) | |
| tree | a0c5c42df701d0d0dd9a6874a1badc17d46237c5 /src | |
| parent | a10917a6a9b087d10ac4fd0186b719218627281e (diff) | |
| parent | 0c18da503ca674eb4cbf8504b52afb2d7c242ae5 (diff) | |
| download | rust-172b59abe510dde5826fec24377f208a19418c04.tar.gz rust-172b59abe510dde5826fec24377f208a19418c04.zip | |
auto merge of #18080 : veddan/rust/assume, r=thestinger
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/intrinsics.rs | 11 | ||||
| -rw-r--r-- | src/librustc/middle/trans/context.rs | 1 | ||||
| -rw-r--r-- | src/librustc/middle/trans/intrinsic.rs | 1 | ||||
| -rw-r--r-- | src/librustc/middle/typeck/check/mod.rs | 2 | ||||
| -rw-r--r-- | src/test/run-pass/intrinsic-assume.rs | 25 |
5 files changed, 40 insertions, 0 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 3d593a0d026..8486535d188 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -260,6 +260,17 @@ 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 intrinsic, but the optimizer will try + /// to preserve it (and its condition) between passes, which may interfere + /// with optimization of surrounding code and reduce performance. It should + /// not be used if the invariant can be discovered by the optimizer on its + /// own, or if it does not enable any significant optimizations. + #[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 683e1b30c8c..90159389688 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -860,6 +860,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 diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index e81844efad3..3e75b0772fb 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 2755c4e2f78..736ebb8244a 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -5703,6 +5703,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 00000000000..abf9b94c59d --- /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 <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); +} + |
