summaryrefslogtreecommitdiffstats
path: root/llvm/utils
diff options
context:
space:
mode:
authorDaniel Sanders <daniel_l_sanders@apple.com>2017-11-11 03:23:44 +0000
committerDaniel Sanders <daniel_l_sanders@apple.com>2017-11-11 03:23:44 +0000
commit7e523673981badcd6d91017835b78bba2d89a67b (patch)
tree5074e30ce3404f154556f59d0f89419f532b1c29 /llvm/utils
parent5f767113c5f3ea29203eca9481179b9bfe1a15ea (diff)
downloadbcm5719-llvm-7e523673981badcd6d91017835b78bba2d89a67b.tar.gz
bcm5719-llvm-7e523673981badcd6d91017835b78bba2d89a67b.zip
[globalisel][tablegen] Import signextload and zeroextload.
Allow a pattern rewriter to be installed in CodeGenDAGPatterns and use it to correct situations where SelectionDAG and GlobalISel disagree on representation. For example, it would rewrite: (sextload:i32 $ptr)<<unindexedload>><<sextload>><<sextloadi16> to: (sext:i32 (load:i16 $ptr)<<unindexedload>>) I'd have preferred to replace the fragments and have the expansion happen naturally as part of PatFrag expansion but the type inferencing system can't cope with loads of types narrower than those mentioned in register classes. This is because the SDTCisInt's on the sext constrain both the result and operand to the 'legal' integer types (where legal is defined as 'a register class can contain the type') which immediately rules the narrower types out. Several targets (those with only one legal integer type) would then go on to crash on the SDTCisOpSmallerThanOp<> when it removes all the possible types for the result of the extend. Also, improve isObviouslySafeToFold() slightly to automatically return true for neighbouring instructions. There can't be any re-ordering problems if re-ordering isn't happenning. We'll need to improve it further to handle sign/zero-extending loads when the extend and load aren't immediate neighbours though. llvm-svn: 317971
Diffstat (limited to 'llvm/utils')
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.cpp10
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.h8
-rw-r--r--llvm/utils/TableGen/GlobalISelEmitter.cpp77
3 files changed, 90 insertions, 5 deletions
diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
index 3b400c1262e..c07a7267bbe 100644
--- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -2744,8 +2744,10 @@ void TreePattern::dump() const { print(errs()); }
// CodeGenDAGPatterns implementation
//
-CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
- Records(R), Target(R), LegalVTS(Target.getLegalValueTypes()) {
+CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R,
+ PatternRewriterFn PatternRewriter)
+ : Records(R), Target(R), LegalVTS(Target.getLegalValueTypes()),
+ PatternRewriter(PatternRewriter) {
Intrinsics = CodeGenIntrinsicTable(Records, false);
TgtIntrinsics = CodeGenIntrinsicTable(Records, true);
@@ -3536,6 +3538,8 @@ void CodeGenDAGPatterns::ParseInstructions() {
TreePattern *I = TheInst.getPattern();
if (!I) continue; // No pattern.
+ if (PatternRewriter)
+ PatternRewriter(I);
// FIXME: Assume only the first tree is the pattern. The others are clobber
// nodes.
TreePatternNode *Pattern = I->getTree(0);
@@ -3936,6 +3940,8 @@ void CodeGenDAGPatterns::ParsePatterns() {
Temp.getOnlyTree()->hasPossibleType()) {
ListInit *Preds = CurPattern->getValueAsListInit("Predicates");
int Complexity = CurPattern->getValueAsInt("AddedComplexity");
+ if (PatternRewriter)
+ PatternRewriter(Pattern);
AddPatternToMatch(
Pattern,
PatternToMatch(
diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.h b/llvm/utils/TableGen/CodeGenDAGPatterns.h
index 1f7e9fb98d3..d3bb99a5a8f 100644
--- a/llvm/utils/TableGen/CodeGenDAGPatterns.h
+++ b/llvm/utils/TableGen/CodeGenDAGPatterns.h
@@ -25,6 +25,7 @@
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <array>
+#include <functional>
#include <map>
#include <set>
#include <vector>
@@ -780,6 +781,7 @@ public:
const std::vector<TreePatternNode*> &getTrees() const { return Trees; }
unsigned getNumTrees() const { return Trees.size(); }
TreePatternNode *getTree(unsigned i) const { return Trees[i]; }
+ void setTree(unsigned i, TreePatternNode *Tree) { Trees[i] = Tree; }
TreePatternNode *getOnlyTree() const {
assert(Trees.size() == 1 && "Doesn't have exactly one pattern!");
return Trees[0];
@@ -1029,8 +1031,12 @@ class CodeGenDAGPatterns {
TypeSetByHwMode LegalVTS;
+ using PatternRewriterFn = std::function<void (TreePattern *)>;
+ PatternRewriterFn PatternRewriter;
+
public:
- CodeGenDAGPatterns(RecordKeeper &R);
+ CodeGenDAGPatterns(RecordKeeper &R,
+ PatternRewriterFn PatternRewriter = nullptr);
CodeGenTarget &getTargetInfo() { return Target; }
const CodeGenTarget &getTargetInfo() const { return Target; }
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index 08649d7f9b5..8a0d625ca44 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -2356,6 +2356,9 @@ private:
Expected<RuleMatcher> runOnPattern(const PatternToMatch &P);
void declareSubtargetFeature(Record *Predicate);
+
+ TreePatternNode *fixupPatternNode(TreePatternNode *N);
+ void fixupPatternTrees(TreePattern *P);
};
void GlobalISelEmitter::gatherNodeEquivs() {
@@ -2377,8 +2380,8 @@ Record *GlobalISelEmitter::findNodeEquiv(Record *N) const {
}
GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK)
- : RK(RK), CGP(RK), Target(CGP.getTargetInfo()),
- CGRegs(RK, Target.getHwModes()) {}
+ : RK(RK), CGP(RK, [&](TreePattern *P) { fixupPatternTrees(P); }),
+ Target(CGP.getTargetInfo()), CGRegs(RK, Target.getHwModes()) {}
//===- Emitter ------------------------------------------------------------===//
@@ -3233,6 +3236,7 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
// Look through the SelectionDAG patterns we found, possibly emitting some.
for (const PatternToMatch &Pat : CGP.ptms()) {
++NumPatternTotal;
+
auto MatcherOrErr = runOnPattern(Pat);
// The pattern analysis can fail, indicating an unsupported pattern.
@@ -3483,6 +3487,75 @@ void GlobalISelEmitter::declareSubtargetFeature(Record *Predicate) {
Predicate, SubtargetFeatureInfo(Predicate, SubtargetFeatures.size()));
}
+TreePatternNode *GlobalISelEmitter::fixupPatternNode(TreePatternNode *N) {
+ if (!N->isLeaf()) {
+ for (unsigned I = 0, E = N->getNumChildren(); I < E; ++I) {
+ TreePatternNode *OrigChild = N->getChild(I);
+ TreePatternNode *NewChild = fixupPatternNode(OrigChild);
+ if (OrigChild != NewChild)
+ N->setChild(I, NewChild);
+ }
+
+ if (N->getOperator()->getName() == "ld") {
+ // If it's a signext-load we need to adapt the pattern slightly. We need
+ // to split the node into (sext (ld ...)), remove the <<signext>> predicate,
+ // and then apply the <<signextTY>> predicate by updating the result type
+ // of the load.
+ //
+ // For example:
+ // (ld:[i32] [iPTR])<<unindexed>><<signext>><<signexti16>>
+ // must be transformed into:
+ // (sext:[i32] (ld:[i16] [iPTR])<<unindexed>>)
+ //
+ // Likewise for zeroext-load.
+
+ std::vector<TreePredicateFn> Predicates;
+ bool IsSignExtLoad = false;
+ bool IsZeroExtLoad = false;
+ Record *MemVT = nullptr;
+ for (const auto &P : N->getPredicateFns()) {
+ if (P.isLoad() && P.isSignExtLoad()) {
+ IsSignExtLoad = true;
+ continue;
+ }
+ if (P.isLoad() && P.isZeroExtLoad()) {
+ IsZeroExtLoad = true;
+ continue;
+ }
+ if (P.isLoad() && P.getMemoryVT()) {
+ MemVT = P.getMemoryVT();
+ continue;
+ }
+ Predicates.push_back(P);
+ }
+
+ if ((IsSignExtLoad || IsZeroExtLoad) && MemVT) {
+ assert(((IsSignExtLoad && !IsZeroExtLoad) ||
+ (!IsSignExtLoad && IsZeroExtLoad)) &&
+ "IsSignExtLoad and IsZeroExtLoad are mutually exclusive");
+ TreePatternNode *Ext = new TreePatternNode(
+ RK.getDef(IsSignExtLoad ? "sext" : "zext"), {N}, 1);
+ Ext->setType(0, N->getType(0));
+ N->clearPredicateFns();
+ N->setPredicateFns(Predicates);
+ N->setType(0, getValueType(MemVT));
+ return Ext;
+ }
+ }
+ }
+
+ return N;
+}
+
+void GlobalISelEmitter::fixupPatternTrees(TreePattern *P) {
+ for (unsigned I = 0, E = P->getNumTrees(); I < E; ++I) {
+ TreePatternNode *OrigTree = P->getTree(I);
+ TreePatternNode *NewTree = fixupPatternNode(OrigTree);
+ if (OrigTree != NewTree)
+ P->setTree(I, NewTree);
+ }
+}
+
} // end anonymous namespace
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud