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'.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
irsub_imm = Instruction(
|
||||
'irsub_imm', """
|
||||
Immediate reverse wrapping subtraction: :math:`a := Y - x \pmod{2^B}`.
|
||||
|
||||
isub_imm = Instruction(
|
||||
'isub_imm', """
|
||||
Immediate wrapping subtraction: :math:`a := X - y \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.
|
||||
|
||||
@@ -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
|
||||
|
||||
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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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")?;
|
||||
|
||||
Reference in New Issue
Block a user