Add Apply.inst_predicate().
Compute an instruction predicate from any constant values given as arguments for the immediate operands in an instruction pattern. Allows for patterns like icmp.i32(intcc.ugt, x, y) or iadd_imm.i32(x, 1) Trap these predicates in the legalizer code generator since we can't actually handle them yet.
This commit is contained in:
@@ -7,11 +7,13 @@ for patern matching an rewriting of cretonne instructions.
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from . import instructions
|
from . import instructions
|
||||||
from .typevar import TypeVar
|
from .typevar import TypeVar
|
||||||
|
from .predicates import IsEqual, And
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from typing import Union, Tuple, Sequence, TYPE_CHECKING # noqa
|
from typing import Union, Tuple, Sequence, TYPE_CHECKING # noqa
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .operands import ImmediateKind # noqa
|
from .operands import ImmediateKind # noqa
|
||||||
|
from .predicates import PredNode # noqa
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -412,6 +414,32 @@ class Apply(Expr):
|
|||||||
method = self.inst.snake_name()
|
method = self.inst.snake_name()
|
||||||
return '{}({})'.format(method, args)
|
return '{}({})'.format(method, args)
|
||||||
|
|
||||||
|
def inst_predicate(self):
|
||||||
|
# type: () -> PredNode
|
||||||
|
"""
|
||||||
|
Construct an instruction predicate that verifies the immediate operands
|
||||||
|
on this instruction.
|
||||||
|
|
||||||
|
Immediate operands in a source pattern can be either free variables or
|
||||||
|
constants like `Enumerator`. We don't currently support constraints on
|
||||||
|
free variables, but we may in the future.
|
||||||
|
"""
|
||||||
|
pred = None # type: PredNode
|
||||||
|
iform = self.inst.format
|
||||||
|
|
||||||
|
# Examine all of the immediate operands.
|
||||||
|
for ffield, opnum in zip(iform.imm_fields, self.inst.imm_opnums):
|
||||||
|
arg = self.args[opnum]
|
||||||
|
|
||||||
|
# Ignore free variables for now. We may add variable predicates
|
||||||
|
# later.
|
||||||
|
if isinstance(arg, Var):
|
||||||
|
continue
|
||||||
|
|
||||||
|
pred = And.combine(pred, IsEqual(ffield, arg))
|
||||||
|
|
||||||
|
return pred
|
||||||
|
|
||||||
|
|
||||||
class Enumerator(Expr):
|
class Enumerator(Expr):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -216,7 +216,8 @@ class FieldPredicate(object):
|
|||||||
This predicate can be evaluated in the context of an instruction
|
This predicate can be evaluated in the context of an instruction
|
||||||
format.
|
format.
|
||||||
"""
|
"""
|
||||||
return self.field.format
|
iform = self.field.format # type: InstructionFormat
|
||||||
|
return iform
|
||||||
|
|
||||||
def predicate_leafs(self, leafs):
|
def predicate_leafs(self, leafs):
|
||||||
# type: (Set[PredLeaf]) -> None
|
# type: (Set[PredLeaf]) -> None
|
||||||
|
|||||||
@@ -211,6 +211,12 @@ def gen_xform(xform, fmt):
|
|||||||
# variables.
|
# variables.
|
||||||
unwrap_inst('inst', xform.src.rtl[0], fmt)
|
unwrap_inst('inst', xform.src.rtl[0], fmt)
|
||||||
|
|
||||||
|
# We could support instruction predicates, but not yet. Should we just
|
||||||
|
# return false if it fails? What about multiple patterns with different
|
||||||
|
# predicates for the same opcode?
|
||||||
|
instp = xform.src.rtl[0].expr.inst_predicate()
|
||||||
|
assert instp is None, "Instruction predicates not supported in legalizer"
|
||||||
|
|
||||||
# Emit the destination pattern.
|
# Emit the destination pattern.
|
||||||
for dst in xform.dst.rtl:
|
for dst in xform.dst.rtl:
|
||||||
emit_dst_inst(dst, fmt)
|
emit_dst_inst(dst, fmt)
|
||||||
|
|||||||
Reference in New Issue
Block a user