From 2bfb4ca5b7830a67022f9ce4e3e95df102acb6b5 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 7 Jul 2016 13:16:24 -0700 Subject: [PATCH] Add meta definitions for floating point operations. Rename the Select instruction format to Ternary since it is also used by the fma instruction. --- docs/langref.rst | 89 +++++++------------- meta/cretonne/base.py | 143 +++++++++++++++++++++++++++++++- meta/cretonne/formats.py | 5 +- src/libcretonne/instructions.rs | 2 +- src/libcretonne/write.rs | 2 +- src/libreader/parser.rs | 6 +- 6 files changed, 183 insertions(+), 64 deletions(-) diff --git a/docs/langref.rst b/docs/langref.rst index 7df404e02c..61c534ad69 100644 --- a/docs/langref.rst +++ b/docs/langref.rst @@ -771,73 +771,48 @@ Floating point operations These operations generally follow IEEE 754-2008 semantics. .. autoinst:: fcmp +.. autoinst:: fadd +.. autoinst:: fsub +.. autoinst:: fmul +.. autoinst:: fdiv +.. autoinst:: sqrt +.. autoinst:: fma -.. inst:: fadd x,y +Sign bit manipulations +~~~~~~~~~~~~~~~~~~~~~~ - Floating point addition. +The sign manipulating instructions work as bitwise operations, so they don't +have special behavior for signaling NaN operands. The exponent and trailing +significand bits are always preserved. -.. inst:: fsub x,y +.. autoinst:: fneg +.. autoinst:: fabs +.. autoinst:: fcopysign - Floating point subtraction. +Minimum and maximum +~~~~~~~~~~~~~~~~~~~ -.. inst:: fneg x +These instructions return the larger or smaller of their operands. They differ +in their handling of quiet NaN inputs. Note that signaling NaN operands always +cause a NaN result. - Floating point negation. +When comparing zeroes, these instructions behave as if :math:`-0.0 < 0.0`. - :result: ``x`` with its sign bit inverted. +.. autoinst:: fmin +.. autoinst:: fminnum +.. autoinst:: fmax +.. autoinst:: fmaxnum - Note that this is a pure bitwise operation. +Rounding +~~~~~~~~ -.. inst:: fabs x +These instructions round their argument to a nearby integral value, still +represented as a floating point number. - Floating point absolute value. - - :result: ``x`` with its sign bit cleared. - - Note that this is a pure bitwise operation. - -.. inst:: a = fcopysign x, y - - Floating point copy sign. - - :result: ``x`` with its sign changed to that of ``y``. - - Note that this is a pure bitwise operation. The sign bit from ``y`` is - copied to the sign bit of ``x``. - -.. inst:: a = fmul x, y -.. inst:: a = fdiv x, y -.. inst:: a = fmin x, y -.. inst:: a = fminnum x, y -.. inst:: a = fmax x, y -.. inst:: a = fmaxnum x, y - -.. inst:: a = ceil x - - Round floating point round to integral, towards positive infinity. - -.. inst:: floor x - - Round floating point round to integral, towards negative infinity. - -.. inst:: trunc x - - Round floating point round to integral, towards zero. - -.. inst:: nearest x - - Round floating point round to integral, towards nearest with ties to even. - -.. inst:: sqrt x - - Floating point square root. - -.. inst:: a = fma x, y, z - - Floating point fused multiply-and-add. - - Computes :math:`a := xy+z` wihtout any intermediate rounding of the - product. +.. autoinst:: ceil +.. autoinst:: floor +.. autoinst:: trunc +.. autoinst:: nearest Conversion operations --------------------- diff --git a/meta/cretonne/base.py b/meta/cretonne/base.py index e6d008585b..fd3e4fdcb5 100644 --- a/meta/cretonne/base.py +++ b/meta/cretonne/base.py @@ -548,7 +548,7 @@ popcnt = Instruction( # Float = TypeVar( - 'Float', 'A scalar or vector floating point type type', + 'Float', 'A scalar or vector floating point number', floats=True, simd=True) Cond = Operand('Cond', floatcc) @@ -620,4 +620,145 @@ fcmp = Instruction( """, ins=(Cond, x, y), outs=a) +x = Operand('x', Float) +y = Operand('y', Float) +z = Operand('z', Float) +a = Operand('a', Float, 'Result of applying operator to each lane') + +fadd = Instruction( + 'fadd', r""" + Floating point addition. + """, + ins=(x, y), outs=a) + +fsub = Instruction( + 'fsub', r""" + Floating point subtraction. + """, + ins=(x, y), outs=a) + +fmul = Instruction( + 'fmul', r""" + Floating point multiplication. + """, + ins=(x, y), outs=a) + +fdiv = Instruction( + 'fdiv', r""" + Floating point division. + + Unlike the integer division instructions :cton:inst:`sdiv` and + :cton:inst:`udiv`, this can't trap. Division by zero is infinity or + NaN, depending on the dividend. + """, + ins=(x, y), outs=a) + +sqrt = Instruction( + 'sqrt', r""" + Floating point square root. + """, + ins=x, outs=a) + +fma = Instruction( + 'fma', r""" + Floating point fused multiply-and-add. + + Computes :math:`a := xy+z` wihtout any intermediate rounding of the + product. + """, + ins=(x, y, z), outs=a) + +a = Operand('a', Float, '``x`` with its sign bit inverted') +fneg = Instruction( + 'fneg', r""" + Floating point negation. + + Note that this is a pure bitwise operation. + """, + ins=x, outs=a) + +a = Operand('a', Float, '``x`` with its sign bit cleared') +fabs = Instruction( + 'fabs', r""" + Floating point absolute value. + + Note that this is a pure bitwise operation. + """, + ins=x, outs=a) + +a = Operand('a', Float, '``x`` with its sign bit changed to that of ``y``') +fcopysign = Instruction( + 'fcopysign', r""" + Floating point copy sign. + + Note that this is a pure bitwise operation. The sign bit from ``y`` is + copied to the sign bit of ``x``. + """, + ins=(x, y), outs=a) + +a = Operand('a', Float, 'The smaller of ``x`` and ``y``') + +fmin = Instruction( + 'fmin', r""" + Floating point minimum, propagating NaNs. + + If either operand is NaN, this returns a NaN. + """, + ins=(x, y), outs=a) + +fminnum = Instruction( + 'fminnum', r""" + Floating point minimum, suppressing quiet NaNs. + + If either operand is a quiet NaN, the other operand is returned. If + either operand is a signaling NaN, NaN is returned. + """, + ins=(x, y), outs=a) + +a = Operand('a', Float, 'The larger of ``x`` and ``y``') + +fmax = Instruction( + 'fmax', r""" + Floating point maximum, propagating NaNs. + + If either operand is NaN, this returns a NaN. + """, + ins=(x, y), outs=a) + +fmaxnum = Instruction( + 'fmaxnum', r""" + Floating point maximum, suppressing quiet NaNs. + + If either operand is a quiet NaN, the other operand is returned. If + either operand is a signaling NaN, NaN is returned. + """, + ins=(x, y), outs=a) + +a = Operand('a', Float, '``x`` rounded to integral value') + +ceil = Instruction( + 'ceil', r""" + Round floating point round to integral, towards positive infinity. + """, + ins=x, outs=a) + +floor = Instruction( + 'floor', r""" + Round floating point round to integral, towards negative infinity. + """, + ins=x, outs=a) + +trunc = Instruction( + 'trunc', r""" + Round floating point round to integral, towards zero. + """, + ins=x, outs=a) + +nearest = Instruction( + 'nearest', r""" + Round floating point round to integral, towards nearest with ties to + even. + """, + ins=x, outs=a) + instructions.close() diff --git a/meta/cretonne/formats.py b/meta/cretonne/formats.py index 62c678f9b9..5fc6cd7a2d 100644 --- a/meta/cretonne/formats.py +++ b/meta/cretonne/formats.py @@ -27,8 +27,9 @@ BinaryImmRev = InstructionFormat(imm64, value) BinaryOverflow = InstructionFormat(value, value, multiple_results=True) # The select instructions are controlled by the second value operand. -# The first value operand is the controlling flag whisch has a derived type. -Select = InstructionFormat(value, value, value, typevar_operand=1) +# The first value operand is the controlling flag which has a derived type. +# The fma instruction has the same constraint on all inputs. +Ternary = InstructionFormat(value, value, value, typevar_operand=1) InsertLane = InstructionFormat(value, uimm8, value) ExtractLane = InstructionFormat(value, uimm8) diff --git a/src/libcretonne/instructions.rs b/src/libcretonne/instructions.rs index 106f506e47..21138e2ce7 100644 --- a/src/libcretonne/instructions.rs +++ b/src/libcretonne/instructions.rs @@ -159,7 +159,7 @@ pub enum InstructionData { second_result: Value, args: [Value; 2], }, - Select { + Ternary { opcode: Opcode, ty: Type, args: [Value; 3], diff --git a/src/libcretonne/write.rs b/src/libcretonne/write.rs index 217d670afc..6a14497f81 100644 --- a/src/libcretonne/write.rs +++ b/src/libcretonne/write.rs @@ -194,7 +194,7 @@ pub fn write_instruction(w: &mut Write, func: &Function, inst: Inst) -> Result { BinaryImm { arg, imm, .. } => writeln!(w, " {}, {}", arg, imm), BinaryImmRev { imm, arg, .. } => writeln!(w, " {}, {}", imm, arg), BinaryOverflow { args, .. } => writeln!(w, " {}, {}", args[0], args[1]), - Select { args, .. } => writeln!(w, " {}, {}, {}", args[0], args[1], args[2]), + Ternary { args, .. } => writeln!(w, " {}, {}, {}", args[0], args[1], args[2]), InsertLane { lane, args, .. } => writeln!(w, " {}, {}, {}", args[0], lane, args[1]), ExtractLane { lane, arg, .. } => writeln!(w, " {}, {}", arg, lane), IntCompare { cond, args, .. } => writeln!(w, " {}, {}, {}", cond, args[0], args[1]), diff --git a/src/libreader/parser.rs b/src/libreader/parser.rs index a17449008e..7977ccbf54 100644 --- a/src/libreader/parser.rs +++ b/src/libreader/parser.rs @@ -815,13 +815,15 @@ impl<'a> Parser<'a> { args: [lhs, rhs], } } - InstructionFormat::Select => { + InstructionFormat::Ternary => { + // Names here refer to the `select` instruction. + // This format is also use by `fma`. let ctrl_arg = try!(self.match_value("expected SSA value control operand")); try!(self.match_token(Token::Comma, "expected ',' between operands")); let true_arg = try!(self.match_value("expected SSA value true operand")); try!(self.match_token(Token::Comma, "expected ',' between operands")); let false_arg = try!(self.match_value("expected SSA value false operand")); - InstructionData::Select { + InstructionData::Ternary { opcode: opcode, ty: VOID, args: [ctrl_arg, true_arg, false_arg],