[llvm] ae35188 - [GISel] Fix match tree emitter.

Kai Nacke via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 17 17:04:16 PDT 2022


Author: Kai Nacke
Date: 2022-09-18T00:00:15Z
New Revision: ae35188f973eb77f5fb22e55d0b8bdac0d15e89b

URL: https://github.com/llvm/llvm-project/commit/ae35188f973eb77f5fb22e55d0b8bdac0d15e89b
DIFF: https://github.com/llvm/llvm-project/commit/ae35188f973eb77f5fb22e55d0b8bdac0d15e89b.diff

LOG: [GISel] Fix match tree emitter.

The following changes are necessasy to get the generated tree
matcher to compile:

- In CodeExpansions::declare(), the assert() prevents connecting
  two instructions. E.g. the match code
    (match (MUL $t, $s1, $s2),
           (SUB $d, $t, $s3)),
  results in two declarations of $t, one for the def and one for
  the use. Removing the assertion allows this construct.
  If $t is later used, it is one of the operands, which should be
  perfectly fine.
- The code emitted in GIMatchTreeVRegDefPartitioner::generatePartitionSelectorCode()
  is not compilable:
  - The value of NewInstrID should be emitted, not the name
  - Both calls involving getOperand() end with one parenthesis too many
- Swaps generated condition for the partition code in the latter function

It also changes the rules i2p_to_p2i, fabs_fabs_fold, and fneg_fneg_fold
to use the tree matcher for a linear match. These rules are tested by:

CodeGen/AArch64/GlobalISel/combine-fabs.mir
CodeGen/AArch64/GlobalISel/combine-fneg.mir
CodeGen/AArch64/GlobalISel/combine-ptrtoint.mir
CodeGen/AMDGPU/GlobalISel/combine-add-nullptr.mir

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D133257

Added: 
    

Modified: 
    llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
    llvm/include/llvm/Target/GlobalISel/Combine.td
    llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
    llvm/test/TableGen/GICombinerEmitter/match-tree.td
    llvm/utils/TableGen/GlobalISel/CodeExpansions.h
    llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index d5e323523024e..fe1585e4600d6 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -362,7 +362,6 @@ class CombinerHelper {
   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 @@ class CombinerHelper {
   void applyCombineExtOfExt(MachineInstr &MI,
                             std::tuple<Register, unsigned> &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
index 5ec829f29869e..26726787e659f 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -416,10 +416,11 @@ def p2i_to_i2p: GICombineRule<
 
 // 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 @@ def not_cmp_fold : GICombineRule<
 
 // 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 @@ def merge_unmerge : GICombineRule<
 
 // 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
index 070a70aeb9285..5ba8bfefe1a40 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -2019,12 +2019,6 @@ void CombinerHelper::applyCombineI2PToP2I(MachineInstr &MI, Register &Reg) {
   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 @@ void CombinerHelper::applyCombineMulByNegativeOne(MachineInstr &MI) {
   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
index fc911fb2f29c5..64ab4350878af 100644
--- 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 @@ def MyCombinerHelper: GICombinerHelper<"GenMyCombinerHelper", [
 // 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
index bb890ec8f57ef..f536e801b27f3 100644
--- a/llvm/utils/TableGen/GlobalISel/CodeExpansions.h
+++ b/llvm/utils/TableGen/GlobalISel/CodeExpansions.h
@@ -24,9 +24,9 @@ class CodeExpansions {
 
 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 
diff erent
+    // 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
index 42055ad4f608e..f797e042e6a05 100644
--- a/llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp
+++ b/llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp
@@ -762,17 +762,18 @@ void GIMatchTreeVRegDefPartitioner::emitPartitionResults(
 
 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";


        


More information about the llvm-commits mailing list