Skip to content

Commit d747de5

Browse files
committed
Compile bools to i1
We currently compiled bools to i8 values, because there was a bug in LLVM that sometimes caused miscompilations when using i1 in, for example, structs. Using i8 means a lot of unnecessary zero-extend and truncate operations though, since we have to convert the value from and to i1 when using for example icmp or br instructions. Besides the unnecessary overhead caused by this, it also sometimes made LLVM miss some optimizations. Fixes #8106.
1 parent 90a9f65 commit d747de5

13 files changed

+44
-69
lines changed

src/librustc/middle/trans/_match.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -1200,8 +1200,6 @@ fn pick_col(m: &[Match]) -> uint {
12001200
pub enum branch_kind { no_branch, single, switch, compare, compare_vec_len, }
12011201

12021202
// Compiles a comparison between two things.
1203-
//
1204-
// NB: This must produce an i1, not a Rust bool (i8).
12051203
fn compare_values<'a>(
12061204
cx: &'a Block<'a>,
12071205
lhs: ValueRef,
@@ -1218,11 +1216,7 @@ fn compare_values<'a>(
12181216
format!("comparison of `{}`",
12191217
cx.ty_to_str(rhs_t)).as_slice(),
12201218
StrEqFnLangItem);
1221-
let result = callee::trans_lang_call(cx, did, [lhs, rhs], None);
1222-
Result {
1223-
bcx: result.bcx,
1224-
val: bool_to_i1(result.bcx, result.val)
1225-
}
1219+
callee::trans_lang_call(cx, did, [lhs, rhs], None)
12261220
}
12271221

12281222
let _icx = push_ctxt("compare_values");
@@ -1243,11 +1237,7 @@ fn compare_values<'a>(
12431237
format!("comparison of `{}`",
12441238
cx.ty_to_str(rhs_t)).as_slice(),
12451239
UniqStrEqFnLangItem);
1246-
let result = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None);
1247-
Result {
1248-
bcx: result.bcx,
1249-
val: bool_to_i1(result.bcx, result.val)
1250-
}
1240+
callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None)
12511241
}
12521242
_ => cx.sess().bug("only strings supported in compare_values"),
12531243
},

src/librustc/middle/trans/base.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,6 @@ pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
501501
// Used only for creating scalar comparison glue.
502502
pub enum scalar_type { nil_type, signed_int, unsigned_int, floating_point, }
503503

504-
// NB: This produces an i1, not a Rust bool (i8).
505504
pub fn compare_scalar_types<'a>(
506505
cx: &'a Block<'a>,
507506
lhs: ValueRef,
@@ -1815,6 +1814,13 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t) -> Vec<(uint, u6
18151814
}
18161815
_ => {}
18171816
}
1817+
1818+
match ty::get(ret_ty).sty {
1819+
ty::ty_bool => {
1820+
attrs.push((lib::llvm::ReturnIndex as uint, lib::llvm::ZExtAttribute as u64));
1821+
}
1822+
_ => {}
1823+
}
18181824
}
18191825

