diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index dd488a74216eb..a87a30196fb0b 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -176,6 +176,26 @@ extern "rust-intrinsic" { /// own, or if it does not enable any significant optimizations. pub fn assume(b: bool); + /// Inform the optimizer that `expected_val` is expected + /// (the most probable) value of val. + #[cfg(not(stage0))] + pub fn expect8(val: u8, expected_val: u8) -> u8; + + /// Inform the optimizer that `expected_val` is expected + /// (the most probable) value of val. + #[cfg(not(stage0))] + pub fn expect16(val: u16, expected_val: u16) -> u16; + + /// Inform the optimizer that `expected_val` is expected + /// (the most probable) value of val. + #[cfg(not(stage0))] + pub fn expect32(val: u32, expected_val: u32) -> u32; + + /// Inform the optimizer that `expected_val` is expected + /// (the most probable) value of val. + #[cfg(not(stage0))] + pub fn expect64(val: u64, expected_val: u64) -> u64; + /// Execute a breakpoint trap, for inspection by a debugger. pub fn breakpoint(); @@ -545,3 +565,32 @@ extern "rust-intrinsic" { /// Performs checked `u64` multiplication. pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool); } + +/// Inform the optimizer that `expected_val` is expected +/// (the most probable) value of val. +#[cfg(stage0)] +pub unsafe fn expect8(val: u8, _expected_val: u8) -> u8 { + val +} + +/// Inform the optimizer that `expected_val` is expected +/// (the most probable) value of val. +#[cfg(stage0)] +pub unsafe fn expect16(val: u16, _expected_val: u16) -> u16 { + val +} + +/// Inform the optimizer that `expected_val` is expected +/// (the most probable) value of val. +#[cfg(stage0)] +pub unsafe fn expect32(val: u32, _expected_val: u32) -> u32 { + val +} + +/// Inform the optimizer that `expected_val` is expected +/// (the most probable) value of val. +#[cfg(stage0)] +pub unsafe fn expect64(val: u64, _expected_val: u64) -> u64 { + val +} + diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 10edb72f0e200..650b36c9f4211 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -873,6 +873,10 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option void); ifn!("llvm.expect.i1", fn(i1, i1) -> i1); + ifn!("llvm.expect.i8", fn(t_i8, t_i8) -> t_i8); + ifn!("llvm.expect.i16", fn(t_i16, t_i16) -> t_i16); + ifn!("llvm.expect.i32", fn(t_i32, t_i32) -> t_i32); + ifn!("llvm.expect.i64", fn(t_i64, t_i64) -> t_i64); ifn!("llvm.assume", fn(i1) -> void); // Some intrinsics were introduced in later versions of LLVM, but they have diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 9bee2c5bbc61c..38d59333c9442 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -83,6 +83,10 @@ pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Opti "bswap32" => "llvm.bswap.i32", "bswap64" => "llvm.bswap.i64", "assume" => "llvm.assume", + "expect8" => "llvm.assume.i8", + "expect16" => "llvm.assume.i16", + "expect32" => "llvm.assume.i32", + "expect64" => "llvm.assume.i64", _ => return None }; Some(ccx.get_intrinsic(&name)) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a9f81d3a26632..85ebe7e301d09 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5434,6 +5434,11 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)), + "expect8" => (0, vec![tcx.types.u8, tcx.types.u8], tcx.types.u8), + "expect16" => (0, vec![tcx.types.u16, tcx.types.u16], tcx.types.u16), + "expect32" => (0, vec![tcx.types.u32, tcx.types.u32], tcx.types.u32), + "expect64" => (0, vec![tcx.types.u64, tcx.types.u64], tcx.types.u64), + ref other => { span_err!(tcx.sess, it.span, E0093, "unrecognized intrinsic function: `{}`", *other); diff --git a/src/test/run-pass/intrinsic-expect.rs b/src/test/run-pass/intrinsic-expect.rs new file mode 100644 index 0000000000000..02fe52ac474cb --- /dev/null +++ b/src/test/run-pass/intrinsic-expect.rs @@ -0,0 +1,35 @@ +// Copyright 2015 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::expect8; + +fn check8(x: u8) -> u8 { + let b = (x > 0) as u8; + if unsafe { expect8(b, 1) == 1 } { + 10 + } else { + 5 + } +} + +fn main() { + let x = check8(1); + assert_eq!(x, 10); + let x = check8(2); + assert_eq!(x, 10); + let x = check8(5); + assert_eq!(x, 10); + let x = check8(10); + assert_eq!(x, 10); + let x = check8(-1); + assert_eq!(x, 5); + +}