]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
Rollup merge of #80327 - PankajChaudhary5:PankajChaudhary, r=GuillaumeGomez
[rust.git] / compiler / rustc_codegen_cranelift / src / optimize / peephole.rs
1 //! Peephole optimizations that can be performed while creating clif ir.
2
3 use cranelift_codegen::ir::{
4     condcodes::IntCC, types, InstBuilder, InstructionData, Opcode, Value, ValueDef,
5 };
6 use cranelift_frontend::FunctionBuilder;
7
8 /// If the given value was produced by a `bint` instruction, return it's input, otherwise return the
9 /// given value.
10 pub(crate) fn maybe_unwrap_bint(bcx: &mut FunctionBuilder<'_>, arg: Value) -> Value {
11     if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
12         match bcx.func.dfg[arg_inst] {
13             InstructionData::Unary {
14                 opcode: Opcode::Bint,
15                 arg,
16             } => arg,
17             _ => arg,
18         }
19     } else {
20         arg
21     }
22 }
23
24 /// If the given value was produced by the lowering of `Rvalue::Not` return the input and true,
25 /// otherwise return the given value and false.
26 pub(crate) fn maybe_unwrap_bool_not(bcx: &mut FunctionBuilder<'_>, arg: Value) -> (Value, bool) {
27     if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
28         match bcx.func.dfg[arg_inst] {
29             // This is the lowering of `Rvalue::Not`
30             InstructionData::IntCompareImm {
31                 opcode: Opcode::IcmpImm,
32                 cond: IntCC::Equal,
33                 arg,
34                 imm,
35             } if imm.bits() == 0 => (arg, true),
36             _ => (arg, false),
37         }
38     } else {
39         (arg, false)
40     }
41 }
42
43 pub(crate) fn make_branchable_value(bcx: &mut FunctionBuilder<'_>, arg: Value) -> Value {
44     if bcx.func.dfg.value_type(arg).is_bool() {
45         return arg;
46     }
47
48     (|| {
49         let arg_inst = if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
50             arg_inst
51         } else {
52             return None;
53         };
54
55         match bcx.func.dfg[arg_inst] {
56             // This is the lowering of Rvalue::Not
57             InstructionData::Load {
58                 opcode: Opcode::Load,
59                 arg: ptr,
60                 flags,
61                 offset,
62             } => {
63                 // Using `load.i8 + uextend.i32` would legalize to `uload8 + ireduce.i8 +
64                 // uextend.i32`. Just `uload8` is much faster.
65                 match bcx.func.dfg.ctrl_typevar(arg_inst) {
66                     types::I8 => Some(bcx.ins().uload8(types::I32, flags, ptr, offset)),
67                     types::I16 => Some(bcx.ins().uload16(types::I32, flags, ptr, offset)),
68                     _ => None,
69                 }
70             }
71             _ => None,
72         }
73     })()
74     .unwrap_or_else(|| {
75         match bcx.func.dfg.value_type(arg) {
76             types::I8 | types::I32 => {
77                 // WORKAROUND for brz.i8 and brnz.i8 not yet being implemented
78                 bcx.ins().uextend(types::I32, arg)
79             }
80             _ => arg,
81         }
82     })
83 }