Skip to content

Improve optimizations for boolean values #15464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 7, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ pub fn trans_case<'a>(bcx: &'a Block<'a>, r: &Repr, discr: Disr)
RawNullablePointer { .. } |
StructWrappedNullablePointer { .. } => {
assert!(discr == 0 || discr == 1);
_match::single_result(Result::new(bcx, C_i1(bcx.ccx(), discr != 0)))
_match::single_result(Result::new(bcx, C_bool(bcx.ccx(), discr != 0)))
}
}
}
Expand All @@ -641,7 +641,7 @@ pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
}
Univariant(ref st, true) => {
assert_eq!(discr, 0);
Store(bcx, C_bool(bcx.ccx(), true),
Store(bcx, C_u8(bcx.ccx(), 1),
GEPi(bcx, val, [0, st.fields.len() - 1]))
}
Univariant(..) => {
Expand Down
66 changes: 53 additions & 13 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,8 @@ pub fn compare_scalar_values<'a>(
// We don't need to do actual comparisons for nil.
// () == () holds but () < () does not.
match op {
ast::BiEq | ast::BiLe | ast::BiGe => return C_i1(cx.ccx(), true),
ast::BiNe | ast::BiLt | ast::BiGt => return C_i1(cx.ccx(), false),
ast::BiEq | ast::BiLe | ast::BiGe => return C_bool(cx.ccx(), true),
ast::BiNe | ast::BiLt | ast::BiGt => return C_bool(cx.ccx(), false),
// refinements would be nice
_ => die(cx)
}
Expand Down Expand Up @@ -959,10 +959,42 @@ pub fn need_invoke(bcx: &Block) -> bool {

pub fn load_if_immediate(cx: &Block, v: ValueRef, t: ty::t) -> ValueRef {
let _icx = push_ctxt("load_if_immediate");
if type_is_immediate(cx.ccx(), t) { return Load(cx, v); }
if type_is_immediate(cx.ccx(), t) { return load_ty(cx, v, t); }
return v;
}

pub fn load_ty(cx: &Block, ptr: ValueRef, t: ty::t) -> ValueRef {
/*!
* Helper for loading values from memory. Does the necessary conversion if
* the in-memory type differs from the type used for SSA values. Also
* handles various special cases where the type gives us better information
* about what we are loading.
*/
if type_is_zero_size(cx.ccx(), t) {
C_undef(type_of::type_of(cx.ccx(), t))
} else if ty::type_is_bool(t) {
Trunc(cx, LoadRangeAssert(cx, ptr, 0, 2, lib::llvm::False), Type::i1(cx.ccx()))
} else if ty::type_is_char(t) {
// a char is a unicode codepoint, and so takes values from 0
// to 0x10FFFF inclusive only.
LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, lib::llvm::False)
} else {
Load(cx, ptr)
}
}

pub fn store_ty(cx: &Block, v: ValueRef, dst: ValueRef, t: ty::t) {
/*!
* Helper for storing values in memory. Does the necessary conversion if
* the in-memory type differs from the type used for SSA values.
*/
if ty::type_is_bool(t) {
Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst);
} else {
Store(cx, v, dst);
};
}

pub fn ignore_lhs(_bcx: &Block, local: &ast::Local) -> bool {
match local.pat.node {
ast::PatWild => true, _ => false
Expand Down Expand Up @@ -1014,7 +1046,7 @@ pub fn call_memcpy(cx: &Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef,
let dst_ptr = PointerCast(cx, dst, Type::i8p(ccx));
let size = IntCast(cx, n_bytes, ccx.int_type);
let align = C_i32(ccx, align as i32);
let volatile = C_i1(ccx, false);
let volatile = C_bool(ccx, false);
Call(cx, memcpy, [dst_ptr, src_ptr, size, align, volatile], []);
}

Expand Down Expand Up @@ -1059,7 +1091,7 @@ fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
let llzeroval = C_u8(ccx, 0);
let size = machine::llsize_of(ccx, ty);
let align = C_i32(ccx, llalign_of_min(ccx, ty) as i32);
let volatile = C_i1(ccx, false);
let volatile = C_bool(ccx, false);
b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile], []);
}

