Define icmp and fcmp comparison instructions.

Add new intcc and floatcc operand types for the immediate condition codes on
these instructions.

Add new IntCompare and FloatCompare instruction formats.

Add a generic match_enum() parser function that can match any identifier-like
enumerated operand kind that implements FromStr.

Define the icmp and fcmp instructions in case.py. Include documentation for the
condition codes with these two instructions.
This commit is contained in:
Jakob Stoklund Olesen
2016-07-07 11:20:56 -07:00
parent 70507a3be0
commit 5d8fb0fdc3
9 changed files with 218 additions and 52 deletions

View File

@@ -270,6 +270,14 @@ indicate the different kinds of immediate operands on an instruction.
bits of the operand are interpreted as if the SIMD vector was loaded from
memory containing the immediate.
.. type:: intcc
An integer condition code. See the :inst:`icmp` instruction for details.
.. type:: floatcc
A floating point condition code. See the :inst:`fcmp` instruction for details.
The two IEEE floating point immediate types :type:`ieee32` and :type:`ieee64`
are displayed as hexadecimal floating point literals in the textual IL format.
Decimal floating point literals are not allowed because some computer systems
@@ -676,29 +684,7 @@ Vector operations
Integer operations
------------------
.. inst:: a = icmp Cond, x, y
Integer comparison.
:arg Cond: Condition code determining how ``x`` and ``y`` are compared.
:arg Int x: First value to compare.
:arg Int y: Second value to compare.
:result Logic a: With the same number of lanes as ``x`` and ``y``.
The condition code determines if the operands are interpreted as signed or
unsigned integers.
====== ======== =========
Signed Unsigned Condition
====== ======== =========
eq eq Equal
ne ne Not equal
slt ult Less than
sge uge Greater than or equal
sgt ugt Greater than
sle ule Less than or equal
====== ======== =========
.. autoinst:: icmp
.. autoinst:: iadd
.. autoinst:: iadd_imm
.. autoinst:: isub
@@ -784,30 +770,7 @@ Floating point operations
These operations generally follow IEEE 754-2008 semantics.
.. inst:: a = fcmp Cond, x, y
Floating point comparison.
:arg Cond: Condition code determining how ``x`` and ``y`` are compared.
:arg x,y: Floating point scalar or vector values of the same type.
:rtype: :type:`b1` or :type:`b1xN` with the same number of lanes as
``x`` and ``y``.
An 'ordered' condition code yields ``false`` if either operand is Nan.
An 'unordered' condition code yields ``true`` if either operand is Nan.
======= ========= =========
Ordered Unordered Condition
======= ========= =========
ord uno None (ord = no NaNs, uno = some NaNs)
oeq ueq Equal
one une Not equal
olt ult Less than
oge uge Greater than or equal
ogt ugt Greater than
ole ule Less than or equal
======= ========= =========
.. autoinst:: fcmp
.. inst:: fadd x,y

View File

