From 57c0801e33ed39560ac23ea8b6b6d87af6fe3a3e Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 15 Nov 2017 23:27:02 -0800 Subject: [PATCH 1/4] Add a MIR pass to lower 128-bit operators to lang item calls Runs only with `-Z lower_128bit_ops` since it's not hooked into targets yet. --- src/librustc/middle/lang_items.rs | 23 +++ src/librustc/mir/mod.rs | 9 ++ src/librustc/session/config.rs | 3 + src/librustc_mir/transform/lower_128bit.rs | 160 ++++++++++++++++++++ src/librustc_mir/transform/mod.rs | 3 + src/test/mir-opt/lower_128bit_debug_test.rs | 104 +++++++++++++ src/test/mir-opt/lower_128bit_test.rs | 97 ++++++++++++ 7 files changed, 399 insertions(+) create mode 100644 src/librustc_mir/transform/lower_128bit.rs create mode 100644 src/test/mir-opt/lower_128bit_debug_test.rs create mode 100644 src/test/mir-opt/lower_128bit_test.rs diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 19a43f3b5dd84..1c52a8dbc97d0 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -310,6 +310,29 @@ language_item_table! { NonZeroItem, "non_zero", non_zero; DebugTraitLangItem, "debug_trait", debug_trait; + + // A lang item for each of the 128-bit operators we can optionally lower. + I128AddFnLangItem, "i128_add", i128_add_fn; + I128SubFnLangItem, "i128_sub", i128_sub_fn; + I128MulFnLangItem, "i128_mul", i128_mul_fn; + I128DivFnLangItem, "i128_div", i128_div_fn; + U128DivFnLangItem, "u128_div", u128_div_fn; + I128RemFnLangItem, "i128_rem", i128_rem_fn; + U128RemFnLangItem, "u128_rem", u128_rem_fn; + I128ShlFnLangItem, "i128_shl", i128_shl_fn; + I128ShrFnLangItem, "i128_shr", i128_shr_fn; + U128ShrFnLangItem, "u128_shr", u128_shr_fn; + // And overflow versions for the operators that are checkable. + // While MIR calls these Checked*, they return (T,bool), not Option. + I128AddoFnLangItem, "i128_addo", i128_addo_fn; + U128AddoFnLangItem, "u128_addo", u128_addo_fn; + I128SuboFnLangItem, "i128_subo", i128_subo_fn; + U128SuboFnLangItem, "u128_subo", u128_subo_fn; + I128MuloFnLangItem, "i128_mulo", i128_mulo_fn; + U128MuloFnLangItem, "u128_mulo", u128_mulo_fn; + I128ShloFnLangItem, "i128_shlo", i128_shlo_fn; + I128ShroFnLangItem, "i128_shro", i128_shro_fn; + U128ShroFnLangItem, "u128_shro", u128_shro_fn; } impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 355fb570c000b..485b7a47fa1f4 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -170,6 +170,15 @@ impl<'tcx> Mir<'tcx> { &mut self.basic_blocks } + #[inline] + pub fn basic_blocks_and_local_decls_mut(&mut self) -> ( + &mut IndexVec>, + &mut LocalDecls<'tcx>, + ) { + self.cache.invalidate(); + (&mut self.basic_blocks, &mut self.local_decls) + } + #[inline] pub fn predecessors(&self) -> Ref>> { self.cache.predecessors(self) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 57fae2200e276..d992dbdfcb776 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1142,6 +1142,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, saturating_float_casts: bool = (false, parse_bool, [TRACKED], "make float->int casts UB-free: numbers outside the integer type's range are clipped to \ the max/min integer respectively, and NaN is mapped to 0"), + lower_128bit_ops: bool = (false, parse_bool, [TRACKED], + "rewrite operators on i128 and u128 into lang item calls (typically provided \ + by compiler-builtins) so translation doesn't need to support them"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs new file mode 100644 index 0000000000000..3a5b8e0790d62 --- /dev/null +++ b/src/librustc_mir/transform/lower_128bit.rs @@ -0,0 +1,160 @@ +// Copyright 2017 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. + +//! Replaces 128-bit operators with lang item calls + +use rustc::hir::def_id::DefId; +use rustc::middle::lang_items::LangItem; +use rustc::mir::*; +use rustc::ty::{Slice, Ty, TyCtxt, TypeVariants}; +use rustc_data_structures::indexed_vec::{Idx}; +use transform::{MirPass, MirSource}; +use syntax; + +pub struct Lower128Bit; + +impl MirPass for Lower128Bit { + fn run_pass<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + _src: MirSource, + mir: &mut Mir<'tcx>) { + if !tcx.sess.opts.debugging_opts.lower_128bit_ops { + return + } + + self.lower_128bit_ops(tcx, mir); + } +} + +impl Lower128Bit { + fn lower_128bit_ops<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) { + let mut new_blocks = Vec::new(); + let cur_len = mir.basic_blocks().len(); + + let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut(); + for block in basic_blocks.iter_mut() { + for i in (0..block.statements.len()).rev() { + let call_did = + if let Some(call_did) = lower_to(&block.statements[i], local_decls, tcx) { + call_did + } else { + continue; + }; + + let after_call = BasicBlockData { + statements: block.statements.drain((i+1)..).collect(), + is_cleanup: block.is_cleanup, + terminator: block.terminator.take(), + }; + + let bin_statement = block.statements.pop().unwrap(); + let (source_info, lvalue, lhs, rhs) = match bin_statement { + Statement { + source_info, + kind: StatementKind::Assign( + lvalue, + Rvalue::BinaryOp(_, lhs, rhs)) + } => (source_info, lvalue, lhs, rhs), + Statement { + source_info, + kind: StatementKind::Assign( + lvalue, + Rvalue::CheckedBinaryOp(_, lhs, rhs)) + } => (source_info, lvalue, lhs, rhs), + _ => bug!("Statement doesn't match pattern any more?"), + }; + + let bb = BasicBlock::new(cur_len + new_blocks.len()); + new_blocks.push(after_call); + + block.terminator = + Some(Terminator { + source_info, + kind: TerminatorKind::Call { + func: Operand::function_handle(tcx, call_did, + Slice::empty(), source_info.span), + args: vec![lhs, rhs], + destination: Some((lvalue, bb)), + cleanup: None, + }, + }); + } + } + + basic_blocks.extend(new_blocks); + } +} + +fn lower_to<'a, 'tcx, D>(statement: &Statement<'tcx>, local_decls: &D, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> Option + where D: HasLocalDecls<'tcx> +{ + match statement.kind { + StatementKind::Assign(_, Rvalue::BinaryOp(bin_op, ref lhs, _)) => { + let ty = lhs.ty(local_decls, tcx); + if let Some(is_signed) = sign_of_128bit(&ty) { + if let Some(item) = item_for_op(bin_op, is_signed) { + return Some(tcx.require_lang_item(item)) + } + } + }, + StatementKind::Assign(_, Rvalue::CheckedBinaryOp(bin_op, ref lhs, _)) => { + let ty = lhs.ty(local_decls, tcx); + if let Some(is_signed) = sign_of_128bit(&ty) { + if let Some(item) = item_for_checked_op(bin_op, is_signed) { + return Some(tcx.require_lang_item(item)) + } + } + }, + _ => {}, + } + None +} + +fn sign_of_128bit(ty: &Ty) -> Option { + match ty.sty { + TypeVariants::TyInt(syntax::ast::IntTy::I128) => Some(true), + TypeVariants::TyUint(syntax::ast::UintTy::U128) => Some(false), + _ => None, + } +} + +fn item_for_op(bin_op: BinOp, is_signed: bool) -> Option { + let i = match (bin_op, is_signed) { + (BinOp::Add, _) => LangItem::I128AddFnLangItem, + (BinOp::Sub, _) => LangItem::I128SubFnLangItem, + (BinOp::Mul, _) => LangItem::I128MulFnLangItem, + (BinOp::Div, true) => LangItem::I128DivFnLangItem, + (BinOp::Div, false) => LangItem::U128DivFnLangItem, + (BinOp::Rem, true) => LangItem::I128RemFnLangItem, + (BinOp::Rem, false) => LangItem::U128RemFnLangItem, + (BinOp::Shl, _) => LangItem::I128ShlFnLangItem, + (BinOp::Shr, true) => LangItem::I128ShrFnLangItem, + (BinOp::Shr, false) => LangItem::U128ShrFnLangItem, + _ => return None, + }; + Some(i) +} + +fn item_for_checked_op(bin_op: BinOp, is_signed: bool) -> Option { + let i = match (bin_op, is_signed) { + (BinOp::Add, true) => LangItem::I128AddoFnLangItem, + (BinOp::Add, false) => LangItem::U128AddoFnLangItem, + (BinOp::Sub, true) => LangItem::I128SuboFnLangItem, + (BinOp::Sub, false) => LangItem::U128SuboFnLangItem, + (BinOp::Mul, true) => LangItem::I128MuloFnLangItem, + (BinOp::Mul, false) => LangItem::U128MuloFnLangItem, + (BinOp::Shl, _) => LangItem::I128ShloFnLangItem, + (BinOp::Shr, true) => LangItem::I128ShroFnLangItem, + (BinOp::Shr, false) => LangItem::U128ShroFnLangItem, + _ => return None, + }; + Some(i) +} \ No newline at end of file diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 441f9be9be1f4..6987cfa79be09 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -42,6 +42,7 @@ pub mod copy_prop; pub mod generator; pub mod inline; pub mod nll; +pub mod lower_128bit; pub(crate) fn provide(providers: &mut Providers) { self::qualify_consts::provide(providers); @@ -241,6 +242,8 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx // From here on out, regions are gone. erase_regions::EraseRegions, + lower_128bit::Lower128Bit, + // Optimizations begin. inline::Inline, instcombine::InstCombine, diff --git a/src/test/mir-opt/lower_128bit_debug_test.rs b/src/test/mir-opt/lower_128bit_debug_test.rs new file mode 100644 index 0000000000000..3280c8db7f223 --- /dev/null +++ b/src/test/mir-opt/lower_128bit_debug_test.rs @@ -0,0 +1,104 @@ +// Copyright 2017 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. + +// compile-flags: -Z lower_128bit_ops -C debug_assertions=yes + +#![feature(i128_type)] +#![feature(lang_items)] + +#[lang="i128_div"] +fn i128_div(_x: i128, _y: i128) -> i128 { 3 } +#[lang="u128_div"] +fn u128_div(_x: i128, _y: i128) -> i128 { 4 } +#[lang="i128_rem"] +fn i128_rem(_x: i128, _y: i128) -> i128 { 5 } +#[lang="u128_rem"] +fn u128_rem(_x: i128, _y: i128) -> i128 { 6 } + +#[lang="i128_addo"] +fn i128_addo(_x: i128, _y: i128) -> (i128, bool) { (0, false) } +#[lang="u128_addo"] +fn u128_addo(_x: i128, _y: i128) -> (i128, bool) { (1, false) } +#[lang="i128_subo"] +fn i128_subo(_x: i128, _y: i128) -> (i128, bool) { (2, false) } +#[lang="u128_subo"] +fn u128_subo(_x: i128, _y: i128) -> (i128, bool) { (3, false) } +#[lang="i128_mulo"] +fn i128_mulo(_x: i128, _y: i128) -> (i128, bool) { (4, false) } +#[lang="u128_mulo"] +fn u128_mulo(_x: i128, _y: i128) -> (i128, bool) { (5, false) } +#[lang="i128_shlo"] +fn i128_shlo(_x: i128, _y: u32) -> (i128, bool) { (6, false) } +#[lang="i128_shro"] +fn i128_shro(_x: i128, _y: u32) -> (i128, bool) { (7, false) } +#[lang="u128_shro"] +fn u128_shro(_x: i128, _y: u32) -> (i128, bool) { (8, false) } + + +fn test_signed(mut x: i128) -> i128 { + x += 1; + x -= 2; + x *= 3; + x /= 4; + x %= 5; + x <<= 6; + x >>= 7; + x +} + +fn test_unsigned(mut x: u128) -> u128 { + x += 1; + x -= 2; + x *= 3; + x /= 4; + x %= 5; + x <<= 6; + x >>= 7; + x +} + +fn main() { + test_signed(-200); + test_unsigned(200); +} + +// END RUST SOURCE + +// START rustc.test_signed.Lower128Bit.after.mir +// _2 = const i128_addo(_1, const 1i128) -> bb10; +// ... +// _3 = const i128_subo(_1, const 2i128) -> bb11; +// ... +// _4 = const i128_mulo(_1, const 3i128) -> bb12; +// ... +// _1 = const i128_div(_1, const 4i128) -> bb13; +// ... +// _1 = const i128_rem(_1, const 5i128) -> bb15; +// ... +// _14 = const i128_shro(_1, const 7i32) -> bb16; +// ... +// _13 = const i128_shlo(_1, const 6i32) -> bb14; +// END rustc.test_signed.Lower128Bit.after.mir + +// START rustc.test_unsigned.Lower128Bit.after.mir +// _2 = const u128_addo(_1, const 1u128) -> bb8; +// ... +// _3 = const u128_subo(_1, const 2u128) -> bb9; +// ... +// _4 = const u128_mulo(_1, const 3u128) -> bb10; +// ... +// _1 = const u128_div(_1, const 4u128) -> bb11; +// ... +// _1 = const u128_rem(_1, const 5u128) -> bb13; +// ... +// _8 = const u128_shro(_1, const 7i32) -> bb14; +// ... +// _7 = const i128_shlo(_1, const 6i32) -> bb12; +// END rustc.test_unsigned.Lower128Bit.after.mir diff --git a/src/test/mir-opt/lower_128bit_test.rs b/src/test/mir-opt/lower_128bit_test.rs new file mode 100644 index 0000000000000..15a5535dba483 --- /dev/null +++ b/src/test/mir-opt/lower_128bit_test.rs @@ -0,0 +1,97 @@ +// Copyright 2017 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. + +// compile-flags: -Z lower_128bit_ops -C debug_assertions=no + +#![feature(i128_type)] +#![feature(lang_items)] + +#[lang="i128_add"] +fn i128_add(_x: i128, _y: i128) -> i128 { 0 } +#[lang="i128_sub"] +fn i128_sub(_x: i128, _y: i128) -> i128 { 1 } +#[lang="i128_mul"] +fn i128_mul(_x: i128, _y: i128) -> i128 { 2 } +#[lang="i128_div"] +fn i128_div(_x: i128, _y: i128) -> i128 { 3 } +#[lang="u128_div"] +fn u128_div(_x: i128, _y: i128) -> i128 { 4 } +#[lang="i128_rem"] +fn i128_rem(_x: i128, _y: i128) -> i128 { 5 } +#[lang="u128_rem"] +fn u128_rem(_x: i128, _y: i128) -> i128 { 6 } +#[lang="i128_shl"] +fn i128_shl(_x: i128, _y: u32) -> i128 { 7 } +#[lang="i128_shr"] +fn i128_shr(_x: i128, _y: u32) -> i128 { 8 } +#[lang="u128_shr"] +fn u128_shr(_x: i128, _y: u32) -> i128 { 9 } + + +fn test_signed(mut x: i128) -> i128 { + x += 1; + x -= 2; + x *= 3; + x /= 4; + x %= 5; + x <<= 6; + x >>= 7; + x +} + +fn test_unsigned(mut x: u128) -> u128 { + x += 1; + x -= 2; + x *= 3; + x /= 4; + x %= 5; + x <<= 6; + x >>= 7; + x +} + +fn main() { + test_signed(-200); + test_unsigned(200); +} + +// END RUST SOURCE + +// START rustc.test_signed.Lower128Bit.after.mir +// _1 = const i128_add(_1, const 1i128) -> bb7; +// ... +// _1 = const i128_div(_1, const 4i128) -> bb8; +// ... +// _1 = const i128_rem(_1, const 5i128) -> bb11; +// ... +// _1 = const i128_mul(_1, const 3i128) -> bb5; +// ... +// _1 = const i128_sub(_1, const 2i128) -> bb6; +// ... +// _1 = const i128_shr(_1, const 7i32) -> bb9; +// ... +// _1 = const i128_shl(_1, const 6i32) -> bb10; +// END rustc.test_signed.Lower128Bit.after.mir + +// START rustc.test_unsigned.Lower128Bit.after.mir +// _1 = const i128_add(_1, const 1u128) -> bb5; +// ... +// _1 = const u128_div(_1, const 4u128) -> bb6; +// ... +// _1 = const u128_rem(_1, const 5u128) -> bb9; +// ... +// _1 = const i128_mul(_1, const 3u128) -> bb3; +// ... +// _1 = const i128_sub(_1, const 2u128) -> bb4; +// ... +// _1 = const u128_shr(_1, const 7i32) -> bb7; +// ... +// _1 = const i128_shl(_1, const 6i32) -> bb8; +// END rustc.test_unsigned.Lower128Bit.after.mir From ee4cd865df06b02e88408fa003cf4987d764c246 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 19 Nov 2017 17:29:56 -0800 Subject: [PATCH 2/4] Include tuple projections in MIR tests --- src/test/mir-opt/lower_128bit_debug_test.rs | 34 +++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/test/mir-opt/lower_128bit_debug_test.rs b/src/test/mir-opt/lower_128bit_debug_test.rs index 3280c8db7f223..1de5e151220fa 100644 --- a/src/test/mir-opt/lower_128bit_debug_test.rs +++ b/src/test/mir-opt/lower_128bit_debug_test.rs @@ -74,31 +74,65 @@ fn main() { // START rustc.test_signed.Lower128Bit.after.mir // _2 = const i128_addo(_1, const 1i128) -> bb10; // ... +// _1 = (_2.0: i128); // _3 = const i128_subo(_1, const 2i128) -> bb11; // ... +// _1 = (_3.0: i128); // _4 = const i128_mulo(_1, const 3i128) -> bb12; // ... +// _1 = (_4.0: i128); +// ... // _1 = const i128_div(_1, const 4i128) -> bb13; // ... // _1 = const i128_rem(_1, const 5i128) -> bb15; // ... +// _1 = (_13.0: i128); // _14 = const i128_shro(_1, const 7i32) -> bb16; // ... +// _1 = (_14.0: i128); +// ... +// assert(!(_2.1: bool), "attempt to add with overflow") -> bb1; +// ... +// assert(!(_3.1: bool), "attempt to subtract with overflow") -> bb2; +// ... +// assert(!(_4.1: bool), "attempt to multiply with overflow") -> bb3; +// ... +// assert(!(_13.1: bool), "attempt to shift left with overflow") -> bb8; +// ... // _13 = const i128_shlo(_1, const 6i32) -> bb14; +// ... +// assert(!(_14.1: bool), "attempt to shift right with overflow") -> bb9; // END rustc.test_signed.Lower128Bit.after.mir // START rustc.test_unsigned.Lower128Bit.after.mir // _2 = const u128_addo(_1, const 1u128) -> bb8; // ... +// _1 = (_2.0: u128); // _3 = const u128_subo(_1, const 2u128) -> bb9; // ... +// _1 = (_3.0: u128); // _4 = const u128_mulo(_1, const 3u128) -> bb10; // ... +// _1 = (_4.0: u128); +// ... // _1 = const u128_div(_1, const 4u128) -> bb11; // ... // _1 = const u128_rem(_1, const 5u128) -> bb13; // ... +// _1 = (_7.0: u128); // _8 = const u128_shro(_1, const 7i32) -> bb14; // ... +// _1 = (_8.0: u128); +// ... +// assert(!(_2.1: bool), "attempt to add with overflow") -> bb1; +// ... +// assert(!(_3.1: bool), "attempt to subtract with overflow") -> bb2; +// ... +// assert(!(_4.1: bool), "attempt to multiply with overflow") -> bb3; +// ... +// assert(!(_7.1: bool), "attempt to shift left with overflow") -> bb6; +// ... // _7 = const i128_shlo(_1, const 6i32) -> bb12; +// ... +// assert(!(_8.1: bool), "attempt to shift right with overflow") -> bb7; // END rustc.test_unsigned.Lower128Bit.after.mir From 6a5a086fd61a87d36cfa3652b279c543601860da Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 20 Nov 2017 00:04:54 -0800 Subject: [PATCH 3/4] Add type checking for the lang item As part of doing so, add more lang items instead of passing u128 to the i128 ones where it doesn't matter in twos-complement. --- src/librustc/middle/lang_items.rs | 5 ++ src/librustc_mir/transform/lower_128bit.rs | 64 +++++++++++++++------ src/test/mir-opt/lower_128bit_debug_test.rs | 21 +++---- src/test/mir-opt/lower_128bit_test.rs | 27 +++++---- 4 files changed, 78 insertions(+), 39 deletions(-) diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 1c52a8dbc97d0..a858a8d7449f4 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -313,13 +313,17 @@ language_item_table! { // A lang item for each of the 128-bit operators we can optionally lower. I128AddFnLangItem, "i128_add", i128_add_fn; + U128AddFnLangItem, "u128_add", u128_add_fn; I128SubFnLangItem, "i128_sub", i128_sub_fn; + U128SubFnLangItem, "u128_sub", u128_sub_fn; I128MulFnLangItem, "i128_mul", i128_mul_fn; + U128MulFnLangItem, "u128_mul", u128_mul_fn; I128DivFnLangItem, "i128_div", i128_div_fn; U128DivFnLangItem, "u128_div", u128_div_fn; I128RemFnLangItem, "i128_rem", i128_rem_fn; U128RemFnLangItem, "u128_rem", u128_rem_fn; I128ShlFnLangItem, "i128_shl", i128_shl_fn; + U128ShlFnLangItem, "u128_shl", u128_shl_fn; I128ShrFnLangItem, "i128_shr", i128_shr_fn; U128ShrFnLangItem, "u128_shr", u128_shr_fn; // And overflow versions for the operators that are checkable. @@ -331,6 +335,7 @@ language_item_table! { I128MuloFnLangItem, "i128_mulo", i128_mulo_fn; U128MuloFnLangItem, "u128_mulo", u128_mulo_fn; I128ShloFnLangItem, "i128_shlo", i128_shlo_fn; + U128ShloFnLangItem, "u128_shlo", u128_shlo_fn; I128ShroFnLangItem, "i128_shro", i128_shro_fn; U128ShroFnLangItem, "u128_shro", u128_shro_fn; } diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs index 3a5b8e0790d62..2075792fb817c 100644 --- a/src/librustc_mir/transform/lower_128bit.rs +++ b/src/librustc_mir/transform/lower_128bit.rs @@ -41,9 +41,9 @@ impl Lower128Bit { let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut(); for block in basic_blocks.iter_mut() { for i in (0..block.statements.len()).rev() { - let call_did = - if let Some(call_did) = lower_to(&block.statements[i], local_decls, tcx) { - call_did + let lang_item = + if let Some(lang_item) = lower_to(&block.statements[i], local_decls, tcx) { + lang_item } else { continue; }; @@ -71,6 +71,9 @@ impl Lower128Bit { _ => bug!("Statement doesn't match pattern any more?"), }; + let call_did = check_lang_item_type( + lang_item, &lvalue, &lhs, &rhs, local_decls, tcx); + let bb = BasicBlock::new(cur_len + new_blocks.len()); new_blocks.push(after_call); @@ -92,25 +95,43 @@ impl Lower128Bit { } } +fn check_lang_item_type<'a, 'tcx, D>( + lang_item: LangItem, + lvalue: &Lvalue<'tcx>, + lhs: &Operand<'tcx>, + rhs: &Operand<'tcx>, + local_decls: &D, + tcx: TyCtxt<'a, 'tcx, 'tcx>) +-> DefId + where D: HasLocalDecls<'tcx> +{ + let did = tcx.require_lang_item(lang_item); + let poly_sig = tcx.fn_sig(did); + let sig = tcx.no_late_bound_regions(&poly_sig).unwrap(); + let lhs_ty = lhs.ty(local_decls, tcx); + let rhs_ty = rhs.ty(local_decls, tcx); + let lvalue_ty = lvalue.ty(local_decls, tcx).to_ty(tcx); + let expected = [lhs_ty, rhs_ty, lvalue_ty]; + assert_eq!(sig.inputs_and_output[..], expected, + "lang item {}", tcx.def_symbol_name(did)); + did +} + fn lower_to<'a, 'tcx, D>(statement: &Statement<'tcx>, local_decls: &D, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Option + -> Option where D: HasLocalDecls<'tcx> { match statement.kind { StatementKind::Assign(_, Rvalue::BinaryOp(bin_op, ref lhs, _)) => { let ty = lhs.ty(local_decls, tcx); - if let Some(is_signed) = sign_of_128bit(&ty) { - if let Some(item) = item_for_op(bin_op, is_signed) { - return Some(tcx.require_lang_item(item)) - } + if let Some(is_signed) = sign_of_128bit(ty) { + return item_for_op(bin_op, is_signed); } }, StatementKind::Assign(_, Rvalue::CheckedBinaryOp(bin_op, ref lhs, _)) => { let ty = lhs.ty(local_decls, tcx); - if let Some(is_signed) = sign_of_128bit(&ty) { - if let Some(item) = item_for_checked_op(bin_op, is_signed) { - return Some(tcx.require_lang_item(item)) - } + if let Some(is_signed) = sign_of_128bit(ty) { + return item_for_checked_op(bin_op, is_signed); } }, _ => {}, @@ -118,7 +139,7 @@ fn lower_to<'a, 'tcx, D>(statement: &Statement<'tcx>, local_decls: &D, tcx: TyCt None } -fn sign_of_128bit(ty: &Ty) -> Option { +fn sign_of_128bit(ty: Ty) -> Option { match ty.sty { TypeVariants::TyInt(syntax::ast::IntTy::I128) => Some(true), TypeVariants::TyUint(syntax::ast::UintTy::U128) => Some(false), @@ -128,14 +149,18 @@ fn sign_of_128bit(ty: &Ty) -> Option { fn item_for_op(bin_op: BinOp, is_signed: bool) -> Option { let i = match (bin_op, is_signed) { - (BinOp::Add, _) => LangItem::I128AddFnLangItem, - (BinOp::Sub, _) => LangItem::I128SubFnLangItem, - (BinOp::Mul, _) => LangItem::I128MulFnLangItem, + (BinOp::Add, true) => LangItem::I128AddFnLangItem, + (BinOp::Add, false) => LangItem::U128AddFnLangItem, + (BinOp::Sub, true) => LangItem::I128SubFnLangItem, + (BinOp::Sub, false) => LangItem::U128SubFnLangItem, + (BinOp::Mul, true) => LangItem::I128MulFnLangItem, + (BinOp::Mul, false) => LangItem::U128MulFnLangItem, (BinOp::Div, true) => LangItem::I128DivFnLangItem, (BinOp::Div, false) => LangItem::U128DivFnLangItem, (BinOp::Rem, true) => LangItem::I128RemFnLangItem, (BinOp::Rem, false) => LangItem::U128RemFnLangItem, - (BinOp::Shl, _) => LangItem::I128ShlFnLangItem, + (BinOp::Shl, true) => LangItem::I128ShlFnLangItem, + (BinOp::Shl, false) => LangItem::U128ShlFnLangItem, (BinOp::Shr, true) => LangItem::I128ShrFnLangItem, (BinOp::Shr, false) => LangItem::U128ShrFnLangItem, _ => return None, @@ -151,10 +176,11 @@ fn item_for_checked_op(bin_op: BinOp, is_signed: bool) -> Option { (BinOp::Sub, false) => LangItem::U128SuboFnLangItem, (BinOp::Mul, true) => LangItem::I128MuloFnLangItem, (BinOp::Mul, false) => LangItem::U128MuloFnLangItem, - (BinOp::Shl, _) => LangItem::I128ShloFnLangItem, + (BinOp::Shl, true) => LangItem::I128ShloFnLangItem, + (BinOp::Shl, false) => LangItem::U128ShloFnLangItem, (BinOp::Shr, true) => LangItem::I128ShroFnLangItem, (BinOp::Shr, false) => LangItem::U128ShroFnLangItem, - _ => return None, + _ => bug!("That should be all the checked ones?"), }; Some(i) } \ No newline at end of file diff --git a/src/test/mir-opt/lower_128bit_debug_test.rs b/src/test/mir-opt/lower_128bit_debug_test.rs index 1de5e151220fa..8d1ef82c187f9 100644 --- a/src/test/mir-opt/lower_128bit_debug_test.rs +++ b/src/test/mir-opt/lower_128bit_debug_test.rs @@ -16,31 +16,32 @@ #[lang="i128_div"] fn i128_div(_x: i128, _y: i128) -> i128 { 3 } #[lang="u128_div"] -fn u128_div(_x: i128, _y: i128) -> i128 { 4 } +fn u128_div(_x: u128, _y: u128) -> u128 { 4 } #[lang="i128_rem"] fn i128_rem(_x: i128, _y: i128) -> i128 { 5 } #[lang="u128_rem"] -fn u128_rem(_x: i128, _y: i128) -> i128 { 6 } +fn u128_rem(_x: u128, _y: u128) -> u128 { 6 } #[lang="i128_addo"] fn i128_addo(_x: i128, _y: i128) -> (i128, bool) { (0, false) } #[lang="u128_addo"] -fn u128_addo(_x: i128, _y: i128) -> (i128, bool) { (1, false) } +fn u128_addo(_x: u128, _y: u128) -> (u128, bool) { (1, false) } #[lang="i128_subo"] fn i128_subo(_x: i128, _y: i128) -> (i128, bool) { (2, false) } #[lang="u128_subo"] -fn u128_subo(_x: i128, _y: i128) -> (i128, bool) { (3, false) } +fn u128_subo(_x: u128, _y: u128) -> (u128, bool) { (3, false) } #[lang="i128_mulo"] fn i128_mulo(_x: i128, _y: i128) -> (i128, bool) { (4, false) } #[lang="u128_mulo"] -fn u128_mulo(_x: i128, _y: i128) -> (i128, bool) { (5, false) } +fn u128_mulo(_x: u128, _y: u128) -> (u128, bool) { (5, false) } #[lang="i128_shlo"] -fn i128_shlo(_x: i128, _y: u32) -> (i128, bool) { (6, false) } +fn i128_shlo(_x: i128, _y: i32) -> (i128, bool) { (6, false) } +#[lang="u128_shlo"] +fn u128_shlo(_x: u128, _y: i32) -> (u128, bool) { (6, false) } #[lang="i128_shro"] -fn i128_shro(_x: i128, _y: u32) -> (i128, bool) { (7, false) } +fn i128_shro(_x: i128, _y: i32) -> (i128, bool) { (7, false) } #[lang="u128_shro"] -fn u128_shro(_x: i128, _y: u32) -> (i128, bool) { (8, false) } - +fn u128_shro(_x: u128, _y: i32) -> (u128, bool) { (8, false) } fn test_signed(mut x: i128) -> i128 { x += 1; @@ -132,7 +133,7 @@ fn main() { // ... // assert(!(_7.1: bool), "attempt to shift left with overflow") -> bb6; // ... -// _7 = const i128_shlo(_1, const 6i32) -> bb12; +// _7 = const u128_shlo(_1, const 6i32) -> bb12; // ... // assert(!(_8.1: bool), "attempt to shift right with overflow") -> bb7; // END rustc.test_unsigned.Lower128Bit.after.mir diff --git a/src/test/mir-opt/lower_128bit_test.rs b/src/test/mir-opt/lower_128bit_test.rs index 15a5535dba483..ba05280e20b72 100644 --- a/src/test/mir-opt/lower_128bit_test.rs +++ b/src/test/mir-opt/lower_128bit_test.rs @@ -15,25 +15,32 @@ #[lang="i128_add"] fn i128_add(_x: i128, _y: i128) -> i128 { 0 } +#[lang="u128_add"] +fn u128_add(_x: u128, _y: u128) -> u128 { 0 } #[lang="i128_sub"] fn i128_sub(_x: i128, _y: i128) -> i128 { 1 } +#[lang="u128_sub"] +fn u128_sub(_x: u128, _y: u128) -> u128 { 1 } #[lang="i128_mul"] fn i128_mul(_x: i128, _y: i128) -> i128 { 2 } +#[lang="u128_mul"] +fn u128_mul(_x: u128, _y: u128) -> u128 { 2 } #[lang="i128_div"] fn i128_div(_x: i128, _y: i128) -> i128 { 3 } #[lang="u128_div"] -fn u128_div(_x: i128, _y: i128) -> i128 { 4 } +fn u128_div(_x: u128, _y: u128) -> u128 { 4 } #[lang="i128_rem"] fn i128_rem(_x: i128, _y: i128) -> i128 { 5 } #[lang="u128_rem"] -fn u128_rem(_x: i128, _y: i128) -> i128 { 6 } +fn u128_rem(_x: u128, _y: u128) -> u128 { 6 } #[lang="i128_shl"] -fn i128_shl(_x: i128, _y: u32) -> i128 { 7 } +fn i128_shl(_x: i128, _y: i32) -> i128 { 7 } +#[lang="u128_shl"] +fn u128_shl(_x: u128, _y: i32) -> u128 { 7 } #[lang="i128_shr"] -fn i128_shr(_x: i128, _y: u32) -> i128 { 8 } +fn i128_shr(_x: i128, _y: i32) -> i128 { 8 } #[lang="u128_shr"] -fn u128_shr(_x: i128, _y: u32) -> i128 { 9 } - +fn u128_shr(_x: u128, _y: i32) -> u128 { 9 } fn test_signed(mut x: i128) -> i128 { x += 1; @@ -81,17 +88,17 @@ fn main() { // END rustc.test_signed.Lower128Bit.after.mir // START rustc.test_unsigned.Lower128Bit.after.mir -// _1 = const i128_add(_1, const 1u128) -> bb5; +// _1 = const u128_add(_1, const 1u128) -> bb5; // ... // _1 = const u128_div(_1, const 4u128) -> bb6; // ... // _1 = const u128_rem(_1, const 5u128) -> bb9; // ... -// _1 = const i128_mul(_1, const 3u128) -> bb3; +// _1 = const u128_mul(_1, const 3u128) -> bb3; // ... -// _1 = const i128_sub(_1, const 2u128) -> bb4; +// _1 = const u128_sub(_1, const 2u128) -> bb4; // ... // _1 = const u128_shr(_1, const 7i32) -> bb7; // ... -// _1 = const i128_shl(_1, const 6i32) -> bb8; +// _1 = const u128_shl(_1, const 6i32) -> bb8; // END rustc.test_unsigned.Lower128Bit.after.mir From 42208c122757fca706bc5224f3a0c7200fae32e9 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 20 Nov 2017 01:54:43 -0800 Subject: [PATCH 4/4] Handle shifts properly * The overflow-checking shift items need to take a full 128-bit type, since they need to be able to detect idiocy like `1i128 << (1u128 << 127)` * The unchecked ones just take u32, like the `*_sh?` methods in core * Because shift-by-anything is allowed, cast into a new local for every shift --- src/librustc_mir/transform/lower_128bit.rs | 118 ++++++++++++++------ src/test/mir-opt/lower_128bit_debug_test.rs | 22 ++-- src/test/mir-opt/lower_128bit_test.rs | 20 ++-- 3 files changed, 112 insertions(+), 48 deletions(-) diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs index 2075792fb817c..9dc5fdadbb195 100644 --- a/src/librustc_mir/transform/lower_128bit.rs +++ b/src/librustc_mir/transform/lower_128bit.rs @@ -41,21 +41,41 @@ impl Lower128Bit { let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut(); for block in basic_blocks.iter_mut() { for i in (0..block.statements.len()).rev() { - let lang_item = - if let Some(lang_item) = lower_to(&block.statements[i], local_decls, tcx) { - lang_item + let (lang_item, rhs_kind) = + if let Some((lang_item, rhs_kind)) = + lower_to(&block.statements[i], local_decls, tcx) + { + (lang_item, rhs_kind) } else { continue; }; + let rhs_override_ty = rhs_kind.ty(tcx); + let cast_local = + match rhs_override_ty { + None => None, + Some(ty) => { + let local_decl = LocalDecl::new_internal( + ty, block.statements[i].source_info.span); + Some(local_decls.push(local_decl)) + }, + }; + + let storage_dead = cast_local.map(|local| { + Statement { + source_info: block.statements[i].source_info, + kind: StatementKind::StorageDead(local), + } + }); let after_call = BasicBlockData { - statements: block.statements.drain((i+1)..).collect(), + statements: storage_dead.into_iter() + .chain(block.statements.drain((i+1)..)).collect(), is_cleanup: block.is_cleanup, terminator: block.terminator.take(), }; let bin_statement = block.statements.pop().unwrap(); - let (source_info, lvalue, lhs, rhs) = match bin_statement { + let (source_info, lvalue, lhs, mut rhs) = match bin_statement { Statement { source_info, kind: StatementKind::Assign( @@ -71,6 +91,23 @@ impl Lower128Bit { _ => bug!("Statement doesn't match pattern any more?"), }; + if let Some(local) = cast_local { + block.statements.push(Statement { + source_info: source_info, + kind: StatementKind::StorageLive(local), + }); + block.statements.push(Statement { + source_info: source_info, + kind: StatementKind::Assign( + Lvalue::Local(local), + Rvalue::Cast( + CastKind::Misc, + rhs, + rhs_override_ty.unwrap())), + }); + rhs = Operand::Consume(Lvalue::Local(local)); + } + let call_did = check_lang_item_type( lang_item, &lvalue, &lhs, &rhs, local_decls, tcx); @@ -118,7 +155,7 @@ fn check_lang_item_type<'a, 'tcx, D>( } fn lower_to<'a, 'tcx, D>(statement: &Statement<'tcx>, local_decls: &D, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Option + -> Option<(LangItem, RhsKind)> where D: HasLocalDecls<'tcx> { match statement.kind { @@ -139,6 +176,23 @@ fn lower_to<'a, 'tcx, D>(statement: &Statement<'tcx>, local_decls: &D, tcx: TyCt None } +#[derive(Copy, Clone)] +enum RhsKind { + Unchanged, + ForceU128, + ForceU32, +} + +impl RhsKind { + fn ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option> { + match *self { + RhsKind::Unchanged => None, + RhsKind::ForceU128 => Some(tcx.types.u128), + RhsKind::ForceU32 => Some(tcx.types.u32), + } + } +} + fn sign_of_128bit(ty: Ty) -> Option { match ty.sty { TypeVariants::TyInt(syntax::ast::IntTy::I128) => Some(true), @@ -147,39 +201,39 @@ fn sign_of_128bit(ty: Ty) -> Option { } } -fn item_for_op(bin_op: BinOp, is_signed: bool) -> Option { +fn item_for_op(bin_op: BinOp, is_signed: bool) -> Option<(LangItem, RhsKind)> { let i = match (bin_op, is_signed) { - (BinOp::Add, true) => LangItem::I128AddFnLangItem, - (BinOp::Add, false) => LangItem::U128AddFnLangItem, - (BinOp::Sub, true) => LangItem::I128SubFnLangItem, - (BinOp::Sub, false) => LangItem::U128SubFnLangItem, - (BinOp::Mul, true) => LangItem::I128MulFnLangItem, - (BinOp::Mul, false) => LangItem::U128MulFnLangItem, - (BinOp::Div, true) => LangItem::I128DivFnLangItem, - (BinOp::Div, false) => LangItem::U128DivFnLangItem, - (BinOp::Rem, true) => LangItem::I128RemFnLangItem, - (BinOp::Rem, false) => LangItem::U128RemFnLangItem, - (BinOp::Shl, true) => LangItem::I128ShlFnLangItem, - (BinOp::Shl, false) => LangItem::U128ShlFnLangItem, - (BinOp::Shr, true) => LangItem::I128ShrFnLangItem, - (BinOp::Shr, false) => LangItem::U128ShrFnLangItem, + (BinOp::Add, true) => (LangItem::I128AddFnLangItem, RhsKind::Unchanged), + (BinOp::Add, false) => (LangItem::U128AddFnLangItem, RhsKind::Unchanged), + (BinOp::Sub, true) => (LangItem::I128SubFnLangItem, RhsKind::Unchanged), + (BinOp::Sub, false) => (LangItem::U128SubFnLangItem, RhsKind::Unchanged), + (BinOp::Mul, true) => (LangItem::I128MulFnLangItem, RhsKind::Unchanged), + (BinOp::Mul, false) => (LangItem::U128MulFnLangItem, RhsKind::Unchanged), + (BinOp::Div, true) => (LangItem::I128DivFnLangItem, RhsKind::Unchanged), + (BinOp::Div, false) => (LangItem::U128DivFnLangItem, RhsKind::Unchanged), + (BinOp::Rem, true) => (LangItem::I128RemFnLangItem, RhsKind::Unchanged), + (BinOp::Rem, false) => (LangItem::U128RemFnLangItem, RhsKind::Unchanged), + (BinOp::Shl, true) => (LangItem::I128ShlFnLangItem, RhsKind::ForceU32), + (BinOp::Shl, false) => (LangItem::U128ShlFnLangItem, RhsKind::ForceU32), + (BinOp::Shr, true) => (LangItem::I128ShrFnLangItem, RhsKind::ForceU32), + (BinOp::Shr, false) => (LangItem::U128ShrFnLangItem, RhsKind::ForceU32), _ => return None, }; Some(i) } -fn item_for_checked_op(bin_op: BinOp, is_signed: bool) -> Option { +fn item_for_checked_op(bin_op: BinOp, is_signed: bool) -> Option<(LangItem, RhsKind)> { let i = match (bin_op, is_signed) { - (BinOp::Add, true) => LangItem::I128AddoFnLangItem, - (BinOp::Add, false) => LangItem::U128AddoFnLangItem, - (BinOp::Sub, true) => LangItem::I128SuboFnLangItem, - (BinOp::Sub, false) => LangItem::U128SuboFnLangItem, - (BinOp::Mul, true) => LangItem::I128MuloFnLangItem, - (BinOp::Mul, false) => LangItem::U128MuloFnLangItem, - (BinOp::Shl, true) => LangItem::I128ShloFnLangItem, - (BinOp::Shl, false) => LangItem::U128ShloFnLangItem, - (BinOp::Shr, true) => LangItem::I128ShroFnLangItem, - (BinOp::Shr, false) => LangItem::U128ShroFnLangItem, + (BinOp::Add, true) => (LangItem::I128AddoFnLangItem, RhsKind::Unchanged), + (BinOp::Add, false) => (LangItem::U128AddoFnLangItem, RhsKind::Unchanged), + (BinOp::Sub, true) => (LangItem::I128SuboFnLangItem, RhsKind::Unchanged), + (BinOp::Sub, false) => (LangItem::U128SuboFnLangItem, RhsKind::Unchanged), + (BinOp::Mul, true) => (LangItem::I128MuloFnLangItem, RhsKind::Unchanged), + (BinOp::Mul, false) => (LangItem::U128MuloFnLangItem, RhsKind::Unchanged), + (BinOp::Shl, true) => (LangItem::I128ShloFnLangItem, RhsKind::ForceU128), + (BinOp::Shl, false) => (LangItem::U128ShloFnLangItem, RhsKind::ForceU128), + (BinOp::Shr, true) => (LangItem::I128ShroFnLangItem, RhsKind::ForceU128), + (BinOp::Shr, false) => (LangItem::U128ShroFnLangItem, RhsKind::ForceU128), _ => bug!("That should be all the checked ones?"), }; Some(i) diff --git a/src/test/mir-opt/lower_128bit_debug_test.rs b/src/test/mir-opt/lower_128bit_debug_test.rs index 8d1ef82c187f9..4626dc17e1f6e 100644 --- a/src/test/mir-opt/lower_128bit_debug_test.rs +++ b/src/test/mir-opt/lower_128bit_debug_test.rs @@ -35,13 +35,13 @@ fn i128_mulo(_x: i128, _y: i128) -> (i128, bool) { (4, false) } #[lang="u128_mulo"] fn u128_mulo(_x: u128, _y: u128) -> (u128, bool) { (5, false) } #[lang="i128_shlo"] -fn i128_shlo(_x: i128, _y: i32) -> (i128, bool) { (6, false) } +fn i128_shlo(_x: i128, _y: u128) -> (i128, bool) { (6, false) } #[lang="u128_shlo"] -fn u128_shlo(_x: u128, _y: i32) -> (u128, bool) { (6, false) } +fn u128_shlo(_x: u128, _y: u128) -> (u128, bool) { (6, false) } #[lang="i128_shro"] -fn i128_shro(_x: i128, _y: i32) -> (i128, bool) { (7, false) } +fn i128_shro(_x: i128, _y: u128) -> (i128, bool) { (7, false) } #[lang="u128_shro"] -fn u128_shro(_x: u128, _y: i32) -> (u128, bool) { (8, false) } +fn u128_shro(_x: u128, _y: u128) -> (u128, bool) { (8, false) } fn test_signed(mut x: i128) -> i128 { x += 1; @@ -88,7 +88,9 @@ fn main() { // _1 = const i128_rem(_1, const 5i128) -> bb15; // ... // _1 = (_13.0: i128); -// _14 = const i128_shro(_1, const 7i32) -> bb16; +// ... +// _17 = const 7i32 as u128 (Misc); +// _14 = const i128_shro(_1, _17) -> bb16; // ... // _1 = (_14.0: i128); // ... @@ -100,7 +102,8 @@ fn main() { // ... // assert(!(_13.1: bool), "attempt to shift left with overflow") -> bb8; // ... -// _13 = const i128_shlo(_1, const 6i32) -> bb14; +// _16 = const 6i32 as u128 (Misc); +// _13 = const i128_shlo(_1, _16) -> bb14; // ... // assert(!(_14.1: bool), "attempt to shift right with overflow") -> bb9; // END rustc.test_signed.Lower128Bit.after.mir @@ -121,7 +124,9 @@ fn main() { // _1 = const u128_rem(_1, const 5u128) -> bb13; // ... // _1 = (_7.0: u128); -// _8 = const u128_shro(_1, const 7i32) -> bb14; +// ... +// _11 = const 7i32 as u128 (Misc); +// _8 = const u128_shro(_1, _11) -> bb14; // ... // _1 = (_8.0: u128); // ... @@ -133,7 +138,8 @@ fn main() { // ... // assert(!(_7.1: bool), "attempt to shift left with overflow") -> bb6; // ... -// _7 = const u128_shlo(_1, const 6i32) -> bb12; +// _10 = const 6i32 as u128 (Misc); +// _7 = const u128_shlo(_1, _10) -> bb12; // ... // assert(!(_8.1: bool), "attempt to shift right with overflow") -> bb7; // END rustc.test_unsigned.Lower128Bit.after.mir diff --git a/src/test/mir-opt/lower_128bit_test.rs b/src/test/mir-opt/lower_128bit_test.rs index ba05280e20b72..207cd0ac57eb0 100644 --- a/src/test/mir-opt/lower_128bit_test.rs +++ b/src/test/mir-opt/lower_128bit_test.rs @@ -34,13 +34,13 @@ fn i128_rem(_x: i128, _y: i128) -> i128 { 5 } #[lang="u128_rem"] fn u128_rem(_x: u128, _y: u128) -> u128 { 6 } #[lang="i128_shl"] -fn i128_shl(_x: i128, _y: i32) -> i128 { 7 } +fn i128_shl(_x: i128, _y: u32) -> i128 { 7 } #[lang="u128_shl"] -fn u128_shl(_x: u128, _y: i32) -> u128 { 7 } +fn u128_shl(_x: u128, _y: u32) -> u128 { 7 } #[lang="i128_shr"] -fn i128_shr(_x: i128, _y: i32) -> i128 { 8 } +fn i128_shr(_x: i128, _y: u32) -> i128 { 8 } #[lang="u128_shr"] -fn u128_shr(_x: u128, _y: i32) -> u128 { 9 } +fn u128_shr(_x: u128, _y: u32) -> u128 { 9 } fn test_signed(mut x: i128) -> i128 { x += 1; @@ -82,9 +82,11 @@ fn main() { // ... // _1 = const i128_sub(_1, const 2i128) -> bb6; // ... -// _1 = const i128_shr(_1, const 7i32) -> bb9; +// _11 = const 7i32 as u32 (Misc); +// _1 = const i128_shr(_1, _11) -> bb9; // ... -// _1 = const i128_shl(_1, const 6i32) -> bb10; +// _12 = const 6i32 as u32 (Misc); +// _1 = const i128_shl(_1, _12) -> bb10; // END rustc.test_signed.Lower128Bit.after.mir // START rustc.test_unsigned.Lower128Bit.after.mir @@ -98,7 +100,9 @@ fn main() { // ... // _1 = const u128_sub(_1, const 2u128) -> bb4; // ... -// _1 = const u128_shr(_1, const 7i32) -> bb7; +// _5 = const 7i32 as u32 (Misc); +// _1 = const u128_shr(_1, _5) -> bb7; // ... -// _1 = const u128_shl(_1, const 6i32) -> bb8; +// _6 = const 6i32 as u32 (Misc); +// _1 = const u128_shl(_1, _6) -> bb8; // END rustc.test_unsigned.Lower128Bit.after.mir