[llvm] r282153 - GlobalISel: handle stack-based parameters on AArch64.
Tim Northover via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 22 06:49:26 PDT 2016
Author: tnorthover
Date: Thu Sep 22 08:49:25 2016
New Revision: 282153
URL: http://llvm.org/viewvc/llvm-project?rev=282153&view=rev
Log:
GlobalISel: handle stack-based parameters on AArch64.
Added:
llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator-ios.ll
Modified:
llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp
llvm/trunk/lib/Target/AArch64/AArch64CallLowering.h
llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator.ll
Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h?rev=282153&r1=282152&r2=282153&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h Thu Sep 22 08:49:25 2016
@@ -111,6 +111,16 @@ public:
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildInstr(unsigned Opcode);
+ /// Build but don't insert <empty> = \p Opcode <empty>.
+ ///
+ /// \pre setMF, setBasicBlock or setMI must have been called.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildInstrNoInsert(unsigned Opcode);
+
+ /// Insert an existing instruction at the insertion point.
+ MachineInstrBuilder insertInstr(MachineInstrBuilder MIB);
+
/// Build and insert \p Res<def> = G_FRAME_INDEX \p Idx
///
/// G_FRAME_INDEX materializes the address of an alloca value or other
Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp?rev=282153&r1=282152&r2=282153&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp Thu Sep 22 08:49:25 2016
@@ -71,7 +71,16 @@ void MachineIRBuilder::stopRecordingInse
//------------------------------------------------------------------------------
MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opcode) {
+ return insertInstr(buildInstrNoInsert(Opcode));
+}
+
+MachineInstrBuilder MachineIRBuilder::buildInstrNoInsert(unsigned Opcode) {
MachineInstrBuilder MIB = BuildMI(getMF(), DL, getTII().get(Opcode));
+ return MIB;
+}
+
+
+MachineInstrBuilder MachineIRBuilder::insertInstr(MachineInstrBuilder MIB) {
getMBB().insert(getInsertPt(), MIB);
if (InsertedInstr)
InsertedInstr(MIB);
Modified: llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp?rev=282153&r1=282152&r2=282153&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64CallLowering.cpp Thu Sep 22 08:49:25 2016
@@ -32,11 +32,10 @@ AArch64CallLowering::AArch64CallLowering
: CallLowering(&TLI) {
}
-
bool AArch64CallLowering::handleAssignments(MachineIRBuilder &MIRBuilder,
CCAssignFn *AssignFn,
ArrayRef<ArgInfo> Args,
- AssignFnTy AssignValToReg) const {
+ ValueHandler &Handler) const {
MachineFunction &MF = MIRBuilder.getMF();
const Function &F = *MF.getFunction();
@@ -49,20 +48,149 @@ bool AArch64CallLowering::handleAssignme
if (AssignFn(i, CurVT, CurVT, CCValAssign::Full, Args[i].Flags, CCInfo))
return false;
}
+
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
- // FIXME: Support non-register argument.
- if (!VA.isRegLoc())
+ if (VA.isRegLoc())
+ Handler.assignValueToReg(Args[i].Reg, VA.getLocReg(), VA);
+ else if (VA.isMemLoc()) {
+ unsigned Size = VA.getValVT().getSizeInBits() / 8;
+ unsigned Offset = VA.getLocMemOffset();
+ MachinePointerInfo MPO;
+ unsigned StackAddr = Handler.getStackAddress(Size, Offset, MPO);
+ Handler.assignValueToAddress(Args[i].Reg, StackAddr, Size, MPO, VA);
+ } else {
+ // FIXME: Support byvals and other weirdness
return false;
-
- // Everything checks out, tell the caller where we've decided this
- // parameter/return value should go.
- AssignValToReg(MIRBuilder, Args[i].Ty, Args[i].Reg, VA);
+ }
}
return true;
}
+unsigned AArch64CallLowering::ValueHandler::extendRegister(unsigned ValReg,
+ CCValAssign &VA) {
+ LLT LocTy{VA.getLocVT()};
+ switch (VA.getLocInfo()) {
+ default: break;
+ case CCValAssign::Full:
+ case CCValAssign::BCvt:
+ // FIXME: bitconverting between vector types may or may not be a
+ // nop in big-endian situations.
+ return ValReg;
+ case CCValAssign::AExt:
+ assert(!VA.getLocVT().isVector() && "unexpected vector extend");
+ // Otherwise, it's a nop.
+ return ValReg;
+ case CCValAssign::SExt: {
+ unsigned NewReg = MRI.createGenericVirtualRegister(LocTy);
+ MIRBuilder.buildSExt(NewReg, ValReg);
+ return NewReg;
+ }
+ case CCValAssign::ZExt: {
+ unsigned NewReg = MRI.createGenericVirtualRegister(LocTy);
+ MIRBuilder.buildZExt(NewReg, ValReg);
+ return NewReg;
+ }
+ }
+ llvm_unreachable("unable to extend register");
+}
+
+struct IncomingArgHandler : public AArch64CallLowering::ValueHandler {
+ IncomingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
+ : ValueHandler(MIRBuilder, MRI) {}
+
+ unsigned getStackAddress(uint64_t Size, int64_t Offset,
+ MachinePointerInfo &MPO) override {
+ auto &MFI = MIRBuilder.getMF().getFrameInfo();
+ int FI = MFI.CreateFixedObject(Size, Offset, true);
+ MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
+ unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 64));
+ MIRBuilder.buildFrameIndex(AddrReg, FI);
+ return AddrReg;
+ }
+
+ void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
+ CCValAssign &VA) override {
+ markPhysRegUsed(PhysReg);
+ MIRBuilder.buildCopy(ValVReg, PhysReg);
+ // FIXME: assert extension
+ }
+
+ void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
+ MachinePointerInfo &MPO, CCValAssign &VA) override {
+ auto MMO = MIRBuilder.getMF().getMachineMemOperand(
+ MPO, MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant, Size,
+ 0);
+ MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
+ }
+
+ /// How the physical register gets marked varies between formal
+ /// parameters (it's a basic-block live-in), and a call instruction
+ /// (it's an implicit-def of the BL).
+ virtual void markPhysRegUsed(unsigned PhysReg) = 0;
+};
+
+struct FormalArgHandler : public IncomingArgHandler {
+ FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
+ : IncomingArgHandler(MIRBuilder, MRI) {}
+
+ void markPhysRegUsed(unsigned PhysReg) override {
+ MIRBuilder.getMBB().addLiveIn(PhysReg);
+ }
+};
+
+struct CallReturnHandler : public IncomingArgHandler {
+ CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ MachineInstrBuilder MIB)
+ : IncomingArgHandler(MIRBuilder, MRI), MIB(MIB) {}
+
+ void markPhysRegUsed(unsigned PhysReg) override {
+ MIB.addDef(PhysReg, RegState::Implicit);
+ }
+
+ MachineInstrBuilder MIB;
+};
+
+struct OutgoingArgHandler : public AArch64CallLowering::ValueHandler {
+ OutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ MachineInstrBuilder MIB)
+ : ValueHandler(MIRBuilder, MRI), MIB(MIB) {}
+
+ unsigned getStackAddress(uint64_t Size, int64_t Offset,
+ MachinePointerInfo &MPO) override {
+ LLT p0 = LLT::pointer(0, 64);
+ LLT s64 = LLT::scalar(64);
+ unsigned SPReg = MRI.createGenericVirtualRegister(p0);
+ MIRBuilder.buildCopy(SPReg, AArch64::SP);
+
+ unsigned OffsetReg = MRI.createGenericVirtualRegister(s64);
+ MIRBuilder.buildConstant(OffsetReg, Offset);
+
+ unsigned AddrReg = MRI.createGenericVirtualRegister(p0);
+ MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg);
+
+ MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
+ return AddrReg;
+ }
+
+ void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
+ CCValAssign &VA) override {
+ MIB.addUse(PhysReg, RegState::Implicit);
+ unsigned ExtReg = extendRegister(ValVReg, VA);
+ MIRBuilder.buildCopy(PhysReg, ExtReg);
+ }
+
+ void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
+ MachinePointerInfo &MPO, CCValAssign &VA) override {
+ auto MMO = MIRBuilder.getMF().getMachineMemOperand(
+ MPO, MachineMemOperand::MOStore, Size, 0);
+ MIRBuilder.buildStore(ValVReg, Addr, *MMO);
+ }
+
+ MachineInstrBuilder MIB;
+};
+
void AArch64CallLowering::splitToValueTypes(const ArgInfo &OrigArg,
SmallVectorImpl<ArgInfo> &SplitArgs,
const DataLayout &DL,
@@ -101,32 +229,6 @@ void AArch64CallLowering::splitToValueTy
PerformArgSplit(SplitRegs, BitOffsets);
}
-static void copyToPhysReg(MachineIRBuilder &MIRBuilder, unsigned ValReg,
- CCValAssign &VA, MachineRegisterInfo &MRI) {
- LLT LocTy{VA.getLocVT()};
- switch (VA.getLocInfo()) {
- default: break;
- case CCValAssign::AExt:
- assert(!VA.getLocVT().isVector() && "unexpected vector extend");
- // Otherwise, it's a nop.
- break;
- case CCValAssign::SExt: {
- unsigned NewReg = MRI.createGenericVirtualRegister(LocTy);
- MIRBuilder.buildSExt(NewReg, ValReg);
- ValReg = NewReg;
- break;
- }
- case CCValAssign::ZExt: {
- unsigned NewReg = MRI.createGenericVirtualRegister(LocTy);
- MIRBuilder.buildZExt(NewReg, ValReg);
- ValReg = NewReg;
- break;
- }
- }
- MIRBuilder.buildCopy(VA.getLocReg(), ValReg);
-}
-
-
bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val, unsigned VReg) const {
MachineFunction &MF = MIRBuilder.getMF();
@@ -152,12 +254,8 @@ bool AArch64CallLowering::lowerReturn(Ma
MIRBuilder.buildExtract(Regs, Offsets, VReg);
});
- return handleAssignments(MIRBuilder, AssignFn, SplitArgs,
- [&](MachineIRBuilder &MIRBuilder, Type *Ty,
- unsigned ValReg, CCValAssign &VA) {
- copyToPhysReg(MIRBuilder, ValReg, VA, MRI);
- MIB.addUse(VA.getLocReg(), RegState::Implicit);
- });
+ OutgoingArgHandler Handler(MIRBuilder, MRI, MIB);
+ return handleAssignments(MIRBuilder, AssignFn, SplitArgs, Handler);
}
return true;
}
@@ -190,14 +288,8 @@ bool AArch64CallLowering::lowerFormalArg
CCAssignFn *AssignFn =
TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false);
- if (!handleAssignments(MIRBuilder, AssignFn, SplitArgs,
- [](MachineIRBuilder &MIRBuilder, Type *Ty,
- unsigned ValReg, CCValAssign &VA) {
- // FIXME: a sign/zeroext loc actually gives
- // us an optimization hint. We should use it.
- MIRBuilder.getMBB().addLiveIn(VA.getLocReg());
- MIRBuilder.buildCopy(ValReg, VA.getLocReg());
- }))
+ FormalArgHandler Handler(MIRBuilder, MRI);
+ if (!handleAssignments(MIRBuilder, AssignFn, SplitArgs, Handler))
return false;
// Move back to the end of the basic block.
@@ -228,27 +320,24 @@ bool AArch64CallLowering::lowerCall(Mach
CCAssignFn *CallAssignFn =
TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false);
- // And finally we can do the actual assignments. For a call we need to keep
- // track of the registers used because they'll be implicit uses of the BL.
- SmallVector<unsigned, 8> PhysRegs;
- if (!handleAssignments(MIRBuilder, CallAssignFn, SplitArgs,
- [&](MachineIRBuilder &MIRBuilder, Type *Ty,
- unsigned ValReg, CCValAssign &VA) {
- copyToPhysReg(MIRBuilder, ValReg, VA, MRI);
- PhysRegs.push_back(VA.getLocReg());
- }))
- return false;
-
- // Now we can build the actual call instruction.
- auto MIB = MIRBuilder.buildInstr(Callee.isReg() ? AArch64::BLR : AArch64::BL);
+ // Create a temporarily-floating call instruction so we can add the implicit
+ // uses of arg registers.
+ auto MIB = MIRBuilder.buildInstrNoInsert(Callee.isReg() ? AArch64::BLR
+ : AArch64::BL);
MIB.addOperand(Callee);
// Tell the call which registers are clobbered.
auto TRI = MF.getSubtarget().getRegisterInfo();
MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv()));
- for (auto Reg : PhysRegs)
- MIB.addUse(Reg, RegState::Implicit);
+ // Do the actual argument marshalling.
+ SmallVector<unsigned, 8> PhysRegs;
+ OutgoingArgHandler Handler(MIRBuilder, MRI, MIB);
+ if (!handleAssignments(MIRBuilder, CallAssignFn, SplitArgs, Handler))
+ return false;
+
+ // Now we can add the actual call instruction to the correct basic block.
+ MIRBuilder.insertInstr(MIB);
// Finally we can copy the returned value back into its virtual-register. In
// symmetry with the arugments, the physical register must be an
@@ -267,14 +356,8 @@ bool AArch64CallLowering::lowerCall(Mach
std::back_inserter(SplitRegs));
});
- if (!handleAssignments(MIRBuilder, RetAssignFn, SplitArgs,
- [&](MachineIRBuilder &MIRBuilder, Type *Ty,
- unsigned ValReg, CCValAssign &VA) {
- // FIXME: a sign/zeroext loc actually gives
- // us an optimization hint. We should use it.
- MIRBuilder.buildCopy(ValReg, VA.getLocReg());
- MIB.addDef(VA.getLocReg(), RegState::Implicit);
- }))
+ CallReturnHandler Handler(MIRBuilder, MRI, MIB);
+ if (!handleAssignments(MIRBuilder, RetAssignFn, SplitArgs, Handler))
return false;
if (!RegOffsets.empty())
Modified: llvm/trunk/lib/Target/AArch64/AArch64CallLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64CallLowering.h?rev=282153&r1=282152&r2=282153&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64CallLowering.h (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64CallLowering.h Thu Sep 22 08:49:25 2016
@@ -25,6 +25,46 @@ class AArch64TargetLowering;
class AArch64CallLowering: public CallLowering {
public:
+
+ /// Argument handling is mostly uniform between the four places that
+ /// make these decisions: function formal arguments, call
+ /// instruction args, call instruction returns and function
+ /// returns. However, once a decision has been made on where an
+ /// arugment should go, exactly what happens can vary slightly. This
+ /// class abstracts the differences.
+ struct ValueHandler {
+ /// Materialize a VReg containing the address of the specified
+ /// stack-based object. This is either based on a FrameIndex or
+ /// direct SP manipulation, depending on the context. \p MPO
+ /// should be initialized to an appropriate description of the
+ /// address created.
+ virtual unsigned getStackAddress(uint64_t Size, int64_t Offset,
+ MachinePointerInfo &MPO) = 0;
+
+ /// The specified value has been assigned to a physical register,
+ /// handle the appropriate COPY (either to or from) and mark any
+ /// relevant uses/defines as needed.
+ virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
+ CCValAssign &VA) = 0;
+
+ /// The specified value has been assigned to a stack
+ /// location. Load or store it there, with appropriate extension
+ /// if necessary.
+ virtual void assignValueToAddress(unsigned ValVReg, unsigned Addr,
+ uint64_t Size, MachinePointerInfo &MPO,
+ CCValAssign &VA) = 0;
+
+ unsigned extendRegister(unsigned ValReg, CCValAssign &VA);
+
+ ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
+ : MIRBuilder(MIRBuilder), MRI(MRI) {}
+
+ virtual ~ValueHandler() {}
+
+ MachineIRBuilder &MIRBuilder;
+ MachineRegisterInfo &MRI;
+ };
+
AArch64CallLowering(const AArch64TargetLowering &TLI);
bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val,
@@ -40,7 +80,10 @@ class AArch64CallLowering: public CallLo
private:
typedef std::function<void(MachineIRBuilder &, Type *, unsigned,
CCValAssign &)>
- AssignFnTy;
+ RegHandler;
+
+ typedef std::function<void(MachineIRBuilder &, int, CCValAssign &)>
+ MemHandler;
typedef std::function<void(ArrayRef<unsigned>, ArrayRef<uint64_t>)>
SplitArgTy;
@@ -52,7 +95,7 @@ private:
bool handleAssignments(MachineIRBuilder &MIRBuilder, CCAssignFn *AssignFn,
ArrayRef<ArgInfo> Args,
- AssignFnTy AssignValToReg) const;
+ ValueHandler &Callback) const;
};
} // End of namespace llvm;
#endif
Added: llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator-ios.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator-ios.ll?rev=282153&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator-ios.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator-ios.ll Thu Sep 22 08:49:25 2016
@@ -0,0 +1,35 @@
+; RUN: llc -mtriple=aarch64-apple-ios -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
+
+
+; CHECK-LABEL: name: test_stack_slots
+; CHECK: fixedStack:
+; CHECK-DAG: - { id: [[STACK0:[0-9]+]], offset: 0, size: 1
+; CHECK-DAG: - { id: [[STACK8:[0-9]+]], offset: 1, size: 1
+; CHECK: [[LHS_ADDR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[STACK0]]
+; CHECK: [[LHS:%[0-9]+]](s8) = G_LOAD [[LHS_ADDR]](p0) :: (invariant load 1 from %fixed-stack.[[STACK0]], align 0)
+; CHECK: [[RHS_ADDR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[STACK8]]
+; CHECK: [[RHS:%[0-9]+]](s8) = G_LOAD [[RHS_ADDR]](p0) :: (invariant load 1 from %fixed-stack.[[STACK8]], align 0)
+; CHECK: [[SUM:%[0-9]+]](s8) = G_ADD [[LHS]], [[RHS]]
+; CHECK: [[SUM32:%[0-9]+]](s32) = G_SEXT [[SUM]](s8)
+; CHECK: %w0 = COPY [[SUM32]](s32)
+define signext i8 @test_stack_slots([8 x i64], i8 signext %lhs, i8 signext %rhs) {
+ %sum = add i8 %lhs, %rhs
+ ret i8 %sum
+}
+
+; CHECK-LABEL: name: test_call_stack
+; CHECK: [[C42:%[0-9]+]](s8) = G_CONSTANT 42
+; CHECK: [[C12:%[0-9]+]](s8) = G_CONSTANT 12
+; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
+; CHECK: [[C42_OFFS:%[0-9]+]](s64) = G_CONSTANT 0
+; CHECK: [[C42_LOC:%[0-9]+]](p0) = G_GEP [[SP]], [[C42_OFFS]](s64)
+; CHECK: G_STORE [[C42]](s8), [[C42_LOC]](p0) :: (store 1 into stack, align 0)
+; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
+; CHECK: [[C12_OFFS:%[0-9]+]](s64) = G_CONSTANT 1
+; CHECK: [[C12_LOC:%[0-9]+]](p0) = G_GEP [[SP]], [[C12_OFFS]](s64)
+; CHECK: G_STORE [[C12]](s8), [[C12_LOC]](p0) :: (store 1 into stack + 1, align 0)
+; CHECK: BL @test_stack_slots
+define void @test_call_stack() {
+ call signext i8 @test_stack_slots([8 x i64] undef, i8 signext 42, i8 signext 12)
+ ret void
+}
Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator.ll?rev=282153&r1=282152&r2=282153&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator.ll Thu Sep 22 08:49:25 2016
@@ -141,3 +141,35 @@ define zeroext i8 @test_abi_zext_ret(i8*
%val = load i8, i8* %addr
ret i8 %val
}
+
+; CHECK-LABEL: name: test_stack_slots
+; CHECK: fixedStack:
+; CHECK-DAG: - { id: [[STACK0:[0-9]+]], offset: 0, size: 8
+; CHECK-DAG: - { id: [[STACK8:[0-9]+]], offset: 8, size: 8
+; CHECK: [[LHS_ADDR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[STACK0]]
+; CHECK: [[LHS:%[0-9]+]](s64) = G_LOAD [[LHS_ADDR]](p0) :: (invariant load 8 from %fixed-stack.[[STACK0]], align 0)
+; CHECK: [[RHS_ADDR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[STACK8]]
+; CHECK: [[RHS:%[0-9]+]](s64) = G_LOAD [[RHS_ADDR]](p0) :: (invariant load 8 from %fixed-stack.[[STACK8]], align 0)
+; CHECK: [[SUM:%[0-9]+]](s64) = G_ADD [[LHS]], [[RHS]]
+; CHECK: %x0 = COPY [[SUM]](s64)
+define i64 @test_stack_slots([8 x i64], i64 %lhs, i64 %rhs) {
+ %sum = add i64 %lhs, %rhs
+ ret i64 %sum
+}
+
+; CHECK-LABEL: name: test_call_stack
+; CHECK: [[C42:%[0-9]+]](s64) = G_CONSTANT 42
+; CHECK: [[C12:%[0-9]+]](s64) = G_CONSTANT 12
+; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
+; CHECK: [[C42_OFFS:%[0-9]+]](s64) = G_CONSTANT 0
+; CHECK: [[C42_LOC:%[0-9]+]](p0) = G_GEP [[SP]], [[C42_OFFS]](s64)
+; CHECK: G_STORE [[C42]](s64), [[C42_LOC]](p0) :: (store 8 into stack, align 0)
+; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
+; CHECK: [[C12_OFFS:%[0-9]+]](s64) = G_CONSTANT 8
+; CHECK: [[C12_LOC:%[0-9]+]](p0) = G_GEP [[SP]], [[C12_OFFS]](s64)
+; CHECK: G_STORE [[C12]](s64), [[C12_LOC]](p0) :: (store 8 into stack + 8, align 0)
+; CHECK: BL @test_stack_slots
+define void @test_call_stack() {
+ call i64 @test_stack_slots([8 x i64] undef, i64 42, i64 12)
+ ret void
+}
More information about the llvm-commits
mailing list