about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-10-25 00:32:07 +0000
committerbors <bors@rust-lang.org>2014-10-25 00:32:07 +0000
commit172b59abe510dde5826fec24377f208a19418c04 (patch)
treea0c5c42df701d0d0dd9a6874a1badc17d46237c5 /src
parenta10917a6a9b087d10ac4fd0186b719218627281e (diff)
parent0c18da503ca674eb4cbf8504b52afb2d7c242ae5 (diff)
downloadrust-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.rs11
-rw-r--r--src/librustc/middle/trans/context.rs1
-rw-r--r--src/librustc/middle/trans/intrinsic.rs1
-rw-r--r--src/librustc/middle/typeck/check/mod.rs2
-rw-r--r--src/test/run-pass/intrinsic-assume.rs25
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);
+}
+