@@ -11,6 +11,7 @@ use std::str::FromStr;
use entities::*;
use immediates::*;
use condcodes::*;
use types::{self, Type};
// Include code generated by `meta/gen_instr.py`. This file contains:
@@ -175,6 +176,18 @@ pub enum InstructionData {
lane: u8,
arg: Value,
},
IntCompare {
opcode: Opcode,
ty: Type,
cond: IntCC,
args: [Value; 2],
},
FloatCompare {
opcode: Opcode,
ty: Type,
cond: FloatCC,
args: [Value; 2],
},
Jump {
opcode: Opcode,
ty: Type,

View File

@@ -197,6 +197,8 @@ pub fn write_instruction(w: &mut Write, func: &Function, inst: Inst) -> Result {
Select { 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]),
FloatCompare { cond, args, .. } => writeln!(w, " {}, {}, {}", cond, args[0], args[1]),
Jump { ref data, .. } => writeln!(w, " {}", data),
Branch { ref data, .. } => writeln!(w, " {}", data),
BranchTable { arg, table, .. } => writeln!(w, " {}, {}", arg, table),

View File

@@ -8,6 +8,7 @@
use std::collections::HashMap;
use std::result;
use std::fmt::{self, Display, Formatter, Write};
use std::str::FromStr;
use std::u32;
use lexer::{self, Lexer, Token};
use cretonne::types::{Type, VOID, FunctionName, Signature, ArgumentType, ArgumentExtension};
@@ -249,7 +250,7 @@ impl<'a> Parser<'a> {
// Match and consume a u8 immediate.
// This is used for lane numbers in SIMD vectors.
fn match_u8(&mut self, err_msg: &str) -> Result<u8> {
fn match_uimm8(&mut self, err_msg: &str) -> Result<u8> {
if let Some(Token::Integer(text)) = self.token() {
self.consume();
// Lexer just gives us raw text that looks like an integer.
@@ -284,6 +285,16 @@ impl<'a> Parser<'a> {
}
}
// Match and consume an enumerated immediate, like one of the condition codes.
fn match_enum<T: FromStr>(&mut self, err_msg: &str) -> Result<T> {
if let Some(Token::Identifier(text)) = self.token() {
self.consume();
text.parse().map_err(|_| self.error(err_msg))
} else {
err!(self.loc, err_msg)
}
}
/// Parse a list of function definitions.
///
/// This is the top-level parse function matching the whole contents of a file.
@@ -847,7 +858,7 @@ impl<'a> Parser<'a> {
InstructionFormat::InsertLane => {
let lhs = try!(self.match_value("expected SSA value first operand"));
try!(self.match_token(Token::Comma, "expected ',' between operands"));
let lane = try!(self.match_u8("expected lane number"));
let lane = try!(self.match_uimm8("expected lane number"));
try!(self.match_token(Token::Comma, "expected ',' between operands"));
let rhs = try!(self.match_value("expected SSA value last operand"));
InstructionData::InsertLane {
@@ -860,7 +871,7 @@ impl<'a> Parser<'a> {
InstructionFormat::ExtractLane => {
let arg = try!(self.match_value("expected SSA value last operand"));
try!(self.match_token(Token::Comma, "expected ',' between operands"));
let lane = try!(self.match_u8("expected lane number"));
let lane = try!(self.match_uimm8("expected lane number"));
InstructionData::ExtractLane {
opcode: opcode,
ty: VOID,
@@ -868,6 +879,32 @@ impl<'a> Parser<'a> {
arg: arg,
}
}
InstructionFormat::IntCompare => {
let cond = try!(self.match_enum("expected intcc condition code"));
try!(self.match_token(Token::Comma, "expected ',' between operands"));
let lhs = try!(self.match_value("expected SSA value first operand"));
try!(self.match_token(Token::Comma, "expected ',' between operands"));
let rhs = try!(self.match_value("expected SSA value second operand"));
InstructionData::IntCompare {
opcode: opcode,
ty: VOID,
cond: cond,
args: [lhs, rhs],
}
}
InstructionFormat::FloatCompare => {
let cond = try!(self.match_enum("expected floatcc condition code"));
try!(self.match_token(Token::Comma, "expected ',' between operands"));
let lhs = try!(self.match_value("expected SSA value first operand"));
try!(self.match_token(Token::Comma, "expected ',' between operands"));
let rhs = try!(self.match_value("expected SSA value second operand"));
InstructionData::FloatCompare {
opcode: opcode,
ty: VOID,
cond: cond,
args: [lhs, rhs],
}
}
InstructionFormat::BranchTable |
InstructionFormat::Call => {
unimplemented!();

View File

@@ -26,3 +26,19 @@ ebb0:
v1 = extractlane v0, 3
v2 = insertlane v0, 1, v1
}
; Integer condition codes.
function icmp(i32, i32) {
ebb0(vx0: i32, vx1: i32):
v0 = icmp eq, vx0, vx1
v1 = icmp ult, vx0, vx1
v2 = icmp sge, vx0, vx1
}
; Floating condition codes.
function fcmp(f32, f32) {
ebb0(vx0: f32, vx1: f32):
v0 = fcmp eq, vx0, vx1
v1 = fcmp uno, vx0, vx1
v2 = fcmp lt, vx0, vx1
}

View File

@@ -21,3 +21,17 @@ ebb0:
v1 = extractlane v0, 3
v2 = insertlane v0, 1, v1
}
function icmp(i32, i32) {
ebb0(vx0: i32, vx1: i32):
v0 = icmp eq, vx0, vx1
v1 = icmp ult, vx0, vx1
v2 = icmp sge, vx0, vx1
}
function fcmp(f32, f32) {
ebb0(vx0: f32, vx1: f32):
v0 = fcmp eq, vx0, vx1
v1 = fcmp uno, vx0, vx1
v2 = fcmp lt, vx0, vx1
}