[llvm] r315884 - [globalisel][tablegen] Implement unindexed load, non-extending load, and MemVT checks
Reid Kleckner via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 16 13:33:41 PDT 2017
This broke the MSVC 2017 build. It has something to do with the relative
order of instantiation and specialization of addPredicate. I tried to fix
this in r315930, which was broken, and r315932, which should fix it without
breaking the build elsewhere.
On Sun, Oct 15, 2017 at 5:56 PM, Daniel Sanders via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: dsanders
> Date: Sun Oct 15 17:56:30 2017
> New Revision: 315884
>
> URL: http://llvm.org/viewvc/llvm-project?rev=315884&view=rev
> Log:
> [globalisel][tablegen] Implement unindexed load, non-extending load, and
> MemVT checks
>
> Summary:
> This includes some context-sensitivity in the MVT to LLT conversion so that
> pointer types are tested correctly.
> FIXME: I'm not happy with the way this is done since everything is a
> special-case. I've yet to find a reasonable way to implement it.
>
> select-load.mir fails because <1 x s64> loads in tablegen get priority
> over s64
> loads. This is fixed in the next patch and as such they should be committed
> together, I've posted them separately to help with the review.
>
> Depends on D37456
>
> Reviewers: ab, qcolombet, t.p.northover, rovka, aditya_nandakumar
>
> Subscribers: kristof.beyls, javed.absar, llvm-commits, igorb
>
> Differential Revision: https://reviews.llvm.org/D37457
>
> Modified:
> llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
> llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
> llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-load.mir
> llvm/trunk/test/TableGen/GlobalISelEmitter.td
> llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
>
> Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/CodeGen/GlobalISel/InstructionSelector.h?rev=
> 315884&r1=315883&r2=315884&view=diff
> ============================================================
> ==================
> --- llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
> (original)
> +++ llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h Sun
> Oct 15 17:56:30 2017
> @@ -117,6 +117,11 @@ enum {
> /// - OpIdx - Operand index
> /// - Expected type
> GIM_CheckType,
> + /// Check the type of a pointer to any address space.
> + /// - InsnID - Instruction ID
> + /// - OpIdx - Operand index
> + /// - SizeInBits - The size of the pointer value in bits.
> + GIM_CheckPointerToAny,
> /// Check the register bank for the specified operand
> /// - InsnID - Instruction ID
> /// - OpIdx - Operand index
>
> Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/
> InstructionSelectorImpl.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h?rev=
> 315884&r1=315883&r2=315884&view=diff
> ============================================================
> ==================
> --- llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
> (original)
> +++ llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
> Sun Oct 15 17:56:30 2017
> @@ -244,7 +244,21 @@ bool InstructionSelector::executeMatchTa
> }
> break;
> }
> -
> + case GIM_CheckPointerToAny: {
> + int64_t InsnID = MatchTable[CurrentIdx++];
> + int64_t OpIdx = MatchTable[CurrentIdx++];
> + int64_t SizeInBits = MatchTable[CurrentIdx++];
> + DEBUG(dbgs() << CurrentIdx << ": GIM_CheckPointerToAny(MIs[" <<
> InsnID
> + << "]->getOperand(" << OpIdx
> + << "), SizeInBits=" << SizeInBits << ")\n");
> + assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
> + const LLT &Ty = MRI.getType(State.MIs[InsnID]-
> >getOperand(OpIdx).getReg());
> + if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits) {
> + if (handleReject() == RejectAndGiveUp)
> + return false;
> + }
> + break;
> + }
> case GIM_CheckRegBankForClass: {
> int64_t InsnID = MatchTable[CurrentIdx++];
> int64_t OpIdx = MatchTable[CurrentIdx++];
>
> Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-load.mir
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> CodeGen/AArch64/GlobalISel/select-load.mir?rev=315884&r1=
> 315883&r2=315884&view=diff
> ============================================================
> ==================
> --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-load.mir (original)
> +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-load.mir Sun Oct 15
> 17:56:30 2017
> @@ -1,5 +1,9 @@
> # RUN: llc -mtriple=aarch64-- -run-pass=instruction-select
> -verify-machineinstrs -global-isel %s -o - | FileCheck %s
>
> +# This patch temporarily causes LD1Onev1d to match instead of LDRDui on a
> +# couple functions. A patch to support iPTR will follow that fixes this.
> +# XFAIL: *
> +
> --- |
> target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
>
> @@ -28,6 +32,7 @@
> define void @load_gep_64_s16_fpr(i16* %addr) { ret void }
> define void @load_gep_32_s8_fpr(i8* %addr) { ret void }
>
> + define void @load_v2s32(i64 *%addr) { ret void }
> ...
>
> ---
> @@ -513,3 +518,28 @@ body: |
> %3(s8) = G_LOAD %2 :: (load 1 from %ir.addr)
> %b0 = COPY %3
> ...
> +---
> +# CHECK-LABEL: name: load_v2s32
> +name: load_v2s32
> +legalized: true
> +regBankSelected: true
> +
> +# CHECK: registers:
> +# CHECK-NEXT: - { id: 0, class: gpr64sp, preferred-register: '' }
> +# CHECK-NEXT: - { id: 1, class: fpr64, preferred-register: '' }
> +registers:
> + - { id: 0, class: gpr }
> + - { id: 1, class: fpr }
> +
> +# CHECK: body:
> +# CHECK: %0 = COPY %x0
> +# CHECK: %1 = LD1Onev2s %0
> +# CHECK: %d0 = COPY %1
> +body: |
> + bb.0:
> + liveins: %x0
> +
> + %0(p0) = COPY %x0
> + %1(<2 x s32>) = G_LOAD %0 :: (load 4 from %ir.addr)
> + %d0 = COPY %1(<2 x s32>)
> +...
>
> Modified: llvm/trunk/test/TableGen/GlobalISelEmitter.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> TableGen/GlobalISelEmitter.td?rev=315884&r1=315883&r2=315884&view=diff
> ============================================================
> ==================
> --- llvm/trunk/test/TableGen/GlobalISelEmitter.td (original)
> +++ llvm/trunk/test/TableGen/GlobalISelEmitter.td Sun Oct 15 17:56:30 2017
> @@ -814,9 +814,29 @@ def MOVimm : I<(outs GPR32:$dst), (ins i
> def fpimmz : FPImmLeaf<f32, [{ return Imm->isExactlyValue(0.0); }]>;
> def MOVfpimmz : I<(outs FPR32:$dst), (ins f32imm:$imm), [(set FPR32:$dst,
> fpimmz:$imm)]>;
>
> -//===- Test a pattern with an MBB operand. ------------------------------
> --===//
> +//===- Test a simple pattern with inferred pointer operands.
> ---------------===//
>
> // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 22*/ [[LABEL:[0-9]+]],
> +// CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
> +// CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_LOAD,
> +// CHECK-NEXT: GIM_CheckNonAtomic, /*MI*/0,
> +// CHECK-NEXT: // MIs[0] dst
> +// CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
> +// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0,
> /*RC*/MyTarget::GPR32RegClassID,
> +// CHECK-NEXT: // MIs[0] src1
> +// CHECK-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/1,
> /*SizeInBits*/32,
> +// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1,
> /*RC*/MyTarget::GPR32RegClassID,
> +// CHECK-NEXT: // (ld:{ *:[i32] } GPR32:{ *:[i32]
> }:$src1)<<P:Predicate_unindexedload>><<P:Predicate_load>> => (LOAD:{
> *:[i32] } GPR32:{ *:[i32] }:$src1)
> +// CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0,
> /*Opcode*/MyTarget::LOAD,
> +// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
> +// CHECK-NEXT: GIR_Done,
> +// CHECK-NEXT: // Label 22: @[[LABEL]]
> +
> +def LOAD : I<(outs GPR32:$dst), (ins GPR32:$src1),
> + [(set GPR32:$dst, (load GPR32:$src1))]>;
> +//===- Test a pattern with an MBB operand. ------------------------------
> --===//
> +
> +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 23*/ [[LABEL:[0-9]+]],
> // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/1,
> // CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_BR,
> // CHECK-NEXT: // MIs[0] target
> @@ -825,7 +845,7 @@ def MOVfpimmz : I<(outs FPR32:$dst), (in
> // CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0,
> /*Opcode*/MyTarget::BR,
> // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
> // CHECK-NEXT: GIR_Done,
> -// CHECK-NEXT: // Label 22: @[[LABEL]]
> +// CHECK-NEXT: // Label 23: @[[LABEL]]
>
> def BR : I<(outs), (ins unknown:$target),
> [(br bb:$target)]>;
>
> Modified: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/
> TableGen/GlobalISelEmitter.cpp?rev=315884&r1=315883&r2=315884&view=diff
> ============================================================
> ==================
> --- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp (original)
> +++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp Sun Oct 15 17:56:30
> 2017
> @@ -103,6 +103,12 @@ public:
> OS << "GILLT_v" << Ty.getNumElements() << "s" <<
> Ty.getScalarSizeInBits();
> return;
> }
> + if (Ty.isPointer()) {
> + OS << "GILLT_p" << Ty.getAddressSpace();
> + if (Ty.getSizeInBits() > 0)
> + OS << "s" << Ty.getSizeInBits();
> + return;
> + }
> llvm_unreachable("Unhandled LLT");
> }
>
> @@ -116,6 +122,11 @@ public:
> << Ty.getScalarSizeInBits() << ")";
> return;
> }
> + if (Ty.isPointer() && Ty.getSizeInBits() > 0) {
> + OS << "LLT::pointer(" << Ty.getAddressSpace() << ", "
> + << Ty.getSizeInBits() << ")";
> + return;
> + }
> llvm_unreachable("Unhandled LLT");
> }
>
> @@ -152,9 +163,11 @@ class InstructionMatcher;
> /// MVTs that don't map cleanly to an LLT (e.g., iPTR, *any, ...).
> static Optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT) {
> MVT VT(SVT);
> +
> if (VT.isVector() && VT.getVectorNumElements() != 1)
> return LLTCodeGen(
> LLT::vector(VT.getVectorNumElements(),
> VT.getScalarSizeInBits()));
> +
> if (VT.isInteger() || VT.isFloatingPoint())
> return LLTCodeGen(LLT::scalar(VT.getSizeInBits()));
> return None;
> @@ -228,6 +241,11 @@ static Error isTrivialOperatorNode(const
> if (Predicate.isImmediatePattern())
> continue;
>
> + if (Predicate.isLoad() && Predicate.isUnindexed())
> + continue;
> +
> + if (Predicate.isNonExtLoad())
> + continue;
> HasUnsupportedPredicate = true;
> Explanation = Separator + "Has a predicate (" + explainPredicates(N)
> + ")";
> Separator = ", ";
> @@ -661,6 +679,7 @@ public:
> OPM_Int,
> OPM_LiteralInt,
> OPM_LLT,
> + OPM_PointerToAny,
> OPM_RegBank,
> OPM_MBB,
> };
> @@ -748,6 +767,37 @@ public:
>
> std::set<LLTCodeGen> LLTOperandMatcher::KnownTypes;
>
> +/// Generates code to check that an operand is a pointer to any address
> space.
> +///
> +/// In SelectionDAG, the types did not describe pointers or address
> spaces. As a
> +/// result, iN is used to describe a pointer of N bits to any address
> space and
> +/// PatFrag predicates are typically used to constrain the address space.
> There's
> +/// no reliable means to derive the missing type information from the
> pattern so
> +/// imported rules must test the components of a pointer separately.
> +///
> +/// SizeInBits must be non-zero and the matched pointer must be that size.
> +/// TODO: Add support for iPTR via SizeInBits==0 and a subtarget query.
> +class PointerToAnyOperandMatcher : public OperandPredicateMatcher {
> +protected:
> + unsigned SizeInBits;
> +
> +public:
> + PointerToAnyOperandMatcher(unsigned SizeInBits)
> + : OperandPredicateMatcher(OPM_PointerToAny),
> SizeInBits(SizeInBits) {}
> +
> + static bool classof(const OperandPredicateMatcher *P) {
> + return P->getKind() == OPM_PointerToAny;
> + }
> +
> + void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule,
> + unsigned InsnVarID, unsigned OpIdx) const
> override {
> + Table << MatchTable::Opcode("GIM_CheckPointerToAny") <<
> MatchTable::Comment("MI")
> + << MatchTable::IntValue(InsnVarID) << MatchTable::Comment("Op")
> + << MatchTable::IntValue(OpIdx) << MatchTable::Comment("
> SizeInBits")
> + << MatchTable::IntValue(SizeInBits) << MatchTable::LineBreak;
> + }
> +};
> +
> /// Generates code to check that an operand is a particular target
> constant.
> class ComplexPatternOperandMatcher : public OperandPredicateMatcher {
> protected:
> @@ -927,6 +977,22 @@ public:
>
> InstructionMatcher &getInstructionMatcher() const { return Insn; }
>
> + Error addTypeCheckPredicate(const TypeSetByHwMode &VTy,
> + bool OperandIsAPointer) {
> + auto OpTyOrNone = VTy.isMachineValueType()
> + ? MVTToLLT(VTy.getMachineValueType().SimpleTy)
> + : None;
> + if (!OpTyOrNone)
> + return failedImport("unsupported type");
> +
> + if (OperandIsAPointer)
> + addPredicate<PointerToAnyOperandMatcher>(
> + OpTyOrNone->get().getSizeInBits());
> + else
> + addPredicate<LLTOperandMatcher>(*OpTyOrNone);
> + return Error::success();
> + }
> +
> /// Emit MatchTable opcodes to capture instructions into the MIs table.
> void emitCaptureOpcodes(MatchTable &Table, RuleMatcher &Rule,
> unsigned InsnVarID) const {
> @@ -2070,7 +2136,8 @@ private:
> Error importComplexPatternOperandMatcher(OperandMatcher &OM, Record *R,
> unsigned &TempOpIdx) const;
> Error importChildMatcher(RuleMatcher &Rule, InstructionMatcher
> &InsnMatcher,
> - const TreePatternNode *SrcChild, unsigned
> OpIdx,
> + const TreePatternNode *SrcChild,
> + bool OperandIsAPointer, unsigned OpIdx,
> unsigned &TempOpIdx) const;
> Expected<BuildMIAction &>
> createAndImportInstructionRenderer(RuleMatcher &M, const
> TreePatternNode *Dst,
> @@ -2164,17 +2231,12 @@ Expected<InstructionMatcher &> GlobalISe
>
> unsigned OpIdx = 0;
> for (const TypeSetByHwMode &VTy : Src->getExtTypes()) {
> - auto OpTyOrNone = VTy.isMachineValueType()
> - ? MVTToLLT(VTy.getMachineValueType().SimpleTy)
> - : None;
> - if (!OpTyOrNone)
> - return failedImport(
> - "Result of Src pattern operator has an unsupported type");
> -
> // Results don't have a name unless they are the root node. The
> caller will
> // set the name if appropriate.
> OperandMatcher &OM = InsnMatcher.addOperand(OpIdx++, "", TempOpIdx);
> - OM.addPredicate<LLTOperandMatcher>(*OpTyOrNone);
> + if (auto Error = OM.addTypeCheckPredicate(VTy, false /*
> OperandIsAPointer */))
> + return failedImport(toString(std::move(Error)) +
> + " for result of Src pattern operator");
> }
>
> for (const auto &Predicate : Src->getPredicateFns()) {
> @@ -2186,6 +2248,25 @@ Expected<InstructionMatcher &> GlobalISe
> continue;
> }
>
> + // No check required. A G_LOAD is an unindexed load.
> + if (Predicate.isLoad() && Predicate.isUnindexed())
> + continue;
> +
> + // No check required. G_LOAD by itself is a non-extending load.
> + if (Predicate.isNonExtLoad())
> + continue;
> +
> + if (Predicate.isLoad() && Predicate.getMemoryVT() != nullptr) {
> + Optional<LLTCodeGen> MemTyOrNone =
> + MVTToLLT(getValueType(Predicate.getMemoryVT()));
> +
> + if (!MemTyOrNone)
> + return failedImport("MemVT could not be converted to LLT");
> +
> + InsnMatcher.getOperand(0).addPredicate<LLTOperandMatcher>(
> MemTyOrNone.getValue());
> + continue;
> + }
> +
> return failedImport("Src pattern child has predicate (" +
> explainPredicates(Src) + ")");
> }
> @@ -2217,6 +2298,13 @@ Expected<InstructionMatcher &> GlobalISe
> for (unsigned i = 0, e = Src->getNumChildren(); i != e; ++i) {
> TreePatternNode *SrcChild = Src->getChild(i);
>
> + // SelectionDAG allows pointers to be represented with iN since it
> doesn't
> + // distinguish between pointers and integers but they are different
> types in GlobalISel.
> + // Coerce integers to pointers to address space 0 if the context
> indicates a pointer.
> + // TODO: Find a better way to do this, SDTCisPtrTy?
> + bool OperandIsAPointer =
> + SrcGIOrNull->TheDef->getName() == "G_LOAD" && i == 0;
> +
> // For G_INTRINSIC/G_INTRINSIC_W_SIDE_EFFECTS, the operand
> immediately
> // following the defs is an intrinsic ID.
> if ((SrcGIOrNull->TheDef->getName() == "G_INTRINSIC" ||
> @@ -2232,8 +2320,9 @@ Expected<InstructionMatcher &> GlobalISe
> return failedImport("Expected IntInit containing instrinsic ID)");
> }
>
> - if (auto Error = importChildMatcher(Rule, InsnMatcher, SrcChild,
> OpIdx++,
> - TempOpIdx))
> + if (auto Error =
> + importChildMatcher(Rule, InsnMatcher, SrcChild,
> OperandIsAPointer,
> + OpIdx++, TempOpIdx))
> return std::move(Error);
> }
> }
> @@ -2256,6 +2345,7 @@ Error GlobalISelEmitter::importComplexPa
> Error GlobalISelEmitter::importChildMatcher(RuleMatcher &Rule,
> InstructionMatcher
> &InsnMatcher,
> const TreePatternNode
> *SrcChild,
> + bool OperandIsAPointer,
> unsigned OpIdx,
> unsigned &TempOpIdx) const {
> OperandMatcher &OM =
> @@ -2278,12 +2368,10 @@ Error GlobalISelEmitter::importChildMatc
> }
> }
>
> - Optional<LLTCodeGen> OpTyOrNone = None;
> - if (ChildTypes.front().isMachineValueType())
> - OpTyOrNone = MVTToLLT(ChildTypes.front().getMachineValueType().
> SimpleTy);
> - if (!OpTyOrNone)
> - return failedImport("Src operand has an unsupported type (" +
> to_string(*SrcChild) + ")");
> - OM.addPredicate<LLTOperandMatcher>(*OpTyOrNone);
> + if (auto Error =
> + OM.addTypeCheckPredicate(ChildTypes.front(),
> OperandIsAPointer))
> + return failedImport(toString(std::move(Error)) + " for Src operand
> (" +
> + to_string(*SrcChild) + ")");
>
> // Check for nested instructions.
> if (!SrcChild->isLeaf()) {
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171016/9533170e/attachment-0001.html>
More information about the llvm-commits
mailing list