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:
@@ -18,14 +18,10 @@ Unary = InstructionFormat(VALUE)
|
|||||||
UnaryImm = InstructionFormat(imm64)
|
UnaryImm = InstructionFormat(imm64)
|
||||||
UnaryIeee32 = InstructionFormat(ieee32)
|
UnaryIeee32 = InstructionFormat(ieee32)
|
||||||
UnaryIeee64 = InstructionFormat(ieee64)
|
UnaryIeee64 = InstructionFormat(ieee64)
|
||||||
UnarySplit = InstructionFormat(VALUE, multiple_results=True)
|
|
||||||
|
|
||||||
Binary = InstructionFormat(VALUE, VALUE)
|
Binary = InstructionFormat(VALUE, VALUE)
|
||||||
BinaryImm = InstructionFormat(VALUE, imm64)
|
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 select instructions are controlled by the second VALUE operand.
|
||||||
# The first VALUE operand is the controlling flag which has a derived type.
|
# The first VALUE operand is the controlling flag which has a derived type.
|
||||||
# The fma instruction has the same constraint on all inputs.
|
# 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
|
# Catch-all for instructions with many outputs and inputs and no immediate
|
||||||
# operands.
|
# operands.
|
||||||
MultiAry = InstructionFormat(VARIABLE_ARGS, multiple_results=True)
|
MultiAry = InstructionFormat(VARIABLE_ARGS)
|
||||||
|
|
||||||
InsertLane = InstructionFormat(VALUE, ('lane', uimm8), VALUE)
|
InsertLane = InstructionFormat(VALUE, ('lane', uimm8), VALUE)
|
||||||
ExtractLane = InstructionFormat(VALUE, ('lane', uimm8))
|
ExtractLane = InstructionFormat(VALUE, ('lane', uimm8))
|
||||||
@@ -47,11 +43,8 @@ Branch = InstructionFormat(VALUE, ebb, VARIABLE_ARGS)
|
|||||||
BranchIcmp = InstructionFormat(intcc, VALUE, VALUE, ebb, VARIABLE_ARGS)
|
BranchIcmp = InstructionFormat(intcc, VALUE, VALUE, ebb, VARIABLE_ARGS)
|
||||||
BranchTable = InstructionFormat(VALUE, jump_table)
|
BranchTable = InstructionFormat(VALUE, jump_table)
|
||||||
|
|
||||||
Call = InstructionFormat(
|
Call = InstructionFormat(func_ref, VARIABLE_ARGS)
|
||||||
func_ref, VARIABLE_ARGS, multiple_results=True)
|
IndirectCall = InstructionFormat(sig_ref, VALUE, VARIABLE_ARGS)
|
||||||
IndirectCall = InstructionFormat(
|
|
||||||
sig_ref, VALUE, VARIABLE_ARGS,
|
|
||||||
multiple_results=True)
|
|
||||||
|
|
||||||
Load = InstructionFormat(memflags, VALUE, offset32)
|
Load = InstructionFormat(memflags, VALUE, offset32)
|
||||||
Store = InstructionFormat(memflags, VALUE, VALUE, offset32)
|
Store = InstructionFormat(memflags, VALUE, VALUE, offset32)
|
||||||
|
|||||||
@@ -18,13 +18,6 @@ class InstructionFormat(object):
|
|||||||
identified structurally, i.e., the format of an instruction is derived from
|
identified structurally, i.e., the format of an instruction is derived from
|
||||||
the kinds of operands used in its declaration.
|
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
|
The instruction format stores two separate lists of operands: Immediates
|
||||||
and values. Immediate operands (including entity references) are
|
and values. Immediate operands (including entity references) are
|
||||||
represented as explicit members in the `InstructionData` variants. The
|
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
|
:param name: Instruction format name in CamelCase. This is used as a Rust
|
||||||
variant name in both the `InstructionData` and `InstructionFormat`
|
variant name in both the `InstructionData` and `InstructionFormat`
|
||||||
enums.
|
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
|
: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
|
infer the controlling type variable. By default, this is `0`, the first
|
||||||
`value` operand. The index is relative to the values only, ignoring
|
`value` operand. The index is relative to the values only, ignoring
|
||||||
immediate operands.
|
immediate operands.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Map (multiple_results, imm_kinds, num_value_operands) -> format
|
# Map (imm_kinds, num_value_operands) -> format
|
||||||
_registry = dict() # type: Dict[Tuple[bool, Tuple[OperandKind, ...], int, bool], InstructionFormat] # noqa
|
_registry = dict() # type: Dict[Tuple[Tuple[OperandKind, ...], int, bool], InstructionFormat] # noqa
|
||||||
|
|
||||||
# All existing formats.
|
# All existing formats.
|
||||||
all_formats = list() # type: List[InstructionFormat]
|
all_formats = list() # type: List[InstructionFormat]
|
||||||
@@ -57,7 +48,6 @@ class InstructionFormat(object):
|
|||||||
def __init__(self, *kinds, **kwargs):
|
def __init__(self, *kinds, **kwargs):
|
||||||
# type: (*Union[OperandKind, Tuple[str, OperandKind]], **Any) -> None # noqa
|
# type: (*Union[OperandKind, Tuple[str, OperandKind]], **Any) -> None # noqa
|
||||||
self.name = kwargs.get('name', None) # type: str
|
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
|
# The number of value operands stored in the format, or `None` when
|
||||||
# `has_value_list` is set.
|
# `has_value_list` is set.
|
||||||
@@ -81,9 +71,7 @@ class InstructionFormat(object):
|
|||||||
|
|
||||||
# Compute a signature for the global registry.
|
# Compute a signature for the global registry.
|
||||||
imm_kinds = tuple(f.kind for f in self.imm_fields)
|
imm_kinds = tuple(f.kind for f in self.imm_fields)
|
||||||
sig = (
|
sig = (imm_kinds, self.num_value_operands, self.has_value_list)
|
||||||
self.multiple_results, imm_kinds, self.num_value_operands,
|
|
||||||
self.has_value_list)
|
|
||||||
if sig in InstructionFormat._registry:
|
if sig in InstructionFormat._registry:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"Format '{}' has the same signature as existing format '{}'"
|
"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
|
:py:class:`Instruction` arguments of the same name, except they must be
|
||||||
tuples of :py:`Operand` objects.
|
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.
|
# Construct a signature.
|
||||||
imm_kinds = tuple(op.kind for op in ins if op.is_immediate())
|
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())
|
num_values = sum(1 for op in ins if op.is_value())
|
||||||
has_varargs = (VARIABLE_ARGS in tuple(op.kind for op in ins))
|
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:
|
if sig in InstructionFormat._registry:
|
||||||
return InstructionFormat._registry[sig]
|
return InstructionFormat._registry[sig]
|
||||||
|
|
||||||
# Try another value list format as an alternative.
|
# Try another value list format as an alternative.
|
||||||
sig = (True, imm_kinds, num_values, has_varargs)
|
sig = (imm_kinds, 0, True)
|
||||||
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)
|
|
||||||
if sig in InstructionFormat._registry:
|
if sig in InstructionFormat._registry:
|
||||||
return InstructionFormat._registry[sig]
|
return InstructionFormat._registry[sig]
|
||||||
|
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
'No instruction format matches multiple_results={},'
|
'No instruction format matches '
|
||||||
'imms={}, vals={}, varargs={}'.format(
|
'imms={}, vals={}, varargs={}'.format(
|
||||||
multiple_results, imm_kinds, num_values, has_varargs))
|
imm_kinds, num_values, has_varargs))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def extract_names(globs):
|
def extract_names(globs):
|
||||||
|
|||||||
@@ -207,8 +207,6 @@ class EncRecipe(object):
|
|||||||
if not format.has_value_list:
|
if not format.has_value_list:
|
||||||
assert len(self.ins) == format.num_value_operands
|
assert len(self.ins) == format.num_value_operands
|
||||||
self.outs = self._verify_constraints(outs)
|
self.outs = self._verify_constraints(outs)
|
||||||
if len(self.outs) > 1:
|
|
||||||
assert format.multiple_results
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# type: () -> str
|
# type: () -> str
|
||||||
|
|||||||
@@ -105,14 +105,12 @@ pub enum InstructionData {
|
|||||||
UnaryImm { opcode: Opcode, imm: Imm64 },
|
UnaryImm { opcode: Opcode, imm: Imm64 },
|
||||||
UnaryIeee32 { opcode: Opcode, imm: Ieee32 },
|
UnaryIeee32 { opcode: Opcode, imm: Ieee32 },
|
||||||
UnaryIeee64 { opcode: Opcode, imm: Ieee64 },
|
UnaryIeee64 { opcode: Opcode, imm: Ieee64 },
|
||||||
UnarySplit { opcode: Opcode, arg: Value },
|
|
||||||
Binary { opcode: Opcode, args: [Value; 2] },
|
Binary { opcode: Opcode, args: [Value; 2] },
|
||||||
BinaryImm {
|
BinaryImm {
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
arg: Value,
|
arg: Value,
|
||||||
imm: Imm64,
|
imm: Imm64,
|
||||||
},
|
},
|
||||||
BinaryOverflow { opcode: Opcode, args: [Value; 2] },
|
|
||||||
Ternary { opcode: Opcode, args: [Value; 3] },
|
Ternary { opcode: Opcode, args: [Value; 3] },
|
||||||
MultiAry { opcode: Opcode, args: ValueList },
|
MultiAry { opcode: Opcode, args: ValueList },
|
||||||
InsertLane {
|
InsertLane {
|
||||||
|
|||||||
@@ -255,10 +255,8 @@ impl<'a> Verifier<'a> {
|
|||||||
&UnaryImm { .. } |
|
&UnaryImm { .. } |
|
||||||
&UnaryIeee32 { .. } |
|
&UnaryIeee32 { .. } |
|
||||||
&UnaryIeee64 { .. } |
|
&UnaryIeee64 { .. } |
|
||||||
&UnarySplit { .. } |
|
|
||||||
&Binary { .. } |
|
&Binary { .. } |
|
||||||
&BinaryImm { .. } |
|
&BinaryImm { .. } |
|
||||||
&BinaryOverflow { .. } |
|
|
||||||
&Ternary { .. } |
|
&Ternary { .. } |
|
||||||
&InsertLane { .. } |
|
&InsertLane { .. } |
|
||||||
&ExtractLane { .. } |
|
&ExtractLane { .. } |
|
||||||
|
|||||||
@@ -245,10 +245,8 @@ pub fn write_operands(w: &mut Write, dfg: &DataFlowGraph, inst: Inst) -> Result
|
|||||||
UnaryImm { imm, .. } => write!(w, " {}", imm),
|
UnaryImm { imm, .. } => write!(w, " {}", imm),
|
||||||
UnaryIeee32 { imm, .. } => write!(w, " {}", imm),
|
UnaryIeee32 { imm, .. } => write!(w, " {}", imm),
|
||||||
UnaryIeee64 { imm, .. } => write!(w, " {}", imm),
|
UnaryIeee64 { imm, .. } => write!(w, " {}", imm),
|
||||||
UnarySplit { arg, .. } => write!(w, " {}", arg),
|
|
||||||
Binary { args, .. } => write!(w, " {}, {}", args[0], args[1]),
|
Binary { args, .. } => write!(w, " {}, {}", args[0], args[1]),
|
||||||
BinaryImm { arg, imm, .. } => write!(w, " {}, {}", arg, imm),
|
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]),
|
Ternary { args, .. } => write!(w, " {}, {}, {}", args[0], args[1], args[2]),
|
||||||
MultiAry { ref args, .. } => {
|
MultiAry { ref args, .. } => {
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
|
|||||||
@@ -1429,12 +1429,6 @@ impl<'a> Parser<'a> {
|
|||||||
imm: self.match_ieee64("expected immediate 64-bit float operand")?,
|
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 => {
|
InstructionFormat::Binary => {
|
||||||
let lhs = self.match_value("expected SSA value first operand")?;
|
let lhs = self.match_value("expected SSA value first operand")?;
|
||||||
self.match_token(Token::Comma, "expected ',' between operands")?;
|
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||||
@@ -1454,15 +1448,6 @@ impl<'a> Parser<'a> {
|
|||||||
imm: rhs,
|
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 => {
|
InstructionFormat::Ternary => {
|
||||||
// Names here refer to the `select` instruction.
|
// Names here refer to the `select` instruction.
|
||||||
// This format is also use by `fma`.
|
// This format is also use by `fma`.
|
||||||
|
|||||||
Reference in New Issue
Block a user