Skip to content

Commit 49b2a8b

Browse files
committed
WIP
1 parent 53a2440 commit 49b2a8b

File tree

3 files changed

+117
-39
lines changed

3 files changed

+117
-39
lines changed

compiler/rustc_mir/src/transform/instcombine.rs

+83-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
use crate::transform::MirPass;
44
use rustc_hir::Mutability;
55
use rustc_middle::mir::{
6-
BinOp, Body, Constant, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo,
7-
StatementKind,
6+
BasicBlock, LocalDecls, PlaceElem, SourceInfo, Statement, StatementKind, Terminator,
7+
TerminatorKind,
88
};
9+
use rustc_middle::mir::{BinOp, Body, Constant, Local, Operand, Place, ProjectionElem, Rvalue};
910
use rustc_middle::ty::{self, TyCtxt};
11+
use rustc_span::{sym, Symbol};
12+
use rustc_target::spec::abi::Abi;
1013

1114
pub struct InstCombine;
1215

@@ -25,6 +28,10 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
2528
_ => {}
2629
}
2730
}
31+
32+
if let Some(terminator) = &mut block.terminator {
33+
ctx.combine_copy_nonoverlapping(terminator, local_decls, &mut block.statements);
34+
}
2835
}
2936
}
3037
}
@@ -120,4 +127,78 @@ impl<'tcx, 'a> InstCombineContext<'tcx, 'a> {
120127
}
121128
}
122129
}
130+
131+
fn func_as_intrinsic(
132+
&self,
133+
operand: &Operand<'tcx>,
134+
locals: &LocalDecls<'tcx>,
135+
) -> Option<Symbol> {
136+
let func_ty = operand.ty(locals, self.tcx);
137+
138+
if let ty::FnDef(def_id, _) = *func_ty.kind() {
139+
let fn_sig = func_ty.fn_sig(self.tcx);
140+
141+
if fn_sig.abi() == Abi::RustIntrinsic {
142+
return Some(self.tcx.item_name(def_id));
143+
}
144+
}
145+
146+
None
147+
}
148+
149+
fn find_copy_nonoverlapping(
150+
&self,
151+
terminator: &Terminator<'tcx>,
152+
locals: &LocalDecls<'tcx>,
153+
) -> Option<(Local, Local, BasicBlock)> {
154+
if let TerminatorKind::Call { func, args, destination: Some((_, next_bb)), .. } =
155+
&terminator.kind
156+
{
157+
let intrinsic = self.func_as_intrinsic(func, locals)?;
158+
159+
if intrinsic == sym::copy_nonoverlapping && args.len() == 3 {
160+
let src = args[0].place()?.as_local()?;
161+
let dest = args[1].place()?.as_local()?;
162+
let constant = args[2].constant()?;
163+
164+
if constant.literal.ty == self.tcx.types.usize {
165+
let val = constant
166+
.literal
167+
.val
168+
.try_to_value()?
169+
.try_to_scalar()?
170+
.to_machine_usize(&self.tcx)
171+
.ok()?;
172+
173+
if val == 1 {
174+
return Some((src, dest, *next_bb));
175+
}
176+
}
177+
}
178+
}
179+
180+
None
181+
}
182+
183+
fn combine_copy_nonoverlapping(
184+
&self,
185+
terminator: &mut Terminator<'tcx>,
186+
locals: &LocalDecls<'tcx>,
187+
statements: &mut Vec<Statement<'tcx>>,
188+
) {
189+
if let Some((src, dest, next_bb)) = self.find_copy_nonoverlapping(terminator, locals) {
190+
trace!("replacing call to copy_nonoverlapping({:?}, {:?}, 1) intrinsic", src, dest);
191+
let deref_projection = self.tcx._intern_place_elems(&[PlaceElem::Deref]);
192+
193+
statements.push(Statement {
194+
source_info: terminator.source_info,
195+
kind: StatementKind::Assign(Box::new((
196+
Place { local: dest, projection: deref_projection },
197+
Rvalue::Use(Operand::Copy(Place { local: src, projection: deref_projection })),
198+
))),
199+
});
200+
201+
terminator.kind = TerminatorKind::Goto { target: next_bb };
202+
}
203+
}
123204
}

