Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
wesleywiser committed Jan 24, 2021
1 parent 53a2440 commit 49b2a8b
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 39 deletions.
85 changes: 83 additions & 2 deletions compiler/rustc_mir/src/transform/instcombine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
use crate::transform::MirPass;
use rustc_hir::Mutability;
use rustc_middle::mir::{
BinOp, Body, Constant, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo,
StatementKind,
BasicBlock, LocalDecls, PlaceElem, SourceInfo, Statement, StatementKind, Terminator,
TerminatorKind,
};
use rustc_middle::mir::{BinOp, Body, Constant, Local, Operand, Place, ProjectionElem, Rvalue};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::{sym, Symbol};
use rustc_target::spec::abi::Abi;

pub struct InstCombine;

Expand All @@ -25,6 +28,10 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
_ => {}
}
}

if let Some(terminator) = &mut block.terminator {
ctx.combine_copy_nonoverlapping(terminator, local_decls, &mut block.statements);
}
}
}
}
Expand Down Expand Up @@ -120,4 +127,78 @@ impl<'tcx, 'a> InstCombineContext<'tcx, 'a> {
}
}
}

fn func_as_intrinsic(
&self,
operand: &Operand<'tcx>,
locals: &LocalDecls<'tcx>,
) -> Option<Symbol> {
let func_ty = operand.ty(locals, self.tcx);

if let ty::FnDef(def_id, _) = *func_ty.kind() {
let fn_sig = func_ty.fn_sig(self.tcx);

if fn_sig.abi() == Abi::RustIntrinsic {
return Some(self.tcx.item_name(def_id));
}
}

None
}

fn find_copy_nonoverlapping(
&self,
terminator: &Terminator<'tcx>,
locals: &LocalDecls<'tcx>,
) -> Option<(Local, Local, BasicBlock)> {
if let TerminatorKind::Call { func, args, destination: Some((_, next_bb)), .. } =
&terminator.kind
{
let intrinsic = self.func_as_intrinsic(func, locals)?;

if intrinsic == sym::copy_nonoverlapping && args.len() == 3 {
let src = args[0].place()?.as_local()?;
let dest = args[1].place()?.as_local()?;
let constant = args[2].constant()?;

if constant.literal.ty == self.tcx.types.usize {
let val = constant
.literal
.val
.try_to_value()?
.try_to_scalar()?
.to_machine_usize(&self.tcx)
.ok()?;

if val == 1 {
return Some((src, dest, *next_bb));
}
}
}
}

None
}

fn combine_copy_nonoverlapping(
&self,
terminator: &mut Terminator<'tcx>,
locals: &LocalDecls<'tcx>,
statements: &mut Vec<Statement<'tcx>>,
) {
if let Some((src, dest, next_bb)) = self.find_copy_nonoverlapping(terminator, locals) {
trace!("replacing call to copy_nonoverlapping({:?}, {:?}, 1) intrinsic", src, dest);
let deref_projection = self.tcx._intern_place_elems(&[PlaceElem::Deref]);

statements.push(Statement {
source_info: terminator.source_info,
kind: StatementKind::Assign(Box::new((
Place { local: dest, projection: deref_projection },
Rvalue::Use(Operand::Copy(Place { local: src, projection: deref_projection })),
))),
});

terminator.kind = TerminatorKind::Goto { target: next_bb };
}
}
}
1 change: 1 addition & 0 deletions compiler/rustc_mir/src/transform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
&multiple_return_terminators::MultipleReturnTerminators,
&instcombine::InstCombine,
&simplify::SimplifyCfg::new("after-instcombine"),
&const_prop::ConstProp,
&simplify_branches::SimplifyBranches::new("after-const-prop"),
&early_otherwise_branch::EarlyOtherwiseBranch,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,45 @@
fn num_to_digit(_1: char) -> u32 {
debug num => _1; // in scope 0 at $DIR/issue-59352.rs:12:21: 12:24
let mut _0: u32; // return place in scope 0 at $DIR/issue-59352.rs:12:35: 12:38
let mut _2: bool; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:41
let mut _4: char; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:29
let mut _5: u32; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
let mut _10: isize; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
let mut _2: std::option::Option<u32>; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:41
let mut _3: char; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:29
let mut _4: u32; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
let mut _9: isize; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue-59352.rs:14:8: 14:23
debug self => _8; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
debug radix => _5; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
let mut _6: &std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
let _7: std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
let mut _8: char; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
debug self => _7; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
debug radix => _4; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
let mut _5: &std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
let _6: std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
let mut _7: char; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
scope 2 (inlined Option::<u32>::is_some) { // at $DIR/issue-59352.rs:14:8: 14:23
debug self => _6; // in scope 2 at $DIR/issue-59352.rs:14:8: 14:23
debug self => _5; // in scope 2 at $DIR/issue-59352.rs:14:8: 14:23
}
}
scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue-59352.rs:14:26: 14:50
debug self => _3; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
let mut _9: isize; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
debug self => _2; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
let mut _8: isize; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
scope 4 {
debug val => _0; // in scope 4 at $DIR/issue-59352.rs:14:26: 14:50
}
}