Expand Down Expand Up @@ -1285,9 +1317,14 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
// Ties up the llstaticallocas -> llloadenv -> lltop edges,
// and builds the return block.
pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>,
last_bcx: &'a Block<'a>) {
last_bcx: &'a Block<'a>,
retty: ty::t) {
let _icx = push_ctxt("finish_fn");

// This shouldn't need to recompute the return type,
// as new_fn_ctxt did it already.
let substd_retty = retty.substp(fcx.ccx.tcx(), fcx.param_substs);

let ret_cx = match fcx.llreturn.get() {
Some(llreturn) => {
if !last_bcx.terminated.get() {
Expand All @@ -1297,13 +1334,13 @@ pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>,
}
None => last_bcx
};
build_return_block(fcx, ret_cx);
build_return_block(fcx, ret_cx, substd_retty);
debuginfo::clear_source_location(fcx);
fcx.cleanup();
}

// Builds the return block for a function.
pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) {
pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block, retty: ty::t) {
// Return the value if this function immediate; otherwise, return void.
if fcx.llretptr.get().is_none() || fcx.caller_expects_out_pointer {
return RetVoid(ret_cx);
Expand All @@ -1321,13 +1358,16 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) {
retptr.erase_from_parent();
}

retval
if ty::type_is_bool(retty) {
Trunc(ret_cx, retval, Type::i1(fcx.ccx))
} else {
retval
}
}
// Otherwise, load the return value from the ret slot
None => Load(ret_cx, fcx.llretptr.get().unwrap())
None => load_ty(ret_cx, fcx.llretptr.get().unwrap(), retty)
};


Ret(ret_cx, retval);
}

Expand Down Expand Up @@ -1429,7 +1469,7 @@ pub fn trans_closure(ccx: &CrateContext,
}

// Insert the mandatory first few basic blocks before lltop.
finish_fn(&fcx, bcx);
finish_fn(&fcx, bcx, output_type);
}

// trans_fn: creates an LLVM function corresponding to a source language
Expand Down Expand Up @@ -1521,7 +1561,7 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
}
}

finish_fn(&fcx, bcx);
finish_fn(&fcx, bcx, result_ty);
}

fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/cabi_arm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ fn ty_size(ty: Type) -> uint {

fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
return ArgType::direct(ty, None, None, attr);
}
let size = ty_size(ty);
Expand All @@ -104,7 +104,7 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {

fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
return ArgType::direct(ty, None, None, attr);
}
let align = ty_align(ty);
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/cabi_mips.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ fn ty_size(ty: Type) -> uint {

fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
ArgType::direct(ty, None, None, attr)
} else {
ArgType::indirect(ty, Some(StructRetAttribute))
Expand All @@ -102,7 +102,7 @@ fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut uint) -> ArgType {
*offset += align_up_to(size, align * 8) / 8;

if is_reg_ty(ty) {
let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
ArgType::direct(ty, None, None, attr)
} else {
ArgType::direct(
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/cabi_x86.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
}
}
} else {
let attr = if rty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
let attr = if rty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
ret_ty = ArgType::direct(rty, None, None, attr);
}

Expand All @@ -74,7 +74,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
}
}
_ => {
let attr = if t == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
let attr = if t == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
ArgType::direct(t, None, None, attr)
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/cabi_x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
None)
}
} else {
let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
ArgType::direct(ty, None, None, attr)
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ pub fn trans_unboxing_shim(bcx: &Block,
}).bcx;

bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope);
finish_fn(&fcx, bcx);
finish_fn(&fcx, bcx, return_type);

llfn
}
Expand Down Expand Up @@ -758,7 +758,7 @@ pub fn trans_call_inner<'a>(
if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
!type_is_zero_size(bcx.ccx(), ret_ty)
{
Store(bcx, llret, llretslot);
store_ty(bcx, llret, llretslot, ret_ty)
}
}
None => {}
Expand Down
4 changes: 0 additions & 4 deletions src/librustc/middle/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,10 +526,6 @@ pub fn C_nil(ccx: &CrateContext) -> ValueRef {
}

pub fn C_bool(ccx: &CrateContext, val: bool) -> ValueRef {
C_integral(Type::bool(ccx), val as u64, false)
}

pub fn C_i1(ccx: &CrateContext, val: bool) -> ValueRef {
C_integral(Type::i1(ccx), val as u64, false)
}

Expand Down
28 changes: 4 additions & 24 deletions src/librustc/middle/trans/datum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@
* Datums are and how they are intended to be used.
*/

use lib;
use lib::llvm::ValueRef;
use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::cleanup;
use middle::trans::cleanup::CleanupMethods;
Expand Down Expand Up @@ -344,7 +342,7 @@ impl Datum<Rvalue> {
match self.kind.mode {
ByValue => DatumBlock::new(bcx, self),
ByRef => {
let llval = load(bcx, self.val, self.ty);
let llval = load_ty(bcx, self.val, self.ty);
DatumBlock::new(bcx, Datum::new(llval, self.ty, Rvalue::new(ByValue)))
}
}
Expand Down Expand Up @@ -471,7 +469,7 @@ impl Datum<Expr> {
DatumBlock::new(bcx, scratch)
}
ByValue => {
let v = load(bcx, l.val, l.ty);
let v = load_ty(bcx, l.val, l.ty);
bcx = l.kind.post_store(bcx, l.val, l.ty);
DatumBlock::new(bcx, Datum::new(v, l.ty, Rvalue::new(ByValue)))
}
Expand Down Expand Up @@ -516,24 +514,6 @@ impl Datum<Lvalue> {
}
}

