Skip to content

Commit 172b59a

Browse files
committed
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.
2 parents a10917a + 0c18da5 commit 172b59a

File tree

5 files changed

+40
-0
lines changed

5 files changed

+40
-0
lines changed

src/libcore/intrinsics.rs

+11
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,17 @@ extern "rust-intrinsic" {
260260
/// NB: This is very different from the `unreachable!()` macro!
261261
pub fn unreachable() -> !;
262262

263+
/// Inform the optimizer that a condition is always true.
264+
/// If the condition is false, the behavior is undefined.
265+
///
266+
/// No code is generated for this intrinsic, but the optimizer will try
267+
/// to preserve it (and its condition) between passes, which may interfere
268+
/// with optimization of surrounding code and reduce performance. It should
269+
/// not be used if the invariant can be discovered by the optimizer on its
270+
/// own, or if it does not enable any significant optimizations.
271+
#[cfg(not(stage0))]
272+
pub fn assume(b: bool);
273+
263274
/// Execute a breakpoint trap, for inspection by a debugger.
264275
pub fn breakpoint();
265276

src/librustc/middle/trans/context.rs

+1
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
860860
ifn!("llvm.lifetime.end" fn(t_i64, i8p) -> void);
861861

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

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

src/librustc/middle/trans/intrinsic.rs

+1
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

+2
Original file line numberDiff line numberDiff line change
@@ -5703,6 +5703,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
57035703

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

5706+
"assume" => (0, vec![ty::mk_bool()], ty::mk_nil()),
5707+
57065708
ref other => {
57075709
span_err!(tcx.sess, it.span, E0093,
57085710
"unrecognized intrinsic function: `{}`", *other);

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

+25
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)