bb0: {
StorageLive(_2); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
_8 = _1; // scope 0 at $DIR/issue-59352.rs:14:8: 14:11
StorageLive(_5); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
_5 = const 8_u32; // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
_7 = _1; // scope 0 at $DIR/issue-59352.rs:14:8: 14:11
StorageLive(_4); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
_4 = const 8_u32; // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
StorageLive(_5); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
StorageLive(_6); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
StorageLive(_7); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
_7 = char::methods::<impl char>::to_digit(move _8, const 8_u32) -> bb5; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
_6 = char::methods::<impl char>::to_digit(move _7, const 8_u32) -> bb5; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
// mir::Constant
// + span: $DIR/issue-59352.rs:14:8: 14:23
// + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
}

bb1: {
StorageLive(_3); // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
StorageLive(_4); // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
_4 = _1; // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
_3 = char::methods::<impl char>::to_digit(move _4, const 8_u32) -> bb3; // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
StorageLive(_2); // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
StorageLive(_3); // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
_3 = _1; // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
_2 = char::methods::<impl char>::to_digit(move _3, const 8_u32) -> bb3; // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
// mir::Constant
// + span: $DIR/issue-59352.rs:14:30: 14:38
// + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
Expand All @@ -55,25 +53,23 @@ fn num_to_digit(_1: char) -> u32 {
}

bb3: {
StorageDead(_4); // scope 0 at $DIR/issue-59352.rs:14:40: 14:41
StorageLive(_9); // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
_9 = discriminant(_3); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
switchInt(move _9) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
StorageDead(_3); // scope 0 at $DIR/issue-59352.rs:14:40: 14:41
StorageLive(_8); // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
_8 = discriminant(_2); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
switchInt(move _8) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
}

bb4: {
StorageDead(_2); // scope 0 at $DIR/issue-59352.rs:14:62: 14:63
return; // scope 0 at $DIR/issue-59352.rs:15:2: 15:2
}

bb5: {
_6 = &_7; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
_10 = discriminant((*_6)); // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
_2 = Eq(_10, const 1_isize); // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
_5 = &_6; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
_9 = discriminant((*_5)); // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
StorageDead(_5); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
StorageDead(_6); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
StorageDead(_7); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
StorageDead(_5); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
StorageDead(_4); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
switchInt(move _9) -> [1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
}

bb6: {
Expand All @@ -94,9 +90,9 @@ fn num_to_digit(_1: char) -> u32 {
}

bb8: {
_0 = move ((_3 as Some).0: u32); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
StorageDead(_9); // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
StorageDead(_3); // scope 0 at $DIR/issue-59352.rs:14:49: 14:50
_0 = move ((_2 as Some).0: u32); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
StorageDead(_8); // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
StorageDead(_2); // scope 0 at $DIR/issue-59352.rs:14:49: 14:50
goto -> bb4; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
}
}

0 comments on commit 49b2a8b

Please sign in to comment.