compiler/rustc_mir/src/transform/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
482482
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
483483
&multiple_return_terminators::MultipleReturnTerminators,
484484
&instcombine::InstCombine,
485+
&simplify::SimplifyCfg::new("after-instcombine"),
485486
&const_prop::ConstProp,
486487
&simplify_branches::SimplifyBranches::new("after-const-prop"),
487488
&early_otherwise_branch::EarlyOtherwiseBranch,

src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir

+33-37
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,45 @@
33
fn num_to_digit(_1: char) -> u32 {
44
debug num => _1; // in scope 0 at $DIR/issue-59352.rs:12:21: 12:24
55
let mut _0: u32; // return place in scope 0 at $DIR/issue-59352.rs:12:35: 12:38
6-
let mut _2: bool; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
7-
let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:41
8-
let mut _4: char; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:29
9-
let mut _5: u32; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
10-
let mut _10: isize; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
6+
let mut _2: std::option::Option<u32>; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:41
7+
let mut _3: char; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:29
8+
let mut _4: u32; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
9+
let mut _9: isize; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
1110
scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue-59352.rs:14:8: 14:23
12-
debug self => _8; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
13-
debug radix => _5; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
14-
let mut _6: &std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
15-
let _7: std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
16-
let mut _8: char; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
11+
debug self => _7; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
12+
debug radix => _4; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
13+
let mut _5: &std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
14+
let _6: std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
15+
let mut _7: char; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
1716
scope 2 (inlined Option::<u32>::is_some) { // at $DIR/issue-59352.rs:14:8: 14:23
18-
debug self => _6; // in scope 2 at $DIR/issue-59352.rs:14:8: 14:23
17+
debug self => _5; // in scope 2 at $DIR/issue-59352.rs:14:8: 14:23
1918
}
2019
}
2120
scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue-59352.rs:14:26: 14:50
22-
debug self => _3; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
23-
let mut _9: isize; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
21+
debug self => _2; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
22+
let mut _8: isize; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
2423
scope 4 {
2524
debug val => _0; // in scope 4 at $DIR/issue-59352.rs:14:26: 14:50
2625
}
2726
}
2827

2928
bb0: {
30-
StorageLive(_2); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
31-
_8 = _1; // scope 0 at $DIR/issue-59352.rs:14:8: 14:11
32-
StorageLive(_5); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
33-
_5 = const 8_u32; // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
29+
_7 = _1; // scope 0 at $DIR/issue-59352.rs:14:8: 14:11
30+
StorageLive(_4); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
31+
_4 = const 8_u32; // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
32+
StorageLive(_5); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
3433
StorageLive(_6); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
35-
StorageLive(_7); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
36-
_7 = char::methods::<impl char>::to_digit(move _8, const 8_u32) -> bb5; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
34+
_6 = char::methods::<impl char>::to_digit(move _7, const 8_u32) -> bb5; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
3735
// mir::Constant
3836
// + span: $DIR/issue-59352.rs:14:8: 14:23
3937
// + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
4038
}
4139

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

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

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

6966
bb5: {
70-
_6 = &_7; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
71-
_10 = discriminant((*_6)); // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
72-
_2 = Eq(_10, const 1_isize); // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
67+
_5 = &_6; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
68+
_9 = discriminant((*_5)); // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
69+
StorageDead(_5); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
7370
StorageDead(_6); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
74-
StorageDead(_7); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
75-
StorageDead(_5); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
76-
switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
71+
StorageDead(_4); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
72+
switchInt(move _9) -> [1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
7773
}
7874

7975
bb6: {
@@ -94,9 +90,9 @@ fn num_to_digit(_1: char) -> u32 {
9490
}
9591

9692
bb8: {
97-
_0 = move ((_3 as Some).0: u32); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
98-
StorageDead(_9); // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
99-
StorageDead(_3); // scope 0 at $DIR/issue-59352.rs:14:49: 14:50
93+
_0 = move ((_2 as Some).0: u32); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
94+
StorageDead(_8); // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
95+
StorageDead(_2); // scope 0 at $DIR/issue-59352.rs:14:49: 14:50
10096
goto -> bb4; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
10197
}
10298
}

0 commit comments

Comments
 (0)