[llvm] 5aa3af3 - [M68k][GlobalISel] Implement lowerCall based on M68k calling convention
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 7 18:19:06 PST 2022
Author: Sheng
Date: 2022-02-07T21:18:54-05:00
New Revision: 5aa3af3fcb014145ab315090bd3cbea00bea0038
URL: https://github.com/llvm/llvm-project/commit/5aa3af3fcb014145ab315090bd3cbea00bea0038
DIFF: https://github.com/llvm/llvm-project/commit/5aa3af3fcb014145ab315090bd3cbea00bea0038.diff
LOG: [M68k][GlobalISel] Implement lowerCall based on M68k calling convention
This patch implements CallLowering::lowerCall based on M68k calling
convention and adds M68kOutgoingValueHandler and CallReturnHandler to
handle argument passing and returned value.
Added:
llvm/test/CodeGen/M68k/GlobalISel/irtranslator-call.ll
llvm/test/CodeGen/M68k/GlobalISel/irtranslator-pic.ll
Modified:
llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp
llvm/lib/Target/M68k/GISel/M68kCallLowering.h
Removed:
################################################################################
diff --git a/llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp b/llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp
index b3d17184f1fe9..2068e044db8ad 100644
--- a/llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp
+++ b/llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp
@@ -27,10 +27,12 @@ using namespace llvm;
M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI)
: CallLowering(&TLI) {}
-struct OutgoingArgHandler : public CallLowering::OutgoingValueHandler {
- OutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
- MachineInstrBuilder MIB)
- : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
+struct M68kOutgoingArgHandler : public CallLowering::OutgoingValueHandler {
+ M68kOutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ MachineInstrBuilder MIB)
+ : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB),
+ DL(MIRBuilder.getMF().getDataLayout()),
+ STI(MIRBuilder.getMF().getSubtarget<M68kSubtarget>()) {}
void assignValueToReg(Register ValVReg, Register PhysReg,
CCValAssign VA) override {
@@ -41,16 +43,29 @@ struct OutgoingArgHandler : public CallLowering::OutgoingValueHandler {
void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
MachinePointerInfo &MPO, CCValAssign &VA) override {
- llvm_unreachable("unimplemented");
+ MachineFunction &MF = MIRBuilder.getMF();
+ Register ExtReg = extendRegister(ValVReg, VA);
+
+ auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy,
+ inferAlignFromPtrInfo(MF, MPO));
+ MIRBuilder.buildStore(ExtReg, Addr, *MMO);
}
Register getStackAddress(uint64_t Size, int64_t Offset,
MachinePointerInfo &MPO,
ISD::ArgFlagsTy Flags) override {
- llvm_unreachable("unimplemented");
+ LLT p0 = LLT::pointer(0, DL.getPointerSizeInBits(0));
+ LLT SType = LLT::scalar(DL.getPointerSizeInBits(0));
+ Register StackReg = STI.getRegisterInfo()->getStackRegister();
+ auto SPReg = MIRBuilder.buildCopy(p0, StackReg).getReg(0);
+ auto OffsetReg = MIRBuilder.buildConstant(SType, Offset);
+ auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);
+ MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
+ return AddrReg.getReg(0);
}
-
MachineInstrBuilder MIB;
+ const DataLayout &DL;
+ const M68kSubtarget &STI;
};
bool M68kCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val, ArrayRef<Register> VRegs,
@@ -72,7 +87,7 @@ bool M68kCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F);
splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
OutgoingValueAssigner ArgAssigner(AssignFn);
- OutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB);
+ M68kOutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB);
Success = determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs,
MIRBuilder, F.getCallingConv(),
F.isVarArg());
@@ -144,9 +159,73 @@ Register M68kIncomingValueHandler::getStackAddress(uint64_t Size,
return AddrReg.getReg(0);
}
+void CallReturnHandler::assignValueToReg(Register ValVReg, Register PhysReg,
+ CCValAssign VA) {
+ MIB.addDef(PhysReg, RegState::Implicit);
+ MIRBuilder.buildCopy(ValVReg, PhysReg);
+}
+
bool M68kCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
CallLoweringInfo &Info) const {
- return false;
+ MachineFunction &MF = MIRBuilder.getMF();
+ Function &F = MF.getFunction();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+ auto &DL = F.getParent()->getDataLayout();
+ const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>();
+ const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>();
+ const TargetInstrInfo &TII = *STI.getInstrInfo();
+ const M68kRegisterInfo *TRI = STI.getRegisterInfo();
+
+ SmallVector<ArgInfo, 8> OutArgs;
+ for (auto &OrigArg : Info.OrigArgs)
+ splitToValueTypes(OrigArg, OutArgs, DL, Info.CallConv);
+
+ SmallVector<ArgInfo, 8> InArgs;
+ if (!Info.OrigRet.Ty->isVoidTy())
+ splitToValueTypes(Info.OrigRet, InArgs, DL, Info.CallConv);
+
+ unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
+ auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown);
+
+ unsigned Opc = TLI.getTargetMachine().isPositionIndependent() ? M68k::CALLq
+ : Info.Callee.isReg() ? M68k::CALLj
+ : M68k::CALLb;
+
+ auto MIB = MIRBuilder.buildInstrNoInsert(Opc)
+ .add(Info.Callee)
+ .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
+
+ CCAssignFn *AssignFn = TLI.getCCAssignFn(Info.CallConv, false, Info.IsVarArg);
+ OutgoingValueAssigner Assigner(AssignFn);
+ M68kOutgoingArgHandler Handler(MIRBuilder, MRI, MIB);
+ if (!determineAndHandleAssignments(Handler, Assigner, OutArgs, MIRBuilder,
+ Info.CallConv, Info.IsVarArg))
+ return false;
+
+ if (Info.Callee.isReg())
+ constrainOperandRegClass(MF, *TRI, MRI, *STI.getInstrInfo(),
+ *STI.getRegBankInfo(), *MIB, MIB->getDesc(),
+ Info.Callee, 0);
+
+ MIRBuilder.insertInstr(MIB);
+
+ if (!Info.OrigRet.Ty->isVoidTy()) {
+ CCAssignFn *RetAssignFn =
+ TLI.getCCAssignFn(Info.CallConv, true, Info.IsVarArg);
+
+ OutgoingValueAssigner Assigner(RetAssignFn, RetAssignFn);
+ CallReturnHandler Handler(MIRBuilder, MRI, MIB);
+ if (!determineAndHandleAssignments(Handler, Assigner, InArgs, MIRBuilder,
+ Info.CallConv, Info.IsVarArg))
+ return false;
+ }
+
+ CallSeqStart.addImm(Assigner.StackOffset).addImm(0);
+
+ unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
+ MIRBuilder.buildInstr(AdjStackUp).addImm(Assigner.StackOffset).addImm(0);
+
+ return true;
}
bool M68kCallLowering::enableBigEndian() const { return true; }
diff --git a/llvm/lib/Target/M68k/GISel/M68kCallLowering.h b/llvm/lib/Target/M68k/GISel/M68kCallLowering.h
index 24212e6dd9c65..a1589e96aa3d9 100644
--- a/llvm/lib/Target/M68k/GISel/M68kCallLowering.h
+++ b/llvm/lib/Target/M68k/GISel/M68kCallLowering.h
@@ -22,6 +22,7 @@
namespace llvm {
class M68kTargetLowering;
+class MachineInstrBuilder;
class M68kCallLowering : public CallLowering {
// TODO: We are only supporting return instruction with no value at this time
@@ -67,6 +68,17 @@ struct FormalArgHandler : public M68kIncomingValueHandler {
: M68kIncomingValueHandler(MIRBuilder, MRI) {}
};
+struct CallReturnHandler : public M68kIncomingValueHandler {
+ CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ MachineInstrBuilder &MIB)
+ : M68kIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
+
+private:
+ void assignValueToReg(Register ValVReg, Register PhysReg,
+ CCValAssign VA) override;
+
+ MachineInstrBuilder &MIB;
+};
} // end namespace llvm
#endif // LLVM_LIB_TARGET_M68K_GLSEL_M68KCALLLOWERING_H
diff --git a/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-call.ll b/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-call.ll
new file mode 100644
index 0000000000000..f4ff2582fbb17
--- /dev/null
+++ b/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-call.ll
@@ -0,0 +1,320 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+; RUN: llc -mtriple=m68k -O0 -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s
+
+%struct.A = type { i8, i16, i32 }
+
+declare void @trivial_callee()
+define void @test_trivial_call() {
+ ; CHECK-LABEL: name: test_trivial_call
+ ; CHECK: bb.1 (%ir-block.0):
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: CALLb @trivial_callee, csr_std, implicit $sp
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: RTS
+ call void @trivial_callee()
+ ret void
+}
+
+declare i32 @ret_i32_callee()
+define i32 @test_ret_i32() {
+ ; CHECK-LABEL: name: test_ret_i32
+ ; CHECK: bb.1 (%ir-block.0):
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: CALLb @ret_i32_callee, csr_std, implicit $sp, implicit-def $d0
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $d0
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: $d0 = COPY [[COPY]](s32)
+ ; CHECK-NEXT: RTS implicit $d0
+ %res = call i32 @ret_i32_callee()
+ ret i32 %res
+}
+
+declare i16 @ret_i16_callee()
+define i16 @test_ret_i16() nounwind {
+ ; CHECK-LABEL: name: test_ret_i16
+ ; CHECK: bb.1 (%ir-block.0):
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: CALLb @ret_i16_callee, csr_std, implicit $sp, implicit-def $wd0
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $wd0
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: $wd0 = COPY [[COPY]](s16)
+ ; CHECK-NEXT: RTS implicit $wd0
+ %1 = call i16 @ret_i16_callee()
+ ret i16 %1
+}
+
+declare i8 @ret_i8_callee()
+define i8 @test_ret_i8() nounwind {
+ ; CHECK-LABEL: name: test_ret_i8
+ ; CHECK: bb.1 (%ir-block.0):
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: CALLb @ret_i8_callee, csr_std, implicit $sp, implicit-def $bd0
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s8) = COPY $bd0
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: $bd0 = COPY [[COPY]](s8)
+ ; CHECK-NEXT: RTS implicit $bd0
+ %1 = call i8 @ret_i8_callee()
+ ret i8 %1
+}
+
+declare void @sret_callee(%struct.A* sret(%struct.A))
+define void @test_sret(%struct.A* sret(%struct.A) %0) nounwind {
+ ; CHECK-LABEL: name: test_sret
+ ; CHECK: bb.1 (%ir-block.1):
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (load (p0) from %fixed-stack.0, align 8)
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 4, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]](s32)
+ ; CHECK-NEXT: G_STORE [[LOAD]](p0), [[PTR_ADD]](p0) :: (store (p0) into stack, align 1)
+ ; CHECK-NEXT: CALLb @sret_callee, csr_std, implicit $sp
+ ; CHECK-NEXT: ADJCALLSTACKUP 4, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: RTS
+ call void @sret_callee(%struct.A* sret(%struct.A) %0)
+ ret void
+}
+
+declare void @arg_i32_i16_i8_callee(i32, i16, i8)
+define void @test_arg_i32_i16_i8() nounwind {
+ ; CHECK-LABEL: name: test_arg_i32_i16_i8
+ ; CHECK: bb.1 (%ir-block.0):
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 12, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C3]](s32)
+ ; CHECK-NEXT: G_STORE [[C]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 1)
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY1]], [[C4]](s32)
+ ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C1]](s16)
+ ; CHECK-NEXT: G_STORE [[ANYEXT]](s32), [[PTR_ADD1]](p0) :: (store (s16) into stack + 4, align 1)
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+ ; CHECK-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY2]], [[C5]](s32)
+ ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[C2]](s8)
+ ; CHECK-NEXT: G_STORE [[ANYEXT1]](s32), [[PTR_ADD2]](p0) :: (store (s8) into stack + 8)
+ ; CHECK-NEXT: CALLb @arg_i32_i16_i8_callee, csr_std, implicit $sp
+ ; CHECK-NEXT: ADJCALLSTACKUP 12, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: RTS
+ call void @arg_i32_i16_i8_callee(i32 0, i16 1, i8 2)
+ ret void
+}
+
+declare void @arg_struct_callee(%struct.A)
+define void @test_arg_struct(%struct.A *%0) nounwind {
+ ; CHECK-LABEL: name: test_arg_struct
+ ; CHECK: bb.1 (%ir-block.1):
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (load (p0) from %fixed-stack.0, align 8)
+ ; CHECK-NEXT: [[LOAD1:%[0-9]+]]:_(s8) = G_LOAD [[LOAD]](p0) :: (load (s8) from %ir.0, align 2)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+ ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[LOAD]], [[C]](s32)
+ ; CHECK-NEXT: [[LOAD2:%[0-9]+]]:_(s16) = G_LOAD [[PTR_ADD]](p0) :: (load (s16) from %ir.0 + 2)
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[LOAD]], [[C1]](s32)
+ ; CHECK-NEXT: [[LOAD3:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD1]](p0) :: (load (s32) from %ir.0 + 4, align 2)
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 12, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C2]](s32)
+ ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD1]](s8)
+ ; CHECK-NEXT: G_STORE [[ANYEXT]](s32), [[PTR_ADD2]](p0) :: (store (s8) into stack)
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[PTR_ADD3:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY1]], [[C3]](s32)
+ ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD2]](s16)
+ ; CHECK-NEXT: G_STORE [[ANYEXT1]](s32), [[PTR_ADD3]](p0) :: (store (s16) into stack + 4, align 1)
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+ ; CHECK-NEXT: [[PTR_ADD4:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY2]], [[C4]](s32)
+ ; CHECK-NEXT: G_STORE [[LOAD3]](s32), [[PTR_ADD4]](p0) :: (store (s32) into stack + 8, align 1)
+ ; CHECK-NEXT: CALLb @arg_struct_callee, csr_std, implicit $sp
+ ; CHECK-NEXT: ADJCALLSTACKUP 12, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: RTS
+ %2 = load %struct.A, %struct.A* %0
+ call void @arg_struct_callee(%struct.A %2)
+ ret void
+}
+
+declare void @arg_array_callee([8 x i8])
+define void @test_arg_array([8 x i8] *%0) nounwind {
+ ; CHECK-LABEL: name: test_arg_array
+ ; CHECK: bb.1 (%ir-block.1):
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (load (p0) from %fixed-stack.0, align 8)
+ ; CHECK-NEXT: [[LOAD1:%[0-9]+]]:_(s8) = G_LOAD [[LOAD]](p0) :: (load (s8) from %ir.0)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[LOAD]], [[C]](s32)
+ ; CHECK-NEXT: [[LOAD2:%[0-9]+]]:_(s8) = G_LOAD [[PTR_ADD]](p0) :: (load (s8) from %ir.0 + 1)
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+ ; CHECK-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[LOAD]], [[C1]](s32)
+ ; CHECK-NEXT: [[LOAD3:%[0-9]+]]:_(s8) = G_LOAD [[PTR_ADD1]](p0) :: (load (s8) from %ir.0 + 2)
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+ ; CHECK-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD [[LOAD]], [[C2]](s32)
+ ; CHECK-NEXT: [[LOAD4:%[0-9]+]]:_(s8) = G_LOAD [[PTR_ADD2]](p0) :: (load (s8) from %ir.0 + 3)
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[PTR_ADD3:%[0-9]+]]:_(p0) = G_PTR_ADD [[LOAD]], [[C3]](s32)
+ ; CHECK-NEXT: [[LOAD5:%[0-9]+]]:_(s8) = G_LOAD [[PTR_ADD3]](p0) :: (load (s8) from %ir.0 + 4)
+ ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+ ; CHECK-NEXT: [[PTR_ADD4:%[0-9]+]]:_(p0) = G_PTR_ADD [[LOAD]], [[C4]](s32)
+ ; CHECK-NEXT: [[LOAD6:%[0-9]+]]:_(s8) = G_LOAD [[PTR_ADD4]](p0) :: (load (s8) from %ir.0 + 5)
+ ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 6
+ ; CHECK-NEXT: [[PTR_ADD5:%[0-9]+]]:_(p0) = G_PTR_ADD [[LOAD]], [[C5]](s32)
+ ; CHECK-NEXT: [[LOAD7:%[0-9]+]]:_(s8) = G_LOAD [[PTR_ADD5]](p0) :: (load (s8) from %ir.0 + 6)
+ ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 7
+ ; CHECK-NEXT: [[PTR_ADD6:%[0-9]+]]:_(p0) = G_PTR_ADD [[LOAD]], [[C6]](s32)
+ ; CHECK-NEXT: [[LOAD8:%[0-9]+]]:_(s8) = G_LOAD [[PTR_ADD6]](p0) :: (load (s8) from %ir.0 + 7)
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 32, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[PTR_ADD7:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C7]](s32)
+ ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD1]](s8)
+ ; CHECK-NEXT: G_STORE [[ANYEXT]](s32), [[PTR_ADD7]](p0) :: (store (s8) into stack)
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[PTR_ADD8:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY1]], [[C8]](s32)
+ ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD2]](s8)
+ ; CHECK-NEXT: G_STORE [[ANYEXT1]](s32), [[PTR_ADD8]](p0) :: (store (s8) into stack + 4)
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+ ; CHECK-NEXT: [[PTR_ADD9:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY2]], [[C9]](s32)
+ ; CHECK-NEXT: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD3]](s8)
+ ; CHECK-NEXT: G_STORE [[ANYEXT2]](s32), [[PTR_ADD9]](p0) :: (store (s8) into stack + 8)
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 12
+ ; CHECK-NEXT: [[PTR_ADD10:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY3]], [[C10]](s32)
+ ; CHECK-NEXT: [[ANYEXT3:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD4]](s8)
+ ; CHECK-NEXT: G_STORE [[ANYEXT3]](s32), [[PTR_ADD10]](p0) :: (store (s8) into stack + 12)
+ ; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+ ; CHECK-NEXT: [[PTR_ADD11:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY4]], [[C11]](s32)
+ ; CHECK-NEXT: [[ANYEXT4:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD5]](s8)
+ ; CHECK-NEXT: G_STORE [[ANYEXT4]](s32), [[PTR_ADD11]](p0) :: (store (s8) into stack + 16)
+ ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C12:%[0-9]+]]:_(s32) = G_CONSTANT i32 20
+ ; CHECK-NEXT: [[PTR_ADD12:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY5]], [[C12]](s32)
+ ; CHECK-NEXT: [[ANYEXT5:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD6]](s8)
+ ; CHECK-NEXT: G_STORE [[ANYEXT5]](s32), [[PTR_ADD12]](p0) :: (store (s8) into stack + 20)
+ ; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+ ; CHECK-NEXT: [[PTR_ADD13:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY6]], [[C13]](s32)
+ ; CHECK-NEXT: [[ANYEXT6:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD7]](s8)
+ ; CHECK-NEXT: G_STORE [[ANYEXT6]](s32), [[PTR_ADD13]](p0) :: (store (s8) into stack + 24)
+ ; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C14:%[0-9]+]]:_(s32) = G_CONSTANT i32 28
+ ; CHECK-NEXT: [[PTR_ADD14:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY7]], [[C14]](s32)
+ ; CHECK-NEXT: [[ANYEXT7:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD8]](s8)
+ ; CHECK-NEXT: G_STORE [[ANYEXT7]](s32), [[PTR_ADD14]](p0) :: (store (s8) into stack + 28)
+ ; CHECK-NEXT: CALLb @arg_array_callee, csr_std, implicit $sp
+ ; CHECK-NEXT: ADJCALLSTACKUP 32, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: RTS
+ %2 = load [8 x i8], [8 x i8]* %0
+ call void @arg_array_callee([8 x i8] %2)
+ ret void
+}
+
+declare void @arg_pass_struct_by_ptr_callee(%struct.A*)
+define void @test_arg_pass_struct_by_ptr(%struct.A *%0) nounwind {
+ ; CHECK-LABEL: name: test_arg_pass_struct_by_ptr
+ ; CHECK: bb.1 (%ir-block.1):
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (load (p0) from %fixed-stack.0, align 8)
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 4, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]](s32)
+ ; CHECK-NEXT: G_STORE [[LOAD]](p0), [[PTR_ADD]](p0) :: (store (p0) into stack, align 1)
+ ; CHECK-NEXT: CALLb @arg_pass_struct_by_ptr_callee, csr_std, implicit $sp
+ ; CHECK-NEXT: ADJCALLSTACKUP 4, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: RTS
+ call void @arg_pass_struct_by_ptr_callee(%struct.A *%0)
+ ret void
+}
+
+declare void @arg_pass_integer_byval_callee(i32* byval(i32), i16* byval(i16), i8* byval(i8))
+define void @test_arg_pass_integer_byval(i32 *%0, i16 *%1, i8 *%2) nounwind {
+ ; CHECK-LABEL: name: test_arg_pass_integer_byval
+ ; CHECK: bb.1 (%ir-block.3):
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.2
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (load (p0) from %fixed-stack.2, align 8)
+ ; CHECK-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.1
+ ; CHECK-NEXT: [[LOAD1:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX1]](p0) :: (load (p0) from %fixed-stack.1)
+ ; CHECK-NEXT: [[FRAME_INDEX2:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+ ; CHECK-NEXT: [[LOAD2:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX2]](p0) :: (load (p0) from %fixed-stack.0, align 8)
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 12, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]](s32)
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: G_MEMCPY [[PTR_ADD]](p0), [[LOAD]](p0), [[C1]](s32), 0 :: (dereferenceable store (s32) into stack, align 2), (dereferenceable load (s32) from %ir.0, align 2)
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY1]], [[C2]](s32)
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+ ; CHECK-NEXT: G_MEMCPY [[PTR_ADD1]](p0), [[LOAD1]](p0), [[C3]](s32), 0 :: (dereferenceable store (s16) into stack + 4), (dereferenceable load (s16) from %ir.1)
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+ ; CHECK-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY2]], [[C4]](s32)
+ ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; CHECK-NEXT: G_MEMCPY [[PTR_ADD2]](p0), [[LOAD2]](p0), [[C5]](s32), 0 :: (dereferenceable store (s8) into stack + 8), (dereferenceable load (s8) from %ir.2)
+ ; CHECK-NEXT: CALLb @arg_pass_integer_byval_callee, csr_std, implicit $sp
+ ; CHECK-NEXT: ADJCALLSTACKUP 12, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: RTS
+ call void @arg_pass_integer_byval_callee(i32* byval(i32) %0, i16* byval(i16) %1, i8* byval(i8) %2)
+ ret void
+}
+
+declare void @arg_pass_struct_byval_callee(%struct.A* byval(%struct.A))
+define void @test_arg_pass_struct_byval(%struct.A *%0) nounwind {
+ ; CHECK-LABEL: name: test_arg_pass_struct_byval
+ ; CHECK: bb.1 (%ir-block.1):
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (load (p0) from %fixed-stack.0, align 8)
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 8, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]](s32)
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+ ; CHECK-NEXT: G_MEMCPY [[PTR_ADD]](p0), [[LOAD]](p0), [[C1]](s32), 0 :: (dereferenceable store (s64) into stack, align 2), (dereferenceable load (s64) from %ir.0, align 2)
+ ; CHECK-NEXT: CALLb @arg_pass_struct_byval_callee, csr_std, implicit $sp
+ ; CHECK-NEXT: ADJCALLSTACKUP 8, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: RTS
+ call void @arg_pass_struct_byval_callee(%struct.A* byval(%struct.A) %0)
+ ret void
+}
+
+declare void @arg_pass_array_byval_callee([32 x i8]* byval([32 x i8]))
+define void @test_arg_pass_array_byval([32 x i8] *%0) nounwind {
+ ; CHECK-LABEL: name: test_arg_pass_array_byval
+ ; CHECK: bb.1 (%ir-block.1):
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (load (p0) from %fixed-stack.0, align 8)
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 32, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $sp
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]](s32)
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 32
+ ; CHECK-NEXT: G_MEMCPY [[PTR_ADD]](p0), [[LOAD]](p0), [[C1]](s32), 0 :: (dereferenceable store (s256) into stack, align 1), (dereferenceable load (s256) from %ir.0, align 1)
+ ; CHECK-NEXT: CALLb @arg_pass_array_byval_callee, csr_std, implicit $sp
+ ; CHECK-NEXT: ADJCALLSTACKUP 32, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: RTS
+ call void @arg_pass_array_byval_callee([32 x i8]* byval([32 x i8]) %0)
+ ret void
+}
+
+define void @test_indirect_call(void() *%fptr) nounwind {
+ ; CHECK-LABEL: name: test_indirect_call
+ ; CHECK: bb.1 (%ir-block.0):
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:ar32(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (load (p0) from %fixed-stack.0, align 8)
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: CALLj [[LOAD]](p0), csr_std, implicit $sp
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: RTS
+ call void %fptr()
+ ret void
+}
diff --git a/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-pic.ll b/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-pic.ll
new file mode 100644
index 0000000000000..fa50b568715de
--- /dev/null
+++ b/llvm/test/CodeGen/M68k/GlobalISel/irtranslator-pic.ll
@@ -0,0 +1,14 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+; RUN: llc -mtriple=m68k --relocation-model=pic -O0 -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s
+
+define void @test_pic() nounwind {
+ ; CHECK-LABEL: name: test_pic
+ ; CHECK: bb.1 (%ir-block.0):
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: CALLq @test_pic_callee, csr_std, implicit $sp
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit-def $ccr, implicit $sp
+ ; CHECK-NEXT: RTS
+ call void @test_pic_callee()
+ ret void
+}
+declare void @test_pic_callee()
More information about the llvm-commits
mailing list