Skip to content

Fix -Z lower_128bit_ops handling of statics #46583

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 1 commit into from
Dec 20, 2017
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
67 changes: 67 additions & 0 deletions src/librustc_trans/mir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,42 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
}
_ => span_bug!(span, "{:?} in constant", terminator.kind)
}
} else if let Some((op, is_checked)) = self.is_binop_lang_item(def_id) {
(||{
assert_eq!(arg_vals.len(), 2);
let rhs = arg_vals.pop().unwrap()?;
let lhs = arg_vals.pop().unwrap()?;
if !is_checked {
let binop_ty = op.ty(tcx, lhs.ty, rhs.ty);
let (lhs, rhs) = (lhs.llval, rhs.llval);
Ok(Const::new(const_scalar_binop(op, lhs, rhs, binop_ty),
binop_ty))
} else {
let ty = lhs.ty;
let val_ty = op.ty(tcx, lhs.ty, rhs.ty);
let binop_ty = tcx.intern_tup(&[val_ty, tcx.types.bool], false);
let (lhs, rhs) = (lhs.llval, rhs.llval);
assert!(!ty.is_fp());

match const_scalar_checked_binop(tcx, op, lhs, rhs, ty) {
Some((llval, of)) => {
Ok(trans_const_adt(
self.ccx,
binop_ty,
&mir::AggregateKind::Tuple,
&[
Const::new(llval, val_ty),
Const::new(C_bool(self.ccx, of), tcx.types.bool)
]))
}
None => {
span_bug!(span,
"{:?} got non-integer operands: {:?} and {:?}",
op, Value(lhs), Value(rhs));
}
}
}
})()
} else {
MirConstContext::trans_def(self.ccx, def_id, substs, arg_vals)
};
Expand All @@ -425,6 +461,37 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
}
}

fn is_binop_lang_item(&mut self, def_id: DefId) -> Option<(mir::BinOp, bool)> {
let tcx = self.ccx.tcx();
let items = tcx.lang_items();
let def_id = Some(def_id);
if items.i128_add_fn() == def_id { Some((mir::BinOp::Add, false)) }
else if items.u128_add_fn() == def_id { Some((mir::BinOp::Add, false)) }
else if items.i128_sub_fn() == def_id { Some((mir::BinOp::Sub, false)) }
else if items.u128_sub_fn() == def_id { Some((mir::BinOp::Sub, false)) }
else if items.i128_mul_fn() == def_id { Some((mir::BinOp::Mul, false)) }
else if items.u128_mul_fn() == def_id { Some((mir::BinOp::Mul, false)) }
else if items.i128_div_fn() == def_id { Some((mir::BinOp::Div, false)) }
else if items.u128_div_fn() == def_id { Some((mir::BinOp::Div, false)) }
else if items.i128_rem_fn() == def_id { Some((mir::BinOp::Rem, false)) }
else if items.u128_rem_fn() == def_id { Some((mir::BinOp::Rem, false)) }
else if items.i128_shl_fn() == def_id { Some((mir::BinOp::Shl, false)) }
else if items.u128_shl_fn() == def_id { Some((mir::BinOp::Shl, false)) }
else if items.i128_shr_fn() == def_id { Some((mir::BinOp::Shr, false)) }
else if items.u128_shr_fn() == def_id { Some((mir::BinOp::Shr, false)) }
else if items.i128_addo_fn() == def_id { Some((mir::BinOp::Add, true)) }
else if items.u128_addo_fn() == def_id { Some((mir::BinOp::Add, true)) }
else if items.i128_subo_fn() == def_id { Some((mir::BinOp::Sub, true)) }
else if items.u128_subo_fn() == def_id { Some((mir::BinOp::Sub, true)) }
else if items.i128_mulo_fn() == def_id { Some((mir::BinOp::Mul, true)) }
else if items.u128_mulo_fn() == def_id { Some((mir::BinOp::Mul, true)) }
else if items.i128_shlo_fn() == def_id { Some((mir::BinOp::Shl, true)) }
else if items.u128_shlo_fn() == def_id { Some((mir::BinOp::Shl, true)) }
else if items.i128_shro_fn() == def_id { Some((mir::BinOp::Shr, true)) }
else if items.u128_shro_fn() == def_id { Some((mir::BinOp::Shr, true)) }
else { None }
}

