cranelift: Remove redundant branch and select instructions (#5097)

As discussed in the 2022/10/19 meeting, this PR removes many of the branch and select instructions that used iflags, in favor if using brz/brnz and select in their place. Additionally, it reworks selectif_spectre_guard to take an i8 input instead of an iflags input.

For reference, the removed instructions are: br_icmp, brif, brff, trueif, trueff, and selectif.
This commit is contained in:
Trevor Elliott
2022-10-24 16:14:35 -07:00
committed by GitHub
parent 30589170b4
commit ec12415b1f
40 changed files with 579 additions and 2527 deletions

View File

@@ -75,82 +75,9 @@ fn define_control_flow(
);
}
let iB = &TypeVar::new(
"iB",
"A scalar integer type",
TypeSetBuilder::new().ints(Interval::All).build(),
);
let iflags: &TypeVar = &ValueType::Special(types::Flag::IFlags.into()).into();
let fflags: &TypeVar = &ValueType::Special(types::Flag::FFlags.into()).into();
{
let Cond = &Operand::new("Cond", &imm.intcc);
let x = &Operand::new("x", iB);
let y = &Operand::new("y", iB);
ig.push(
Inst::new(
"br_icmp",
r#"
Compare scalar integers and branch.
Compare ``x`` and ``y`` in the same way as the `icmp` instruction
and take the branch if the condition is true:
```text
br_icmp ugt v1, v2, block4(v5, v6)
```
is semantically equivalent to:
```text
v10 = icmp ugt, v1, v2
brnz v10, block4(v5, v6)
```
Some RISC architectures like MIPS and RISC-V provide instructions that
implement all or some of the condition codes. The instruction can also
be used to represent *macro-op fusion* on architectures like Intel's.
"#,
&formats.branch_icmp,
)
.operands_in(vec![Cond, x, y, block, args])
.is_branch(true),
);
let f = &Operand::new("f", iflags);
ig.push(
Inst::new(
"brif",
r#"
Branch when condition is true in integer CPU flags.
"#,
&formats.branch_int,
)
.operands_in(vec![Cond, f, block, args])
.is_branch(true),
);
}
{
let Cond = &Operand::new("Cond", &imm.floatcc);
let f = &Operand::new("f", fflags);
ig.push(
Inst::new(
"brff",
r#"
Branch when condition is true in floating point CPU flags.
"#,
&formats.branch_float,
)
.operands_in(vec![Cond, f, block, args])
.is_branch(true),
);
}
{
let _i32 = &TypeVar::new(
"i32",
@@ -1498,28 +1425,13 @@ pub(crate) fn define(
.operands_out(vec![a]),
);
let cc = &Operand::new("cc", &imm.intcc).with_doc("Controlling condition code");
let flags = &Operand::new("flags", iflags).with_doc("The machine's flag register");
ig.push(
Inst::new(
"selectif",
r#"
Conditional select, dependent on integer condition codes.
"#,
&formats.int_select,
)
.operands_in(vec![cc, flags, x, y])
.operands_out(vec![a]),
);
ig.push(
Inst::new(
"selectif_spectre_guard",
"select_spectre_guard",
r#"
Conditional select intended for Spectre guards.
This operation is semantically equivalent to a selectif instruction.
This operation is semantically equivalent to a select instruction.
However, it is guaranteed to not be removed or otherwise altered by any
optimization pass, and is guaranteed to result in a conditional-move
instruction, not a branch-based lowering. As such, it is suitable
@@ -1534,9 +1446,9 @@ pub(crate) fn define(
speculative path, this ensures that no Spectre vulnerability will
exist.
"#,
&formats.int_select,
&formats.ternary,
)
.operands_in(vec![cc, flags, x, y])
.operands_in(vec![c, x, y])
.operands_out(vec![a])
.other_side_effects(true),
);
@@ -3194,43 +3106,6 @@ pub(crate) fn define(
.operands_out(vec![a]),
);
let Cond = &Operand::new("Cond", &imm.intcc);
let f = &Operand::new("f", iflags);
let a = &Operand::new("a", i8);
ig.push(
Inst::new(
"trueif",
r#"
Test integer CPU flags for a specific condition.
Check the CPU flags in ``f`` against the ``Cond`` condition code and
return true when the condition code is satisfied.
"#,
&formats.int_cond,
)
.operands_in(vec![Cond, f])
.operands_out(vec![a]),
);
let Cond = &Operand::new("Cond", &imm.floatcc);
let f = &Operand::new("f", fflags);
ig.push(
Inst::new(
"trueff",
r#"
Test floating point CPU flags for a specific condition.
Check the CPU flags in ``f`` against the ``Cond`` condition code and
return true when the condition code is satisfied.
"#,
&formats.float_cond,
)
.operands_in(vec![Cond, f])
.operands_out(vec![a]),
);
let x = &Operand::new("x", Mem);
let a = &Operand::new("a", MemTo).with_doc("Bits of `x` reinterpreted");