Remove support for -Zlower-128bit-ops

It is broken and unused
This commit is contained in:
bjorn3 2019-07-19 14:21:06 +02:00
parent f9477a77c5
commit 3427a14bdf
8 changed files with 3 additions and 325 deletions

View file

@ -367,34 +367,6 @@ language_item_table! {
DebugTraitLangItem, "debug_trait", debug_trait, Target::Trait;
// A lang item for each of the 128-bit operators we can optionally lower.
I128AddFnLangItem, "i128_add", i128_add_fn, Target::Fn;
U128AddFnLangItem, "u128_add", u128_add_fn, Target::Fn;
I128SubFnLangItem, "i128_sub", i128_sub_fn, Target::Fn;
U128SubFnLangItem, "u128_sub", u128_sub_fn, Target::Fn;
I128MulFnLangItem, "i128_mul", i128_mul_fn, Target::Fn;
U128MulFnLangItem, "u128_mul", u128_mul_fn, Target::Fn;
I128DivFnLangItem, "i128_div", i128_div_fn, Target::Fn;
U128DivFnLangItem, "u128_div", u128_div_fn, Target::Fn;
I128RemFnLangItem, "i128_rem", i128_rem_fn, Target::Fn;
U128RemFnLangItem, "u128_rem", u128_rem_fn, Target::Fn;
I128ShlFnLangItem, "i128_shl", i128_shl_fn, Target::Fn;
U128ShlFnLangItem, "u128_shl", u128_shl_fn, Target::Fn;
I128ShrFnLangItem, "i128_shr", i128_shr_fn, Target::Fn;
U128ShrFnLangItem, "u128_shr", u128_shr_fn, Target::Fn;
// And overflow versions for the operators that are checkable.
// While MIR calls these Checked*, they return (T,bool), not Option<T>.
I128AddoFnLangItem, "i128_addo", i128_addo_fn, Target::Fn;
U128AddoFnLangItem, "u128_addo", u128_addo_fn, Target::Fn;
I128SuboFnLangItem, "i128_subo", i128_subo_fn, Target::Fn;
U128SuboFnLangItem, "u128_subo", u128_subo_fn, Target::Fn;
I128MuloFnLangItem, "i128_mulo", i128_mulo_fn, Target::Fn;
U128MuloFnLangItem, "u128_mulo", u128_mulo_fn, Target::Fn;
I128ShloFnLangItem, "i128_shlo", i128_shlo_fn, Target::Fn;
U128ShloFnLangItem, "u128_shlo", u128_shlo_fn, Target::Fn;
I128ShroFnLangItem, "i128_shro", i128_shro_fn, Target::Fn;
U128ShroFnLangItem, "u128_shro", u128_shro_fn, Target::Fn;
// Align offset for stride != 1, must not panic.
AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn;

View file

@ -1406,10 +1406,6 @@ 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: Option<bool> = (None, parse_opt_bool, [TRACKED],
"rewrite operators on i128 and u128 into lang item calls (typically provided \
by compiler-builtins) so codegen doesn't need to support them,
overriding the default for the current target"),
human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
"generate human-readable, predictable names for codegen units"),
dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],

View file

@ -21,7 +21,7 @@ use crate::middle::cstore::EncodedMetadata;
use crate::middle::lang_items;
use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
use crate::middle::stability;
use crate::mir::{self, Body, interpret, ProjectionKind};
use crate::mir::{Body, interpret, ProjectionKind};
use crate::mir::interpret::{ConstValue, Allocation, Scalar};
use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst};
use crate::ty::ReprOptions;
@ -1297,40 +1297,6 @@ impl<'tcx> TyCtxt<'tcx> {
self.get_lang_items(LOCAL_CRATE)
}
/// Due to missing llvm support for lowering 128 bit math to software emulation
/// (on some targets), the lowering can be done in MIR.
///
/// This function only exists until said support is implemented.
pub fn is_binop_lang_item(&self, def_id: DefId) -> Option<(mir::BinOp, bool)> {
let items = self.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 }
}
pub fn stability(self) -> &'tcx stability::Index<'tcx> {
self.stability_index(LOCAL_CRATE)
}

View file

