diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 5f069801a6d..ff006b609d3 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -595,6 +595,13 @@ def not : PatFrag<(ops node:$in), (xor node:$in, -1)>; def vnot : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV)>; def ineg : PatFrag<(ops node:$in), (sub 0, node:$in)>; +// null_frag - The null pattern operator is used in multiclass instantiations +// which accept an SDPatternOperator for use in matching patterns for internal +// definitions. When expanding a pattern, if the null fragment is referenced +// in the expansion, the pattern is discarded and it is as-if '[]' had been +// specified. This allows multiclasses to have the isel patterns be optional. +def null_frag : SDPatternOperator; + // load fragments. def unindexedload : PatFrag<(ops node:$ptr), (ld node:$ptr), [{ return cast(N)->getAddressingMode() == ISD::UNINDEXED; diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index d4b02fbd2f3..09c00dd4f7d 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -2520,6 +2520,37 @@ static void InferFromPattern(const CodeGenInstruction &Inst, IsVariadic = true; // Can warn if we want. } +/// hasNullFragReference - Return true if the DAG has any reference to the +/// null_frag operator. +static bool hasNullFragReference(DagInit *DI) { + DefInit *OpDef = dynamic_cast(DI->getOperator()); + if (!OpDef) return false; + Record *Operator = OpDef->getDef(); + + // If this is the null fragment, return true. + if (Operator->getName() == "null_frag") return true; + // If any of the arguments reference the null fragment, return true. + for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) { + DagInit *Arg = dynamic_cast(DI->getArg(i)); + if (Arg && hasNullFragReference(Arg)) + return true; + } + + return false; +} + +/// hasNullFragReference - Return true if any DAG in the list references +/// the null_frag operator. +static bool hasNullFragReference(ListInit *LI) { + for (unsigned i = 0, e = LI->getSize(); i != e; ++i) { + DagInit *DI = dynamic_cast(LI->getElement(i)); + assert(DI && "non-dag in an instruction Pattern list?!"); + if (hasNullFragReference(DI)) + return true; + } + return false; +} + /// ParseInstructions - Parse all of the instructions, inlining and resolving /// any fragments involved. This populates the Instructions list with fully /// resolved instructions. @@ -2534,8 +2565,11 @@ void CodeGenDAGPatterns::ParseInstructions() { // If there is no pattern, only collect minimal information about the // instruction for its operand list. We have to assume that there is one - // result, as we have no detailed info. - if (!LI || LI->getSize() == 0) { + // result, as we have no detailed info. A pattern which references the + // null_frag operator is as-if no pattern were specified. Normally this + // is from a multiclass expansion w/ a SDPatternOperator passed in as + // null_frag. + if (!LI || LI->getSize() == 0 || hasNullFragReference(LI)) { std::vector Results; std::vector Operands;