1 //! Peephole optimizations that can be performed while creating clif ir.
3 use cranelift_codegen
::ir
::{
4 condcodes
::IntCC
, types
, InstBuilder
, InstructionData
, Opcode
, Value
, ValueDef
,
6 use cranelift_frontend
::FunctionBuilder
;
8 /// If the given value was produced by a `bint` instruction, return it's input, otherwise return the
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 { opcode: Opcode::Bint, arg }
=> arg
,
21 /// If the given value was produced by the lowering of `Rvalue::Not` return the input and true,
22 /// otherwise return the given value and false.
23 pub(crate) fn maybe_unwrap_bool_not(bcx
: &mut FunctionBuilder
<'_
>, arg
: Value
) -> (Value
, bool
) {
24 if let ValueDef
::Result(arg_inst
, 0) = bcx
.func
.dfg
.value_def(arg
) {
25 match bcx
.func
.dfg
[arg_inst
] {
26 // This is the lowering of `Rvalue::Not`
27 InstructionData
::IntCompareImm
{
28 opcode
: Opcode
::IcmpImm
,
32 } if imm
.bits() == 0 => (arg
, true),
40 pub(crate) fn make_branchable_value(bcx
: &mut FunctionBuilder
<'_
>, arg
: Value
) -> Value
{
41 if bcx
.func
.dfg
.value_type(arg
).is_bool() {
46 let arg_inst
= if let ValueDef
::Result(arg_inst
, 0) = bcx
.func
.dfg
.value_def(arg
) {
52 match bcx
.func
.dfg
[arg_inst
] {
53 // This is the lowering of Rvalue::Not
54 InstructionData
::Load { opcode: Opcode::Load, arg: ptr, flags, offset }
=> {
55 // Using `load.i8 + uextend.i32` would legalize to `uload8 + ireduce.i8 +
56 // uextend.i32`. Just `uload8` is much faster.
57 match bcx
.func
.dfg
.ctrl_typevar(arg_inst
) {
58 types
::I8
=> Some(bcx
.ins().uload8(types
::I32
, flags
, ptr
, offset
)),
59 types
::I16
=> Some(bcx
.ins().uload16(types
::I32
, flags
, ptr
, offset
)),
67 match bcx
.func
.dfg
.value_type(arg
) {
68 types
::I8
| types
::I16
=> {
69 // WORKAROUND for brz.i8 and brnz.i8 not yet being implemented
70 bcx
.ins().uextend(types
::I32
, arg
)
77 /// Returns whether the branch is statically known to be taken or `None` if it isn't statically known.
78 pub(crate) fn maybe_known_branch_taken(
79 bcx
: &FunctionBuilder
<'_
>,
83 let arg_inst
= if let ValueDef
::Result(arg_inst
, 0) = bcx
.func
.dfg
.value_def(arg
) {
89 match bcx
.func
.dfg
[arg_inst
] {
90 InstructionData
::UnaryBool { opcode: Opcode::Bconst, imm }
=> {
97 InstructionData
::UnaryImm { opcode: Opcode::Iconst, imm }
=> {
101 Some(imm
.bits() != 0)