fn store(&mut self,
dest: &mir::Place<'tcx>,
value: Result<Const<'tcx>, ConstEvalErr<'tcx>>,
Expand Down
124 changes: 122 additions & 2 deletions src/test/mir-opt/lower_128bit_debug_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@
// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=yes

#![feature(i128_type)]
#![feature(const_fn)]

static TEST_SIGNED: i128 = const_signed(-222);
static TEST_UNSIGNED: u128 = const_unsigned(200);

const fn const_signed(mut x: i128) -> i128 {
((((((x + 1) - 2) * 3) / 4) % 5) << 6) >> 7
}

const fn const_unsigned(mut x: u128) -> u128 {
((((((x + 1) - 2) * 3) / 4) % 5) << 6) >> 7
}

fn test_signed(mut x: i128) -> i128 {
x += 1;
Expand All @@ -39,13 +51,121 @@ fn test_unsigned(mut x: u128) -> u128 {
x
}

fn check(x: i128, y: u128) {
assert_eq!(test_signed(x), -1);
assert_eq!(const_signed(x), -1);
assert_eq!(TEST_SIGNED, -1);
assert_eq!(test_unsigned(y), 2);
assert_eq!(const_unsigned(y), 2);
assert_eq!(TEST_UNSIGNED, 2);
}

fn main() {
assert_eq!(test_signed(-222), -1);
assert_eq!(test_unsigned(200), 2);
check(-222, 200);
}

// END RUST SOURCE

// START rustc.const_signed.Lower128Bit.after.mir
// _8 = _1;
// _9 = const compiler_builtins::int::addsub::rust_i128_addo(move _8, const 1i128) -> bb10;
// ...
// _7 = move (_9.0: i128);
// ...
// _10 = const compiler_builtins::int::addsub::rust_i128_subo(move _7, const 2i128) -> bb11;
// ...
// _6 = move (_10.0: i128);
// ...
// _11 = const compiler_builtins::int::mul::rust_i128_mulo(move _6, const 3i128) -> bb12;
// ...
// _5 = move (_11.0: i128);
// ...
// _12 = Eq(const 4i128, const 0i128);
// assert(!move _12, "attempt to divide by zero") -> bb4;
// ...
// _13 = Eq(const 4i128, const -1i128);
// _14 = Eq(_5, const -170141183460469231731687303715884105728i128);
// _15 = BitAnd(move _13, move _14);
// assert(!move _15, "attempt to divide with overflow") -> bb5;
// ...
// _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb13;
// ...
// _17 = Eq(const 5i128, const -1i128);
// _18 = Eq(_4, const -170141183460469231731687303715884105728i128);
// _19 = BitAnd(move _17, move _18);
// assert(!move _19, "attempt to calculate the remainder with overflow") -> bb7;
// ...
// _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb15;
// ...
// _2 = move (_20.0: i128);
// ...
// _23 = const 7i32 as u128 (Misc);
// _21 = const compiler_builtins::int::shift::rust_i128_shro(move _2, move _23) -> bb16;
// ...
// _0 = move (_21.0: i128);
// ...
// assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1;
// ...
// assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2;
// ...
// assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3;
// ...
// _16 = Eq(const 5i128, const 0i128);
// assert(!move _16, "attempt to calculate the remainder with a divisor of zero") -> bb6;
// ...
// assert(!move (_20.1: bool), "attempt to shift left with overflow") -> bb8;
// ...
// _22 = const 6i32 as u128 (Misc);
// _20 = const compiler_builtins::int::shift::rust_i128_shlo(move _3, move _22) -> bb14;
// ...
// assert(!move (_21.1: bool), "attempt to shift right with overflow") -> bb9;
// END rustc.const_signed.Lower128Bit.after.mir

// START rustc.const_unsigned.Lower128Bit.after.mir
// _8 = _1;
// _9 = const compiler_builtins::int::addsub::rust_u128_addo(move _8, const 1u128) -> bb8;
// ...
// _7 = move (_9.0: u128);
// ...
// _10 = const compiler_builtins::int::addsub::rust_u128_subo(move _7, const 2u128) -> bb9;
// ...
// _6 = move (_10.0: u128);
// ...
// _11 = const compiler_builtins::int::mul::rust_u128_mulo(move _6, const 3u128) -> bb10;
// ...
// _5 = move (_11.0: u128);
// ...
// _12 = Eq(const 4u128, const 0u128);
// assert(!move _12, "attempt to divide by zero") -> bb4;
// ...
// _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb11;
// ...
// _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb13;
// ...
// _2 = move (_14.0: u128);
// ...
// _17 = const 7i32 as u128 (Misc);
// _15 = const compiler_builtins::int::shift::rust_u128_shro(move _2, move _17) -> bb14;
// ...
// _0 = move (_15.0: u128);
// ...
// assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1;
// ...
// assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2;
// ...
// assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3;
// ...
// _13 = Eq(const 5u128, const 0u128);
// assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb5;
// ...
// assert(!move (_14.1: bool), "attempt to shift left with overflow") -> bb6;
// ...
// _16 = const 6i32 as u128 (Misc);
// _14 = const compiler_builtins::int::shift::rust_u128_shlo(move _3, move _16) -> bb12;
// ...
// assert(!move (_15.1: bool), "attempt to shift right with overflow") -> bb7;
// END rustc.const_unsigned.Lower128Bit.after.mir

// START rustc.test_signed.Lower128Bit.after.mir
// _2 = const compiler_builtins::int::addsub::rust_i128_addo(_1, const 1i128) -> bb10;
// ...
Expand Down
124 changes: 122 additions & 2 deletions src/test/mir-opt/lower_128bit_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@
// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no

#![feature(i128_type)]
#![feature(const_fn)]

static TEST_SIGNED: i128 = const_signed(-222);
static TEST_UNSIGNED: u128 = const_unsigned(200);

const fn const_signed(mut x: i128) -> i128 {
((((((x + 1) - 2) * 3) / 4) % 5) << 6) >> 7
}

const fn const_unsigned(mut x: u128) -> u128 {
((((((x + 1) - 2) * 3) / 4) % 5) << 6) >> 7
}

fn test_signed(mut x: i128) -> i128 {
x += 1;
Expand All @@ -39,13 +51,121 @@ fn test_unsigned(mut x: u128) -> u128 {
x
}

fn check(x: i128, y: u128) {
assert_eq!(test_signed(x), -1);
assert_eq!(const_signed(x), -1);
assert_eq!(TEST_SIGNED, -1);
assert_eq!(test_unsigned(y), 2);
assert_eq!(const_unsigned(y), 2);
assert_eq!(TEST_UNSIGNED, 2);
}

fn main() {
assert_eq!(test_signed(-222), -1);
assert_eq!(test_unsigned(200), 2);
check(-222, 200);
}

// END RUST SOURCE

// START rustc.const_signed.Lower128Bit.after.mir
// _8 = _1;
// _9 = const compiler_builtins::int::addsub::rust_i128_addo(move _8, const 1i128) -> bb10;
// ...
// _7 = move (_9.0: i128);
// ...
// _10 = const compiler_builtins::int::addsub::rust_i128_subo(move _7, const 2i128) -> bb11;
// ...
// _6 = move (_10.0: i128);
// ...
// _11 = const compiler_builtins::int::mul::rust_i128_mulo(move _6, const 3i128) -> bb12;
// ...
// _5 = move (_11.0: i128);
// ...
// _12 = Eq(const 4i128, const 0i128);
// assert(!move _12, "attempt to divide by zero") -> bb4;
// ...
// _13 = Eq(const 4i128, const -1i128);
// _14 = Eq(_5, const -170141183460469231731687303715884105728i128);
// _15 = BitAnd(move _13, move _14);
// assert(!move _15, "attempt to divide with overflow") -> bb5;
// ...
// _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb13;
// ...
// _17 = Eq(const 5i128, const -1i128);
// _18 = Eq(_4, const -170141183460469231731687303715884105728i128);
// _19 = BitAnd(move _17, move _18);
// assert(!move _19, "attempt to calculate the remainder with overflow") -> bb7;
// ...
// _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb15;
// ...
// _2 = move (_20.0: i128);
// ...
// _23 = const 7i32 as u128 (Misc);
// _21 = const compiler_builtins::int::shift::rust_i128_shro(move _2, move _23) -> bb16;
// ...
// _0 = move (_21.0: i128);
// ...
// assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1;
// ...
// assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2;
// ...
// assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3;
// ...
// _16 = Eq(const 5i128, const 0i128);
// assert(!move _16, "attempt to calculate the remainder with a divisor of zero") -> bb6;
// ...
// assert(!move (_20.1: bool), "attempt to shift left with overflow") -> bb8;
// ...
// _22 = const 6i32 as u128 (Misc);
// _20 = const compiler_builtins::int::shift::rust_i128_shlo(move _3, move _22) -> bb14;
// ...
// assert(!move (_21.1: bool), "attempt to shift right with overflow") -> bb9;
// END rustc.const_signed.Lower128Bit.after.mir

// START rustc.const_unsigned.Lower128Bit.after.mir
// _8 = _1;
// _9 = const compiler_builtins::int::addsub::rust_u128_addo(move _8, const 1u128) -> bb8;
// ...
// _7 = move (_9.0: u128);
// ...
// _10 = const compiler_builtins::int::addsub::rust_u128_subo(move _7, const 2u128) -> bb9;
// ...
// _6 = move (_10.0: u128);
// ...
// _11 = const compiler_builtins::int::mul::rust_u128_mulo(move _6, const 3u128) -> bb10;
// ...
// _5 = move (_11.0: u128);
// ...
// _12 = Eq(const 4u128, const 0u128);
// assert(!move _12, "attempt to divide by zero") -> bb4;
// ...
// _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb11;
// ...
// _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb13;
// ...
// _2 = move (_14.0: u128);
// ...
// _17 = const 7i32 as u128 (Misc);
// _15 = const compiler_builtins::int::shift::rust_u128_shro(move _2, move _17) -> bb14;
// ...
// _0 = move (_15.0: u128);
// ...
// assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1;
// ...
// assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2;
// ...
// assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3;
// ...
// _13 = Eq(const 5u128, const 0u128);
// assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb5;
// ...
// assert(!move (_14.1: bool), "attempt to shift left with overflow") -> bb6;
// ...
// _16 = const 6i32 as u128 (Misc);
// _14 = const compiler_builtins::int::shift::rust_u128_shlo(move _3, move _16) -> bb12;
// ...
// assert(!move (_15.1: bool), "attempt to shift right with overflow") -> bb7;
// END rustc.const_unsigned.Lower128Bit.after.mir

// START rustc.test_signed.Lower128Bit.after.mir
// _1 = const compiler_builtins::int::addsub::rust_i128_add(_1, const 1i128) -> bb7;
// ...
Expand Down