Browse Source

Separate immediate and value operands in the instruction format.

Instruction formats are now identified by a signature that doesn't
include the ordering of value operands relative to immediate operands.

This means that the BinaryRev instruction format becomes redundant, so
delete it. The isub_imm instruction was the only one using that format.
Rename it to irsub_imm to make it clear what it does now that it is
printed as 'irsub_imm v2, 45'.
pull/3/head
Jakob Stoklund Olesen 8 years ago
parent
commit
60daf3e76b
  1. 2
      docs/langref.rst
  2. 2
      filetests/parser/tiny.cton
  3. 1
      lib/cretonne/meta/base/formats.py
  4. 14
      lib/cretonne/meta/base/instructions.py
  5. 41
      lib/cretonne/meta/cdsl/formats.py
  6. 7
      lib/cretonne/src/ir/instructions.rs
  7. 1
      lib/cretonne/src/write.rs
  8. 12
      lib/reader/src/parser.rs

2
docs/langref.rst

@ -685,7 +685,7 @@ Integer operations
.. autoinst:: iadd_cout
.. autoinst:: iadd_carry
.. autoinst:: isub
.. autoinst:: isub_imm
.. autoinst:: irsub_imm
.. autoinst:: isub_bin
.. autoinst:: isub_bout
.. autoinst:: isub_borrow

2
filetests/parser/tiny.cton

@ -55,12 +55,14 @@ ebb0(vx0: i32, vx1: i32):
v0 = icmp eq, vx0, vx1
v1 = icmp ult, vx0, vx1
v2 = icmp sge, vx0, vx1
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: v3 = irsub_imm vx1, 45
; nextln: }
; Floating condition codes.

1
lib/cretonne/meta/base/formats.py

@ -22,7 +22,6 @@ UnarySplit = InstructionFormat(VALUE, multiple_results=True)
Binary = InstructionFormat(VALUE, VALUE)
BinaryImm = InstructionFormat(VALUE, imm64)
BinaryImmRev = InstructionFormat(imm64, VALUE)
# Generate result + overflow flag.
BinaryOverflow = InstructionFormat(VALUE, VALUE, multiple_results=True)

14
lib/cretonne/meta/base/instructions.py

@ -507,22 +507,18 @@ srem_imm = Instruction(
allowed. """,
ins=(x, Y), outs=a)
# Swap x and y for isub_imm.
X = Operand('X', imm64)
y = Operand('y', iB)
isub_imm = Instruction(
'isub_imm', """
Immediate wrapping subtraction: :math:`a := X - y \pmod{2^B}`.
irsub_imm = Instruction(
'irsub_imm', """
Immediate reverse wrapping subtraction: :math:`a := Y - x \pmod{2^B}`.
Also works as integer negation when :math:`X = 0`. Use :inst:`iadd_imm`
Also works as integer negation when :math:`Y = 0`. Use :inst:`iadd_imm`
with a negative immediate operand for the reverse immediate
subtraction.
Polymorphic over all scalar integer types, but does not support vector
types.
""",
ins=(X, y), outs=a)
ins=(x, Y), outs=a)
#
# Integer arithmetic with carry and/or borrow.

41
lib/cretonne/meta/cdsl/formats.py

