[llvm] b2b9af5 - [TableGen][GlobalISel] Fix tblgen optimization bug

Bjorn Pettersson via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 26 03:11:10 PDT 2020


Author: Gabriel Hjort Ã…kerlund
Date: 2020-08-26T12:09:01+02:00
New Revision: b2b9af5a1397f15fbbef18497359245d8d221b86

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

LOG: [TableGen][GlobalISel] Fix tblgen optimization bug

When optimizing the table, PointerToAnyOperandMatchers would be
incorrectly reported as identical even though they have different
SizeInBits values. This bug was due to failing to overload the
isIdentical() method, which this patch addresses.

Reviewed By: arsenm

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

Added: 
    llvm/test/TableGen/GlobalISelEmitterMatchTableOptimizer.td

Modified: 
    llvm/utils/TableGen/GlobalISelEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/TableGen/GlobalISelEmitterMatchTableOptimizer.td b/llvm/test/TableGen/GlobalISelEmitterMatchTableOptimizer.td
new file mode 100644
index 000000000000..cd7a177b8426
--- /dev/null
+++ b/llvm/test/TableGen/GlobalISelEmitterMatchTableOptimizer.td
@@ -0,0 +1,85 @@
+// RUN: llvm-tblgen %s -gen-global-isel -optimize-match-table=true -I %p/../../include -I %p/Common -o - | FileCheck %s
+
+include "llvm/Target/Target.td"
+include "GlobalISelEmitterCommon.td"
+
+// Two LOADs with same output size but 
diff erent input size, hence their
+// GIM_CheckPointerToAny should *not* be merged
+def LOAD8 : I<(outs GPR8:$dst), (ins GPR8:$src), []>;
+def LOAD32 : I<(outs GPR8:$dst), (ins GPR32:$src), []>;
+// CHECK: Label 1: @{{[0-9]+}}
+// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[L1_ID:[0-9]+]]*/ [[L1_AT:[0-9]+]],
+// CHECK-NEXT: GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0,
+// CHECK-NEXT:   GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(int64_t)AtomicOrdering::NotAtomic,
+// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR8RegClassID,
+// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[L2_ID:[0-9]+]]*/ [[L2_AT:[0-9]+]],
+// CHECK-NEXT: // MIs[0] src
+// CHECK-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/8,
+// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR8RegClassID,
+// CHECK-NEXT: // (ld:{ *:[i8] } GPR8:{ *:[i8] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>>  =>  (LOAD8:{ *:[i8] } GPR8:{ *:[i8] }:$src)
+// CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::LOAD8,
+// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT: // GIR_Coverage, 0,
+// CHECK-NEXT: GIR_Done,
+// CHECK-NEXT: // Label [[L2_ID]]: @[[L2_AT]]
+// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[L3_ID:[0-9]+]]*/ [[L3_AT:[0-9]+]],
+// CHECK-NEXT: // MIs[0] src
+// CHECK-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
+// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
+// CHECK-NEXT: // (ld:{ *:[i8] } GPR32:{ *:[i32] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>>  =>  (LOAD32:{ *:[i8] } GPR32:{ *:[i32] }:$src)
+// CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::LOAD32,
+// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT: // GIR_Coverage, 1,
+// CHECK-NEXT: GIR_Done,
+// CHECK-NEXT: // Label [[L3_ID]]: @[[L3_AT]]
+// CHECK-NEXT: GIM_Reject,
+// CHECK-NEXT: // Label [[L1_ID]]: @[[L1_AT]]
+def : Pat<(i8 (load GPR8:$src)),
+          (LOAD8 GPR8:$src)>;
+def : Pat<(i8 (load GPR32:$src)),
+          (LOAD32 GPR32:$src)>;
+
+// Two LOADs with same output size and input size, hence their
+// GIM_CheckPointerToAny *should* be merged
+def S0 : Register<"s0"> { let Namespace = "MyTarget"; }
+def GPR16 : RegisterClass<"MyTarget", [i16], 16, (add S0)>;
+def LOAD16 : I<(outs GPR16:$dst), (ins GPR16:$src), []>;
+def LOAD16Imm : I<(outs GPR16:$dst), (ins GPR16:$src), []>;
+// CHECK: // Label 2: @{{[0-9]+}}
+// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[L1_ID:[0-9]+]]*/ [[L1_AT:[0-9]+]],
+// CHECK-NEXT: GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0,
+// CHECK-NEXT: GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(int64_t)AtomicOrdering::NotAtomic,
+// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR16RegClassID,
+// CHECK-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/16,
+// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[L2_ID:[0-9]+]]*/ [[L2_AT:[0-9]+]],
+// CHECK-NEXT: GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
+// CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_ADD,
+// CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s16,
+// CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s16,
+// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/MyTarget::GPR16RegClassID,
+// CHECK-NEXT: GIM_CheckConstantInt, /*MI*/1, /*Op*/2, 10,
+// CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
+// CHECK-NEXT: // (ld:{ *:[i16] } (add:{ *:[i16] } GPR16:{ *:[i16] }:$src, 10:{ *:[i16] }))<<P:Predicate_unindexedload>><<P:Predicate_load>>  =>  (LOAD16Imm:{ *:[i16] } GPR16:{ *:[i16] }:$src)
+// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::LOAD16Imm,
+// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src
+// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0, /*MergeInsnID's*/0, 1, GIU_MergeMemOperands_EndOfList,
+// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT: // GIR_Coverage, 3,
+// CHECK-NEXT: GIR_Done,
+// CHECK-NEXT: // Label [[L2_ID]]: @[[L2_AT]]
+// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[L3_ID:[0-9]+]]*/ [[L3_AT:[0-9]+]],
+// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR16RegClassID,
+// CHECK-NEXT: // (ld:{ *:[i16] } GPR16:{ *:[i16] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>>  =>  (LOAD16:{ *:[i16] } GPR16:{ *:[i16] }:$src)
+// CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::LOAD16,
+// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT: // GIR_Coverage, 2,
+// CHECK-NEXT: GIR_Done,
+// CHECK-NEXT: // Label [[L3_ID]]: @[[L3_AT]]
+// CHECK-NEXT: GIM_Reject,
+// CHECK-NEXT: // Label [[L1_ID]]: @[[L1_AT]]
+def : Pat<(i16 (load GPR16:$src)),
+          (LOAD16 GPR16:$src)>;
+def : Pat<(i16 (load (add GPR16:$src, 10))),
+          (LOAD16Imm GPR16:$src)>;

diff  --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index 862523efd5be..d74cfae629f5 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -1271,10 +1271,15 @@ class PointerToAnyOperandMatcher : public OperandPredicateMatcher {
       : OperandPredicateMatcher(OPM_PointerToAny, InsnVarID, OpIdx),
         SizeInBits(SizeInBits) {}
 
-  static bool classof(const OperandPredicateMatcher *P) {
+  static bool classof(const PredicateMatcher *P) {
     return P->getKind() == OPM_PointerToAny;
   }
 
+  bool isIdentical(const PredicateMatcher &B) const override {
+    return OperandPredicateMatcher::isIdentical(B) &&
+           SizeInBits == cast<PointerToAnyOperandMatcher>(&B)->SizeInBits;
+  }
+
   void emitPredicateOpcodes(MatchTable &Table,
                             RuleMatcher &Rule) const override {
     Table << MatchTable::Opcode("GIM_CheckPointerToAny")


        


More information about the llvm-commits mailing list