diff options
author | Kai Nacke <kai@redstar.de> | 2022-06-07 22:51:05 -0400 |
---|---|---|
committer | Kai Nacke <kai@redstar.de> | 2022-11-13 11:07:25 -0500 |
commit | 6ff1ec18c7945938ef4cab5114db8bdccab409a3 (patch) | |
tree | 82c235a26ca21a3a770aca72a512293d9931f674 | |
parent | 710b75b79b1f9564200248609f9c181f0ed8b10e (diff) | |
download | llvm-6ff1ec18c7945938ef4cab5114db8bdccab409a3.zip llvm-6ff1ec18c7945938ef4cab5114db8bdccab409a3.tar.gz llvm-6ff1ec18c7945938ef4cab5114db8bdccab409a3.tar.bz2 |
[m88k] Implement returnaddr/frameaddr intrinsics.
-rw-r--r-- | llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp b/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp index e9b3ff2..cfe4701 100644 --- a/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp +++ b/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp @@ -20,6 +20,10 @@ #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/Register.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" @@ -41,6 +45,9 @@ public: const M88kRegisterBankInfo &RBI); bool select(MachineInstr &I) override; + void setupMF(MachineFunction &MF, GISelKnownBits *KB, + CodeGenCoverage &CoverageInfo, ProfileSummaryInfo *PSI, + BlockFrequencyInfo *BFI) override; static const char *getName() { return DEBUG_TYPE; } private: @@ -66,12 +73,19 @@ private: MachineRegisterInfo &MRI) const; bool selectMergeUnmerge(MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const; + bool selectIntrinsic(MachineInstr &I, MachineBasicBlock &MBB, + MachineRegisterInfo &MRI); const M88kTargetMachine &TM; const M88kInstrInfo &TII; const M88kRegisterInfo &TRI; const M88kRegisterBankInfo &RBI; + // Some cached values used during selection. + // We use R1 as a live-in register, and we keep track of it here as it can be + // clobbered by calls. + Register MFReturnAddr; + #define GET_GLOBALISEL_PREDICATES_DECL #include "M88kGenGlobalISel.inc" #undef GET_GLOBALISEL_PREDICATES_DECL @@ -548,6 +562,70 @@ bool M88kInstructionSelector::selectMergeUnmerge( return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); } +bool M88kInstructionSelector::selectIntrinsic(MachineInstr &I, + MachineBasicBlock &MBB, + MachineRegisterInfo &MRI) { + unsigned IntrinID = I.getIntrinsicID(); + MachineInstr *MI = nullptr; + + switch (IntrinID) { + default: + break; + case Intrinsic::frameaddress: + case Intrinsic::returnaddress: { + MachineFunction &MF = *I.getParent()->getParent(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + + unsigned Depth = I.getOperand(2).getImm(); + Register DstReg = I.getOperand(0).getReg(); + RBI.constrainGenericRegister(DstReg, M88k::GPRRCRegClass, MRI); + + if (Depth == 0 && IntrinID == Intrinsic::returnaddress) { + if (!MFReturnAddr) { + // Insert the copy from R1 into the entry block, before it can be + // clobbered by anything. + MFI.setReturnAddressIsTaken(true); + MFReturnAddr = getFunctionLiveInPhysReg( + MF, TII, M88k::R1, M88k::GPRRCRegClass, I.getDebugLoc()); + } + + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::COPY), DstReg) + .addReg(MFReturnAddr); + + I.eraseFromParent(); + return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); + } + + MFI.setFrameAddressIsTaken(true); + Register FrameAddr(M88k::R30); + while (Depth--) { + Register NextFrame = MRI.createVirtualRegister(&M88k::GPRRCRegClass); + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(M88k::LDriw), NextFrame) + .addUse(FrameAddr) + .addImm(0); + + constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); + FrameAddr = NextFrame; + } + + if (IntrinID == Intrinsic::frameaddress) + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::COPY), DstReg) + .addReg(FrameAddr); + else { + MFI.setReturnAddressIsTaken(true); + + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(M88k::LDriw), DstReg) + .addUse(FrameAddr) + .addImm(4); + } + + I.eraseFromParent(); + return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); + } + } + return false; +} + bool M88kInstructionSelector::earlySelect(MachineInstr &I) { assert(I.getParent() && "Instruction should be in a basic block!"); assert(I.getParent()->getParent() && "Instruction should be in a function!"); @@ -605,6 +683,14 @@ bool M88kInstructionSelector::earlySelect(MachineInstr &I) { } } +void M88kInstructionSelector::setupMF(MachineFunction &MF, GISelKnownBits *KB, + CodeGenCoverage &CoverageInfo, + ProfileSummaryInfo *PSI, + BlockFrequencyInfo *BFI) { + InstructionSelector::setupMF(MF, KB, CoverageInfo, PSI, BFI); + MFReturnAddr = Register(); +} + bool M88kInstructionSelector::select(MachineInstr &I) { assert(I.getParent() && "Instruction should be in a basic block!"); assert(I.getParent()->getParent() && "Instruction should be in a function!"); @@ -628,6 +714,8 @@ bool M88kInstructionSelector::select(MachineInstr &I) { return true; switch (I.getOpcode()) { + case TargetOpcode::G_INTRINSIC: + return selectIntrinsic(I, MBB, MRI); case TargetOpcode::G_GLOBAL_VALUE: return selectGlobalValue(I, MBB, MRI); case TargetOpcode::G_UBFX: |