llvm.org GIT mirror llvm / 33b4099
[GlobalISel][InstructionSelect] Removing redundant num operands and nested def operands checks, perf patch 2 This patch continues a series of patches that decrease time spent by GlobalISel in its InstructionSelect pass by roughly 60% for -O0 builds for large inputs as measured on sqlite3-amalgamation (http://sqlite.org/download.html) targeting AArch64. This commit specifically removes number of operands checks that are redundant if the instruction's opcode already guarantees that number of operands (or more), and also avoids any kind of checks on a def operand of a nested instruction as everything about it was already checked at its use. The expected performance implication is about 3% off InstructionSelect comparing to the baseline (before the series of patches) This patch also contains a bit of NFC changes required for further patches in the series. Every commit planned shares the same Phabricator Review. Reviewers: qcolombet, dsanders, bogner, aemerson, javed.absar Reviewed By: qcolombet Subscribers: rovka, llvm-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D44700 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@332945 91177308-0d34-0410-b5e6-96231b3b80d8 Roman Tereshin 1 year, 4 months ago
2 changed file(s) with 66 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
242242 // R19O-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SELECT,
243243 //
244244 // R19C-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
245 // R19C-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4,
245 // R19N-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4,
246246 // R19N-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SELECT,
247247 // R19N-NEXT: // MIs[0] dst
248248 // R19C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
256256 // R19C-NEXT: // MIs[0] Operand 3
257257 // R19C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/3, /*Type*/GILLT_s32,
258258 // R19C-NEXT: GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/3, // MIs[1]
259 // R19C-NEXT: GIM_CheckNumOperands, /*MI*/1, /*Expected*/4,
259 // R19N-NEXT: GIM_CheckNumOperands, /*MI*/1, /*Expected*/4,
260260 // R19C-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_SELECT,
261 // R19C-NEXT: // MIs[1] Operand 0
262 // R19C-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
261 // R19N-NEXT: // MIs[1] Operand 0
262 // R19N-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
263263 // R19N-NEXT: // MIs[1] src3
264264 // R19C-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
265265 // R19N-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
322322 // R21C-NEXT: // Label [[PREV_NUM]]: @[[PREV]]
323323 // R21C-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]], // Rule ID 21 //
324324 //
325 // R21C-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4,
325 // R21N-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4,
326326 // R21N-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SELECT,
327327 // R21N-NEXT: // MIs[0] dst
328328 // R21C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
853853 LLTCodeGen getFirstConditionAsRootType();
854854 bool hasFirstCondition() const override;
855855 unsigned getNumOperands() const;
856 StringRef getOpcode() const;
856857
857858 // FIXME: Remove this as soon as possible
858859 InstructionMatcher &insnmatchers_front() const { return *Matchers.front(); }
15441545 return I->TheDef->getName() == "G_CONSTANT";
15451546 }
15461547
1548 StringRef getOpcode() const { return I->TheDef->getName(); }
15471549 unsigned getNumOperands() const { return I->Operands.size(); }
15481550
15491551 StringRef getOperandType(unsigned OpIdx) const {
15531555
15541556 DenseMap
15551557 InstructionOpcodeMatcher::OpcodeValues;
1558
1559 class InstructionNumOperandsMatcher final : public InstructionPredicateMatcher {
1560 unsigned NumOperands = 0;
1561
1562 public:
1563 InstructionNumOperandsMatcher(unsigned InsnVarID, unsigned NumOperands)
1564 : InstructionPredicateMatcher(IPM_NumOperands, InsnVarID),
1565 NumOperands(NumOperands) {}
1566
1567 static bool classof(const PredicateMatcher *P) {
1568 return P->getKind() == IPM_NumOperands;
1569 }
1570
1571 bool isIdentical(const PredicateMatcher &B) const override {
1572 return InstructionPredicateMatcher::isIdentical(B) &&
1573 NumOperands == cast(&B)->NumOperands;
1574 }
1575
1576 void emitPredicateOpcodes(MatchTable &Table,
1577 RuleMatcher &Rule) const override {
1578 Table << MatchTable::Opcode("GIM_CheckNumOperands")
1579 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
1580 << MatchTable::Comment("Expected")
1581 << MatchTable::IntValue(NumOperands) << MatchTable::LineBreak;
1582 }
1583 };
15561584
15571585 /// Generates code to check that this instruction is a constant whose value
15581586 /// meets an immediate predicate.
17491777 /// The operands to match. All rendered operands must be present even if the
17501778 /// condition is always true.
17511779 OperandVec Operands;
1780 bool NumOperandsCheck = true;
17521781
17531782 std::string SymbolicName;
17541783 unsigned InsnVarID;
18101839
18111840 void pop_front() { Operands.erase(Operands.begin()); }
18121841
1813 void optimize() {}
1842 void optimize();
18141843
18151844 /// Emit MatchTable opcodes that test whether the instruction named in
18161845 /// InsnVarName matches all the predicates and all the operands.
18171846 void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule) {
1818 Table << MatchTable::Opcode("GIM_CheckNumOperands")
1819 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
1820 << MatchTable::Comment("Expected")
1821 << MatchTable::IntValue(getNumOperands()) << MatchTable::LineBreak;
1847 if (NumOperandsCheck)
1848 InstructionNumOperandsMatcher(InsnVarID, getNumOperands())
1849 .emitPredicateOpcodes(Table, Rule);
18221850
18231851 emitPredicateListOpcodes(Table, Rule);
18241852
18811909 bool isConstantInstruction() {
18821910 return getOpcodeMatcher().isConstantInstruction();
18831911 }
1912
1913 StringRef getOpcode() { return getOpcodeMatcher().getOpcode(); }
18841914 };
1915
1916 StringRef RuleMatcher::getOpcode() const {
1917 return Matchers.front()->getOpcode();
1918 }
18851919
18861920 unsigned RuleMatcher::getNumOperands() const {
18871921 return Matchers.front()->getNumOperands();
19521986 return false;
19531987 }
19541988 };
1989
1990 void InstructionMatcher::optimize() {
1991 SmallVector, 8> Stash;
1992 const auto &OpcMatcher = getOpcodeMatcher();
1993
1994 Stash.push_back(predicates_pop_front());
1995 if (Stash.back().get() == &OpcMatcher) {
1996 if (NumOperandsCheck && OpcMatcher.getNumOperands() < getNumOperands())
1997 Stash.emplace_back(
1998 new InstructionNumOperandsMatcher(InsnVarID, getNumOperands()));
1999 NumOperandsCheck = false;
2000 }
2001
2002 if (InsnVarID > 0) {
2003 assert(!Operands.empty() && "Nested instruction is expected to def a vreg");
2004 for (auto &OP : Operands[0]->predicates())
2005 OP.reset();
2006 Operands[0]->eraseNullPredicates();
2007 }
2008 while (!Stash.empty())
2009 prependPredicate(Stash.pop_back_val());
2010 }
19552011
19562012 //===- Actions ------------------------------------------------------------===//
19572013 class OperandRenderer {