Add an icmp_imm instruction.

Compare a scalar integer to an immediate constant. Both Intel and RISC-V
ISAs have this operation.

This requires the addition of a new IntCompareImm instruction format.
This commit is contained in:
Jakob Stoklund Olesen
2017-04-03 09:49:44 -07:00
parent 6532cbab6c
commit 2e45365ee1
8 changed files with 48 additions and 6 deletions

View File

@@ -678,6 +678,7 @@ Integer operations
------------------ ------------------
.. autoinst:: icmp .. autoinst:: icmp
.. autoinst:: icmp_imm
.. autoinst:: iadd .. autoinst:: iadd
.. autoinst:: iadd_imm .. autoinst:: iadd_imm
.. autoinst:: iadd_cin .. autoinst:: iadd_cin

View File

@@ -54,14 +54,14 @@ function icmp(i32, i32) {
ebb0(vx0: i32, vx1: i32): ebb0(vx0: i32, vx1: i32):
v0 = icmp eq, vx0, vx1 v0 = icmp eq, vx0, vx1
v1 = icmp ult, vx0, vx1 v1 = icmp ult, vx0, vx1
v2 = icmp sge, vx0, vx1 v2 = icmp_imm sge, vx0, -12
v3 = irsub_imm vx1, 45 v3 = irsub_imm vx1, 45
} }
; sameln: function icmp(i32, i32) { ; sameln: function icmp(i32, i32) {
; nextln: ebb0(vx0: i32, vx1: i32): ; nextln: ebb0(vx0: i32, vx1: i32):
; nextln: v0 = icmp eq, vx0, vx1 ; nextln: v0 = icmp eq, vx0, vx1
; nextln: v1 = icmp ult, vx0, vx1 ; nextln: v1 = icmp ult, vx0, vx1
; nextln: v2 = icmp sge, vx0, vx1 ; nextln: v2 = icmp_imm sge, vx0, -12
; nextln: v3 = irsub_imm vx1, 45 ; nextln: v3 = irsub_imm vx1, 45
; nextln: } ; nextln: }

View File

@@ -38,6 +38,7 @@ InsertLane = InstructionFormat(VALUE, ('lane', uimm8), VALUE)
ExtractLane = InstructionFormat(VALUE, ('lane', uimm8)) ExtractLane = InstructionFormat(VALUE, ('lane', uimm8))
IntCompare = InstructionFormat(intcc, VALUE, VALUE) IntCompare = InstructionFormat(intcc, VALUE, VALUE)
IntCompareImm = InstructionFormat(intcc, VALUE, imm64)
FloatCompare = InstructionFormat(floatcc, VALUE, VALUE) FloatCompare = InstructionFormat(floatcc, VALUE, VALUE)
Jump = InstructionFormat(ebb, VARIABLE_ARGS) Jump = InstructionFormat(ebb, VARIABLE_ARGS)

View File

@@ -367,6 +367,22 @@ icmp = Instruction(
""", """,
ins=(Cond, x, y), outs=a) ins=(Cond, x, y), outs=a)
a = Operand('a', b1)
x = Operand('x', iB)
Y = Operand('Y', imm64)
icmp_imm = Instruction(
'icmp_imm', r"""
Compare scalar integer to a constant.
This is the same as the :inst:`icmp` instruction, except one operand is
an immediate constant.
This instruction can only compare scalars. Use :inst:`icmp` for
lane-wise vector comparisons.
""",
ins=(Cond, x, Y), outs=a)
a = Operand('a', Int) a = Operand('a', Int)
x = Operand('x', Int) x = Operand('x', Int)
y = Operand('y', Int) y = Operand('y', Int)

View File

