Skip extra work when calculating sizes for recipes with inferred REX prefixes
As explained in the added documentation and #1342, if we prevent `infer_rex()` and `w()` from being used together then we don't need to check whether the W bit is set when calculating the size of a recipe. This should improve compile time for x86 very slightly since all `infer_rex()` instructions will no longer need this check.
This commit is contained in:
@@ -16,8 +16,6 @@ use crate::isa::{self, TargetIsa};
|
||||
use crate::predicates;
|
||||
use crate::regalloc::RegDiversions;
|
||||
|
||||
use cranelift_codegen_shared::isa::x86::EncodingBits;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/encoding-x86.rs"));
|
||||
include!(concat!(env!("OUT_DIR"), "/legalize-x86.rs"));
|
||||
|
||||
@@ -132,8 +130,8 @@ fn size_plus_maybe_sib_or_offset_inreg1_plus_rex_prefix_for_inreg0_inreg1(
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg)
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_input(1, inst, divert, func, is_extended_reg);
|
||||
size_plus_maybe_sib_or_offset_for_inreg_1(sizing, enc, inst, divert, func)
|
||||
+ if needs_rex { 1 } else { 0 }
|
||||
@@ -148,8 +146,8 @@ fn size_plus_maybe_sib_inreg1_plus_rex_prefix_for_inreg0_inreg1(
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg)
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_input(1, inst, divert, func, is_extended_reg);
|
||||
size_plus_maybe_sib_for_inreg_1(sizing, enc, inst, divert, func) + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
@@ -164,8 +162,8 @@ fn size_plus_maybe_sib_or_offset_for_inreg_0_plus_rex_prefix_for_inreg0_outreg0(
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg)
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_result(0, inst, divert, func, is_extended_reg);
|
||||
size_plus_maybe_sib_or_offset_for_inreg_0(sizing, enc, inst, divert, func)
|
||||
+ if needs_rex { 1 } else { 0 }
|
||||
@@ -181,8 +179,8 @@ fn size_plus_maybe_sib_for_inreg_0_plus_rex_prefix_for_inreg0_outreg0(
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg)
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_result(0, inst, divert, func, is_extended_reg);
|
||||
size_plus_maybe_sib_for_inreg_0(sizing, enc, inst, divert, func) + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
@@ -194,39 +192,39 @@ fn size_plus_maybe_sib_for_inreg_0_plus_rex_prefix_for_inreg0_outreg0(
|
||||
/// 2. Registers are used that require REX.R or REX.B bits for encoding.
|
||||
fn size_with_inferred_rex_for_inreg0(
|
||||
sizing: &RecipeSizing,
|
||||
enc: Encoding,
|
||||
_enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg);
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
/// Infers whether a dynamic REX prefix will be emitted, based on the second operand.
|
||||
fn size_with_inferred_rex_for_inreg1(
|
||||
sizing: &RecipeSizing,
|
||||
enc: Encoding,
|
||||
_enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(1, inst, divert, func, is_extended_reg);
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(1, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
/// Infers whether a dynamic REX prefix will be emitted, based on the third operand.
|
||||
fn size_with_inferred_rex_for_inreg2(
|
||||
sizing: &RecipeSizing,
|
||||
enc: Encoding,
|
||||
_: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(2, inst, divert, func, is_extended_reg);
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(2, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
@@ -237,13 +235,13 @@ fn size_with_inferred_rex_for_inreg2(
|
||||
/// 2. Registers are used that require REX.R or REX.B bits for encoding.
|
||||
fn size_with_inferred_rex_for_inreg0_inreg1(
|
||||
sizing: &RecipeSizing,
|
||||
enc: Encoding,
|
||||
_enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg)
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_input(1, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
@@ -252,13 +250,13 @@ fn size_with_inferred_rex_for_inreg0_inreg1(
|
||||
/// input register and a single output register.
|
||||
fn size_with_inferred_rex_for_inreg0_outreg0(
|
||||
sizing: &RecipeSizing,
|
||||
enc: Encoding,
|
||||
_enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(0, inst, divert, func, is_extended_reg)
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(0, inst, divert, func, is_extended_reg)
|
||||
|| test_result(0, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
@@ -266,13 +264,13 @@ fn size_with_inferred_rex_for_inreg0_outreg0(
|
||||
/// Infers whether a dynamic REX prefix will be emitted, based on a single output register.
|
||||
fn size_with_inferred_rex_for_outreg0(
|
||||
sizing: &RecipeSizing,
|
||||
enc: Encoding,
|
||||
_enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_result(0, inst, divert, func, is_extended_reg);
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_result(0, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
@@ -281,13 +279,13 @@ fn size_with_inferred_rex_for_outreg0(
|
||||
/// CMOV uses 3 inputs, with the REX is inferred from reg1 and reg2.
|
||||
fn size_with_inferred_rex_for_cmov(
|
||||
sizing: &RecipeSizing,
|
||||
enc: Encoding,
|
||||
_enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
let needs_rex = (EncodingBits::from(enc.bits()).rex_w() != 0)
|
||||
|| test_input(1, inst, divert, func, is_extended_reg)
|
||||
// No need to check for REX.W in `needs_rex` because `infer_rex().w()` is not allowed.
|
||||
let needs_rex = test_input(1, inst, divert, func, is_extended_reg)
|
||||
|| test_input(2, inst, divert, func, is_extended_reg);
|
||||
sizing.base_size + if needs_rex { 1 } else { 0 }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user