diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -362,7 +362,6 @@ void applyCombineI2PToP2I(MachineInstr &MI, Register &Reg); /// Transform PtrToInt(IntToPtr(x)) to x. - bool matchCombineP2IToI2P(MachineInstr &MI, Register &Reg); void applyCombineP2IToI2P(MachineInstr &MI, Register &Reg); /// Transform G_ADD (G_PTRTOINT x), y -> G_PTRTOINT (G_PTR_ADD x, y) @@ -389,11 +388,7 @@ void applyCombineExtOfExt(MachineInstr &MI, std::tuple &MatchInfo); - /// Transform fneg(fneg(x)) to x. - bool matchCombineFNegOfFNeg(MachineInstr &MI, Register &Reg); - - /// Match fabs(fabs(x)) to fabs(x). - bool matchCombineFAbsOfFAbs(MachineInstr &MI, Register &Src); + /// Transform fabs(fabs(x)) to fabs(x). void applyCombineFAbsOfFAbs(MachineInstr &MI, Register &Src); /// Transform fabs(fneg(x)) to fabs(x). diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -416,10 +416,11 @@ // Fold ptr2int(int2ptr(x)) -> x def i2p_to_p2i: GICombineRule< - (defs root:$root, register_matchinfo:$info), - (match (wip_match_opcode G_PTRTOINT):$root, - [{ return Helper.matchCombineP2IToI2P(*${root}, ${info}); }]), - (apply [{ Helper.applyCombineP2IToI2P(*${root}, ${info}); }]) + (defs root:$dst, register_matchinfo:$info), + (match (G_INTTOPTR $t, $ptr), + (G_PTRTOINT $dst, $t):$mi, + [{ ${info} = ${ptr}.getReg(); }]), + (apply [{ Helper.applyCombineP2IToI2P(*${mi}, ${info}); }]) >; // Fold add ptrtoint(x), y -> ptrtoint (ptr_add x), y @@ -529,10 +530,11 @@ // Fold (fneg (fneg x)) -> x. def fneg_fneg_fold: GICombineRule < - (defs root:$root, register_matchinfo:$matchinfo), - (match (wip_match_opcode G_FNEG):$root, - [{ return Helper.matchCombineFNegOfFNeg(*${root}, ${matchinfo}); }]), - (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) + (defs root:$dst, register_matchinfo:$matchinfo), + (match (G_FNEG $t, $src), + (G_FNEG $dst, $t):$mi, + [{ ${matchinfo} = ${src}.getReg(); }]), + (apply [{ return Helper.replaceSingleDefInstWithReg(*${mi}, ${matchinfo}); }]) >; // Fold (unmerge(merge x, y, z)) -> z, y, z. @@ -554,10 +556,11 @@ // Fold (fabs (fabs x)) -> (fabs x). def fabs_fabs_fold: GICombineRule< - (defs root:$root, register_matchinfo:$matchinfo), - (match (wip_match_opcode G_FABS):$root, - [{ return Helper.matchCombineFAbsOfFAbs(*${root}, ${matchinfo}); }]), - (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) + (defs root:$dst, register_matchinfo:$matchinfo), + (match (G_FABS $abs, $src), + (G_FABS $dst, $abs):$mi, + [{ ${matchinfo} = ${abs}.getReg(); }]), + (apply [{ return Helper.replaceSingleDefInstWithReg(*${mi}, ${matchinfo}); }]) >; // Fold (fabs (fneg x)) -> (fabs x). diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -2019,12 +2019,6 @@ MI.eraseFromParent(); } -bool CombinerHelper::matchCombineP2IToI2P(MachineInstr &MI, Register &Reg) { - assert(MI.getOpcode() == TargetOpcode::G_PTRTOINT && "Expected a G_PTRTOINT"); - Register SrcReg = MI.getOperand(1).getReg(); - return mi_match(SrcReg, MRI, m_GIntToPtr(m_Reg(Reg))); -} - void CombinerHelper::applyCombineP2IToI2P(MachineInstr &MI, Register &Reg) { assert(MI.getOpcode() == TargetOpcode::G_PTRTOINT && "Expected a G_PTRTOINT"); Register DstReg = MI.getOperand(0).getReg(); @@ -2195,19 +2189,6 @@ MI.eraseFromParent(); } -bool CombinerHelper::matchCombineFNegOfFNeg(MachineInstr &MI, Register &Reg) { - assert(MI.getOpcode() == TargetOpcode::G_FNEG && "Expected a G_FNEG"); - Register SrcReg = MI.getOperand(1).getReg(); - return mi_match(SrcReg, MRI, m_GFNeg(m_Reg(Reg))); -} - -bool CombinerHelper::matchCombineFAbsOfFAbs(MachineInstr &MI, Register &Src) { - assert(MI.getOpcode() == TargetOpcode::G_FABS && "Expected a G_FABS"); - Src = MI.getOperand(1).getReg(); - Register AbsSrc; - return mi_match(Src, MRI, m_GFabs(m_Reg(AbsSrc))); -} - bool CombinerHelper::matchCombineFAbsOfFNeg(MachineInstr &MI, BuildFnTy &MatchInfo) { assert(MI.getOpcode() == TargetOpcode::G_FABS && "Expected a G_FABS"); diff --git a/llvm/test/TableGen/GICombinerEmitter/match-tree.td b/llvm/test/TableGen/GICombinerEmitter/match-tree.td --- a/llvm/test/TableGen/GICombinerEmitter/match-tree.td +++ b/llvm/test/TableGen/GICombinerEmitter/match-tree.td @@ -1,6 +1,10 @@ // RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \ // RUN: -combiners=MyCombinerHelper -gicombiner-stop-after-build %s \ // RUN: -o %t.inc | FileCheck %s +// +// RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \ +// RUN: -combiners=MyCombinerHelper %s | \ +// RUN: FileCheck --check-prefix=CODE %s include "llvm/Target/Target.td" include "llvm/Target/GlobalISel/Combine.td" @@ -140,3 +144,88 @@ // CHECK-DAG: Node[[N17]] -> Node[[N18]] [label="#0 MyTarget::SEXT"] // CHECK-DAG: Node[[N17]] -> Node[[N19]] [label="#1 MyTarget::ZEXT"] // CHECK-LABEL: {{^}$}} + + +// Check the generated source code. + +// CODE-LABEL: GenMyCombinerHelper::tryCombineAll + +// Check the first partition. The numbers correspond to the labels above. +// CODE: switch (MIs[0]->getOpcode()) { +// CODE-NEXT: case MyTarget::SUB: Partition = 0; break; +// CODE-NEXT: case MyTarget::MOV: Partition = 1; break; +// CODE-NEXT: case MyTarget::ADD: Partition = 2; break; +// CODE-NEXT: case MyTarget::TRUNC: Partition = 3; break; +// CODE-NEXT: } + +// Check that the correct partition is choosen if operand 1 is a register. + +// CODE: if (Partition == 0 /* MyTarget::SUB */) { +// CODE-NEXT: Partition = -1; +// CODE-NEXT: if (MIs.size() <= 1) MIs.resize(2); +// CODE-NEXT: MIs[1] = nullptr; +// CODE-NEXT: if (MIs[0]->getOperand(1).isReg()) +// CODE-NEXT: MIs[1] = MRI.getVRegDef(MIs[0]->getOperand(1).getReg()); +// CODE-NEXT: if (MIs[1] == nullptr) Partition = 1; +// CODE-NEXT: if (MIs[1] != nullptr) Partition = 0; + + +// Check that the MUL opcode is tested. + +// CODE: if (Partition == 0 /* true */) { +// CODE-NEXT: Partition = -1; +// CODE-NEXT: switch (MIs[1]->getOpcode()) { +// CODE-NEXT: case MyTarget::MUL: Partition = 0; break; +// CODE-NEXT: default: Partition = 1; break; +// CODE-NEXT: } + +// Check that action for MUL is executed. + +// CODE: if (Partition == 0 /* MyTarget::MUL */) { +// CODE-NEXT: // Leaf name: Rule0 +// CODE-NEXT: // Rule: Rule0 +// CODE-NEXT: if (!RuleConfig->isRuleDisabled(0)) { +// CODE-NEXT: if (1 +// CODE-NEXT:) { +// CODE-NEXT: APPLY +// CODE-NEXT: return true; +// CODE-NEXT: } +// CODE-NEXT: } +// CODE-NEXT: llvm_unreachable("Combine rule elision was incorrect"); +// CODE-NEXT: return false; +// CODE-NEXT: } + +// Check that the other rule involving SUB (Rule5) is run otherwise. + +// CODE-NEXT: if (Partition == 1 /* * or nullptr */) { +// CODE-NEXT: // Leaf name: Rule5 +// CODE-NEXT: // Rule: Rule5 +// CODE-NEXT: if (!RuleConfig->isRuleDisabled(5)) { +// CODE-NEXT: if (1 +// CODE-NEXT:) { +// CODE-NEXT: APPLY +// CODE-NEXT: return true; +// CODE-NEXT: } +// CODE-NEXT: } +// CODE-NEXT: llvm_unreachable("Combine rule elision was incorrect"); +// CODE-NEXT: return false; +// CODE-NEXT: } +// CODE-NEXT: } + +// Check that Rule5 is run if operand 1 is not MUL. + +// CODE-NEXT: if (Partition == 1 /* false */) { +// CODE-NEXT: // Leaf name: Rule5 +// CODE-NEXT: // Rule: Rule5 +// CODE-NEXT: if (!RuleConfig->isRuleDisabled(5)) { +// CODE-NEXT: if (1 +// CODE-NEXT:) { +// CODE-NEXT: APPLY +// CODE-NEXT: return true; +// CODE-NEXT: } +// CODE-NEXT: } +// CODE-NEXT: llvm_unreachable("Combine rule elision was incorrect"); +// CODE-NEXT: return false; +// CODE-NEXT: } +// CODE-NEXT: } + diff --git a/llvm/utils/TableGen/GlobalISel/CodeExpansions.h b/llvm/utils/TableGen/GlobalISel/CodeExpansions.h --- a/llvm/utils/TableGen/GlobalISel/CodeExpansions.h +++ b/llvm/utils/TableGen/GlobalISel/CodeExpansions.h @@ -24,9 +24,9 @@ public: void declare(StringRef Name, StringRef Expansion) { - bool Inserted = Expansions.try_emplace(Name, Expansion).second; - assert(Inserted && "Declared variable twice"); - (void)Inserted; + // Duplicates are not inserted. The expansion refers to different + // MachineOperands using the same virtual register. + Expansions.try_emplace(Name, Expansion); } std::string lookup(StringRef Variable) const { diff --git a/llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp b/llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp --- a/llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp +++ b/llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp @@ -762,17 +762,18 @@ void GIMatchTreeVRegDefPartitioner::generatePartitionSelectorCode( raw_ostream &OS, StringRef Indent) const { - OS << Indent << "Partition = -1\n" - << Indent << "if (MIs.size() <= NewInstrID) MIs.resize(NewInstrID + 1);\n" + OS << Indent << "Partition = -1;\n" + << Indent << "if (MIs.size() <= " << NewInstrID << ") MIs.resize(" + << (NewInstrID + 1) << ");\n" << Indent << "MIs[" << NewInstrID << "] = nullptr;\n" - << Indent << "if (MIs[" << InstrID << "].getOperand(" << OpIdx - << ").isReg()))\n" + << Indent << "if (MIs[" << InstrID << "]->getOperand(" << OpIdx + << ").isReg())\n" << Indent << " MIs[" << NewInstrID << "] = MRI.getVRegDef(MIs[" << InstrID - << "].getOperand(" << OpIdx << ").getReg()));\n"; + << "]->getOperand(" << OpIdx << ").getReg());\n"; for (const auto &Pair : ResultToPartition) OS << Indent << "if (MIs[" << NewInstrID << "] " - << (Pair.first ? "==" : "!=") + << (Pair.first ? "!=" : "==") << " nullptr) Partition = " << Pair.second << ";\n"; OS << Indent << "if (Partition == -1) return false;\n";