18201826
for (idx, &t) in fn_sig.inputs.iter().enumerate().map(|(i, v)| (i + first_arg_offset, v)) {
@@ -1828,6 +1834,9 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t) -> Vec<(uint, u6
18281834
attrs.push((idx, lib::llvm::NoCaptureAttribute as u64));
18291835
attrs.push((idx, lib::llvm::NonNullAttribute as u64));
18301836
}
1837+
ty::ty_bool => {
1838+
attrs.push((idx, lib::llvm::ZExtAttribute as u64));
1839+
}
18311840
// `~` pointer parameters never alias because ownership is transferred
18321841
ty::ty_uniq(_) => {
18331842
attrs.push((idx, lib::llvm::NoAliasAttribute as u64));

src/librustc/middle/trans/cabi_arm.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#![allow(non_uppercase_pattern_statics)]
1212

1313
use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
14-
use lib::llvm::StructRetAttribute;
14+
use lib::llvm::{StructRetAttribute, ZExtAttribute};
1515
use middle::trans::cabi::{FnType, ArgType};
1616
use middle::trans::context::CrateContext;
1717
use middle::trans::type_::Type;
@@ -85,7 +85,8 @@ fn ty_size(ty: Type) -> uint {
8585

8686
fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
8787
if is_reg_ty(ty) {
88-
return ArgType::direct(ty, None, None, None);
88+
let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
89+
return ArgType::direct(ty, None, None, attr);
8990
}
9091
let size = ty_size(ty);
9192
if size <= 4 {
@@ -103,7 +104,8 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
103104

104105
fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
105106
if is_reg_ty(ty) {
106-
return ArgType::direct(ty, None, None, None);
107+
let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
108+
return ArgType::direct(ty, None, None, attr);
107109
}
108110
let align = ty_align(ty);
109111
let size = ty_size(ty);

src/librustc/middle/trans/cabi_mips.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use libc::c_uint;
1414
use std::cmp;
1515
use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
16-
use lib::llvm::StructRetAttribute;
16+
use lib::llvm::{StructRetAttribute, ZExtAttribute};
1717
use middle::trans::context::CrateContext;
1818
use middle::trans::cabi::*;
1919
use middle::trans::type_::Type;
@@ -83,9 +83,10 @@ fn ty_size(ty: Type) -> uint {
8383
}
8484
}
8585

86-
fn classify_ret_ty(ty: Type) -> ArgType {
86+
fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
8787
if is_reg_ty(ty) {
88-
ArgType::direct(ty, None, None, None)
88+
let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
89+
ArgType::direct(ty, None, None, attr)
8990
} else {
9091
ArgType::indirect(ty, Some(StructRetAttribute))
9192
}
@@ -101,7 +102,8 @@ fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut uint) -> ArgType {
101102
*offset += align_up_to(size, align * 8) / 8;
102103

103104
if is_reg_ty(ty) {
104-
ArgType::direct(ty, None, None, None)
105+
let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
106+
ArgType::direct(ty, None, None, attr)
105107
} else {
106108
ArgType::direct(
107109
ty,
@@ -160,7 +162,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
160162
rty: Type,
161163
ret_def: bool) -> FnType {
162164
let ret_ty = if ret_def {
163-
classify_ret_ty(rty)
165+
classify_ret_ty(ccx, rty)
164166
} else {
165167
ArgType::direct(Type::void(ccx), None, None, None)
166168
};

src/librustc/middle/trans/cabi_x86.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ pub fn compute_abi_info(ccx: &CrateContext,
5959
}
6060
}
6161
} else {
62-
ret_ty = ArgType::direct(rty, None, None, None);
62+
let attr = if rty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
63+
ret_ty = ArgType::direct(rty, None, None, attr);
6364
}
6465

6566
for &t in atys.iter() {
@@ -72,7 +73,10 @@ pub fn compute_abi_info(ccx: &CrateContext,
7273
ArgType::indirect(t, Some(ByValAttribute))
7374
}
7475
}
75-
_ => ArgType::direct(t, None, None, None),
76+
_ => {
77+
let attr = if t == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
78+
ArgType::direct(t, None, None, attr)
79+
}
7680
};
7781
arg_tys.push(ty);
7882
}

src/librustc/middle/trans/cabi_x86_64.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
use lib::llvm::{llvm, Integer, Pointer, Float, Double};
1717
use lib::llvm::{Struct, Array, Attribute};
18-
use lib::llvm::{StructRetAttribute, ByValAttribute};
18+
use lib::llvm::{StructRetAttribute, ByValAttribute, ZExtAttribute};
1919
use middle::trans::cabi::*;
2020
use middle::trans::context::CrateContext;
2121
use middle::trans::type_::Type;
@@ -337,20 +337,21 @@ pub fn compute_abi_info(ccx: &CrateContext,
337337
fn x86_64_ty(ccx: &CrateContext,
338338
ty: Type,
339339
is_mem_cls: |cls: &[RegClass]| -> bool,
340-
attr: Attribute)
340+
ind_attr: Attribute)
341341
-> ArgType {
342342
if !ty.is_reg_ty() {
343343
let cls = classify_ty(ty);
344344
if is_mem_cls(cls.as_slice()) {
345-
ArgType::indirect(ty, Some(attr))
345+
ArgType::indirect(ty, Some(ind_attr))
346346
} else {
347347
ArgType::direct(ty,
348348
Some(llreg_ty(ccx, cls.as_slice())),
349349
None,
350350
None)
351351
}
352352
} else {
353-
ArgType::direct(ty, None, None, None)
353+
let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
354+
ArgType::direct(ty, None, None, attr)
354355
}
355356
}
356357

src/librustc/middle/trans/common.rs

-5
Original file line numberDiff line numberDiff line change
@@ -818,11 +818,6 @@ pub fn find_vtable(tcx: &ty::ctxt,
818818
param_bounds.get(n_bound).clone()
819819
}
820820

821-
// Casts a Rust bool value to an i1.
822-
pub fn bool_to_i1(bcx: &Block, llval: ValueRef) -> ValueRef {
823-
build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(bcx.ccx(), false))
824-
}
825-
826821
pub fn langcall(bcx: &Block,
827822
span: Option<Span>,
828823
msg: &str,

src/librustc/middle/trans/consts.rs

+1-12
Original file line numberDiff line numberDiff line change
@@ -399,18 +399,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
399399
let (dv, _dt) = const_deref(cx, te, ty, true);
400400
dv
401401
}
402-
ast::UnNot => {
403-
match ty::get(ty).sty {
404-
ty::ty_bool => {
405-
// Somewhat questionable, but I believe this is
406-
// correct.
407-
let te = llvm::LLVMConstTrunc(te, Type::i1(cx).to_ref());
408-
let te = llvm::LLVMConstNot(te);
409-
llvm::LLVMConstZExt(te, Type::bool(cx).to_ref())
410-
}
411-
_ => llvm::LLVMConstNot(te),
412-
}
413-
}
402+
ast::UnNot => llvm::LLVMConstNot(te),
414403
ast::UnNeg => {
415404
if is_float { llvm::LLVMConstFNeg(te) }
416405
else { llvm::LLVMConstNeg(te) }

src/librustc/middle/trans/datum.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,6 @@ fn load<'a>(bcx: &'a Block<'a>, llptr: ValueRef, ty: ty::t) -> ValueRef {
525525

526526
if type_is_zero_size(bcx.ccx(), ty) {
527527
C_undef(type_of::type_of(bcx.ccx(), ty))
528-
} else if ty::type_is_bool(ty) {
529-
LoadRangeAssert(bcx, llptr, 0, 2, lib::llvm::False)
530528
} else if ty::type_is_char(ty) {
531529
// a char is a unicode codepoint, and so takes values from 0
532530
// to 0x10FFFF inclusive only.
@@ -652,8 +650,7 @@ impl<K:KindOps> Datum<K> {
652650

653651
pub fn to_llbool<'a>(self, bcx: &'a Block<'a>) -> ValueRef {
654652
assert!(ty::type_is_bool(self.ty) || ty::type_is_bot(self.ty))
655-
let cond_val = self.to_llscalarish(bcx);
656-
bool_to_i1(bcx, cond_val)
653+
self.to_llscalarish(bcx)
657654
}
658655
}
659656

src/librustc/middle/trans/expr.rs

+4-11
Original file line numberDiff line numberDiff line change
@@ -1147,11 +1147,7 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
11471147
let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
11481148
let llresult = if ty::type_is_bool(un_ty) {
11491149
let val = datum.to_llscalarish(bcx);
1150-
let llcond = ICmp(bcx,
1151-
lib::llvm::IntEQ,
1152-
val,
1153-
C_bool(ccx, false));
1154-
Select(bcx, llcond, C_bool(ccx, true), C_bool(ccx, false))
1150+
Xor(bcx, val, C_bool(ccx, true))
11551151
} else {
11561152
// Note: `Not` is bitwise, not suitable for logical not.
11571153
Not(bcx, datum.to_llscalarish(bcx))
@@ -1325,9 +1321,7 @@ fn trans_eager_binop<'a>(
13251321
if ty::type_is_bot(rhs_t) {
13261322
C_bool(bcx.ccx(), false)
13271323
} else if ty::type_is_scalar(rhs_t) {
1328-
let cmpr = base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op);
1329-
bcx = cmpr.bcx;
1330-
ZExt(bcx, cmpr.val, Type::i8(bcx.ccx()))
1324+
unpack_result!(bcx, base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op))
13311325
} else if is_simd {
13321326
base::compare_simd_types(bcx, lhs, rhs, intype, ty::simd_size(tcx, lhs_t), op)
13331327
} else {
@@ -1369,10 +1363,9 @@ fn trans_lazy_binop<'a>(
13691363
let join = fcx.new_id_block("join", binop_expr.id);
13701364
let before_rhs = fcx.new_id_block("before_rhs", b.id);
13711365

1372-
let lhs_i1 = bool_to_i1(past_lhs, lhs);
13731366
match op {
1374-
lazy_and => CondBr(past_lhs, lhs_i1, before_rhs.llbb, join.llbb),
1375-
lazy_or => CondBr(past_lhs, lhs_i1, join.llbb, before_rhs.llbb)
1367+
lazy_and => CondBr(past_lhs, lhs, before_rhs.llbb, join.llbb),
1368+
lazy_or => CondBr(past_lhs, lhs, join.llbb, before_rhs.llbb)
13761369
}
13771370

13781371
let DatumBlock {bcx: past_rhs, datum: rhs} = trans(before_rhs, b);

src/librustc/middle/trans/intrinsic.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,13 @@ pub fn trans_intrinsic(ccx: &CrateContext,
9696
let b = get_param(bcx.fcx.llfn, first_real_arg + 1);
9797
let llfn = bcx.ccx().get_intrinsic(&name);
9898

99-
// convert `i1` to a `bool`, and write to the out parameter
10099
let val = Call(bcx, llfn, [a, b], []);
101-
let result = ExtractValue(bcx, val, 0);
102-
let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool(bcx.ccx()));
103-
let ret = C_undef(type_of::type_of(bcx.ccx(), t));
104-
let ret = InsertValue(bcx, ret, result, 0);
105-
let ret = InsertValue(bcx, ret, overflow, 1);
106100

107101
if type_is_immediate(bcx.ccx(), t) {
108-
Ret(bcx, ret);
102+
Ret(bcx, val);
109103
} else {
110104
let retptr = get_param(bcx.fcx.llfn, bcx.fcx.out_arg_pos());
111-
Store(bcx, ret, retptr);
105+
Store(bcx, val, retptr);
112106
RetVoid(bcx);
113107
}
114108
}

src/librustc/middle/trans/reflect.rs

-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ impl<'a, 'b> Reflector<'a, 'b> {
107107
mth_idx,
108108
v),
109109
ArgVals(args), None));
110-
let result = bool_to_i1(bcx, result);
111110
let next_bcx = fcx.new_temp_block("next");
112111
CondBr(bcx, result, next_bcx.llbb, self.final_bcx.llbb);
113112
self.bcx = next_bcx

src/librustc/middle/trans/type_.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl Type {
9393
}
9494

9595
pub fn bool(ccx: &CrateContext) -> Type {
96-
Type::i8(ccx)
96+
Type::i1(ccx)
9797
}
9898

9999
pub fn char(ccx: &CrateContext) -> Type {

0 commit comments

Comments
 (0)