Add legalization patterns for fabs and fneg.

These sign bit manipulations need to use a -0.0 floating point constant
which we didn't have a way of materializing previously.

Add a ieee32.bits(0x...) syntax to the Python AST nodes that creates am
f32 immediate value with the exact requested bitwise representation.
This commit is contained in:
Jakob Stoklund Olesen
2017-09-25 12:12:47 -07:00
parent ba1c50d6c1
commit 8deca67968
5 changed files with 75 additions and 6 deletions

View File

@@ -17,8 +17,18 @@ ebb0:
; Unary operations ; Unary operations
; function %f32_abs(f32) -> f32 function %f32_abs(f32) -> f32 {
; function %f32_neg(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_sqrt(f32) -> f32
; function %f32_ceil(f32) -> f32 ; function %f32_ceil(f32) -> f32
; function %f32_floor(f32) -> f32 ; function %f32_floor(f32) -> f32

View File

@@ -14,8 +14,18 @@ ebb0:
; Unary operations ; Unary operations
; function %f64_abs(f64) -> f64 function %f64_abs(f64) -> f64 {
; function %f64_neg(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_sqrt(f64) -> f64
; function %f64_ceil(f64) -> f64 ; function %f64_ceil(f64) -> f64
; function %f64_floor(f64) -> f64 ; function %f64_floor(f64) -> f64

View File

@@ -7,8 +7,9 @@ patterns that describe how base instructions can be transformed to other base
instructions that are legal. instructions that are legal.
""" """
from __future__ import absolute_import from __future__ import absolute_import
from .immediates import intcc from .immediates import intcc, ieee32, ieee64
from . import instructions as insts from . import instructions as insts
from . import types
from .instructions import iadd, iadd_cout, iadd_cin, iadd_carry, iadd_imm 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 isub, isub_bin, isub_bout, isub_borrow
from .instructions import imul, imul_imm from .instructions import imul, imul_imm
@@ -18,6 +19,7 @@ from .instructions import icmp, icmp_imm
from .instructions import iconst, bint from .instructions import iconst, bint
from .instructions import ishl, ishl_imm, sshr, sshr_imm, ushr, ushr_imm from .instructions import ishl, ishl_imm, sshr, sshr_imm, ushr, ushr_imm
from .instructions import rotl, rotl_imm, rotr, rotr_imm from .instructions import rotl, rotl_imm, rotr, rotr_imm
from .instructions import f32const, f64const
from cdsl.ast import Var from cdsl.ast import Var
from cdsl.xform import Rtl, XFormGroup from cdsl.xform import Rtl, XFormGroup
@@ -207,3 +209,20 @@ for inst_not, inst in [
a1 << bnot(y), a1 << bnot(y),
a << inst(x, a1) 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),
))

View File

@@ -502,6 +502,27 @@ class ConstantInt(Literal):
return str(self.value) 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): class Enumerator(Literal):
""" """
A value of an enumerated immediate operand. A value of an enumerated immediate operand.

View File

@@ -8,7 +8,7 @@ try:
from typing import Union, Dict, TYPE_CHECKING, Iterable # noqa from typing import Union, Dict, TYPE_CHECKING, Iterable # noqa
OperandSpec = Union['OperandKind', ValueType, TypeVar] OperandSpec = Union['OperandKind', ValueType, TypeVar]
if TYPE_CHECKING: if TYPE_CHECKING:
from .ast import Enumerator, ConstantInt, Literal # noqa from .ast import Enumerator, ConstantInt, ConstantBits, Literal # noqa
except ImportError: except ImportError:
pass pass
@@ -123,6 +123,15 @@ class ImmediateKind(OperandKind):
.format(self.name, value)) .format(self.name, value))
return ConstantInt(self, 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): def rust_enumerator(self, value):
# type: (str) -> str # type: (str) -> str
""" """