TableGen: Allow conditional instruction pattern in multiclass.

Define a 'null_frag' SDPatternOperator node, which if referenced in an
instruction Pattern, results in the pattern being collapsed to be as-if
'[]' had been specified instead. This allows supporting a multiclass
definition where some instaniations have ISel patterns associated and
others do not.

For example,
multiclass myMulti<RegisterClass rc, SDPatternOperator OpNode = null_frag> {
  def _x : myI<(outs rc:), (ins rc:), []>;
  def _r : myI<(outs rc:), (ins rc:), [(set rc:, (OpNode rc:))]>;
}

defm foo : myMulti<GRa, not>;
defm bar : myMulti<GRb>;

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160333 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2012-07-17 00:47:06 +00:00
parent 1bda7863e3
commit ac915b48d8
2 changed files with 43 additions and 2 deletions

View File

@ -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<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED;

View File

@ -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<DefInit*>(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<DagInit*>(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<DagInit*>(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<Record*> Results;
std::vector<Record*> Operands;