Rework x64 addressing-mode lowering to be slightly more flexible. (#4080)

This PR refactors the x64 backend address-mode lowering to use an
incremental-build approach, where it considers each node in a tree of
`iadd`s that feed into a load/store address and, at each step, builds
the best possible `Amode`. It will combine an arbitrary number of
constant offsets (an extension beyond the current rules), and can
capture a left-shifted (scaled) index in any position of the tree
(another extension).

This doesn't have any measurable performance improvement on our Wasm
benchmarks in Sightglass, unfortunately, because the IR lowered from
wasm32 will do address computation in 32 bits and then `uextend` it to
add to the 64-bit heap base. We can't quite lift the 32-bit adds to 64
bits because this loses the wraparound semantics.

(We could label adds as "expected not to overflow", and allow *those* to
be lifted to 64 bit operations; wasm32 heap address computation should
fit this.  This is `add nuw` (no unsigned wrap) in LLVM IR terms. That's
likely my next step.)

Nevertheless, (i) this generalizes the cases we can handle, which should
be a good thing, all other things being equal (and in this case, no
compile time impact was measured); and (ii) might benefit non-Wasm
frontends.
This commit is contained in:
Chris Fallin
2022-05-02 16:20:39 -07:00
committed by GitHub
parent 61dc38c065
commit f85047b084
13 changed files with 1416 additions and 742 deletions

View File

@@ -249,30 +249,11 @@ newtype_of_reg!(
|reg| reg.class() == RegClass::Float
);
/// A possible addressing mode (amode) that can be used in instructions.
/// These denote a 64-bit value only.
#[derive(Clone, Debug)]
pub enum Amode {
/// Immediate sign-extended and a Register.
ImmReg {
simm32: u32,
base: Reg,
flags: MemFlags,
},
// N.B.: `Amode` is defined in `inst.isle`. We add some convenience
// constructors here.
/// sign-extend-32-to-64(Immediate) + Register1 + (Register2 << Shift)
ImmRegRegShift {
simm32: u32,
base: Gpr,
index: Gpr,
shift: u8, /* 0 .. 3 only */
flags: MemFlags,
},
/// sign-extend-32-to-64(Immediate) + RIP (instruction pointer).
/// To wit: not supported in 32-bits mode.
RipRelative { target: MachLabel },
}
// Re-export the type from the ISLE generated code.
pub use crate::isa::x64::lower::isle::generated_code::Amode;
impl Amode {
pub(crate) fn imm_reg(simm32: u32, base: Reg) -> Self {