fn load<'a>(bcx: &'a Block<'a>, llptr: ValueRef, ty: ty::t) -> ValueRef {
/*!
* Private helper for loading from a by-ref datum. Handles various
* special cases where the type gives us better information about
* what we are loading.
*/

if type_is_zero_size(bcx.ccx(), ty) {
C_undef(type_of::type_of(bcx.ccx(), ty))
} else if ty::type_is_char(ty) {
// a char is a unicode codepoint, and so takes values from 0
// to 0x10FFFF inclusive only.
LoadRangeAssert(bcx, llptr, 0, 0x10FFFF + 1, lib::llvm::False)
} else {
Load(bcx, llptr)
}
}

/**
* Generic methods applicable to any sort of datum.
*/
Expand Down Expand Up @@ -591,7 +571,7 @@ impl<K:KindOps> Datum<K> {
if self.kind.is_by_ref() {
memcpy_ty(bcx, dst, self.val, self.ty);
} else {
Store(bcx, self.val, dst);
store_ty(bcx, self.val, dst, self.ty);
}

return bcx;
Expand Down Expand Up @@ -642,7 +622,7 @@ impl<K:KindOps> Datum<K> {
assert!(!ty::type_needs_drop(bcx.tcx(), self.ty));
assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue);
if self.kind.is_by_ref() {
load(bcx, self.val, self.ty)
load_ty(bcx, self.val, self.ty)
} else {
self.val
}
Expand Down
18 changes: 6 additions & 12 deletions src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ fn trans_index<'a>(bcx: &'a Block<'a>,

let bounds_check = ICmp(bcx, lib::llvm::IntUGE, ix_val, len);
let expect = ccx.get_intrinsic(&("llvm.expect.i1"));
let expected = Call(bcx, expect, [bounds_check, C_i1(ccx, false)], []);
let expected = Call(bcx, expect, [bounds_check, C_bool(ccx, false)], []);
let bcx = with_cond(bcx, expected, |bcx| {
controlflow::trans_fail_bounds_check(bcx, index_expr.span, ix_val, len)
});
Expand Down Expand Up @@ -1149,13 +1149,7 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
match op {
ast::UnNot => {
let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
let llresult = if ty::type_is_bool(un_ty) {
let val = datum.to_llscalarish(bcx);
Xor(bcx, val, C_bool(ccx, true))
} else {
// Note: `Not` is bitwise, not suitable for logical not.
Not(bcx, datum.to_llscalarish(bcx))
};
let llresult = Not(bcx, datum.to_llscalarish(bcx));
immediate_rvalue_bcx(bcx, llresult, un_ty).to_expr_datumblock()
}
ast::UnNeg => {
Expand Down Expand Up @@ -1380,7 +1374,7 @@ fn trans_lazy_binop<'a>(
}

Br(past_rhs, join.llbb);
let phi = Phi(join, Type::bool(bcx.ccx()), [lhs, rhs],
let phi = Phi(join, Type::i1(bcx.ccx()), [lhs, rhs],
[past_lhs.llbb, past_rhs.llbb]);

return immediate_rvalue_bcx(join, phi, binop_ty).to_expr_datumblock();
Expand Down Expand Up @@ -1597,8 +1591,8 @@ fn trans_imm_cast<'a>(bcx: &'a Block<'a>,
let k_in = cast_type_kind(t_in);
let k_out = cast_type_kind(t_out);
let s_in = k_in == cast_integral && ty::type_is_signed(t_in);
let ll_t_in = type_of::type_of(ccx, t_in);
let ll_t_out = type_of::type_of(ccx, t_out);
let ll_t_in = type_of::arg_type_of(ccx, t_in);
let ll_t_out = type_of::arg_type_of(ccx, t_out);

// Convert the value to be cast into a ValueRef, either by-ref or
// by-value as appropriate given its type:
Expand Down Expand Up @@ -1689,7 +1683,7 @@ fn trans_assign_op<'a>(
let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op"));
assert!(!ty::type_needs_drop(bcx.tcx(), dst_datum.ty));
let dst_ty = dst_datum.ty;
let dst = Load(bcx, dst_datum.val);
let dst = load_ty(bcx, dst_datum.val, dst_datum.ty);

// Evaluate RHS
let rhs_datum = unpack_datum!(bcx, trans(bcx, &*src));
Expand Down
Loading