Add custom legalization for floating point constants.
Use the simplest expansion which materializes the bits of the floating point constant as an integer and then bit-casts to the floating point type. In the future, we may want to use constant pools instead. Either way, we need custom legalization. Also add a legalize_monomorphic() function to the Python targetISA class which permits the configuration of a default legalization action for monomorphic instructions, just like legalize_type() does for polymorphic instructions.
This commit is contained in:
@@ -52,3 +52,19 @@ ebb0(v1: i32):
|
||||
; check: $new:
|
||||
; nextln: return
|
||||
}
|
||||
|
||||
function %f32const() -> f32 {
|
||||
ebb0:
|
||||
v1 = f32const 0x1.0p1
|
||||
; check: $(tmp=$V) = iconst.i32
|
||||
; check: $v1 = bitcast.f32 $tmp
|
||||
return v1
|
||||
}
|
||||
|
||||
function %f64const() -> f64 {
|
||||
ebb0:
|
||||
v1 = f64const 0x1.0p1
|
||||
; check: $(tmp=$V) = iconst.i64
|
||||
; check: $v1 = bitcast.f64 $tmp
|
||||
return v1
|
||||
}
|
||||
|
||||
@@ -54,6 +54,11 @@ expand.custom_legalize(insts.heap_addr, 'expand_heap_addr')
|
||||
expand.custom_legalize(insts.trapz, 'expand_cond_trap')
|
||||
expand.custom_legalize(insts.trapnz, 'expand_cond_trap')
|
||||
|
||||
# Custom expansions for floating point constants.
|
||||
# These expansions require bit-casting or creating constant pool entries.
|
||||
expand.custom_legalize(insts.f32const, 'expand_fconst')
|
||||
expand.custom_legalize(insts.f64const, 'expand_fconst')
|
||||
|
||||
x = Var('x')
|
||||
y = Var('y')
|
||||
a = Var('a')
|
||||
|
||||
@@ -263,6 +263,16 @@ class CPUMode(object):
|
||||
ty = ValueType.by_name(name)
|
||||
self.type_legalize[ty] = xgrp
|
||||
|
||||
def legalize_monomorphic(self, xgrp):
|
||||
# type: (XFormGroup) -> None
|
||||
"""
|
||||
Configure the legalization action to take for monomorphic instructions
|
||||
which don't have a controlling type variable.
|
||||
|
||||
See also `legalize_type()` for polymorphic instructions.
|
||||
"""
|
||||
self.type_legalize[None] = xgrp
|
||||
|
||||
def get_legalize_action(self, ty):
|
||||
# type: (ValueType) -> XFormGroup
|
||||
"""
|
||||
|
||||
@@ -20,6 +20,7 @@ except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
I32.legalize_monomorphic(expand)
|
||||
I32.legalize_type(
|
||||
default=narrow,
|
||||
b1=expand,
|
||||
@@ -27,6 +28,7 @@ I32.legalize_type(
|
||||
f32=expand,
|
||||
f64=expand)
|
||||
|
||||
I64.legalize_monomorphic(expand)
|
||||
I64.legalize_type(
|
||||
default=narrow,
|
||||
b1=expand,
|
||||
|
||||
@@ -13,12 +13,14 @@ from .settings import use_m
|
||||
from cdsl.ast import Var
|
||||
from base.legalize import narrow, expand
|
||||
|
||||
RV32.legalize_monomorphic(expand)
|
||||
RV32.legalize_type(
|
||||
default=narrow,
|
||||
i32=expand,
|
||||
f32=expand,
|
||||
f64=expand)
|
||||
|
||||
RV64.legalize_monomorphic(expand)
|
||||
RV64.legalize_type(
|
||||
default=narrow,
|
||||
i32=expand,
|
||||
|
||||
@@ -599,6 +599,11 @@ impl Ieee32 {
|
||||
pub fn with_float(x: f32) -> Ieee32 {
|
||||
Ieee32(unsafe { mem::transmute(x) })
|
||||
}
|
||||
|
||||
/// Get the bitwise representation.
|
||||
pub fn bits(self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Ieee32 {
|
||||
@@ -630,6 +635,11 @@ impl Ieee64 {
|
||||
pub fn with_float(x: f64) -> Ieee64 {
|
||||
Ieee64(unsafe { mem::transmute(x) })
|
||||
}
|
||||
|
||||
/// Get the bitwise representation.
|
||||
pub fn bits(self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Ieee64 {
|
||||
|
||||
@@ -146,3 +146,25 @@ fn expand_cond_trap(inst: ir::Inst, func: &mut ir::Function, cfg: &mut ControlFl
|
||||
cfg.recompute_ebb(pos.func, old_ebb);
|
||||
cfg.recompute_ebb(pos.func, new_ebb);
|
||||
}
|
||||
|
||||
/// Expand illegal `f32const` and `f64const` instructions.
|
||||
fn expand_fconst(inst: ir::Inst, func: &mut ir::Function, _cfg: &mut ControlFlowGraph) {
|
||||
let ty = func.dfg.value_type(func.dfg.first_result(inst));
|
||||
assert!(ty.is_scalar(), "Only scalar fconst supported: {}", ty);
|
||||
|
||||
// In the future, we may want to generate constant pool entries for these constants, but for
|
||||
// now use an `iconst` and a bit cast.
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
let ival = match pos.func.dfg[inst] {
|
||||
ir::InstructionData::UnaryIeee32 {
|
||||
opcode: ir::Opcode::F32const,
|
||||
imm,
|
||||
} => pos.ins().iconst(ir::types::I32, imm.bits() as i64),
|
||||
ir::InstructionData::UnaryIeee64 {
|
||||
opcode: ir::Opcode::F64const,
|
||||
imm,
|
||||
} => pos.ins().iconst(ir::types::I64, imm.bits() as i64),
|
||||
_ => panic!("Expected fconst: {}", pos.func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
pos.func.dfg.replace(inst).bitcast(ty, ival);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user