diff --git a/docs/langref.rst b/docs/langref.rst index 19e17490a2..507cef3cc4 100644 --- a/docs/langref.rst +++ b/docs/langref.rst @@ -678,6 +678,7 @@ Integer operations ------------------ .. autoinst:: icmp +.. autoinst:: icmp_imm .. autoinst:: iadd .. autoinst:: iadd_imm .. autoinst:: iadd_cin diff --git a/filetests/parser/tiny.cton b/filetests/parser/tiny.cton index 7158441ed2..eb6a28c982 100644 --- a/filetests/parser/tiny.cton +++ b/filetests/parser/tiny.cton @@ -54,14 +54,14 @@ function icmp(i32, i32) { ebb0(vx0: i32, vx1: i32): v0 = icmp eq, vx0, vx1 v1 = icmp ult, vx0, vx1 - v2 = icmp sge, vx0, vx1 + v2 = icmp_imm sge, vx0, -12 v3 = irsub_imm vx1, 45 } ; sameln: function icmp(i32, i32) { ; nextln: ebb0(vx0: i32, vx1: i32): ; nextln: v0 = icmp eq, 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: } diff --git a/lib/cretonne/meta/base/formats.py b/lib/cretonne/meta/base/formats.py index 5ae806b936..a80fa03fd9 100644 --- a/lib/cretonne/meta/base/formats.py +++ b/lib/cretonne/meta/base/formats.py @@ -38,6 +38,7 @@ InsertLane = InstructionFormat(VALUE, ('lane', uimm8), VALUE) ExtractLane = InstructionFormat(VALUE, ('lane', uimm8)) IntCompare = InstructionFormat(intcc, VALUE, VALUE) +IntCompareImm = InstructionFormat(intcc, VALUE, imm64) FloatCompare = InstructionFormat(floatcc, VALUE, VALUE) Jump = InstructionFormat(ebb, VARIABLE_ARGS) diff --git a/lib/cretonne/meta/base/instructions.py b/lib/cretonne/meta/base/instructions.py index 541889f7d5..f618be7a75 100644 --- a/lib/cretonne/meta/base/instructions.py +++ b/lib/cretonne/meta/base/instructions.py @@ -367,6 +367,22 @@ icmp = Instruction( """, 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) x = Operand('x', Int) y = Operand('y', Int) diff --git a/lib/cretonne/src/ir/instructions.rs b/lib/cretonne/src/ir/instructions.rs index f5fd0c0a98..8502954cd1 100644 --- a/lib/cretonne/src/ir/instructions.rs +++ b/lib/cretonne/src/ir/instructions.rs @@ -175,6 +175,13 @@ pub enum InstructionData { cond: IntCC, args: [Value; 2], }, + IntCompareImm { + opcode: Opcode, + ty: Type, + cond: IntCC, + arg: Value, + imm: Imm64, + }, FloatCompare { opcode: Opcode, ty: Type, diff --git a/lib/cretonne/src/verifier.rs b/lib/cretonne/src/verifier.rs index 37dc5e20f7..0267d297a2 100644 --- a/lib/cretonne/src/verifier.rs +++ b/lib/cretonne/src/verifier.rs @@ -251,6 +251,7 @@ impl<'a> Verifier<'a> { &InsertLane { .. } | &ExtractLane { .. } | &IntCompare { .. } | + &IntCompareImm { .. } | &FloatCompare { .. } => {} } @@ -682,4 +683,4 @@ mod tests { let verifier = Verifier::new(&func); assert_err_with_msg!(verifier.run(), "instruction format"); } -} \ No newline at end of file +} diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index 548f718099..23889390e7 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -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]), ExtractLane { lane, arg, .. } => write!(w, " {}, {}", arg, lane), 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]), Jump { destination, ref args, .. } => { if args.is_empty() { diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index 414dd291e2..2e523eeb01 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -216,11 +216,12 @@ impl<'a> Context<'a> { InstructionData::UnaryIeee32 { .. } | InstructionData::UnaryIeee64 { .. } => {} - InstructionData::Unary { ref mut arg, .. } | - InstructionData::UnarySplit { ref mut arg, .. } | InstructionData::BinaryImm { ref mut arg, .. } | + InstructionData::BranchTable { 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)?; } @@ -1557,6 +1558,20 @@ impl<'a> Parser<'a> { 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 => { let cond = self.match_enum("expected floatcc condition code")?; self.match_token(Token::Comma, "expected ',' between operands")?;