isle: Migrate f32const/f64const to ISLE (#3537)
This moves the `f32const` and `f64const` instructions from `lower.rs` to
ISLE. I was originally going to add something else but due to the
`isle.rs`'s manual use of `constructor_imm(..)` it necessitated filling
out the `imm` cases for f32/f64 constants, so I figured I'd go ahead and
move these instructions as well.
The special case for 0 constants which use `xorp{s,d}` is preserved from
`lower.rs` today, but a special case isn't added for the all-ones
constant. The comment says to use `cmpeqp{s,d}` but as discovered on
other recent PRs that's not quite sufficient because comparing a
register against itself which happens to be NaN wouldn't work, so
something else will be required (perhaps `pcmpeq` or similar? I figured
I'd defer to later)
This commit is contained in:
@@ -58,7 +58,12 @@
|
|||||||
(XmmRmREvex (op Avx512Opcode)
|
(XmmRmREvex (op Avx512Opcode)
|
||||||
(src1 RegMem)
|
(src1 RegMem)
|
||||||
(src2 Reg)
|
(src2 Reg)
|
||||||
(dst WritableReg))))
|
(dst WritableReg))
|
||||||
|
(GprToXmm (op SseOpcode)
|
||||||
|
(src RegMem)
|
||||||
|
(dst WritableReg)
|
||||||
|
(src_size OperandSize))
|
||||||
|
))
|
||||||
|
|
||||||
(type OperandSize extern
|
(type OperandSize extern
|
||||||
(enum Size8
|
(enum Size8
|
||||||
@@ -624,12 +629,22 @@
|
|||||||
|
|
||||||
;; Helper for emitting immediates.
|
;; Helper for emitting immediates.
|
||||||
(decl imm (Type u64) Reg)
|
(decl imm (Type u64) Reg)
|
||||||
|
|
||||||
|
;; Integer immediates.
|
||||||
(rule (imm ty simm64)
|
(rule (imm ty simm64)
|
||||||
(let ((dst WritableReg (temp_writable_reg ty))
|
(let ((dst WritableReg (temp_writable_reg ty))
|
||||||
(size OperandSize (operand_size_of_type ty))
|
(size OperandSize (operand_size_of_type ty))
|
||||||
(_ Unit (emit (MInst.Imm size simm64 dst))))
|
(_ Unit (emit (MInst.Imm size simm64 dst))))
|
||||||
(writable_reg_to_reg dst)))
|
(writable_reg_to_reg dst)))
|
||||||
|
|
||||||
|
;; `f32` immediates.
|
||||||
|
(rule (imm $F32 bits)
|
||||||
|
(gpr_to_xmm $F32 (SseOpcode.Movd) (RegMem.Reg (imm $I32 bits)) (OperandSize.Size32)))
|
||||||
|
|
||||||
|
;; `f64` immediates.
|
||||||
|
(rule (imm $F64 bits)
|
||||||
|
(gpr_to_xmm $F64 (SseOpcode.Movq) (RegMem.Reg (imm $I64 bits)) (OperandSize.Size64)))
|
||||||
|
|
||||||
(decl nonzero_u64_fits_in_u32 (u64) u64)
|
(decl nonzero_u64_fits_in_u32 (u64) u64)
|
||||||
(extern extractor nonzero_u64_fits_in_u32 nonzero_u64_fits_in_u32)
|
(extern extractor nonzero_u64_fits_in_u32 nonzero_u64_fits_in_u32)
|
||||||
|
|
||||||
@@ -640,7 +655,7 @@
|
|||||||
(_ Unit (emit (MInst.Imm (OperandSize.Size32) x dst))))
|
(_ Unit (emit (MInst.Imm (OperandSize.Size32) x dst))))
|
||||||
(writable_reg_to_reg dst)))
|
(writable_reg_to_reg dst)))
|
||||||
|
|
||||||
;; Special case for zero immediates: turn them into an `xor r, r`.
|
;; Special case for integer zero immediates: turn them into an `xor r, r`.
|
||||||
(rule (imm ty 0)
|
(rule (imm ty 0)
|
||||||
(let ((wr WritableReg (temp_writable_reg ty))
|
(let ((wr WritableReg (temp_writable_reg ty))
|
||||||
(r Reg (writable_reg_to_reg wr))
|
(r Reg (writable_reg_to_reg wr))
|
||||||
@@ -663,6 +678,30 @@
|
|||||||
wr))))
|
wr))))
|
||||||
r))
|
r))
|
||||||
|
|
||||||
|
;; Special case for `f32` zero immediates to use `xorps`.
|
||||||
|
(rule (imm $F32 0)
|
||||||
|
(let ((wr WritableReg (temp_writable_reg $F32))
|
||||||
|
(r Reg (writable_reg_to_reg wr))
|
||||||
|
(_ Unit (emit (MInst.XmmRmR (SseOpcode.Xorps)
|
||||||
|
r
|
||||||
|
(RegMem.Reg r)
|
||||||
|
wr))))
|
||||||
|
r))
|
||||||
|
|
||||||
|
;; TODO: use cmpeqps for all 1s
|
||||||
|
|
||||||
|
;; Special case for `f64` zero immediates to use `xorpd`.
|
||||||
|
(rule (imm $F64 0)
|
||||||
|
(let ((wr WritableReg (temp_writable_reg $F64))
|
||||||
|
(r Reg (writable_reg_to_reg wr))
|
||||||
|
(_ Unit (emit (MInst.XmmRmR (SseOpcode.Xorpd)
|
||||||
|
r
|
||||||
|
(RegMem.Reg r)
|
||||||
|
wr))))
|
||||||
|
r))
|
||||||
|
|
||||||
|
;; TODO: use cmpeqpd for all 1s
|
||||||
|
|
||||||
;; Helper for creating `MInst.ShifR` instructions.
|
;; Helper for creating `MInst.ShifR` instructions.
|
||||||
(decl shift_r (Type ShiftKind Reg Imm8Reg) Reg)
|
(decl shift_r (Type ShiftKind Reg Imm8Reg) Reg)
|
||||||
(rule (shift_r ty kind src1 src2)
|
(rule (shift_r ty kind src1 src2)
|
||||||
@@ -1069,3 +1108,10 @@
|
|||||||
src2
|
src2
|
||||||
(encode_fcmp_imm imm)
|
(encode_fcmp_imm imm)
|
||||||
(OperandSize.Size32)))
|
(OperandSize.Size32)))
|
||||||
|
|
||||||
|
;; Helper for creating `MInst.GprToXmm` instructions.
|
||||||
|
(decl gpr_to_xmm (Type SseOpcode RegMem OperandSize) Reg)
|
||||||
|
(rule (gpr_to_xmm ty op src size)
|
||||||
|
(let ((dst WritableReg (temp_writable_reg ty))
|
||||||
|
(_ Unit (emit (MInst.GprToXmm op src dst size))))
|
||||||
|
(writable_reg_to_reg dst)))
|
||||||
|
|||||||
@@ -41,6 +41,16 @@
|
|||||||
(value_regs (imm $B64 1)
|
(value_regs (imm $B64 1)
|
||||||
(imm $B64 0)))
|
(imm $B64 0)))
|
||||||
|
|
||||||
|
;;;; Rules for `f32const` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(rule (lower (f32const (u64_from_ieee32 x)))
|
||||||
|
(value_reg (imm $F32 x)))
|
||||||
|
|
||||||
|
;;;; Rules for `f64const` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(rule (lower (f64const (u64_from_ieee64 x)))
|
||||||
|
(value_reg (imm $F64 x)))
|
||||||
|
|
||||||
;;;; Rules for `null` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;; Rules for `null` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(rule (lower (has_type ty (null)))
|
(rule (lower (has_type ty (null)))
|
||||||
|
|||||||
@@ -3361,25 +3361,19 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Opcode::F64const => {
|
Opcode::F64const => {
|
||||||
// TODO use cmpeqpd for all 1s.
|
unreachable!(
|
||||||
let value = ctx.get_constant(insn).unwrap();
|
"implemented in ISLE: inst = `{}`, type = `{:?}`",
|
||||||
let dst = get_output_reg(ctx, outputs[0]);
|
ctx.dfg().display_inst(insn),
|
||||||
for inst in Inst::gen_constant(dst, value as u128, types::F64, |ty| {
|
ty
|
||||||
ctx.alloc_tmp(ty).only_reg().unwrap()
|
);
|
||||||
}) {
|
|
||||||
ctx.emit(inst);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode::F32const => {
|
Opcode::F32const => {
|
||||||
// TODO use cmpeqps for all 1s.
|
unreachable!(
|
||||||
let value = ctx.get_constant(insn).unwrap();
|
"implemented in ISLE: inst = `{}`, type = `{:?}`",
|
||||||
let dst = get_output_reg(ctx, outputs[0]);
|
ctx.dfg().display_inst(insn),
|
||||||
for inst in Inst::gen_constant(dst, value as u128, types::F32, |ty| {
|
ty
|
||||||
ctx.alloc_tmp(ty).only_reg().unwrap()
|
);
|
||||||
}) {
|
|
||||||
ctx.emit(inst);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode::WideningPairwiseDotProductS => {
|
Opcode::WideningPairwiseDotProductS => {
|
||||||
|
|||||||
@@ -400,6 +400,14 @@ where
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn u64_from_ieee32(&mut self, val: Ieee32) -> u64 {
|
||||||
|
val.bits().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u64_from_ieee64(&mut self, val: Ieee64) -> u64 {
|
||||||
|
val.bits()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -119,6 +119,9 @@
|
|||||||
(extern const $I64 Type)
|
(extern const $I64 Type)
|
||||||
(extern const $I128 Type)
|
(extern const $I128 Type)
|
||||||
|
|
||||||
|
(extern const $F32 Type)
|
||||||
|
(extern const $F64 Type)
|
||||||
|
|
||||||
(extern const $B8X16 Type)
|
(extern const $B8X16 Type)
|
||||||
(extern const $B16X8 Type)
|
(extern const $B16X8 Type)
|
||||||
(extern const $B32X4 Type)
|
(extern const $B32X4 Type)
|
||||||
@@ -164,6 +167,14 @@
|
|||||||
(decl u64_from_imm64 (u64) Imm64)
|
(decl u64_from_imm64 (u64) Imm64)
|
||||||
(extern extractor infallible u64_from_imm64 u64_from_imm64)
|
(extern extractor infallible u64_from_imm64 u64_from_imm64)
|
||||||
|
|
||||||
|
;; Extract a `u64` from an `Ieee32`.
|
||||||
|
(decl u64_from_ieee32 (u64) Ieee32)
|
||||||
|
(extern extractor infallible u64_from_ieee32 u64_from_ieee32)
|
||||||
|
|
||||||
|
;; Extract a `u64` from an `Ieee64`.
|
||||||
|
(decl u64_from_ieee64 (u64) Ieee64)
|
||||||
|
(extern extractor infallible u64_from_ieee64 u64_from_ieee64)
|
||||||
|
|
||||||
;; Extract the result values for the given instruction.
|
;; Extract the result values for the given instruction.
|
||||||
(decl inst_results (ValueSlice) Inst)
|
(decl inst_results (ValueSlice) Inst)
|
||||||
(extern extractor infallible inst_results inst_results)
|
(extern extractor infallible inst_results inst_results)
|
||||||
|
|||||||
Reference in New Issue
Block a user