From 88348368a8be42071262f6c184b6dcdddbe43761 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 18 Sep 2017 13:27:25 -0700 Subject: [PATCH] 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. --- .../filetests/isa/intel/legalize-custom.cton | 16 ++++++++++++++ lib/cretonne/meta/base/legalize.py | 5 +++++ lib/cretonne/meta/cdsl/isa.py | 10 +++++++++ lib/cretonne/meta/isa/intel/encodings.py | 2 ++ lib/cretonne/meta/isa/riscv/encodings.py | 2 ++ lib/cretonne/src/ir/immediates.rs | 10 +++++++++ lib/cretonne/src/legalizer/mod.rs | 22 +++++++++++++++++++ 7 files changed, 67 insertions(+) diff --git a/cranelift/filetests/isa/intel/legalize-custom.cton b/cranelift/filetests/isa/intel/legalize-custom.cton index e8af47a460..4c8488173b 100644 --- a/cranelift/filetests/isa/intel/legalize-custom.cton +++ b/cranelift/filetests/isa/intel/legalize-custom.cton @@ -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 +} diff --git a/lib/cretonne/meta/base/legalize.py b/lib/cretonne/meta/base/legalize.py index 7fc252bc0c..626295e165 100644 --- a/lib/cretonne/meta/base/legalize.py +++ b/lib/cretonne/meta/base/legalize.py @@ -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') diff --git a/lib/cretonne/meta/cdsl/isa.py b/lib/cretonne/meta/cdsl/isa.py index 3e971e7a5a..ae517203e1 100644 --- a/lib/cretonne/meta/cdsl/isa.py +++ b/lib/cretonne/meta/cdsl/isa.py @@ -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 """ diff --git a/lib/cretonne/meta/isa/intel/encodings.py b/lib/cretonne/meta/isa/intel/encodings.py index ed0bbb433d..ffc6d28458 100644 --- a/lib/cretonne/meta/isa/intel/encodings.py +++ b/lib/cretonne/meta/isa/intel/encodings.py @@ -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, diff --git a/lib/cretonne/meta/isa/riscv/encodings.py b/lib/cretonne/meta/isa/riscv/encodings.py index b9f1f8245d..990b5c4112 100644 --- a/lib/cretonne/meta/isa/riscv/encodings.py +++ b/lib/cretonne/meta/isa/riscv/encodings.py @@ -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, diff --git a/lib/cretonne/src/ir/immediates.rs b/lib/cretonne/src/ir/immediates.rs index f33e13eccf..51120344cd 100644 --- a/lib/cretonne/src/ir/immediates.rs +++ b/lib/cretonne/src/ir/immediates.rs @@ -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 { diff --git a/lib/cretonne/src/legalizer/mod.rs b/lib/cretonne/src/legalizer/mod.rs index 0367854681..f47dc87241 100644 --- a/lib/cretonne/src/legalizer/mod.rs +++ b/lib/cretonne/src/legalizer/mod.rs @@ -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); +}