@ -230,21 +230,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&mut self,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, M::PointerTag>],
dest: Option<PlaceTy<'tcx, M::PointerTag>>,
_dest: Option<PlaceTy<'tcx, M::PointerTag>>,
) -> InterpResult<'tcx, bool> {
let def_id = instance.def_id();
// Some fn calls are actually BinOp intrinsics
if let Some((op, oflo)) = self.tcx.is_binop_lang_item(def_id) {
let dest = dest.expect("128 lowerings can't diverge");
let l = self.read_immediate(args[0])?;
let r = self.read_immediate(args[1])?;
if oflo {
self.binop_with_overflow(op, l, r, dest)?;
} else {
self.binop_ignore_overflow(op, l, r, dest)?;
}
return Ok(true);
} else if Some(def_id) == self.tcx.lang_items().panic_fn() {
if Some(def_id) == self.tcx.lang_items().panic_fn() {
assert!(args.len() == 1);
// &(&'static str, &'static str, u32, u32)
let place = self.deref_operand(args[0])?;

View file

@ -232,13 +232,6 @@ impl Inliner<'tcx> {
return false;
}
// Do not inline {u,i}128 lang items, codegen const eval depends
// on detecting calls to these lang items and intercepting them
if tcx.is_binop_lang_item(callsite.callee).is_some() {
debug!(" not inlining 128bit integer lang item");
return false;
}
let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee);
let hinted = match codegen_fn_attrs.inline {

View file

@ -1,230 +0,0 @@
//! 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::{self, List, Ty, TyCtxt};
use rustc_data_structures::indexed_vec::{Idx};
use crate::transform::{MirPass, MirSource};
pub struct Lower128Bit;
impl MirPass for Lower128Bit {
fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
let debugging_override = tcx.sess.opts.debugging_opts.lower_128bit_ops;
let target_default = tcx.sess.host.options.i128_lowering;
if !debugging_override.unwrap_or(target_default) {
return
}
self.lower_128bit_ops(tcx, body);
}
}
impl Lower128Bit {
fn lower_128bit_ops<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut new_blocks = Vec::new();
let cur_len = body.basic_blocks().len();
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
for block in basic_blocks.iter_mut() {
for i in (0..block.statements.len()).rev() {
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: 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 = bin_statement.source_info;
let (place, lhs, mut rhs) = match bin_statement.kind {
StatementKind::Assign(place, box rvalue) => {
match rvalue {
Rvalue::BinaryOp(_, lhs, rhs)
| Rvalue::CheckedBinaryOp(_, lhs, rhs) => (place, lhs, rhs),
_ => bug!(),
}
}
_ => bug!()
};
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(
Place::from(local),
box Rvalue::Cast(
CastKind::Misc,
rhs,
rhs_override_ty.unwrap())),
});
rhs = Operand::Move(Place::from(local));
}
let call_did = check_lang_item_type(
lang_item, &place, &lhs, &rhs, local_decls, tcx);
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,
List::empty(), source_info.span),
args: vec![lhs, rhs],
destination: Some((place, bb)),
cleanup: None,
from_hir_call: false,
},
});
}
}
basic_blocks.extend(new_blocks);
}
}
fn check_lang_item_type<'tcx, D>(
lang_item: LangItem,
place: &Place<'tcx>,
lhs: &Operand<'tcx>,
rhs: &Operand<'tcx>,
local_decls: &D,
tcx: TyCtxt<'tcx>,
) -> DefId
where
D: HasLocalDecls<'tcx>,
{
let did = tcx.require_lang_item(lang_item);
let poly_sig = tcx.fn_sig(did);
let sig = poly_sig.no_bound_vars().unwrap();
let lhs_ty = lhs.ty(local_decls, tcx);
let rhs_ty = rhs.ty(local_decls, tcx);
let place_ty = place.ty(local_decls, tcx).ty;
let expected = [lhs_ty, rhs_ty, place_ty];
assert_eq!(sig.inputs_and_output[..], expected,
"lang item `{}`", tcx.def_path_str(did));
did
}
fn lower_to<'tcx, D>(
statement: &Statement<'tcx>,
local_decls: &D,
tcx: TyCtxt<'tcx>,
) -> Option<(LangItem, RhsKind)>
where
D: HasLocalDecls<'tcx>,
{
match statement.kind {
StatementKind::Assign(_, box Rvalue::BinaryOp(bin_op, ref lhs, _)) => {
let ty = lhs.ty(local_decls, tcx);
if let Some(is_signed) = sign_of_128bit(ty) {
return item_for_op(bin_op, is_signed);
}
},
StatementKind::Assign(_, box Rvalue::CheckedBinaryOp(bin_op, ref lhs, _)) => {
let ty = lhs.ty(local_decls, tcx);
if let Some(is_signed) = sign_of_128bit(ty) {
return item_for_checked_op(bin_op, is_signed);
}
},
_ => {},
}
None
}
#[derive(Copy, Clone)]
enum RhsKind {
Unchanged,
ForceU128,
ForceU32,
}
impl RhsKind {
fn ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<Ty<'tcx>> {
match *self {
RhsKind::Unchanged => None,
RhsKind::ForceU128 => Some(tcx.types.u128),
RhsKind::ForceU32 => Some(tcx.types.u32),
}
}
}
fn sign_of_128bit(ty: Ty<'_>) -> Option<bool> {
match ty.sty {
ty::Int(syntax::ast::IntTy::I128) => Some(true),
ty::Uint(syntax::ast::UintTy::U128) => Some(false),
_ => None,
}
}
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, 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<(LangItem, RhsKind)> {
let i = match (bin_op, is_signed) {
(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)
}

View file

@ -34,7 +34,6 @@ pub mod copy_prop;
pub mod const_prop;
pub mod generator;
pub mod inline;
pub mod lower_128bit;
pub mod uniform_array_move_out;
pub(crate) fn provide(providers: &mut Providers<'_>) {
@ -272,8 +271,6 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> {
// From here on out, regions are gone.
&erase_regions::EraseRegions,
&lower_128bit::Lower128Bit,
// Optimizations begin.
&uniform_array_move_out::RestoreSubsliceArrayMoveOut,

View file

@ -731,10 +731,6 @@ pub struct TargetOptions {
/// for this target unconditionally.
pub no_builtins: bool,
/// Whether to lower 128-bit operations to compiler_builtins calls. Use if
/// your backend only supports 64-bit and smaller math.
pub i128_lowering: bool,
/// The codegen backend to use for this target, typically "llvm"
pub codegen_backend: String,
@ -850,7 +846,6 @@ impl Default for TargetOptions {
requires_lto: false,
singlethread: false,
no_builtins: false,
i128_lowering: false,
codegen_backend: "llvm".to_string(),
default_hidden_visibility: false,
embed_bitcode: false,