[llvm] [AVR] Support return address intrinsics (PR #67266)
Emil J via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 12 12:55:54 PDT 2023
https://github.com/ekliptik updated https://github.com/llvm/llvm-project/pull/67266
>From 24f98d3c29c41ce16e12262cd414efd7e8b37a29 Mon Sep 17 00:00:00 2001
From: "Emil J. Tywoniak" <emil at tywoniak.eu>
Date: Thu, 12 Oct 2023 21:55:41 +0200
Subject: [PATCH] [AVR] Support return address intrinsics
---
llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp | 31 ++++++++------
llvm/lib/Target/AVR/AVRISelLowering.cpp | 43 ++++++++++++++++++++
llvm/lib/Target/AVR/AVRISelLowering.h | 3 ++
llvm/lib/Target/AVR/AVRMachineFunctionInfo.h | 8 +++-
llvm/test/CodeGen/AVR/addr-of-ret-addr.ll | 32 +++++++++++++++
llvm/test/CodeGen/AVR/returnaddr.ll | 20 +++++++++
6 files changed, 123 insertions(+), 14 deletions(-)
create mode 100644 llvm/test/CodeGen/AVR/addr-of-ret-addr.ll
create mode 100644 llvm/test/CodeGen/AVR/returnaddr.ll
diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index f257ccea6c50a91..a5c3090a0495b02 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -2498,6 +2498,7 @@ template <> bool AVRExpandPseudo::expand<AVR::ZEXT>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::SPREAD>(Block &MBB, BlockIt MBBI) {
+ const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
MachineInstr &MI = *MBBI;
Register DstLoReg, DstHiReg;
Register DstReg = MI.getOperand(0).getReg();
@@ -2514,10 +2515,12 @@ bool AVRExpandPseudo::expand<AVR::SPREAD>(Block &MBB, BlockIt MBBI) {
.setMIFlags(Flags);
// High part
- buildMI(MBB, MBBI, OpHi)
- .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
- .addImm(0x3e)
- .setMIFlags(Flags);
+ if (!STI.hasSmallStack()) {
+ buildMI(MBB, MBBI, OpHi)
+ .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addImm(0x3e)
+ .setMIFlags(Flags);
+ }
MI.eraseFromParent();
return true;
@@ -2533,17 +2536,19 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
unsigned Flags = MI.getFlags();
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
- buildMI(MBB, MBBI, AVR::INRdA)
- .addReg(STI.getTmpRegister(), RegState::Define)
- .addImm(STI.getIORegSREG())
- .setMIFlags(Flags);
+ if (!STI.hasSmallStack()) {
+ buildMI(MBB, MBBI, AVR::INRdA)
+ .addReg(STI.getTmpRegister(), RegState::Define)
+ .addImm(STI.getIORegSREG())
+ .setMIFlags(Flags);
- buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
+ buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
- buildMI(MBB, MBBI, AVR::OUTARr)
- .addImm(0x3e)
- .addReg(SrcHiReg, getKillRegState(SrcIsKill))
- .setMIFlags(Flags);
+ buildMI(MBB, MBBI, AVR::OUTARr)
+ .addImm(0x3e)
+ .addReg(SrcHiReg, getKillRegState(SrcIsKill))
+ .setMIFlags(Flags);
+ }
buildMI(MBB, MBBI, AVR::OUTARr)
.addImm(STI.getIORegSREG())
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp
index 4f5a48bd05a4e86..e253fa0cdd545cd 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp
@@ -992,6 +992,45 @@ SDValue AVRTargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
return New;
}
+SDValue AVRTargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) const {
+ MachineFunction &MF = DAG.getMachineFunction();
+ AVRMachineFunctionInfo *FuncInfo = MF.getInfo<AVRMachineFunctionInfo>();
+ int ReturnAddrIndex = FuncInfo->getRAIndex();
+ MVT PtrVT = getFrameIndexTy(MF.getDataLayout());
+
+ if (ReturnAddrIndex == 0) {
+ // Set up a frame object for the return address.
+ unsigned SlotSize = PtrVT.getStoreSize();
+ ReturnAddrIndex = MF.getFrameInfo().CreateFixedObject(
+ SlotSize, -(int64_t)SlotSize, false);
+ FuncInfo->setRAIndex(ReturnAddrIndex);
+ }
+
+ return DAG.getFrameIndex(ReturnAddrIndex, getPointerTy(DAG.getDataLayout()));
+}
+
+SDValue AVRTargetLowering::LowerRETURNADDR(SDValue Op,
+ SelectionDAG &DAG) const {
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
+ MFI.setReturnAddressIsTaken(true);
+
+ EVT VT = Op.getValueType();
+ SDLoc DL(Op);
+ unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
+ assert(Depth == 0 && "AVR RETURNADDR depth must be 0!");
+ // Just load the return address off the stack.
+ SDValue RetAddrFI = getReturnAddressFrameIndex(DAG);
+ return DAG.getLoad(VT, DL, DAG.getEntryNode(), RetAddrFI,
+ MachinePointerInfo());
+}
+SDValue AVRTargetLowering::LowerADDROFRETURNADDR(SDValue Op,
+ SelectionDAG &DAG) const {
+ DAG.getMachineFunction().getFrameInfo().setReturnAddressIsTaken(true);
+ return getReturnAddressFrameIndex(DAG);
+}
+
SDValue AVRTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
switch (Op.getOpcode()) {
default:
@@ -1019,6 +1058,10 @@ SDValue AVRTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
return LowerDivRem(Op, DAG);
case ISD::INLINEASM:
return LowerINLINEASM(Op, DAG);
+ case ISD::RETURNADDR:
+ return LowerRETURNADDR(Op, DAG);
+ case ISD::ADDROFRETURNADDR:
+ return LowerADDROFRETURNADDR(Op, DAG);
}
return SDValue();
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.h b/llvm/lib/Target/AVR/AVRISelLowering.h
index 6815b519bebf74d..443913541b340c2 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.h
+++ b/llvm/lib/Target/AVR/AVRISelLowering.h
@@ -155,6 +155,7 @@ class AVRTargetLowering : public TargetLowering {
}
private:
+ SDValue getReturnAddressFrameIndex(SelectionDAG &DAG) const;
SDValue getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &AVRcc,
SelectionDAG &DAG, SDLoc dl) const;
SDValue getAVRCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG,
@@ -190,6 +191,8 @@ class AVRTargetLowering : public TargetLowering {
const SmallVectorImpl<ISD::InputArg> &Ins,
const SDLoc &dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const;
+ SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerADDROFRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
protected:
const AVRSubtarget &Subtarget;
diff --git a/llvm/lib/Target/AVR/AVRMachineFunctionInfo.h b/llvm/lib/Target/AVR/AVRMachineFunctionInfo.h
index 45c367a4dcd493f..dad0b1ca62ca19a 100644
--- a/llvm/lib/Target/AVR/AVRMachineFunctionInfo.h
+++ b/llvm/lib/Target/AVR/AVRMachineFunctionInfo.h
@@ -44,10 +44,13 @@ class AVRMachineFunctionInfo : public MachineFunctionInfo {
/// FrameIndex for start of varargs area.
int VarArgsFrameIndex;
+ /// FrameIndex for return slot.
+ int ReturnAddrIndex;
+
public:
AVRMachineFunctionInfo(const Function &F, const TargetSubtargetInfo *STI)
: HasSpills(false), HasAllocas(false), HasStackArgs(false),
- CalleeSavedFrameSize(0), VarArgsFrameIndex(0) {
+ CalleeSavedFrameSize(0), VarArgsFrameIndex(0), ReturnAddrIndex(0) {
CallingConv::ID CallConv = F.getCallingConv();
this->IsInterruptHandler =
@@ -85,6 +88,9 @@ class AVRMachineFunctionInfo : public MachineFunctionInfo {
int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
void setVarArgsFrameIndex(int Idx) { VarArgsFrameIndex = Idx; }
+
+ int getRAIndex() const { return ReturnAddrIndex; }
+ void setRAIndex(int Index) { ReturnAddrIndex = Index; }
};
} // namespace llvm
diff --git a/llvm/test/CodeGen/AVR/addr-of-ret-addr.ll b/llvm/test/CodeGen/AVR/addr-of-ret-addr.ll
new file mode 100644
index 000000000000000..0b70aee28b1f4f2
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/addr-of-ret-addr.ll
@@ -0,0 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=avr -mcpu=attiny25 | FileCheck %s --check-prefix=SMALL-SP
+; RUN: llc < %s -mtriple=avr -mcpu=attiny45 | FileCheck %s --check-prefix=BIG-SP
+
+declare ptr @llvm.addressofreturnaddress()
+
+define ptr @a() {
+; SMALL-SP-LABEL: a:
+; SMALL-SP: ; %bb.0:
+; SMALL-SP-NEXT: push r28
+; SMALL-SP-NEXT: push r29
+; SMALL-SP-NEXT: in r28, 61
+; SMALL-SP-NEXT: movw r24, r28
+; SMALL-SP-NEXT: adiw r24, 3
+; SMALL-SP-NEXT: pop r29
+; SMALL-SP-NEXT: pop r28
+; SMALL-SP-NEXT: ret
+;
+; BIG-SP-LABEL: a:
+; BIG-SP: ; %bb.0:
+; BIG-SP-NEXT: push r28
+; BIG-SP-NEXT: push r29
+; BIG-SP-NEXT: in r28, 61
+; BIG-SP-NEXT: in r29, 62
+; BIG-SP-NEXT: movw r24, r28
+; BIG-SP-NEXT: adiw r24, 3
+; BIG-SP-NEXT: pop r29
+; BIG-SP-NEXT: pop r28
+; BIG-SP-NEXT: ret
+ %1 = call ptr @llvm.addressofreturnaddress()
+ ret ptr %1
+}
diff --git a/llvm/test/CodeGen/AVR/returnaddr.ll b/llvm/test/CodeGen/AVR/returnaddr.ll
new file mode 100644
index 000000000000000..5e7b3a22a4bc2b8
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/returnaddr.ll
@@ -0,0 +1,20 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=avr | FileCheck %s
+
+declare ptr @llvm.returnaddress(i32) nounwind readnone
+
+define ptr @a() {
+; CHECK-LABEL: a:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: push r28
+; CHECK-NEXT: push r29
+; CHECK-NEXT: in r28, 61
+; CHECK-NEXT: in r29, 62
+; CHECK-NEXT: ldd r24, Y+3
+; CHECK-NEXT: ldd r25, Y+4
+; CHECK-NEXT: pop r29
+; CHECK-NEXT: pop r28
+; CHECK-NEXT: ret
+ %1 = call ptr @llvm.returnaddress(i32 0)
+ ret ptr %1
+}
More information about the llvm-commits
mailing list