@@ -175,6 +175,13 @@ pub enum InstructionData {
cond: IntCC, cond: IntCC,
args: [Value; 2], args: [Value; 2],
}, },
IntCompareImm {
opcode: Opcode,
ty: Type,
cond: IntCC,
arg: Value,
imm: Imm64,
},
FloatCompare { FloatCompare {
opcode: Opcode, opcode: Opcode,
ty: Type, ty: Type,

View File

@@ -251,6 +251,7 @@ impl<'a> Verifier<'a> {
&InsertLane { .. } | &InsertLane { .. } |
&ExtractLane { .. } | &ExtractLane { .. } |
&IntCompare { .. } | &IntCompare { .. } |
&IntCompareImm { .. } |
&FloatCompare { .. } => {} &FloatCompare { .. } => {}
} }
@@ -682,4 +683,4 @@ mod tests {
let verifier = Verifier::new(&func); let verifier = Verifier::new(&func);
assert_err_with_msg!(verifier.run(), "instruction format"); assert_err_with_msg!(verifier.run(), "instruction format");
} }
} }

View File

@@ -260,6 +260,7 @@ pub fn write_operands(w: &mut Write, dfg: &DataFlowGraph, inst: Inst) -> Result
InsertLane { lane, args, .. } => write!(w, " {}, {}, {}", args[0], lane, args[1]), InsertLane { lane, args, .. } => write!(w, " {}, {}, {}", args[0], lane, args[1]),
ExtractLane { lane, arg, .. } => write!(w, " {}, {}", arg, lane), ExtractLane { lane, arg, .. } => write!(w, " {}, {}", arg, lane),
IntCompare { cond, args, .. } => write!(w, " {}, {}, {}", cond, args[0], args[1]), IntCompare { cond, args, .. } => write!(w, " {}, {}, {}", cond, args[0], args[1]),
IntCompareImm { cond, arg, imm, .. } => write!(w, " {}, {}, {}", cond, arg, imm),
FloatCompare { cond, args, .. } => write!(w, " {}, {}, {}", cond, args[0], args[1]), FloatCompare { cond, args, .. } => write!(w, " {}, {}, {}", cond, args[0], args[1]),
Jump { destination, ref args, .. } => { Jump { destination, ref args, .. } => {
if args.is_empty() { if args.is_empty() {

View File

@@ -216,11 +216,12 @@ impl<'a> Context<'a> {
InstructionData::UnaryIeee32 { .. } | InstructionData::UnaryIeee32 { .. } |
InstructionData::UnaryIeee64 { .. } => {} InstructionData::UnaryIeee64 { .. } => {}
InstructionData::Unary { ref mut arg, .. } |
InstructionData::UnarySplit { ref mut arg, .. } |
InstructionData::BinaryImm { ref mut arg, .. } | InstructionData::BinaryImm { ref mut arg, .. } |
InstructionData::BranchTable { ref mut arg, .. } |
InstructionData::ExtractLane { ref mut arg, .. } | InstructionData::ExtractLane { ref mut arg, .. } |
InstructionData::BranchTable { ref mut arg, .. } => { InstructionData::IntCompareImm { ref mut arg, .. } |
InstructionData::Unary { ref mut arg, .. } |
InstructionData::UnarySplit { ref mut arg, .. } => {
self.map.rewrite_value(arg, loc)?; self.map.rewrite_value(arg, loc)?;
} }
@@ -1557,6 +1558,20 @@ impl<'a> Parser<'a> {
args: [lhs, rhs], args: [lhs, rhs],
} }
} }
InstructionFormat::IntCompareImm => {
let cond = self.match_enum("expected intcc condition code")?;
self.match_token(Token::Comma, "expected ',' between operands")?;
let lhs = self.match_value("expected SSA value first operand")?;
self.match_token(Token::Comma, "expected ',' between operands")?;
let rhs = self.match_imm64("expected immediate second operand")?;
InstructionData::IntCompareImm {
opcode: opcode,
ty: VOID,
cond: cond,
arg: lhs,
imm: rhs,
}
}
InstructionFormat::FloatCompare => { InstructionFormat::FloatCompare => {
let cond = self.match_enum("expected floatcc condition code")?; let cond = self.match_enum("expected floatcc condition code")?;
self.match_token(Token::Comma, "expected ',' between operands")?; self.match_token(Token::Comma, "expected ',' between operands")?;