diff options
| author | Daniel Sanders <daniel_l_sanders@apple.com> | 2017-10-13 20:42:18 +0000 |
|---|---|---|
| committer | Daniel Sanders <daniel_l_sanders@apple.com> | 2017-10-13 20:42:18 +0000 |
| commit | 649c585710df40c22765fcc1822cc2d0f0ebb4c2 (patch) | |
| tree | 35d2c064af1353194ec3c266b2aa14dbf7ac0b9e /llvm/utils | |
| parent | d76ed069eb208db4b8342003abb7e09f24b35bc1 (diff) | |
| download | bcm5719-llvm-649c585710df40c22765fcc1822cc2d0f0ebb4c2.tar.gz bcm5719-llvm-649c585710df40c22765fcc1822cc2d0f0ebb4c2.zip | |
[aarch64] Support APInt and APFloat in ImmLeaf subclasses and make AArch64 use them.
Summary:
The purpose of this patch is to expose more information about ImmLeaf-like
PatLeaf's so that GlobalISel can learn to import them. Previously, ImmLeaf
could only be used to test int64_t's produced by sign-extending an APInt.
Other tests on immediates had to use the generic PatLeaf and extract the
constant using C++.
With this patch, tablegen will know how to generate predicates for APInt,
and APFloat. This will allow it to 'do the right thing' for both SelectionDAG
and GlobalISel which require different methods of extracting the immediate
from the IR.
This is NFC for SelectionDAG since the new code is equivalent to the
previous code. It's also NFC for FastISel because FastIselShouldIgnore is 1
for the ImmLeaf subclasses. Enabling FastIselShouldIgnore == 0 for these new
subclasses will require a significant re-factor of FastISel.
For GlobalISel, it's currently NFC because the relevant code to import the
affected rules is not yet present. This will be added in a later patch.
Depends on D36086
Reviewers: ab, t.p.northover, qcolombet, rovka, aditya_nandakumar
Reviewed By: qcolombet
Subscribers: bjope, aemerson, rengolin, javed.absar, igorb, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D36534
llvm-svn: 315747
Diffstat (limited to 'llvm/utils')
| -rw-r--r-- | llvm/utils/TableGen/CodeGenDAGPatterns.cpp | 27 | ||||
| -rw-r--r-- | llvm/utils/TableGen/CodeGenDAGPatterns.h | 5 | ||||
| -rw-r--r-- | llvm/utils/TableGen/GlobalISelEmitter.cpp | 66 |
3 files changed, 70 insertions, 28 deletions
diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index 1b5c1ae89b3..a9f1b0be816 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -862,6 +862,24 @@ std::string TreePredicateFn::getImmCode() const { return PatFragRec->getRecord()->getValueAsString("ImmediateCode"); } +bool TreePredicateFn::immCodeUsesAPInt() const { + return getOrigPatFragRecord()->getRecord()->getValueAsBit("IsAPInt"); +} + +bool TreePredicateFn::immCodeUsesAPFloat() const { + bool Unset; + // The return value will be false when IsAPFloat is unset. + return getOrigPatFragRecord()->getRecord()->getValueAsBitOrUnset("IsAPFloat", + Unset); +} + +std::string TreePredicateFn::getImmType() const { + if (immCodeUsesAPInt()) + return "const APInt &"; + if (immCodeUsesAPFloat()) + return "const APFloat &"; + return "int64_t"; +} /// isAlwaysTrue - Return true if this is a noop predicate. bool TreePredicateFn::isAlwaysTrue() const { @@ -882,8 +900,13 @@ std::string TreePredicateFn::getCodeToRunOnSDNode() const { // Handle immediate predicates first. std::string ImmCode = getImmCode(); if (!ImmCode.empty()) { - std::string Result = - " int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue();\n"; + std::string Result = " " + getImmType() + " Imm = "; + if (immCodeUsesAPFloat()) + Result += "cast<ConstantFPSDNode>(Node)->getValueAPF();\n"; + else if (immCodeUsesAPInt()) + Result += "cast<ConstantSDNode>(Node)->getAPIntValue();\n"; + else + Result += "cast<ConstantSDNode>(Node)->getSExtValue();\n"; return Result + ImmCode; } diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.h b/llvm/utils/TableGen/CodeGenDAGPatterns.h index 2b434261680..3033986fdd4 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -475,9 +475,14 @@ public: /// appropriate. std::string getCodeToRunOnSDNode() const; + /// Get the data type of the argument to getImmediatePredicateCode(). + std::string getImmType() const; + private: std::string getPredCode() const; std::string getImmCode() const; + bool immCodeUsesAPInt() const; + bool immCodeUsesAPFloat() const; }; diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index eb2d128dc96..18eb271d4ef 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -1913,6 +1913,9 @@ private: importImplicitDefRenderers(BuildMIAction &DstMIBuilder, const std::vector<Record *> &ImplicitDefs) const; + void emitImmPredicates(raw_ostream &OS, + std::function<bool(const Record *R)> Filter); + /// Analyze pattern \p P, returning a matcher for it if possible. /// Otherwise, return an Error explaining why we don't support it. Expected<RuleMatcher> runOnPattern(const PatternToMatch &P); @@ -2559,6 +2562,38 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) { return std::move(M); } +// Emit imm predicate table and an enum to reference them with. +// The 'Predicate_' part of the name is redundant but eliminating it is more +// trouble than it's worth. +void GlobalISelEmitter::emitImmPredicates( + raw_ostream &OS, std::function<bool(const Record *R)> Filter) { + std::vector<const Record *> MatchedRecords; + const auto &Defs = RK.getAllDerivedDefinitions("PatFrag"); + std::copy_if(Defs.begin(), Defs.end(), std::back_inserter(MatchedRecords), + [&](Record *Record) { + return !Record->getValueAsString("ImmediateCode").empty() && + Filter(Record); + }); + + OS << "// PatFrag predicates.\n" + << "enum {\n"; + StringRef EnumeratorSeparator = " = GIPFP_Invalid + 1,\n"; + for (const auto *Record : MatchedRecords) { + OS << " GIPFP_Predicate_" << Record->getName() << EnumeratorSeparator; + EnumeratorSeparator = ",\n"; + } + OS << "};\n"; + for (const auto *Record : MatchedRecords) + OS << " static bool Predicate_" << Record->getName() << "(int64_t Imm) {" + << Record->getValueAsString("ImmediateCode") << " }\n"; + OS << "static InstructionSelector::ImmediatePredicateFn ImmPredicateFns[] = " + "{\n" + << " nullptr,\n"; + for (const auto *Record : MatchedRecords) + OS << " Predicate_" << Record->getName() << ",\n"; + OS << "};\n"; +} + void GlobalISelEmitter::run(raw_ostream &OS) { // Track the GINodeEquiv definitions. gatherNodeEquivs(); @@ -2742,32 +2777,11 @@ void GlobalISelEmitter::run(raw_ostream &OS) { OS << "};\n" << "// See constructor for table contents\n\n"; - // Emit imm predicate table and an enum to reference them with. - // The 'Predicate_' part of the name is redundant but eliminating it is more - // trouble than it's worth. - { - OS << "// PatFrag predicates.\n" - << "enum {\n"; - StringRef EnumeratorSeparator = " = GIPFP_Invalid + 1,\n"; - for (const auto *Record : RK.getAllDerivedDefinitions("PatFrag")) { - if (!Record->getValueAsString("ImmediateCode").empty()) { - OS << " GIPFP_Predicate_" << Record->getName() << EnumeratorSeparator; - EnumeratorSeparator = ",\n"; - } - } - OS << "};\n"; - } - for (const auto *Record : RK.getAllDerivedDefinitions("PatFrag")) - if (!Record->getValueAsString("ImmediateCode").empty()) - OS << " static bool Predicate_" << Record->getName() << "(int64_t Imm) {" - << Record->getValueAsString("ImmediateCode") << " }\n"; - OS << "static InstructionSelector::ImmediatePredicateFn ImmPredicateFns[] = " - "{\n" - << " nullptr,\n"; - for (const auto *Record : RK.getAllDerivedDefinitions("PatFrag")) - if (!Record->getValueAsString("ImmediateCode").empty()) - OS << " Predicate_" << Record->getName() << ",\n"; - OS << "};\n"; + emitImmPredicates(OS, [](const Record *R) { + bool Unset; + return !R->getValueAsBitOrUnset("IsAPFloat", Unset) && + !R->getValueAsBit("IsAPInt"); + }); OS << "bool " << Target.getName() << "InstructionSelector::selectImpl(MachineInstr &I) const {\n" |

