forked from OSchip/llvm-project
[MIPS GlobalISel] Lower i64 arguments
Lower integer arguments larger then 32 bits for MIPS32. setMostSignificantFirst is used in order for G_UNMERGE_VALUES and G_MERGE_VALUES to always hold registers in same order, regardless of endianness. Patch by Petar Avramovic. Differential Revision: https://reviews.llvm.org/D52409 llvm-svn: 343315
This commit is contained in:
parent
66da1ed29d
commit
ff1bc621a0
|
@ -36,15 +36,58 @@ bool MipsCallLowering::MipsHandler::assign(unsigned VReg,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MipsCallLowering::MipsHandler::assignVRegs(ArrayRef<unsigned> VRegs,
|
||||
ArrayRef<CCValAssign> ArgLocs,
|
||||
unsigned ArgLocsStartIndex) {
|
||||
for (unsigned i = 0; i < VRegs.size(); ++i)
|
||||
if (!assign(VRegs[i], ArgLocs[ArgLocsStartIndex + i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MipsCallLowering::MipsHandler::setMostSignificantFirst(
|
||||
SmallVectorImpl<unsigned> &VRegs) {
|
||||
if (MIRBuilder.getMF().getDataLayout().isLittleEndian())
|
||||
std::reverse(VRegs.begin(), VRegs.end());
|
||||
}
|
||||
|
||||
bool MipsCallLowering::MipsHandler::handle(
|
||||
ArrayRef<CCValAssign> ArgLocs, ArrayRef<CallLowering::ArgInfo> Args) {
|
||||
SmallVector<unsigned, 4> VRegs;
|
||||
unsigned SplitLength;
|
||||
const Function &F = MIRBuilder.getMF().getFunction();
|
||||
const DataLayout &DL = F.getParent()->getDataLayout();
|
||||
const MipsTargetLowering &TLI = *static_cast<const MipsTargetLowering *>(
|
||||
MIRBuilder.getMF().getSubtarget().getTargetLowering());
|
||||
|
||||
for (unsigned ArgsIndex = 0, ArgLocsIndex = 0; ArgsIndex < Args.size();
|
||||
++ArgsIndex, ArgLocsIndex += SplitLength) {
|
||||
EVT VT = TLI.getValueType(DL, Args[ArgsIndex].Ty);
|
||||
SplitLength = TLI.getNumRegistersForCallingConv(F.getContext(),
|
||||
F.getCallingConv(), VT);
|
||||
if (SplitLength > 1) {
|
||||
VRegs.clear();
|
||||
MVT RegisterVT = TLI.getRegisterTypeForCallingConv(
|
||||
F.getContext(), F.getCallingConv(), VT);
|
||||
for (unsigned i = 0; i < SplitLength; ++i)
|
||||
VRegs.push_back(MRI.createGenericVirtualRegister(LLT{RegisterVT}));
|
||||
|
||||
if (!handleSplit(VRegs, ArgLocs, ArgLocsIndex, Args[ArgsIndex].Reg))
|
||||
return false;
|
||||
} else {
|
||||
if (!assign(Args[ArgsIndex].Reg, ArgLocs[ArgLocsIndex]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class IncomingValueHandler : public MipsCallLowering::MipsHandler {
|
||||
public:
|
||||
IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
|
||||
: MipsHandler(MIRBuilder, MRI) {}
|
||||
|
||||
bool handle(ArrayRef<CCValAssign> ArgLocs,
|
||||
ArrayRef<CallLowering::ArgInfo> Args);
|
||||
|
||||
private:
|
||||
void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) override;
|
||||
|
||||
|
@ -53,6 +96,10 @@ private:
|
|||
|
||||
void assignValueToAddress(unsigned ValVReg, const CCValAssign &VA) override;
|
||||
|
||||
bool handleSplit(SmallVectorImpl<unsigned> &VRegs,
|
||||
ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex,
|
||||
unsigned ArgsReg) override;
|
||||
|
||||
virtual void markPhysRegUsed(unsigned PhysReg) {
|
||||
MIRBuilder.getMBB().addLiveIn(PhysReg);
|
||||
}
|
||||
|
@ -128,12 +175,14 @@ void IncomingValueHandler::assignValueToAddress(unsigned ValVReg,
|
|||
buildLoad(ValVReg, VA);
|
||||
}
|
||||
|
||||
bool IncomingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs,
|
||||
ArrayRef<CallLowering::ArgInfo> Args) {
|
||||
for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) {
|
||||
if (!assign(Args[i].Reg, ArgLocs[i]))
|
||||
return false;
|
||||
}
|
||||
bool IncomingValueHandler::handleSplit(SmallVectorImpl<unsigned> &VRegs,
|
||||
ArrayRef<CCValAssign> ArgLocs,
|
||||
unsigned ArgLocsStartIndex,
|
||||
unsigned ArgsReg) {
|
||||
if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex))
|
||||
return false;
|
||||
setMostSignificantFirst(VRegs);
|
||||
MIRBuilder.buildMerge(ArgsReg, VRegs);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -144,9 +193,6 @@ public:
|
|||
MachineInstrBuilder &MIB)
|
||||
: MipsHandler(MIRBuilder, MRI), MIB(MIB) {}
|
||||
|
||||
bool handle(ArrayRef<CCValAssign> ArgLocs,
|
||||
ArrayRef<CallLowering::ArgInfo> Args);
|
||||
|
||||
private:
|
||||
void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) override;
|
||||
|
||||
|
@ -155,6 +201,10 @@ private:
|
|||
|
||||
void assignValueToAddress(unsigned ValVReg, const CCValAssign &VA) override;
|
||||
|
||||
bool handleSplit(SmallVectorImpl<unsigned> &VRegs,
|
||||
ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex,
|
||||
unsigned ArgsReg) override;
|
||||
|
||||
unsigned extendRegister(unsigned ValReg, const CCValAssign &VA);
|
||||
|
||||
MachineInstrBuilder &MIB;
|
||||
|
@ -228,17 +278,20 @@ unsigned OutgoingValueHandler::extendRegister(unsigned ValReg,
|
|||
llvm_unreachable("unable to extend register");
|
||||
}
|
||||
|
||||
bool OutgoingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs,
|
||||
ArrayRef<CallLowering::ArgInfo> Args) {
|
||||
for (unsigned i = 0; i < Args.size(); ++i) {
|
||||
if (!assign(Args[i].Reg, ArgLocs[i]))
|
||||
return false;
|
||||
}
|
||||
bool OutgoingValueHandler::handleSplit(SmallVectorImpl<unsigned> &VRegs,
|
||||
ArrayRef<CCValAssign> ArgLocs,
|
||||
unsigned ArgLocsStartIndex,
|
||||
unsigned ArgsReg) {
|
||||
MIRBuilder.buildUnmerge(VRegs, ArgsReg);
|
||||
setMostSignificantFirst(VRegs);
|
||||
if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isSupportedType(Type *T) {
|
||||
if (T->isIntegerTy() && T->getScalarSizeInBits() <= 32)
|
||||
if (T->isIntegerTy())
|
||||
return true;
|
||||
if (T->isPointerTy())
|
||||
return true;
|
||||
|
@ -247,7 +300,9 @@ static bool isSupportedType(Type *T) {
|
|||
|
||||
CCValAssign::LocInfo determineLocInfo(const MVT RegisterVT, const EVT VT,
|
||||
const ISD::ArgFlagsTy &Flags) {
|
||||
if (VT.getSizeInBits() == RegisterVT.getSizeInBits())
|
||||
// > does not mean loss of information as type RegisterVT can't hold type VT,
|
||||
// it means that type VT is split into multiple registers of type RegisterVT
|
||||
if (VT.getSizeInBits() >= RegisterVT.getSizeInBits())
|
||||
return CCValAssign::LocInfo::Full;
|
||||
if (Flags.isSExt())
|
||||
return CCValAssign::LocInfo::SExt;
|
||||
|
@ -304,12 +359,7 @@ bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
|
|||
}
|
||||
|
||||
SmallVector<ISD::OutputArg, 8> Outs;
|
||||
subTargetRegTypeForCallingConv(
|
||||
MIRBuilder, RetInfos, OrigArgIndices,
|
||||
[&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
|
||||
unsigned origIdx, unsigned partOffs) {
|
||||
Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
|
||||
});
|
||||
subTargetRegTypeForCallingConv(F, RetInfos, OrigArgIndices, Outs);
|
||||
|
||||
SmallVector<CCValAssign, 16> ArgLocs;
|
||||
MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
|
||||
|
@ -358,12 +408,7 @@ bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
|
|||
}
|
||||
|
||||
SmallVector<ISD::InputArg, 8> Ins;
|
||||
subTargetRegTypeForCallingConv(
|
||||
MIRBuilder, ArgInfos, OrigArgIndices,
|
||||
[&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx,
|
||||
unsigned partOffs) {
|
||||
Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
|
||||
});
|
||||
subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Ins);
|
||||
|
||||
SmallVector<CCValAssign, 16> ArgLocs;
|
||||
MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
|
||||
|
@ -440,12 +485,7 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
|
|||
}
|
||||
|
||||
SmallVector<ISD::OutputArg, 8> Outs;
|
||||
subTargetRegTypeForCallingConv(
|
||||
MIRBuilder, ArgInfos, OrigArgIndices,
|
||||
[&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx,
|
||||
unsigned partOffs) {
|
||||
Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
|
||||
});
|
||||
subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Outs);
|
||||
|
||||
SmallVector<CCValAssign, 8> ArgLocs;
|
||||
MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
|
||||
|
@ -477,12 +517,7 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
|
|||
splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices);
|
||||
|
||||
SmallVector<ISD::InputArg, 8> Ins;
|
||||
subTargetRegTypeForCallingConv(
|
||||
MIRBuilder, ArgInfos, OrigRetIndices,
|
||||
[&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
|
||||
unsigned origIdx, unsigned partOffs) {
|
||||
Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
|
||||
});
|
||||
subTargetRegTypeForCallingConv(F, ArgInfos, OrigRetIndices, Ins);
|
||||
|
||||
SmallVector<CCValAssign, 8> ArgLocs;
|
||||
MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
|
||||
|
@ -501,11 +536,10 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void MipsCallLowering::subTargetRegTypeForCallingConv(
|
||||
MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args,
|
||||
ArrayRef<unsigned> OrigArgIndices, const FunTy &PushBack) const {
|
||||
MachineFunction &MF = MIRBuilder.getMF();
|
||||
const Function &F = MF.getFunction();
|
||||
const Function &F, ArrayRef<ArgInfo> Args,
|
||||
ArrayRef<unsigned> OrigArgIndices, SmallVectorImpl<T> &ISDArgs) const {
|
||||
const DataLayout &DL = F.getParent()->getDataLayout();
|
||||
const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
|
||||
|
||||
|
@ -515,12 +549,20 @@ void MipsCallLowering::subTargetRegTypeForCallingConv(
|
|||
EVT VT = TLI.getValueType(DL, Arg.Ty);
|
||||
MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(),
|
||||
F.getCallingConv(), VT);
|
||||
unsigned NumRegs = TLI.getNumRegistersForCallingConv(
|
||||
F.getContext(), F.getCallingConv(), VT);
|
||||
|
||||
ISD::ArgFlagsTy Flags = Arg.Flags;
|
||||
Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL));
|
||||
for (unsigned i = 0; i < NumRegs; ++i) {
|
||||
ISD::ArgFlagsTy Flags = Arg.Flags;
|
||||
|
||||
PushBack(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], 0);
|
||||
if (i == 0)
|
||||
Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL));
|
||||
else
|
||||
Flags.setOrigAlign(1);
|
||||
|
||||
ISDArgs.emplace_back(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo],
|
||||
0);
|
||||
}
|
||||
++ArgNo;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,13 +31,21 @@ public:
|
|||
|
||||
virtual ~MipsHandler() = default;
|
||||
|
||||
bool handle(ArrayRef<CCValAssign> ArgLocs,
|
||||
ArrayRef<CallLowering::ArgInfo> Args);
|
||||
|
||||
protected:
|
||||
bool assign(unsigned VReg, const CCValAssign &VA);
|
||||
bool assignVRegs(ArrayRef<unsigned> VRegs, ArrayRef<CCValAssign> ArgLocs,
|
||||
unsigned Index);
|
||||
|
||||
void setMostSignificantFirst(SmallVectorImpl<unsigned> &VRegs);
|
||||
|
||||
MachineIRBuilder &MIRBuilder;
|
||||
MachineRegisterInfo &MRI;
|
||||
|
||||
private:
|
||||
bool assign(unsigned VReg, const CCValAssign &VA);
|
||||
|
||||
virtual unsigned getStackAddress(const CCValAssign &VA,
|
||||
MachineMemOperand *&MMO) = 0;
|
||||
|
||||
|
@ -45,6 +53,10 @@ public:
|
|||
|
||||
virtual void assignValueToAddress(unsigned ValVReg,
|
||||
const CCValAssign &VA) = 0;
|
||||
|
||||
virtual bool handleSplit(SmallVectorImpl<unsigned> &VRegs,
|
||||
ArrayRef<CCValAssign> ArgLocs,
|
||||
unsigned ArgLocsStartIndex, unsigned ArgsReg) = 0;
|
||||
};
|
||||
|
||||
MipsCallLowering(const MipsTargetLowering &TLI);
|
||||
|
@ -60,18 +72,13 @@ public:
|
|||
ArrayRef<ArgInfo> OrigArgs) const override;
|
||||
|
||||
private:
|
||||
using FunTy =
|
||||
std::function<void(ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
|
||||
unsigned origIdx, unsigned partOffs)>;
|
||||
|
||||
/// Based on registers available on target machine split or extend
|
||||
/// type if needed, also change pointer type to appropriate integer
|
||||
/// type. Lambda will fill some info so we can tell MipsCCState to
|
||||
/// assign physical registers.
|
||||
void subTargetRegTypeForCallingConv(MachineIRBuilder &MIRBuilder,
|
||||
ArrayRef<ArgInfo> Args,
|
||||
/// type.
|
||||
template <typename T>
|
||||
void subTargetRegTypeForCallingConv(const Function &F, ArrayRef<ArgInfo> Args,
|
||||
ArrayRef<unsigned> OrigArgIndices,
|
||||
const FunTy &PushBack) const;
|
||||
SmallVectorImpl<T> &ISDArgs) const;
|
||||
|
||||
/// Split structures and arrays, save original argument indices since
|
||||
/// Mips calling conv needs info about original argument type.
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
|
||||
|
||||
define i64 @i64_reg(i64 %a) {
|
||||
; MIPS32-LABEL: name: i64_reg
|
||||
; MIPS32: bb.1.entry:
|
||||
; MIPS32: liveins: $a0, $a1
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0
|
||||
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
|
||||
; MIPS32: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY1]](s32), [[COPY]](s32)
|
||||
; MIPS32: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[MV]](s64)
|
||||
; MIPS32: $v0 = COPY [[UV1]](s32)
|
||||
; MIPS32: $v1 = COPY [[UV]](s32)
|
||||
; MIPS32: RetRA implicit $v0, implicit $v1
|
||||
entry:
|
||||
ret i64 %a
|
||||
}
|
||||
|
||||
define i64 @i64_stack(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i64 %a) {
|
||||
; MIPS32-LABEL: name: i64_stack
|
||||
; MIPS32: fixedStack:
|
||||
; MIPS32-DAG: - { id: [[STACK0:[0-9]+]], type: default, offset: 20, size: 4, alignment: 4,
|
||||
; MIPS32-DAG: - { id: [[STACK1:[0-9]+]], type: default, offset: 16, size: 4, alignment: 8,
|
||||
; MIPS32: bb.1.entry:
|
||||
; MIPS32: liveins: $a0, $a1, $a2, $a3
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0
|
||||
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
|
||||
; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2
|
||||
; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3
|
||||
; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.1
|
||||
; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.[[STACK1]], align 0)
|
||||
; MIPS32: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
|
||||
; MIPS32: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX1]](p0) :: (load 4 from %fixed-stack.[[STACK0]], align 0)
|
||||
; MIPS32: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[LOAD1]](s32), [[LOAD]](s32)
|
||||
; MIPS32: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[MV]](s64)
|
||||
; MIPS32: $v0 = COPY [[UV1]](s32)
|
||||
; MIPS32: $v1 = COPY [[UV]](s32)
|
||||
; MIPS32: RetRA implicit $v0, implicit $v1
|
||||
entry:
|
||||
ret i64 %a
|
||||
}
|
||||
|
||||
define i64 @i64_reg_allign(i32 %a0, i64 %a) {
|
||||
; MIPS32-LABEL: name: i64_reg_allign
|
||||
; MIPS32: bb.1.entry:
|
||||
; MIPS32: liveins: $a0, $a2, $a3
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0
|
||||
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a2
|
||||
; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a3
|
||||
; MIPS32: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY2]](s32), [[COPY1]](s32)
|
||||
; MIPS32: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[MV]](s64)
|
||||
; MIPS32: $v0 = COPY [[UV1]](s32)
|
||||
; MIPS32: $v1 = COPY [[UV]](s32)
|
||||
; MIPS32: RetRA implicit $v0, implicit $v1
|
||||
entry:
|
||||
ret i64 %a
|
||||
}
|
||||
|
||||
define i64 @i64_stack_allign(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %s16, i64 %a) {
|
||||
; MIPS32-LABEL: name: i64_stack_allign
|
||||
; MIPS32: fixedStack:
|
||||
; MIPS32-DAG: - { id: [[STACK0:[0-9]+]], type: default, offset: 28, size: 4, alignment: 4,
|
||||
; MIPS32-DAG: - { id: [[STACK1:[0-9]+]], type: default, offset: 24, size: 4, alignment: 8,
|
||||
; MIPS32-DAG: - { id: [[STACK2:[0-9]+]], type: default, offset: 16, size: 4, alignment: 8,
|
||||
; MIPS32: bb.1.entry:
|
||||
; MIPS32: liveins: $a0, $a1, $a2, $a3
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0
|
||||
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
|
||||
; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2
|
||||
; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3
|
||||
; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.2
|
||||
; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.[[STACK2]], align 0)
|
||||
; MIPS32: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.1
|
||||
; MIPS32: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX1]](p0) :: (load 4 from %fixed-stack.[[STACK1]], align 0)
|
||||
; MIPS32: [[FRAME_INDEX2:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
|
||||
; MIPS32: [[LOAD2:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX2]](p0) :: (load 4 from %fixed-stack.[[STACK0]], align 0)
|
||||
; MIPS32: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[LOAD2]](s32), [[LOAD1]](s32)
|
||||
; MIPS32: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[MV]](s64)
|
||||
; MIPS32: $v0 = COPY [[UV1]](s32)
|
||||
; MIPS32: $v1 = COPY [[UV]](s32)
|
||||
; MIPS32: RetRA implicit $v0, implicit $v1
|
||||
entry:
|
||||
ret i64 %a
|
||||
}
|
||||
|
||||
define i64 @i64_reg_stack(i32 %a0, i32 %a1, i32 %a2, i64 %a) {
|
||||
; MIPS32-LABEL: name: i64_reg_stack
|
||||
; MIPS32: fixedStack:
|
||||
; MIPS32-DAG: - { id: [[STACK0:[0-9]+]], type: default, offset: 20, size: 4, alignment: 4,
|
||||
; MIPS32-DAG: - { id: [[STACK1:[0-9]+]], type: default, offset: 16, size: 4, alignment: 8,
|
||||
; MIPS32: bb.1.entry:
|
||||
; MIPS32: liveins: $a0, $a1, $a2
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0
|
||||
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
|
||||
; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2
|
||||
; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.1
|
||||
; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.[[STACK1]], align 0)
|
||||
; MIPS32: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
|
||||
; MIPS32: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX1]](p0) :: (load 4 from %fixed-stack.[[STACK0]], align 0)
|
||||
; MIPS32: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[LOAD1]](s32), [[LOAD]](s32)
|
||||
; MIPS32: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[MV]](s64)
|
||||
; MIPS32: $v0 = COPY [[UV1]](s32)
|
||||
; MIPS32: $v1 = COPY [[UV]](s32)
|
||||
; MIPS32: RetRA implicit $v0, implicit $v1
|
||||
entry:
|
||||
ret i64 %a
|
||||
}
|
Loading…
Reference in New Issue