diff options
-rw-r--r-- | llvm/test/TableGen/dag-isel-res-order.td | 22 | ||||
-rw-r--r-- | llvm/utils/TableGen/CodeGenDAGPatterns.cpp | 40 | ||||
-rw-r--r-- | llvm/utils/TableGen/CodeGenDAGPatterns.h | 16 | ||||
-rw-r--r-- | llvm/utils/TableGen/DAGISelMatcherGen.cpp | 11 |
4 files changed, 76 insertions, 13 deletions
diff --git a/llvm/test/TableGen/dag-isel-res-order.td b/llvm/test/TableGen/dag-isel-res-order.td new file mode 100644 index 00000000000..4da6b6d6867 --- /dev/null +++ b/llvm/test/TableGen/dag-isel-res-order.td @@ -0,0 +1,22 @@ +// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include %s | FileCheck %s + +include "llvm/Target/Target.td" + +def TestTargetInstrInfo : InstrInfo; + +def TestTarget : Target { + let InstructionSet = TestTargetInstrInfo; +} + +def REG : Register<"REG">; +def GPR : RegisterClass<"TestTarget", [i32], 32, (add REG)>; + +// CHECK-LABEL: OPC_CheckOpcode, TARGET_VAL(ISD::UDIVREM) +// CHECK: OPC_EmitNode2, TARGET_VAL(::INSTR) +// CHECK: Results = #2 #3 +// CHECK: OPC_CompleteMatch, 2, 3, 2 +def INSTR : Instruction { + let OutOperandList = (outs GPR:$r1, GPR:$r0); + let InOperandList = (ins GPR:$t0, GPR:$t1); + let Pattern = [(set i32:$r0, i32:$r1, (udivrem i32:$t0, i32:$t1))]; +} diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index 97ce5ecbf97..96c90c9cf6b 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -15,6 +15,7 @@ #include "CodeGenDAGPatterns.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" @@ -27,6 +28,7 @@ #include "llvm/TableGen/Record.h" #include <algorithm> #include <cstdio> +#include <iterator> #include <set> using namespace llvm; @@ -1940,6 +1942,8 @@ void TreePatternNode::InlinePatternFragments( R->setTransformFn(getTransformFn()); for (unsigned i = 0, e = getNumTypes(); i != e; ++i) R->setType(i, getExtType(i)); + for (unsigned i = 0, e = getNumResults(); i != e; ++i) + R->setResultIndex(i, getResultIndex(i)); // Register alternative. OutAlternatives.push_back(R); @@ -3207,7 +3211,8 @@ static bool HandleUse(TreePattern &I, TreePatternNodePtr Pat, void CodeGenDAGPatterns::FindPatternInputsAndOutputs( TreePattern &I, TreePatternNodePtr Pat, std::map<std::string, TreePatternNodePtr> &InstInputs, - std::map<std::string, TreePatternNodePtr> &InstResults, + MapVector<std::string, TreePatternNodePtr, std::map<std::string, unsigned>> + &InstResults, std::vector<Record *> &InstImpResults) { // The instruction pattern still has unresolved fragments. For *named* @@ -3527,7 +3532,8 @@ void CodeGenDAGPatterns::parseInstructionPattern( // InstResults - Keep track of all the virtual registers that are 'set' // in the instruction, including what reg class they are. - std::map<std::string, TreePatternNodePtr> InstResults; + MapVector<std::string, TreePatternNodePtr, std::map<std::string, unsigned>> + InstResults; std::vector<Record*> InstImpResults; @@ -3564,19 +3570,28 @@ void CodeGenDAGPatterns::parseInstructionPattern( // Check that all of the results occur first in the list. std::vector<Record*> Results; + std::vector<unsigned> ResultIndices; SmallVector<TreePatternNodePtr, 2> ResNodes; for (unsigned i = 0; i != NumResults; ++i) { - if (i == CGI.Operands.size()) - I.error("'" + InstResults.begin()->first + - "' set but does not appear in operand list!"); + if (i == CGI.Operands.size()) { + const std::string &OpName = + std::find_if(InstResults.begin(), InstResults.end(), + [](const std::pair<std::string, TreePatternNodePtr> &P) { + return P.second; + }) + ->first; + + I.error("'" + OpName + "' set but does not appear in operand list!"); + } + const std::string &OpName = CGI.Operands[i].Name; // Check that it exists in InstResults. - TreePatternNodePtr RNode = InstResults[OpName]; - if (!RNode) + auto InstResultIter = InstResults.find(OpName); + if (InstResultIter == InstResults.end() || !InstResultIter->second) I.error("Operand $" + OpName + " does not exist in operand list!"); - + TreePatternNodePtr RNode = InstResultIter->second; Record *R = cast<DefInit>(RNode->getLeafValue())->getDef(); ResNodes.push_back(std::move(RNode)); if (!R) @@ -3589,8 +3604,11 @@ void CodeGenDAGPatterns::parseInstructionPattern( // Remember the return type. Results.push_back(CGI.Operands[i].Rec); + // Remember the result index. + ResultIndices.push_back(std::distance(InstResults.begin(), InstResultIter)); + // Okay, this one checks out. - InstResults.erase(OpName); + InstResultIter->second = nullptr; } // Loop over the inputs next. @@ -3654,6 +3672,7 @@ void CodeGenDAGPatterns::parseInstructionPattern( for (unsigned i = 0; i != NumResults; ++i) { assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled"); ResultPattern->setType(i, ResNodes[i]->getExtType(0)); + ResultPattern->setResultIndex(i, ResultIndices[i]); } // FIXME: Assume only the first tree is the pattern. The others are clobber @@ -4113,7 +4132,8 @@ void CodeGenDAGPatterns::ParsePatterns() { // Validate that the input pattern is correct. std::map<std::string, TreePatternNodePtr> InstInputs; - std::map<std::string, TreePatternNodePtr> InstResults; + MapVector<std::string, TreePatternNodePtr, std::map<std::string, unsigned>> + InstResults; std::vector<Record*> InstImpResults; for (unsigned j = 0, ee = Pattern.getNumTrees(); j != ee; ++j) FindPatternInputsAndOutputs(Pattern, Pattern.getTree(j), InstInputs, diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.h b/llvm/utils/TableGen/CodeGenDAGPatterns.h index b04a928e0f3..4be9afdcacd 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -19,6 +19,7 @@ #include "CodeGenIntrinsics.h" #include "CodeGenTarget.h" #include "SDNodeProperties.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" @@ -28,6 +29,7 @@ #include <array> #include <functional> #include <map> +#include <numeric> #include <set> #include <vector> @@ -620,6 +622,9 @@ class TreePatternNode { /// each is a single concrete type. std::vector<TypeSetByHwMode> Types; + /// The index of each result in results of the pattern. + std::vector<unsigned> ResultPerm; + /// Operator - The Record for the operator if this is an interior node (not /// a leaf). Record *Operator; @@ -650,10 +655,14 @@ public: : Operator(Op), Val(nullptr), TransformFn(nullptr), Children(std::move(Ch)) { Types.resize(NumResults); + ResultPerm.resize(NumResults); + std::iota(ResultPerm.begin(), ResultPerm.end(), 0); } TreePatternNode(Init *val, unsigned NumResults) // leaf ctor : Operator(nullptr), Val(val), TransformFn(nullptr) { Types.resize(NumResults); + ResultPerm.resize(NumResults); + std::iota(ResultPerm.begin(), ResultPerm.end(), 0); } bool hasName() const { return !Name.empty(); } @@ -694,6 +703,10 @@ public: return Types[ResNo].empty(); } + unsigned getNumResults() const { return ResultPerm.size(); } + unsigned getResultIndex(unsigned ResNo) const { return ResultPerm[ResNo]; } + void setResultIndex(unsigned ResNo, unsigned RI) { ResultPerm[ResNo] = RI; } + Init *getLeafValue() const { assert(isLeaf()); return Val; } Record *getOperator() const { assert(!isLeaf()); return Operator; } @@ -1281,7 +1294,8 @@ private: void FindPatternInputsAndOutputs( TreePattern &I, TreePatternNodePtr Pat, std::map<std::string, TreePatternNodePtr> &InstInputs, - std::map<std::string, TreePatternNodePtr> &InstResults, + MapVector<std::string, TreePatternNodePtr, + std::map<std::string, unsigned>> &InstResults, std::vector<Record *> &InstImpResults); }; diff --git a/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/llvm/utils/TableGen/DAGISelMatcherGen.cpp index 875c64f18d1..612342ddcdd 100644 --- a/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -1000,9 +1000,16 @@ void MatcherGen::EmitResultCode() { } assert(Ops.size() >= NumSrcResults && "Didn't provide enough results"); - Ops.resize(NumSrcResults); + SmallVector<unsigned, 8> Results(Ops); - AddMatcher(new CompleteMatchMatcher(Ops, Pattern)); + // Apply result permutation. + for (unsigned ResNo = 0; ResNo < Pattern.getDstPattern()->getNumResults(); + ++ResNo) { + Results[ResNo] = Ops[Pattern.getDstPattern()->getResultIndex(ResNo)]; + } + + Results.resize(NumSrcResults); + AddMatcher(new CompleteMatchMatcher(Results, Pattern)); } |