@ -25,6 +25,14 @@ class InstructionFormat(object):
produced. Some instructions, like `call`, may have a variable number of
results.
The instruction format stores two separate lists of operands: Immediates
and values. Immediate operands (including entity references) are
represented as explicit members in the `InstructionData` variants. The
value operands are stored differently, depending on how many there are.
Beyond a certain point, instruction formats switch to an external value
list for storing value arguments. Value lists can hold an arbitrary number
of values.
All instruction formats must be predefined in the
:py:mod:`cretonne.formats` module.
@ -45,8 +53,8 @@ class InstructionFormat(object):
immediate operands.
"""
# Map (multiple_results, kind, kind, ...) -> InstructionFormat
_registry = dict() # type: Dict[Tuple[bool, Tuple[OperandKind, ...]], InstructionFormat] # noqa
# Map (multiple_results, imm_kinds, num_value_operands) -> format
_registry = dict() # type: Dict[Tuple[bool, Tuple[OperandKind, ...], int, bool], InstructionFormat] # noqa
# All existing formats.
all_formats = list() # type: List[InstructionFormat]
@ -62,13 +70,11 @@ class InstructionFormat(object):
# operands are values or variable argument lists. They are all handled
# specially.
self.imm_members = list() # type: List[str]
# Operand kinds for the immediate operands.
self.imm_kinds = list() # type: List[OperandKind]
# The number of value operands stored in the format, or `None` when
# `has_value_list` is set.
self.num_value_operands = 0
sig_kinds = tuple(self._process_member_names(kinds))
# Operand kinds for the immediate operands.
self.imm_kinds = tuple(self._process_member_names(kinds))
# The typevar_operand argument must point to a 'value' operand.
self.typevar_operand = kwargs.get('typevar_operand', None) # type: int
@ -81,7 +87,10 @@ class InstructionFormat(object):
self.typevar_operand = 0
# Compute a signature for the global registry.
sig = (self.multiple_results, sig_kinds)
sig = (
self.multiple_results, self.imm_kinds,
self.num_value_operands,
self.has_value_list)
if sig in InstructionFormat._registry:
raise RuntimeError(
"Format '{}' has the same signature as existing format '{}'"
@ -98,9 +107,9 @@ class InstructionFormat(object):
pair. The member names correspond to members in the Rust
`InstructionData` data structure.
Update the fields `num_value_operands`, `imm_kinds`, and `imm_members`.
Update the fields `num_value_operands` and `imm_members`.
Yields the operand kinds.
Yields the immediate operand kinds.
"""
for arg in kinds:
if isinstance(arg, OperandKind):
@ -116,16 +125,14 @@ class InstructionFormat(object):
# We require a value list for storage of variable arguments.
assert self.has_value_list, "Need a value list"
else:
self.imm_kinds.append(k)
self.imm_members.append(member)
yield k
yield k
def __str__(self):
# type: () -> str
args = ', '.join('{}: {}'.format(m, k)
for m, k in zip(self.imm_members, self.imm_kinds))
return '{}({}, values={})'.format(
return '{}(imms=({}), vals={})'.format(
self.name, args, self.num_value_operands)
def __getattr__(self, attr):
@ -162,7 +169,13 @@ class InstructionFormat(object):
multiple_results = outs[0].kind == VARIABLE_ARGS
else:
multiple_results = len(outs) > 1
sig = (multiple_results, tuple(op.kind for op in ins))
# Construct a signature.
imm_kinds = tuple(op.kind for op in ins if op.is_immediate())
num_values = sum(1 for op in ins if op.is_value())
has_varargs = (VARIABLE_ARGS in tuple(op.kind for op in ins))
sig = (multiple_results, imm_kinds, num_values, has_varargs)
if sig not in InstructionFormat._registry:
raise RuntimeError(
"No instruction format matches ins = ({}){}".format(

7
lib/cretonne/src/ir/instructions.rs

@ -145,13 +145,6 @@ pub enum InstructionData {
arg: Value,
imm: Imm64,
},
// Same as `BinaryImm`, but the immediate is the left-hand-side operand.
BinaryImmRev {
opcode: Opcode,
ty: Type,
arg: Value,
imm: Imm64,
},
BinaryOverflow {
opcode: Opcode,
ty: Type,

1
lib/cretonne/src/write.rs

@ -237,7 +237,6 @@ fn write_instruction(w: &mut Write,
UnarySplit { arg, .. } => writeln!(w, " {}", arg),
Binary { args, .. } => writeln!(w, " {}, {}", args[0], args[1]),
BinaryImm { arg, imm, .. } => writeln!(w, " {}, {}", arg, imm),
BinaryImmRev { imm, arg, .. } => writeln!(w, " {}, {}", imm, arg),
BinaryOverflow { args, .. } => writeln!(w, " {}, {}", args[0], args[1]),
Ternary { args, .. } => writeln!(w, " {}, {}, {}", args[0], args[1], args[2]),
TernaryOverflow { ref data, .. } => writeln!(w, " {}", data),

12
lib/reader/src/parser.rs

@ -177,7 +177,6 @@ impl<'a> Context<'a> {
InstructionData::Unary { ref mut arg, .. } |
InstructionData::UnarySplit { ref mut arg, .. } |
InstructionData::BinaryImm { ref mut arg, .. } |
InstructionData::BinaryImmRev { ref mut arg, .. } |
InstructionData::ExtractLane { ref mut arg, .. } |
InstructionData::BranchTable { ref mut arg, .. } => {
self.map.rewrite_value(arg, loc)?;
@ -1368,17 +1367,6 @@ impl<'a> Parser<'a> {
imm: rhs,
}
}
InstructionFormat::BinaryImmRev => {
let lhs = self.match_imm64("expected immediate integer first operand")?;
self.match_token(Token::Comma, "expected ',' between operands")?;
let rhs = self.match_value("expected SSA value second operand")?;
InstructionData::BinaryImmRev {
opcode: opcode,
ty: VOID,
imm: lhs,
arg: rhs,
}
}
InstructionFormat::BinaryOverflow => {
let lhs = self.match_value("expected SSA value first operand")?;
self.match_token(Token::Comma, "expected ',' between operands")?;

Loading…
Cancel
Save