From eb773d9b315e3a1213ca7f08ff83c40692a2bb6d Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Wed, 20 Feb 2019 19:43:47 +0000 Subject: [PATCH] Add support for pointer types in patterns Summary: This adds support for defining patterns for global isel using pointer types, for example: def : Pat<(load GPR32:$src), (p1 (LOAD GPR32:$src))>; DAGISelEmitter will ignore the pointer information and treat these types as integers with the same bit-width as the pointer type. Reviewers: dsanders, rtereshin, arsenm Reviewed By: arsenm Subscribers: Petar.Avramovic, wdng, rovka, kristof.beyls, jfb, volkan, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D57065 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354510 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/ValueTypes.td | 11 +++++++++ test/TableGen/GlobalISelEmitter.td | 35 ++++++++++++++++++++++++--- utils/TableGen/CodeGenDAGPatterns.cpp | 8 +++++- utils/TableGen/CodeGenDAGPatterns.h | 11 +++++++++ utils/TableGen/GlobalISelEmitter.cpp | 3 +++ utils/TableGen/InfoByHwMode.cpp | 7 +++++- utils/TableGen/InfoByHwMode.h | 6 +++++ 7 files changed, 75 insertions(+), 6 deletions(-) diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index f82faf259c7..f40e8ed8691 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -166,3 +166,14 @@ def iPTR : ValueType<0 , 254>; // Pseudo valuetype to represent "any type of any size". def Any : ValueType<0 , 255>; + +/// This class is for targets that want to use pointer types in patterns +/// with the GlobalISelEmitter. Targets must define their own pointer +/// derived from this class. The scalar argument should be an +/// integer type with the same bit size as the ponter. +/// e.g. def p0 : PtrValueType ; + +class PtrValueType : + ValueType { + int AddrSpace = addrspace; +} diff --git a/test/TableGen/GlobalISelEmitter.td b/test/TableGen/GlobalISelEmitter.td index 15e14a0a8bc..0e88ddd2eb3 100644 --- a/test/TableGen/GlobalISelEmitter.td +++ b/test/TableGen/GlobalISelEmitter.td @@ -128,10 +128,12 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; } // CHECK-LABEL: // LLT Objects. // CHECK-NEXT: enum { +// CHECK-NEXT: GILLT_p0s32 // CHECK-NEXT: GILLT_s32, // CHECK-NEXT: } -// CHECK-NEXT: const static size_t NumTypeObjects = 1; +// CHECK-NEXT: const static size_t NumTypeObjects = 2; // CHECK-NEXT: const static LLT TypeObjects[] = { +// CHECK-NEXT: LLT::pointer(0, 32), // CHECK-NEXT: LLT::scalar(32), // CHECK-NEXT: }; @@ -829,7 +831,7 @@ def : Pat<(not GPR32:$Wm), (ORN R0, GPR32:$Wm)>; // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src3 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0, // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0, -// NOOPT-NEXT: // GIR_Coverage, 25, +// NOOPT-NEXT: // GIR_Coverage, 26, // NOOPT-NEXT: GIR_Done, // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]] @@ -974,6 +976,31 @@ def MOVcimm8 : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, cimm8:$ def LOAD : I<(outs GPR32:$dst), (ins GPR32:$src1), [(set GPR32:$dst, (load GPR32:$src1))]>; +//===- Test a simple pattern with explicit pointer operands. ---------------===// + +// NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]], +// NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2, +// NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_LOAD, +// NOOPT-NEXT: GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0, +// NOOPT-NEXT: GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(int64_t)AtomicOrdering::NotAtomic, +// NOOPT-NEXT: // MIs[0] dst +// NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_p0s32, +// NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID, +// NOOPT-NEXT: // MIs[0] src +// NOOPT-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32, +// NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID, +// NOOPT-NEXT: // (ld:{ *:[i32] } GPR32:{ *:[i32] }:$src)<><> => (LOAD:{ *:[i32] } GPR32:{ *:[i32] }:$src) +// NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::LOAD, +// NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0, +// NOOPT-NEXT: // GIR_Coverage, 23, +// NOOPT-NEXT: GIR_Done, +// NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]] + +def p0 : PtrValueType ; + +def : Pat<(load GPR32:$src), + (p0 (LOAD GPR32:$src))>; + //===- Test a simple pattern with a sextload -------------------------------===// // // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]], @@ -1061,7 +1088,7 @@ def DOUBLE : I<(outs GPR32:$dst), (ins GPR32:$src), [(set GPR32:$dst, (add GPR32 // NOOPT-NEXT: // (add:{ *:[i32] } i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2) => (ADD:{ *:[i32] } i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2) // NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::ADD, // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0, -// NOOPT-NEXT: // GIR_Coverage, 23, +// NOOPT-NEXT: // GIR_Coverage, 24, // NOOPT-NEXT: GIR_Done, // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]] @@ -1113,7 +1140,7 @@ def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1), // NOOPT-NEXT: // (bitconvert:{ *:[i32] } FPR32:{ *:[f32] }:$src1) => (COPY_TO_REGCLASS:{ *:[i32] } FPR32:{ *:[f32] }:$src1, GPR32:{ *:[i32] }) // NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/TargetOpcode::COPY, // NOOPT-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC GPR32*/1, -// NOOPT-NEXT: // GIR_Coverage, 24, +// NOOPT-NEXT: // GIR_Coverage, 25, // NOOPT-NEXT: GIR_Done, // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]] diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index f231c3a4aa7..19a7874ee1f 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -67,8 +67,10 @@ static bool berase_if(MachineValueTypeSet &S, Predicate P) { // inference will apply to each mode separately. TypeSetByHwMode::TypeSetByHwMode(ArrayRef VTList) { - for (const ValueTypeByHwMode &VVT : VTList) + for (const ValueTypeByHwMode &VVT : VTList) { insert(VVT); + AddrSpaces.push_back(VVT.PtrAddrSpace); + } } bool TypeSetByHwMode::isValueTypeByHwMode(bool AllowEmpty) const { @@ -85,9 +87,13 @@ ValueTypeByHwMode TypeSetByHwMode::getValueTypeByHwMode() const { assert(isValueTypeByHwMode(true) && "The type set has multiple types for at least one HW mode"); ValueTypeByHwMode VVT; + auto ASI = AddrSpaces.begin(); + for (const auto &I : *this) { MVT T = I.second.empty() ? MVT::Other : *I.second.begin(); VVT.getOrCreateTypeForMode(I.first, T); + if (ASI != AddrSpaces.end()) + VVT.PtrAddrSpace = *ASI++; } return VVT; } diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 24b58b1d949..81ee2d0204d 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -190,6 +190,7 @@ private: struct TypeSetByHwMode : public InfoByHwMode { using SetType = MachineValueTypeSet; + std::vector AddrSpaces; TypeSetByHwMode() = default; TypeSetByHwMode(const TypeSetByHwMode &VTS) = default; @@ -226,6 +227,15 @@ struct TypeSetByHwMode : public InfoByHwMode { return Map.size() == 1 && Map.begin()->first == DefaultMode; } + bool isPointer() const { + return getValueTypeByHwMode().isPointer(); + } + + unsigned getPtrAddrSpace() const { + assert(isPointer()); + return getValueTypeByHwMode().PtrAddrSpace; + } + bool insert(const ValueTypeByHwMode &VVT); bool constrain(const TypeSetByHwMode &VTS); template bool constrain(Predicate P); @@ -242,6 +252,7 @@ struct TypeSetByHwMode : public InfoByHwMode { bool validate() const; private: + unsigned PtrAddrSpace = std::numeric_limits::max(); /// Intersect two sets. Return true if anything has changed. bool intersect(SetType &Out, const SetType &In); }; diff --git a/utils/TableGen/GlobalISelEmitter.cpp b/utils/TableGen/GlobalISelEmitter.cpp index 8079e2989b6..1e71d1317ed 100644 --- a/utils/TableGen/GlobalISelEmitter.cpp +++ b/utils/TableGen/GlobalISelEmitter.cpp @@ -1513,6 +1513,9 @@ Error OperandMatcher::addTypeCheckPredicate(const TypeSetByHwMode &VTy, if (OperandIsAPointer) addPredicate(OpTyOrNone->get().getSizeInBits()); + else if (VTy.isPointer()) + addPredicate(LLT::pointer(VTy.getPtrAddrSpace(), + OpTyOrNone->get().getSizeInBits())); else addPredicate(*OpTyOrNone); return Error::success(); diff --git a/utils/TableGen/InfoByHwMode.cpp b/utils/TableGen/InfoByHwMode.cpp index ce1b78a8f17..d9662889a5d 100644 --- a/utils/TableGen/InfoByHwMode.cpp +++ b/utils/TableGen/InfoByHwMode.cpp @@ -38,6 +38,11 @@ ValueTypeByHwMode::ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH) { } } +ValueTypeByHwMode::ValueTypeByHwMode(Record *R, MVT T) : ValueTypeByHwMode(T) { + if (R->isSubClassOf("PtrValueType")) + PtrAddrSpace = R->getValueAsInt("AddrSpace"); +} + bool ValueTypeByHwMode::operator== (const ValueTypeByHwMode &T) const { assert(isValid() && T.isValid() && "Invalid type in assignment"); bool Simple = isSimple(); @@ -111,7 +116,7 @@ ValueTypeByHwMode llvm::getValueTypeByHwMode(Record *Rec, "Record must be derived from ValueType"); if (Rec->isSubClassOf("HwModeSelect")) return ValueTypeByHwMode(Rec, CGH); - return ValueTypeByHwMode(llvm::getValueType(Rec)); + return ValueTypeByHwMode(Rec, llvm::getValueType(Rec)); } RegSizeInfo::RegSizeInfo(Record *R, const CodeGenHwModes &CGH) { diff --git a/utils/TableGen/InfoByHwMode.h b/utils/TableGen/InfoByHwMode.h index 6871d61028c..9e5cc3d5f2a 100644 --- a/utils/TableGen/InfoByHwMode.h +++ b/utils/TableGen/InfoByHwMode.h @@ -119,6 +119,7 @@ struct InfoByHwMode { struct ValueTypeByHwMode : public InfoByHwMode { ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH); + ValueTypeByHwMode(Record *R, MVT T); ValueTypeByHwMode(MVT T) { Map.insert({DefaultMode,T}); } ValueTypeByHwMode() = default; @@ -134,6 +135,11 @@ struct ValueTypeByHwMode : public InfoByHwMode { static StringRef getMVTName(MVT T); void writeToStream(raw_ostream &OS) const; void dump() const; + + unsigned PtrAddrSpace = std::numeric_limits::max(); + bool isPointer() const { + return PtrAddrSpace != std::numeric_limits::max(); + } }; ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, -- 2.40.0