Stop tracking if instruction formats have multiple results.

All instruction formats can represent multiple results now, so a few
redundant formats can be removed: UnarySplit and BinaryOverflow.
This commit is contained in:
Jakob Stoklund Olesen
2017-04-13 12:24:20 -07:00
parent bf74445eac
commit d3235eb81f
7 changed files with 10 additions and 65 deletions

View File

@@ -18,14 +18,10 @@ Unary = InstructionFormat(VALUE)
UnaryImm = InstructionFormat(imm64)
UnaryIeee32 = InstructionFormat(ieee32)
UnaryIeee64 = InstructionFormat(ieee64)
UnarySplit = InstructionFormat(VALUE, multiple_results=True)
Binary = InstructionFormat(VALUE, VALUE)
BinaryImm = InstructionFormat(VALUE, imm64)
# Generate result + overflow flag.
BinaryOverflow = InstructionFormat(VALUE, VALUE, multiple_results=True)
# The select instructions are controlled by the second VALUE operand.
# The first VALUE operand is the controlling flag which has a derived type.
# The fma instruction has the same constraint on all inputs.
@@ -33,7 +29,7 @@ Ternary = InstructionFormat(VALUE, VALUE, VALUE, typevar_operand=1)
# Catch-all for instructions with many outputs and inputs and no immediate
# operands.
MultiAry = InstructionFormat(VARIABLE_ARGS, multiple_results=True)
MultiAry = InstructionFormat(VARIABLE_ARGS)
InsertLane = InstructionFormat(VALUE, ('lane', uimm8), VALUE)
ExtractLane = InstructionFormat(VALUE, ('lane', uimm8))
@@ -47,11 +43,8 @@ Branch = InstructionFormat(VALUE, ebb, VARIABLE_ARGS)
BranchIcmp = InstructionFormat(intcc, VALUE, VALUE, ebb, VARIABLE_ARGS)
BranchTable = InstructionFormat(VALUE, jump_table)
Call = InstructionFormat(
func_ref, VARIABLE_ARGS, multiple_results=True)
IndirectCall = InstructionFormat(
sig_ref, VALUE, VARIABLE_ARGS,
multiple_results=True)
Call = InstructionFormat(func_ref, VARIABLE_ARGS)
IndirectCall = InstructionFormat(sig_ref, VALUE, VARIABLE_ARGS)
Load = InstructionFormat(memflags, VALUE, offset32)
Store = InstructionFormat(memflags, VALUE, VALUE, offset32)

View File

@@ -18,13 +18,6 @@ class InstructionFormat(object):
identified structurally, i.e., the format of an instruction is derived from
the kinds of operands used in its declaration.
Most instruction formats produce a single result, or no result at all. If
an instruction can produce more than one result, the `multiple_results`
flag must be set on its format. All results are of the `value` kind, and
the instruction format does not keep track of how many results are
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
@@ -40,16 +33,14 @@ class InstructionFormat(object):
:param name: Instruction format name in CamelCase. This is used as a Rust
variant name in both the `InstructionData` and `InstructionFormat`
enums.
:param multiple_results: Set to `True` if this instruction format allows
more than one result to be produced.
:param typevar_operand: Index of the value input operand that is used to
infer the controlling type variable. By default, this is `0`, the first
`value` operand. The index is relative to the values only, ignoring
immediate operands.
"""
# Map (multiple_results, imm_kinds, num_value_operands) -> format
_registry = dict() # type: Dict[Tuple[bool, Tuple[OperandKind, ...], int, bool], InstructionFormat] # noqa
# Map (imm_kinds, num_value_operands) -> format
_registry = dict() # type: Dict[Tuple[Tuple[OperandKind, ...], int, bool], InstructionFormat] # noqa
# All existing formats.
all_formats = list() # type: List[InstructionFormat]
@@ -57,7 +48,6 @@ class InstructionFormat(object):
def __init__(self, *kinds, **kwargs):
# type: (*Union[OperandKind, Tuple[str, OperandKind]], **Any) -> None # noqa
self.name = kwargs.get('name', None) # type: str
self.multiple_results = kwargs.get('multiple_results', False)
# The number of value operands stored in the format, or `None` when
# `has_value_list` is set.
@@ -81,9 +71,7 @@ class InstructionFormat(object):
# Compute a signature for the global registry.
imm_kinds = tuple(f.kind for f in self.imm_fields)
sig = (
self.multiple_results, imm_kinds, self.num_value_operands,
self.has_value_list)
sig = (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 '{}'"
@@ -158,37 +146,24 @@ class InstructionFormat(object):
:py:class:`Instruction` arguments of the same name, except they must be
tuples of :py:`Operand` objects.
"""
if len(outs) == 1:
multiple_results = outs[0].kind == VARIABLE_ARGS
else:
multiple_results = len(outs) > 1
# 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)
sig = (imm_kinds, num_values, has_varargs)
if sig in InstructionFormat._registry:
return InstructionFormat._registry[sig]
# Try another value list format as an alternative.
sig = (True, imm_kinds, num_values, has_varargs)
if sig in InstructionFormat._registry:
return InstructionFormat._registry[sig]
sig = (multiple_results, imm_kinds, 0, True)
if sig in InstructionFormat._registry:
return InstructionFormat._registry[sig]
sig = (True, imm_kinds, 0, True)
sig = (imm_kinds, 0, True)
if sig in InstructionFormat._registry:
return InstructionFormat._registry[sig]
raise RuntimeError(
'No instruction format matches multiple_results={},'
'No instruction format matches '
'imms={}, vals={}, varargs={}'.format(
multiple_results, imm_kinds, num_values, has_varargs))
imm_kinds, num_values, has_varargs))
@staticmethod
def extract_names(globs):

