1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[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
This commit is contained in:
Gabriel Hjort Åkerlund 2020-08-26 10:48:15 +02:00 committed by Bjorn Pettersson
parent d40ac7afef
commit da7e406656
2 changed files with 91 additions and 1 deletions

View File

@ -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 different 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)>;

View File

@ -1271,10 +1271,15 @@ public:
: 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")