diff --git a/cranelift/filetests/wasm/f32-arith.cton b/cranelift/filetests/wasm/f32-arith.cton index a72b2ae3ff..cb912dc3fc 100644 --- a/cranelift/filetests/wasm/f32-arith.cton +++ b/cranelift/filetests/wasm/f32-arith.cton @@ -17,8 +17,18 @@ ebb0: ; Unary operations -; function %f32_abs(f32) -> f32 -; function %f32_neg(f32) -> f32 +function %f32_abs(f32) -> f32 { +ebb0(v0: f32): + v1 = fabs v0 + return v1 +} + +function %f32_neg(f32) -> f32 { +ebb0(v0: f32): + v1 = fneg v0 + return v1 +} + ; function %f32_sqrt(f32) -> f32 ; function %f32_ceil(f32) -> f32 ; function %f32_floor(f32) -> f32 diff --git a/cranelift/filetests/wasm/f64-arith.cton b/cranelift/filetests/wasm/f64-arith.cton index decfa6cba0..1adc36e4f4 100644 --- a/cranelift/filetests/wasm/f64-arith.cton +++ b/cranelift/filetests/wasm/f64-arith.cton @@ -14,8 +14,18 @@ ebb0: ; Unary operations -; function %f64_abs(f64) -> f64 -; function %f64_neg(f64) -> f64 +function %f64_abs(f64) -> f64 { +ebb0(v0: f64): + v1 = fabs v0 + return v1 +} + +function %f64_neg(f64) -> f64 { +ebb0(v0: f64): + v1 = fneg v0 + return v1 +} + ; function %f64_sqrt(f64) -> f64 ; function %f64_ceil(f64) -> f64 ; function %f64_floor(f64) -> f64 diff --git a/lib/cretonne/meta/base/legalize.py b/lib/cretonne/meta/base/legalize.py index 4f92827b24..e535f62114 100644 --- a/lib/cretonne/meta/base/legalize.py +++ b/lib/cretonne/meta/base/legalize.py @@ -7,8 +7,9 @@ patterns that describe how base instructions can be transformed to other base instructions that are legal. """ from __future__ import absolute_import -from .immediates import intcc +from .immediates import intcc, ieee32, ieee64 from . import instructions as insts +from . import types from .instructions import iadd, iadd_cout, iadd_cin, iadd_carry, iadd_imm from .instructions import isub, isub_bin, isub_bout, isub_borrow from .instructions import imul, imul_imm @@ -18,6 +19,7 @@ from .instructions import icmp, icmp_imm from .instructions import iconst, bint from .instructions import ishl, ishl_imm, sshr, sshr_imm, ushr, ushr_imm from .instructions import rotl, rotl_imm, rotr, rotr_imm +from .instructions import f32const, f64const from cdsl.ast import Var from cdsl.xform import Rtl, XFormGroup @@ -207,3 +209,20 @@ for inst_not, inst in [ a1 << bnot(y), a << inst(x, a1) )) + +# Floating-point sign manipulations. +for ty, minus_zero in [ + (types.f32, f32const(ieee32.bits(0x80000000))), + (types.f64, f64const(ieee64.bits(0x8000000000000000)))]: + expand.legalize( + a << insts.fabs.bind(ty)(x), + Rtl( + b << minus_zero, + a << band_not(x, b), + )) + expand.legalize( + a << insts.fneg.bind(ty)(x), + Rtl( + b << minus_zero, + a << bxor(x, b), + )) diff --git a/lib/cretonne/meta/cdsl/ast.py b/lib/cretonne/meta/cdsl/ast.py index 251fee3641..619c2d36a2 100644 --- a/lib/cretonne/meta/cdsl/ast.py +++ b/lib/cretonne/meta/cdsl/ast.py @@ -502,6 +502,27 @@ class ConstantInt(Literal): return str(self.value) +class ConstantBits(Literal): + """ + A bitwise value of an immediate operand. + + This is used to create bitwise exact floating point constants using + `ieee32.bits(0x80000000)`. + """ + + def __init__(self, kind, bits): + # type: (ImmediateKind, int) -> None + v = '{}::with_bits({:#x})'.format(kind.rust_type, bits) + super(ConstantBits, self).__init__(kind, v) + + def __str__(self): + # type: () -> str + """ + Get the Rust expression form of this constant. + """ + return str(self.value) + + class Enumerator(Literal): """ A value of an enumerated immediate operand. diff --git a/lib/cretonne/meta/cdsl/operands.py b/lib/cretonne/meta/cdsl/operands.py index ea59de5b3e..85d4adef99 100644 --- a/lib/cretonne/meta/cdsl/operands.py +++ b/lib/cretonne/meta/cdsl/operands.py @@ -8,7 +8,7 @@ try: from typing import Union, Dict, TYPE_CHECKING, Iterable # noqa OperandSpec = Union['OperandKind', ValueType, TypeVar] if TYPE_CHECKING: - from .ast import Enumerator, ConstantInt, Literal # noqa + from .ast import Enumerator, ConstantInt, ConstantBits, Literal # noqa except ImportError: pass @@ -123,6 +123,15 @@ class ImmediateKind(OperandKind): .format(self.name, value)) return ConstantInt(self, value) + def bits(self, bits): + # type: (int) -> ConstantBits + """ + Create an AST literal node for the given bitwise representation of this + immediate operand kind. + """ + from .ast import ConstantBits # noqa + return ConstantBits(self, bits) + def rust_enumerator(self, value): # type: (str) -> str """