diff options
author | Tim Northover <tnorthover@apple.com> | 2017-02-15 23:22:50 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2017-02-15 23:22:50 +0000 |
commit | 5562e17d88f00450fbea5dc825f8cb7b2f6e343e (patch) | |
tree | baddb9a12dfeff438933a82a8c87b3a1ba76d1ac | |
parent | 432026394b19c5e4f988fd396f8e980ea072868e (diff) |
GlobalISel: legalize va_arg on AArch64.
Uses a Custom implementation because the slot sizes being a multiple of the
pointer size isn't really universal, even for the architectures that do have a
simple "void *" va_list.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295255 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/CodeGen/GlobalISel/LegalizerInfo.h | 5 | ||||
-rw-r--r-- | lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/GlobalISel/LegalizerInfo.cpp | 7 | ||||
-rw-r--r-- | lib/Target/AArch64/AArch64LegalizerInfo.cpp | 78 | ||||
-rw-r--r-- | lib/Target/AArch64/AArch64LegalizerInfo.h | 7 | ||||
-rw-r--r-- | test/CodeGen/AArch64/GlobalISel/legalize-vaarg.mir | 39 |
6 files changed, 139 insertions, 0 deletions
diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h index 079b7725272..30d67eb4992 100644 --- a/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ b/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -25,6 +25,7 @@ namespace llvm { class LLVMContext; class MachineInstr; +class MachineIRBuilder; class MachineRegisterInfo; class Type; class VectorType; @@ -187,6 +188,10 @@ public: bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; + virtual bool legalizeCustom(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const; + private: static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START; static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END; diff --git a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 1f78243e115..6bb64e068ec 100644 --- a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -50,6 +50,9 @@ LegalizerHelper::legalizeInstrStep(MachineInstr &MI, return lower(MI, std::get<1>(Action), std::get<2>(Action)); case LegalizerInfo::FewerElements: return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action)); + case LegalizerInfo::Custom: + return LegalizerInfo.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized + : UnableToLegalize; default: return UnableToLegalize; } diff --git a/lib/CodeGen/GlobalISel/LegalizerInfo.cpp b/lib/CodeGen/GlobalISel/LegalizerInfo.cpp index e757f2587ac..75c54c23872 100644 --- a/lib/CodeGen/GlobalISel/LegalizerInfo.cpp +++ b/lib/CodeGen/GlobalISel/LegalizerInfo.cpp @@ -161,6 +161,7 @@ LLT LegalizerInfo::findLegalType(const InstrAspect &Aspect, case Legal: case Lower: case Libcall: + case Custom: return Aspect.Type; case NarrowScalar: { return findLegalType(Aspect, @@ -181,3 +182,9 @@ LLT LegalizerInfo::findLegalType(const InstrAspect &Aspect, } } } + +bool LegalizerInfo::legalizeCustom(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const { + return false; +} diff --git a/lib/Target/AArch64/AArch64LegalizerInfo.cpp b/lib/Target/AArch64/AArch64LegalizerInfo.cpp index fc224d22a13..651925e616f 100644 --- a/lib/Target/AArch64/AArch64LegalizerInfo.cpp +++ b/lib/Target/AArch64/AArch64LegalizerInfo.cpp @@ -13,7 +13,10 @@ //===----------------------------------------------------------------------===// #include "AArch64LegalizerInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/IR/Type.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/Target/TargetOpcodes.h" @@ -234,5 +237,80 @@ AArch64LegalizerInfo::AArch64LegalizerInfo() { setAction({G_VASTART, p0}, Legal); + // va_list must be a pointer, but most sized types are pretty easy to handle + // as the destination. + setAction({G_VAARG, 1, p0}, Legal); + + for (auto Ty : {s8, s16, s32, s64, p0}) + setAction({G_VAARG, Ty}, Custom); + computeTables(); } + +bool AArch64LegalizerInfo::legalizeCustom(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const { + switch (MI.getOpcode()) { + default: + // No idea what to do. + return false; + case TargetOpcode::G_VAARG: + return legalizeVaArg(MI, MRI, MIRBuilder); + } + + llvm_unreachable("expected switch to return"); +} + +bool AArch64LegalizerInfo::legalizeVaArg(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const { + MIRBuilder.setInstr(MI); + MachineFunction &MF = MIRBuilder.getMF(); + unsigned Align = MI.getOperand(2).getImm(); + unsigned Dst = MI.getOperand(0).getReg(); + unsigned ListPtr = MI.getOperand(1).getReg(); + + LLT PtrTy = MRI.getType(ListPtr); + LLT IntPtrTy = LLT::scalar(PtrTy.getSizeInBits()); + + const unsigned PtrSize = PtrTy.getSizeInBits() / 8; + unsigned List = MRI.createGenericVirtualRegister(PtrTy); + MIRBuilder.buildLoad( + List, ListPtr, + *MF.getMachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOLoad, + PtrSize, /* Align = */ PtrSize)); + + unsigned DstPtr; + if (Align > PtrSize) { + // Realign the list to the actual required alignment. + unsigned AlignMinus1 = MRI.createGenericVirtualRegister(IntPtrTy); + MIRBuilder.buildConstant(AlignMinus1, Align - 1); + + unsigned ListTmp = MRI.createGenericVirtualRegister(PtrTy); + MIRBuilder.buildGEP(ListTmp, List, AlignMinus1); + + DstPtr = MRI.createGenericVirtualRegister(PtrTy); + MIRBuilder.buildPtrMask(DstPtr, ListTmp, Log2_64(Align)); + } else + DstPtr = List; + + uint64_t ValSize = MRI.getType(Dst).getSizeInBits() / 8; + MIRBuilder.buildLoad( + Dst, DstPtr, + *MF.getMachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOLoad, + ValSize, std::max(Align, PtrSize))); + + unsigned SizeReg = MRI.createGenericVirtualRegister(IntPtrTy); + MIRBuilder.buildConstant(SizeReg, alignTo(ValSize, PtrSize)); + + unsigned NewList = MRI.createGenericVirtualRegister(PtrTy); + MIRBuilder.buildGEP(NewList, DstPtr, SizeReg); + + MIRBuilder.buildStore( + NewList, ListPtr, + *MF.getMachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOStore, + PtrSize, /* Align = */ PtrSize)); + + MI.eraseFromParent(); + return true; +} diff --git a/lib/Target/AArch64/AArch64LegalizerInfo.h b/lib/Target/AArch64/AArch64LegalizerInfo.h index feacbef9f14..42d4ac130c5 100644 --- a/lib/Target/AArch64/AArch64LegalizerInfo.h +++ b/lib/Target/AArch64/AArch64LegalizerInfo.h @@ -25,6 +25,13 @@ class LLVMContext; class AArch64LegalizerInfo : public LegalizerInfo { public: AArch64LegalizerInfo(); + + bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const override; + +private: + bool legalizeVaArg(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const; }; } // End llvm namespace. #endif diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-vaarg.mir b/test/CodeGen/AArch64/GlobalISel/legalize-vaarg.mir new file mode 100644 index 00000000000..21def851959 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/legalize-vaarg.mir @@ -0,0 +1,39 @@ +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_vaarg() { ret void } +... + +--- +name: test_vaarg +body: | + bb.0: + %0:_(p0) = COPY %x0 + + ; CHECK-LABEL: name: test_vaarg + ; CHECK: [[LIST:%[0-9]+]](p0) = G_LOAD %0(p0) :: (load 8) + ; CHECK: %1(s8) = G_LOAD [[LIST]](p0) :: (load 1, align 8) + ; CHECK: [[SLOTSIZE:%[0-9]+]](s64) = G_CONSTANT i64 8 + ; CHECK: [[NEXT:%[0-9]+]](p0) = G_GEP [[LIST]], [[SLOTSIZE]](s64) + ; CHECK: G_STORE [[NEXT]](p0), %0(p0) :: (store 8) + %1:_(s8) = G_VAARG %0(p0), 1 + + ; CHECK: [[LIST:%[0-9]+]](p0) = G_LOAD %0(p0) :: (load 8) + ; CHECK: %2(s64) = G_LOAD [[LIST]](p0) :: (load 8) + ; CHECK: [[SLOTSIZE:%[0-9]+]](s64) = G_CONSTANT i64 8 + ; CHECK: [[NEXT:%[0-9]+]](p0) = G_GEP [[LIST]], [[SLOTSIZE]](s64) + ; CHECK: G_STORE [[NEXT]](p0), %0(p0) :: (store 8) + %2:_(s64) = G_VAARG %0(p0), 8 + + ; CHECK: [[LIST:%[0-9]+]](p0) = G_LOAD %0(p0) :: (load 8) + ; CHECK: [[ALIGNM1:%[0-9]+]](s64) = G_CONSTANT i64 15 + ; CHECK: [[ALIGNTMP:%[0-9]+]](p0) = G_GEP [[LIST]], [[ALIGNM1]](s64) + ; CHECK: [[LIST:%[0-9]+]](p0) = G_PTR_MASK [[ALIGNTMP]], 4 + ; CHECK: %3(s64) = G_LOAD [[LIST]](p0) :: (load 8, align 16) + ; CHECK: [[SLOTSIZE:%[0-9]+]](s64) = G_CONSTANT i64 8 + ; CHECK: [[NEXT:%[0-9]+]](p0) = G_GEP [[LIST]], [[SLOTSIZE]](s64) + ; CHECK: G_STORE [[NEXT]](p0), %0(p0) :: (store 8) + %3:_(s64) = G_VAARG %0(p0), 16 +... |