diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 3cdbc38ab07f9..a2ffb191436ed 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1066,14 +1066,46 @@ pub fn with_cond<'a>( -> &'a Block<'a> { let _icx = push_ctxt("with_cond"); let fcx = bcx.fcx; - let next_cx = fcx.new_temp_block("next"); - let cond_cx = fcx.new_temp_block("cond"); - CondBr(bcx, val, cond_cx.llbb, next_cx.llbb); - let after_cx = f(cond_cx); - if !after_cx.terminated.get() { - Br(after_cx, next_cx.llbb); - } - next_cx + + let is_const = unsafe { llvm::LLVMIsConstant(val) != 0}; + + if !is_const { + let next_cx = fcx.new_temp_block("next"); + let cond_cx = fcx.new_temp_block("cond"); + CondBr(bcx, val, cond_cx.llbb, next_cx.llbb); + let after_cx = f(cond_cx); + if !after_cx.terminated.get() { + Br(after_cx, next_cx.llbb); + } + next_cx + } else { + let val = unsafe { + llvm::LLVMConstIntGetZExtValue(val) != 0 + }; + if val { + f(bcx) + } else { + bcx + } + } +} + +pub fn with_cond_expected<'a>( + bcx: &'a Block<'a>, + val: ValueRef, + expected: bool, + f: |&'a Block<'a>| -> &'a Block<'a>) + -> &'a Block<'a> { + + let is_const = unsafe { llvm::LLVMIsConstant(val) != 0}; + + if !is_const { + let expect = bcx.ccx().intrinsics.get_copy(&("llvm.expect.i1")); + let expected = Call(bcx, expect, [val, C_i1(bcx.ccx(), expected)], []); + with_cond(bcx, expected, f) + } else { + with_cond(bcx, val, f) + } } pub fn call_memcpy(cx: &Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) { diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 543f2bcf968ae..94f5600998ffb 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -521,11 +521,9 @@ fn trans_index<'a>(bcx: &'a Block<'a>, debug!("trans_index: len {}", bcx.val_to_str(len)); let bounds_check = ICmp(bcx, lib::llvm::IntUGE, ix_val, len); - let expect = ccx.intrinsics.get_copy(&("llvm.expect.i1")); - let expected = Call(bcx, expect, [bounds_check, C_i1(ccx, false)], []); - let bcx = with_cond(bcx, expected, |bcx| { - controlflow::trans_fail_bounds_check(bcx, index_expr.span, ix_val, len) - }); + let bcx = with_cond_expected(bcx, bounds_check, false, |bcx| { + controlflow::trans_fail_bounds_check(bcx, index_expr.span, ix_val, len) + }); let elt = InBoundsGEP(bcx, base, [ix_val]); let elt = PointerCast(bcx, elt, vt.llunit_ty.ptr_to()); DatumBlock(bcx, Datum(elt, vt.unit_ty, LvalueExpr))