mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-18 10:32:48 +02:00
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. llvm-svn: 295255
This commit is contained in:
parent
675ff280b6
commit
5b6f2d0cd7
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
39
test/CodeGen/AArch64/GlobalISel/legalize-vaarg.mir
Normal file
39
test/CodeGen/AArch64/GlobalISel/legalize-vaarg.mir
Normal file
@ -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
|
||||
...
|
Loading…
Reference in New Issue
Block a user