diff options
author | Stephen Chou <stephenchouca@users.noreply.github.com> | 2024-10-01 00:17:00 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-01 11:17:00 +0400 |
commit | ec61311e77b39fc7f9b45ffdb8a29b2d96f67265 (patch) | |
tree | addce6c6aaec31adb7fd6a5d160ef3eb9b70d4ef /llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp | |
parent | 2da417e7f6149f0f1079a8162fb25161b8a80332 (diff) | |
download | llvm-ec61311e77b39fc7f9b45ffdb8a29b2d96f67265.zip llvm-ec61311e77b39fc7f9b45ffdb8a29b2d96f67265.tar.gz llvm-ec61311e77b39fc7f9b45ffdb8a29b2d96f67265.tar.bz2 |
[LLVM][TableGen] Support type casts of nodes with multiple results (#109728)
Currently, type casts can only be used to pattern match for intrinsics
with a single overloaded return value. For instance:
```
def int_foo : Intrinsic<[llvm_anyint_ty], []>;
def : Pat<(i32 (int_foo)), ...>;
```
This patch extends type casts to support matching intrinsics with
multiple overloaded return values. As an example, the following defines
a pattern that matches only if the overloaded intrinsic call returns an
`i16` for the first result and an `i32` for the second result:
```
def int_bar : Intrinsic<[llvm_anyint_ty, llvm_anyint_ty], []>;
def : Pat<([i16, i32] (int_bar)), ...>;
```
Diffstat (limited to 'llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp')
-rw-r--r-- | llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp index e8cf7e3..dd728da 100644 --- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp @@ -2886,6 +2886,35 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit, error("Pattern has unexpected init kind!"); return nullptr; } + + auto ParseCastOperand = [this](DagInit *Dag, StringRef OpName) { + if (Dag->getNumArgs() != 1) + error("Type cast only takes one operand!"); + + if (!OpName.empty()) + error("Type cast should not have a name!"); + + return ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0)); + }; + + if (ListInit *LI = dyn_cast<ListInit>(Dag->getOperator())) { + // If the operator is a list (of value types), then this must be "type cast" + // of a leaf node with multiple results. + TreePatternNodePtr New = ParseCastOperand(Dag, OpName); + + size_t NumTypes = New->getNumTypes(); + if (LI->empty() || LI->size() != NumTypes) + error("Invalid number of type casts!"); + + // Apply the type casts. + const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes(); + for (unsigned i = 0; i < std::min(NumTypes, LI->size()); ++i) + New->UpdateNodeType( + i, getValueTypeByHwMode(LI->getElementAsRecord(i), CGH), *this); + + return New; + } + DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator()); if (!OpDef) { error("Pattern has unexpected operator type!"); @@ -2896,20 +2925,15 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit, if (Operator->isSubClassOf("ValueType")) { // If the operator is a ValueType, then this must be "type cast" of a leaf // node. - if (Dag->getNumArgs() != 1) - error("Type cast only takes one operand!"); + TreePatternNodePtr New = ParseCastOperand(Dag, OpName); - TreePatternNodePtr New = - ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0)); + if (New->getNumTypes() != 1) + error("ValueType cast can only have one type!"); // Apply the type cast. - if (New->getNumTypes() != 1) - error("Type cast can only have one type!"); const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes(); New->UpdateNodeType(0, getValueTypeByHwMode(Operator, CGH), *this); - if (!OpName.empty()) - error("ValueType cast should not have a name!"); return New; } @@ -4223,8 +4247,10 @@ void CodeGenDAGPatterns::ParseOnePattern( Pattern.InlinePatternFragments(); Result.InlinePatternFragments(); - if (Result.getNumTrees() != 1) + if (Result.getNumTrees() != 1) { Result.error("Cannot use multi-alternative fragments in result pattern!"); + return; + } // Infer types. bool IterateInference; |