diff --git a/lib/cretonne/meta/cdsl/ast.py b/lib/cretonne/meta/cdsl/ast.py index d2296e8fdb..2b671fc46e 100644 --- a/lib/cretonne/meta/cdsl/ast.py +++ b/lib/cretonne/meta/cdsl/ast.py @@ -7,11 +7,13 @@ for patern matching an rewriting of cretonne instructions. from __future__ import absolute_import from . import instructions from .typevar import TypeVar +from .predicates import IsEqual, And try: from typing import Union, Tuple, Sequence, TYPE_CHECKING # noqa if TYPE_CHECKING: from .operands import ImmediateKind # noqa + from .predicates import PredNode # noqa except ImportError: pass @@ -412,6 +414,32 @@ class Apply(Expr): method = self.inst.snake_name() 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): """ diff --git a/lib/cretonne/meta/cdsl/predicates.py b/lib/cretonne/meta/cdsl/predicates.py index 273f8be9a1..8a1cc147f9 100644 --- a/lib/cretonne/meta/cdsl/predicates.py +++ b/lib/cretonne/meta/cdsl/predicates.py @@ -216,7 +216,8 @@ class FieldPredicate(object): This predicate can be evaluated in the context of an instruction format. """ - return self.field.format + iform = self.field.format # type: InstructionFormat + return iform def predicate_leafs(self, leafs): # type: (Set[PredLeaf]) -> None diff --git a/lib/cretonne/meta/gen_legalizer.py b/lib/cretonne/meta/gen_legalizer.py index 7beda84771..41cd9bab56 100644 --- a/lib/cretonne/meta/gen_legalizer.py +++ b/lib/cretonne/meta/gen_legalizer.py @@ -211,6 +211,12 @@ def gen_xform(xform, fmt): # variables. 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. for dst in xform.dst.rtl: emit_dst_inst(dst, fmt)