View File

@@ -207,8 +207,6 @@ class EncRecipe(object):
if not format.has_value_list:
assert len(self.ins) == format.num_value_operands
self.outs = self._verify_constraints(outs)
if len(self.outs) > 1:
assert format.multiple_results
def __str__(self):
# type: () -> str

View File

@@ -105,14 +105,12 @@ pub enum InstructionData {
UnaryImm { opcode: Opcode, imm: Imm64 },
UnaryIeee32 { opcode: Opcode, imm: Ieee32 },
UnaryIeee64 { opcode: Opcode, imm: Ieee64 },
UnarySplit { opcode: Opcode, arg: Value },
Binary { opcode: Opcode, args: [Value; 2] },
BinaryImm {
opcode: Opcode,
arg: Value,
imm: Imm64,
},
BinaryOverflow { opcode: Opcode, args: [Value; 2] },
Ternary { opcode: Opcode, args: [Value; 3] },
MultiAry { opcode: Opcode, args: ValueList },
InsertLane {

View File

@@ -255,10 +255,8 @@ impl<'a> Verifier<'a> {
&UnaryImm { .. } |
&UnaryIeee32 { .. } |
&UnaryIeee64 { .. } |
&UnarySplit { .. } |
&Binary { .. } |
&BinaryImm { .. } |
&BinaryOverflow { .. } |
&Ternary { .. } |
&InsertLane { .. } |
&ExtractLane { .. } |

View File

@@ -245,10 +245,8 @@ pub fn write_operands(w: &mut Write, dfg: &DataFlowGraph, inst: Inst) -> Result
UnaryImm { imm, .. } => write!(w, " {}", imm),
UnaryIeee32 { imm, .. } => write!(w, " {}", imm),
UnaryIeee64 { imm, .. } => write!(w, " {}", imm),
UnarySplit { arg, .. } => write!(w, " {}", arg),
Binary { args, .. } => write!(w, " {}, {}", args[0], args[1]),
BinaryImm { arg, imm, .. } => write!(w, " {}, {}", arg, imm),
BinaryOverflow { args, .. } => write!(w, " {}, {}", args[0], args[1]),
Ternary { args, .. } => write!(w, " {}, {}, {}", args[0], args[1], args[2]),
MultiAry { ref args, .. } => {
if args.is_empty() {

View File

@@ -1429,12 +1429,6 @@ impl<'a> Parser<'a> {
imm: self.match_ieee64("expected immediate 64-bit float operand")?,
}
}
InstructionFormat::UnarySplit => {
InstructionData::UnarySplit {
opcode: opcode,
arg: self.match_value("expected SSA value operand")?,
}
}
InstructionFormat::Binary => {
let lhs = self.match_value("expected SSA value first operand")?;
self.match_token(Token::Comma, "expected ',' between operands")?;
@@ -1454,15 +1448,6 @@ impl<'a> Parser<'a> {
imm: rhs,
}
}
InstructionFormat::BinaryOverflow => {
let lhs = self.match_value("expected SSA value first operand")?;
self.match_token(Token::Comma, "expected ',' between operands")?;
let rhs = self.match_value("expected SSA value second operand")?;
InstructionData::BinaryOverflow {
opcode: opcode,
args: [lhs, rhs],
}
}
InstructionFormat::Ternary => {
// Names here refer to the `select` instruction.
// This format is also use by `fma`.