summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/test/TableGen/dag-isel-res-order.td22
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.cpp40
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.h16
-rw-r--r--llvm/utils/TableGen/DAGISelMatcherGen.cpp11
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));
}
OpenPOWER on IntegriCloud