Index: test/TableGen/dag-isel-res-order.td =================================================================== --- /dev/null +++ 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))]; +} Index: utils/TableGen/CodeGenDAGPatterns.h =================================================================== --- utils/TableGen/CodeGenDAGPatterns.h +++ 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 #include #include +#include #include #include @@ -577,6 +579,9 @@ /// each is a single concrete type. std::vector Types; + /// The index of each result in results of the pattern. + std::vector ResultPerm; + /// Operator - The Record for the operator if this is an interior node (not /// a leaf). Record *Operator; @@ -605,10 +610,14 @@ : 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(); } @@ -639,6 +648,10 @@ 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; } @@ -1218,7 +1231,8 @@ void FindPatternInputsAndOutputs( TreePattern &I, TreePatternNodePtr Pat, std::map &InstInputs, - std::map &InstResults, + MapVector> &InstResults, std::vector &InstImpResults); }; Index: utils/TableGen/CodeGenDAGPatterns.cpp =================================================================== --- utils/TableGen/CodeGenDAGPatterns.cpp +++ 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 #include +#include #include using namespace llvm; @@ -1915,6 +1917,8 @@ 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); @@ -3174,7 +3178,8 @@ void CodeGenDAGPatterns::FindPatternInputsAndOutputs( TreePattern &I, TreePatternNodePtr Pat, std::map &InstInputs, - std::map &InstResults, + MapVector> + &InstResults, std::vector &InstImpResults) { // The instruction pattern still has unresolved fragments. For *named* @@ -3494,7 +3499,8 @@ // InstResults - Keep track of all the virtual registers that are 'set' // in the instruction, including what reg class they are. - std::map InstResults; + MapVector> + InstResults; std::vector InstImpResults; @@ -3531,19 +3537,28 @@ // Check that all of the results occur first in the list. std::vector Results; + std::vector ResultIndices; SmallVector 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 &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(RNode->getLeafValue())->getDef(); ResNodes.push_back(std::move(RNode)); if (!R) @@ -3556,8 +3571,11 @@ // 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. @@ -3621,6 +3639,7 @@ 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 @@ -4080,7 +4099,8 @@ // Validate that the input pattern is correct. std::map InstInputs; - std::map InstResults; + MapVector> + InstResults; std::vector InstImpResults; for (unsigned j = 0, ee = Pattern.getNumTrees(); j != ee; ++j) FindPatternInputsAndOutputs(Pattern, Pattern.getTree(j), InstInputs, Index: utils/TableGen/DAGISelMatcherGen.cpp =================================================================== --- utils/TableGen/DAGISelMatcherGen.cpp +++ utils/TableGen/DAGISelMatcherGen.cpp @@ -962,9 +962,16 @@ } assert(Ops.size() >= NumSrcResults && "Didn't provide enough results"); - Ops.resize(NumSrcResults); + SmallVector 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)); }