#define DEBUG_TYPE "hexagon-pei"
#include "HexagonFrameLowering.h"
-#include "Hexagon.h"
#include "HexagonInstrInfo.h"
#include "HexagonMachineFunctionInfo.h"
#include "HexagonRegisterInfo.h"
#include "HexagonTargetMachine.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/PostOrderIterator.h"
-#include "llvm/ADT/SCCIterator.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineDominators.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachinePostDominators.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
static cl::opt<bool> DisableDeallocRet("disable-hexagon-dealloc-ret",
cl::Hidden, cl::desc("Disable Dealloc Return for Hexagon target"));
-
static cl::opt<int> NumberScavengerSlots("number-scavenger-slots",
cl::Hidden, cl::desc("Set the number of scavenger slots"), cl::init(2),
cl::ZeroOrMore);
auto &HST = static_cast<const HexagonSubtarget&>(MF.getSubtarget());
auto &HRI = *HST.getRegisterInfo();
- assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
MachineFrameInfo *MFI = MF.getFrameInfo();
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
auto &MFI = *MF.getFrameInfo();
auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
- // Large parts of this code are shared with HRI::eliminateFrameIndex.
int Offset = MFI.getObjectOffset(FI);
bool HasAlloca = MFI.hasVarSizedObjects();
bool HasExtraAlign = HRI.needsStackRealignment(MF);
}
-/// Find a GPR register that's available in the range from It to any use of
-/// the 'spill' in FI.
-static bool findAvailableReg(int FI, MachineBasicBlock::iterator It,
- MachineBasicBlock::iterator End,
- unsigned *AvailReg,
- unsigned *NumUses,
- const TargetRegisterInfo *TRI,
- RegScavenger *Scavenger) {
- assert(Scavenger->getCurrentPosition() == It &&
- "Unexpected scavenger position!");
-
- BitVector Avail(Scavenger->getRegsAvailable(&Hexagon::IntRegsRegClass));
- if (Avail.none())
- return false;
-
- BitVector AvailByLastLoad(Avail.size());
-
- while (++It != End) {
- MachineInstr *MI = It;
- if (MI->isDebugValue())
- continue;
-
- // Remove all registers modified by this inst from Avail
- int Reg = Avail.find_first();
- while (Reg != -1) {
- if (MI->modifiesRegister(Reg, TRI))
- Avail[Reg] = false;
- else
- assert(!MI->readsRegister(Reg, TRI) && "Inst reads undefined register");
-
- Reg = Avail.find_next(Reg);
- }
-
- int Opc = MI->getOpcode();
- // Stop if we find a store that overwrites the current spill in FI
- if ((Opc == Hexagon::STriw_pred || Opc == Hexagon::STriw_mod) &&
- MI->getOperand(0).getIndex() == FI)
- break;
-
- if ((Opc == Hexagon::LDriw_pred || Opc == Hexagon::LDriw_mod) &&
- MI->getOperand(1).getIndex() == FI && !MI->getOperand(0).isDead()) {
- AvailByLastLoad = Avail;
- ++(*NumUses);
- }
-
- // Give up early if there are no registers available
- if (AvailByLastLoad.none() && Avail.none())
- break;
- }
-
- if (AvailByLastLoad.none())
- return false;
-
- *AvailReg = (unsigned) AvailByLastLoad.find_first();
- return true;
-}
-
-
-
-void HexagonFrameLowering::determineCalleeSaves(MachineFunction &MF,
- BitVector &SavedRegs,
- RegScavenger *RS) const {
- TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
-
- auto &HST = static_cast<const HexagonSubtarget&>(MF.getSubtarget());
- auto &HRI = *HST.getRegisterInfo();
-
- bool HasEHReturn = MF.getInfo<HexagonMachineFunctionInfo>()->hasEHReturn();
-
- // If we have a function containing __builtin_eh_return we want to spill and
- // restore all callee saved registers. Pretend that they are used.
- if (HasEHReturn) {
- for (const MCPhysReg *CSRegs = HRI.getCalleeSavedRegs(&MF); *CSRegs;
- ++CSRegs)
- SavedRegs.set(*CSRegs);
- }
-
- const TargetRegisterClass &RC = Hexagon::IntRegsRegClass;
-
- // Replace predicate register pseudo spill code.
- bool HasReplacedPseudoInst = replacePseudoRegTransferCode(MF);
-
- // We need to reserve a a spill slot if scavenging could potentially require
- // spilling a scavenged register.
- if (HasReplacedPseudoInst && needToReserveScavengingSpillSlots(MF, HRI)) {
- MachineFrameInfo *MFI = MF.getFrameInfo();
- for (int i = 0; i < NumberScavengerSlots; i++)
- RS->addScavengingFrameIndex(
- MFI->CreateSpillStackObject(RC.getSize(), RC.getAlignment()));
- }
-}
-
-
#ifndef NDEBUG
static void dump_registers(BitVector &Regs, const TargetRegisterInfo &TRI) {
dbgs() << '{';
}
-/// Expands pseudo instructions that copy/spill/restore registers that cannot
-/// have these operations done directly. For spills/restores, it will attempt
-/// to spill into a general-purpose register, instead of spilling to memory.
-bool HexagonFrameLowering::replacePseudoRegTransferCode(MachineFunction &MF)
- const {
- auto &HST = static_cast<const HexagonSubtarget&>(MF.getSubtarget());
+bool HexagonFrameLowering::expandCopy(MachineBasicBlock &B,
+ MachineBasicBlock::iterator It, MachineRegisterInfo &MRI,
+ const HexagonInstrInfo &HII, SmallVectorImpl<unsigned> &NewRegs) const {
+ MachineInstr *MI = &*It;
+ DebugLoc DL = MI->getDebugLoc();
+ unsigned DstR = MI->getOperand(0).getReg();
+ unsigned SrcR = MI->getOperand(1).getReg();
+ if (!Hexagon::ModRegsRegClass.contains(DstR) ||
+ !Hexagon::ModRegsRegClass.contains(SrcR))
+ return false;
+
+ unsigned TmpR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
+ BuildMI(B, It, DL, HII.get(TargetOpcode::COPY), TmpR)
+ .addOperand(MI->getOperand(1));
+ BuildMI(B, It, DL, HII.get(TargetOpcode::COPY), DstR)
+ .addReg(TmpR, RegState::Kill);
+
+ NewRegs.push_back(TmpR);
+ B.erase(It);
+ return true;
+}
+
+bool HexagonFrameLowering::expandStoreInt(MachineBasicBlock &B,
+ MachineBasicBlock::iterator It, MachineRegisterInfo &MRI,
+ const HexagonInstrInfo &HII, SmallVectorImpl<unsigned> &NewRegs) const {
+ MachineInstr *MI = &*It;
+ DebugLoc DL = MI->getDebugLoc();
+ unsigned Opc = MI->getOpcode();
+ unsigned SrcR = MI->getOperand(2).getReg();
+ bool IsKill = MI->getOperand(2).isKill();
+
+ assert(MI->getOperand(0).isFI() && "Expect a frame index");
+ int FI = MI->getOperand(0).getIndex();
+
+ // TmpR = C2_tfrpr SrcR if SrcR is a predicate register
+ // TmpR = A2_tfrcrr SrcR if SrcR is a modifier register
+ unsigned TmpR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
+ unsigned TfrOpc = (Opc == Hexagon::STriw_pred) ? Hexagon::C2_tfrpr
+ : Hexagon::A2_tfrcrr;
+ BuildMI(B, It, DL, HII.get(TfrOpc), TmpR)
+ .addReg(SrcR, getKillRegState(IsKill));
+
+ // S2_storeri_io FI, 0, TmpR
+ BuildMI(B, It, DL, HII.get(Hexagon::S2_storeri_io))
+ .addFrameIndex(FI)
+ .addImm(0)
+ .addReg(TmpR, RegState::Kill)
+ .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+
+ NewRegs.push_back(TmpR);
+ B.erase(It);
+ return true;
+}
+
+bool HexagonFrameLowering::expandLoadInt(MachineBasicBlock &B,
+ MachineBasicBlock::iterator It, MachineRegisterInfo &MRI,
+ const HexagonInstrInfo &HII, SmallVectorImpl<unsigned> &NewRegs) const {
+ MachineInstr *MI = &*It;
+ DebugLoc DL = MI->getDebugLoc();
+ unsigned Opc = MI->getOpcode();
+ unsigned DstR = MI->getOperand(0).getReg();
+
+ assert(MI->getOperand(1).isFI() && "Expect a frame index");
+ int FI = MI->getOperand(1).getIndex();
+
+ // TmpR = L2_loadri_io FI, 0
+ unsigned TmpR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
+ BuildMI(B, It, DL, HII.get(Hexagon::L2_loadri_io), TmpR)
+ .addFrameIndex(FI)
+ .addImm(0)
+ .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+
+ // DstR = C2_tfrrp TmpR if DstR is a predicate register
+ // DstR = A2_tfrrcr TmpR if DstR is a modifier register
+ unsigned TfrOpc = (Opc == Hexagon::LDriw_pred) ? Hexagon::C2_tfrrp
+ : Hexagon::A2_tfrrcr;
+ BuildMI(B, It, DL, HII.get(TfrOpc), DstR)
+ .addReg(TmpR, RegState::Kill);
+
+ NewRegs.push_back(TmpR);
+ B.erase(It);
+ return true;
+}
+
+
+bool HexagonFrameLowering::expandStoreVecPred(MachineBasicBlock &B,
+ MachineBasicBlock::iterator It, MachineRegisterInfo &MRI,
+ const HexagonInstrInfo &HII, SmallVectorImpl<unsigned> &NewRegs) const {
+ auto &HST = B.getParent()->getSubtarget<HexagonSubtarget>();
+ MachineInstr *MI = &*It;
+ DebugLoc DL = MI->getDebugLoc();
+ unsigned SrcR = MI->getOperand(2).getReg();
+ bool IsKill = MI->getOperand(2).isKill();
+
+ assert(MI->getOperand(0).isFI() && "Expect a frame index");
+ int FI = MI->getOperand(0).getIndex();
+
+ bool Is128B = HST.useHVXDblOps();
+ auto *RC = !Is128B ? &Hexagon::VectorRegsRegClass
+ : &Hexagon::VectorRegs128BRegClass;
+
+ // Insert transfer to general vector register.
+ // TmpR0 = A2_tfrsi 0x01010101
+ // TmpR1 = V6_vandqrt Qx, TmpR0
+ // store FI, 0, TmpR1
+ unsigned TmpR0 = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
+ unsigned TmpR1 = MRI.createVirtualRegister(RC);
+
+ BuildMI(B, It, DL, HII.get(Hexagon::A2_tfrsi), TmpR0)
+ .addImm(0x01010101);
+
+ unsigned VandOpc = !Is128B ? Hexagon::V6_vandqrt : Hexagon::V6_vandqrt_128B;
+ BuildMI(B, It, DL, HII.get(VandOpc), TmpR1)
+ .addReg(SrcR, getKillRegState(IsKill))
+ .addReg(TmpR0, RegState::Kill);
+
+ auto *HRI = B.getParent()->getSubtarget<HexagonSubtarget>().getRegisterInfo();
+ HII.storeRegToStackSlot(B, It, TmpR1, true, FI, RC, HRI);
+ expandStoreVec(B, std::prev(It), MRI, HII, NewRegs);
+
+ NewRegs.push_back(TmpR0);
+ NewRegs.push_back(TmpR1);
+ B.erase(It);
+ return true;
+}
+
+bool HexagonFrameLowering::expandLoadVecPred(MachineBasicBlock &B,
+ MachineBasicBlock::iterator It, MachineRegisterInfo &MRI,
+ const HexagonInstrInfo &HII, SmallVectorImpl<unsigned> &NewRegs) const {
+ auto &HST = B.getParent()->getSubtarget<HexagonSubtarget>();
+ MachineInstr *MI = &*It;
+ DebugLoc DL = MI->getDebugLoc();
+ unsigned DstR = MI->getOperand(0).getReg();
+
+ assert(MI->getOperand(1).isFI() && "Expect a frame index");
+ int FI = MI->getOperand(1).getIndex();
+
+ bool Is128B = HST.useHVXDblOps();
+ auto *RC = !Is128B ? &Hexagon::VectorRegsRegClass
+ : &Hexagon::VectorRegs128BRegClass;
+
+ // TmpR0 = A2_tfrsi 0x01010101
+ // TmpR1 = load FI, 0
+ // DstR = V6_vandvrt TmpR1, TmpR0
+ unsigned TmpR0 = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
+ unsigned TmpR1 = MRI.createVirtualRegister(RC);
+
+ BuildMI(B, It, DL, HII.get(Hexagon::A2_tfrsi), TmpR0)
+ .addImm(0x01010101);
+ auto *HRI = B.getParent()->getSubtarget<HexagonSubtarget>().getRegisterInfo();
+ HII.loadRegFromStackSlot(B, It, TmpR1, FI, RC, HRI);
+ expandLoadVec(B, std::prev(It), MRI, HII, NewRegs);
+
+ unsigned VandOpc = !Is128B ? Hexagon::V6_vandvrt : Hexagon::V6_vandvrt_128B;
+ BuildMI(B, It, DL, HII.get(VandOpc), DstR)
+ .addReg(TmpR1, RegState::Kill)
+ .addReg(TmpR0, RegState::Kill);
+
+ NewRegs.push_back(TmpR0);
+ NewRegs.push_back(TmpR1);
+ B.erase(It);
+ return true;
+}
+
+bool HexagonFrameLowering::expandStoreVec2(MachineBasicBlock &B,
+ MachineBasicBlock::iterator It, MachineRegisterInfo &MRI,
+ const HexagonInstrInfo &HII, SmallVectorImpl<unsigned> &NewRegs) const {
+ MachineFunction &MF = *B.getParent();
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
+ auto &MFI = *MF.getFrameInfo();
+ auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
+ MachineInstr *MI = &*It;
+ DebugLoc DL = MI->getDebugLoc();
+
+ unsigned SrcR = MI->getOperand(2).getReg();
+ unsigned SrcLo = HRI.getSubReg(SrcR, Hexagon::subreg_loreg);
+ unsigned SrcHi = HRI.getSubReg(SrcR, Hexagon::subreg_hireg);
+ bool IsKill = MI->getOperand(2).isKill();
+
+ assert(MI->getOperand(0).isFI() && "Expect a frame index");
+ int FI = MI->getOperand(0).getIndex();
+
+ bool Is128B = HST.useHVXDblOps();
+ auto *RC = !Is128B ? &Hexagon::VectorRegsRegClass
+ : &Hexagon::VectorRegs128BRegClass;
+ unsigned Size = RC->getSize();
+ unsigned NeedAlign = RC->getAlignment();
+ unsigned HasAlign = MFI.getObjectAlignment(FI);
+ unsigned StoreOpc;
+
+ // Store low part.
+ if (NeedAlign <= HasAlign)
+ StoreOpc = !Is128B ? Hexagon::V6_vS32b_ai : Hexagon::V6_vS32b_ai_128B;
+ else
+ StoreOpc = !Is128B ? Hexagon::V6_vS32Ub_ai : Hexagon::V6_vS32Ub_ai_128B;
+
+ BuildMI(B, It, DL, HII.get(StoreOpc))
+ .addFrameIndex(FI)
+ .addImm(0)
+ .addReg(SrcLo, getKillRegState(IsKill))
+ .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+
+ // Load high part.
+ if (NeedAlign <= MinAlign(HasAlign, Size))
+ StoreOpc = !Is128B ? Hexagon::V6_vS32b_ai : Hexagon::V6_vS32b_ai_128B;
+ else
+ StoreOpc = !Is128B ? Hexagon::V6_vS32Ub_ai : Hexagon::V6_vS32Ub_ai_128B;
+
+ BuildMI(B, It, DL, HII.get(StoreOpc))
+ .addFrameIndex(FI)
+ .addImm(Size)
+ .addReg(SrcHi, getKillRegState(IsKill))
+ .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+
+ B.erase(It);
+ return true;
+}
+
+bool HexagonFrameLowering::expandLoadVec2(MachineBasicBlock &B,
+ MachineBasicBlock::iterator It, MachineRegisterInfo &MRI,
+ const HexagonInstrInfo &HII, SmallVectorImpl<unsigned> &NewRegs) const {
+ MachineFunction &MF = *B.getParent();
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
+ auto &MFI = *MF.getFrameInfo();
+ auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
+ MachineInstr *MI = &*It;
+ DebugLoc DL = MI->getDebugLoc();
+
+ unsigned DstR = MI->getOperand(0).getReg();
+ unsigned DstHi = HRI.getSubReg(DstR, Hexagon::subreg_hireg);
+ unsigned DstLo = HRI.getSubReg(DstR, Hexagon::subreg_loreg);
+
+ assert(MI->getOperand(1).isFI() && "Expect a frame index");
+ int FI = MI->getOperand(1).getIndex();
+
+ bool Is128B = HST.useHVXDblOps();
+ auto *RC = !Is128B ? &Hexagon::VectorRegsRegClass
+ : &Hexagon::VectorRegs128BRegClass;
+ unsigned Size = RC->getSize();
+ unsigned NeedAlign = RC->getAlignment();
+ unsigned HasAlign = MFI.getObjectAlignment(FI);
+ unsigned LoadOpc;
+
+ // Load low part.
+ if (NeedAlign <= HasAlign)
+ LoadOpc = !Is128B ? Hexagon::V6_vL32b_ai : Hexagon::V6_vL32b_ai_128B;
+ else
+ LoadOpc = !Is128B ? Hexagon::V6_vL32Ub_ai : Hexagon::V6_vL32Ub_ai_128B;
+
+ BuildMI(B, It, DL, HII.get(LoadOpc), DstLo)
+ .addFrameIndex(FI)
+ .addImm(0)
+ .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+
+ // Load high part.
+ if (NeedAlign <= MinAlign(HasAlign, Size))
+ LoadOpc = !Is128B ? Hexagon::V6_vL32b_ai : Hexagon::V6_vL32b_ai_128B;
+ else
+ LoadOpc = !Is128B ? Hexagon::V6_vL32Ub_ai : Hexagon::V6_vL32Ub_ai_128B;
+
+ BuildMI(B, It, DL, HII.get(LoadOpc), DstHi)
+ .addFrameIndex(FI)
+ .addImm(Size)
+ .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+
+ B.erase(It);
+ return true;
+}
+
+bool HexagonFrameLowering::expandStoreVec(MachineBasicBlock &B,
+ MachineBasicBlock::iterator It, MachineRegisterInfo &MRI,
+ const HexagonInstrInfo &HII, SmallVectorImpl<unsigned> &NewRegs) const {
+ MachineFunction &MF = *B.getParent();
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
+ auto &MFI = *MF.getFrameInfo();
+ MachineInstr *MI = &*It;
+ DebugLoc DL = MI->getDebugLoc();
+
+ unsigned SrcR = MI->getOperand(2).getReg();
+ bool IsKill = MI->getOperand(2).isKill();
+
+ assert(MI->getOperand(0).isFI() && "Expect a frame index");
+ int FI = MI->getOperand(0).getIndex();
+
+ bool Is128B = HST.useHVXDblOps();
+ auto *RC = !Is128B ? &Hexagon::VectorRegsRegClass
+ : &Hexagon::VectorRegs128BRegClass;
+
+ unsigned NeedAlign = RC->getAlignment();
+ unsigned HasAlign = MFI.getObjectAlignment(FI);
+ unsigned StoreOpc;
+
+ if (NeedAlign <= HasAlign)
+ StoreOpc = !Is128B ? Hexagon::V6_vS32b_ai : Hexagon::V6_vS32b_ai_128B;
+ else
+ StoreOpc = !Is128B ? Hexagon::V6_vS32Ub_ai : Hexagon::V6_vS32Ub_ai_128B;
+
+ BuildMI(B, It, DL, HII.get(StoreOpc))
+ .addFrameIndex(FI)
+ .addImm(0)
+ .addReg(SrcR, getKillRegState(IsKill))
+ .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+
+ B.erase(It);
+ return true;
+}
+
+bool HexagonFrameLowering::expandLoadVec(MachineBasicBlock &B,
+ MachineBasicBlock::iterator It, MachineRegisterInfo &MRI,
+ const HexagonInstrInfo &HII, SmallVectorImpl<unsigned> &NewRegs) const {
+ MachineFunction &MF = *B.getParent();
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
+ auto &MFI = *MF.getFrameInfo();
+ MachineInstr *MI = &*It;
+ DebugLoc DL = MI->getDebugLoc();
+
+ unsigned DstR = MI->getOperand(0).getReg();
+
+ assert(MI->getOperand(1).isFI() && "Expect a frame index");
+ int FI = MI->getOperand(1).getIndex();
+
+ bool Is128B = HST.useHVXDblOps();
+ auto *RC = !Is128B ? &Hexagon::VectorRegsRegClass
+ : &Hexagon::VectorRegs128BRegClass;
+
+ unsigned NeedAlign = RC->getAlignment();
+ unsigned HasAlign = MFI.getObjectAlignment(FI);
+ unsigned LoadOpc;
+
+ if (NeedAlign <= HasAlign)
+ LoadOpc = !Is128B ? Hexagon::V6_vL32b_ai : Hexagon::V6_vL32b_ai_128B;
+ else
+ LoadOpc = !Is128B ? Hexagon::V6_vL32Ub_ai : Hexagon::V6_vL32Ub_ai_128B;
+
+ BuildMI(B, It, DL, HII.get(LoadOpc), DstR)
+ .addFrameIndex(FI)
+ .addImm(0)
+ .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+
+ B.erase(It);
+ return true;
+}
+
+
+bool HexagonFrameLowering::expandSpillMacros(MachineFunction &MF,
+ SmallVectorImpl<unsigned> &NewRegs) const {
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
auto &HII = *HST.getInstrInfo();
- auto &HRI = *HST.getRegisterInfo();
MachineRegisterInfo &MRI = MF.getRegInfo();
- bool HasReplacedPseudoInst = false;
-
- // We use the register scavenger purely for tracking of available registers
- // here, but do the 'scavenging' on our own.
- RegScavenger Scavenger;
-
- // Map from PredReg spill FIs to GPRs and remaining number of uses
- DenseMap<int,std::pair<unsigned, unsigned>> FItoRegUses;
-
- // PredReg FIs that cannot be 'spilled' into GPRs because they are live
- // across BB boundaries.
- SmallSet<int, 8> AlwaysSpill;
-
- // Pred Reg FIs that have been spilled in a block due to shortage of GPRs
- SmallSet<int, 8> LocallySpilled;
-
- // Do an SCC traversal of the MachineFunction. This is to make sure we detect
- // cases where a PredReg *must* be spilled to memory because it is live across
- // BasicBlock boundaries: we see the reload before the spill and can mark the
- // PredReg's FI in AlwaysSpill.
- for (auto It = scc_begin(&MF); !It.isAtEnd(); ++It) {
- const std::vector<MachineBasicBlock *> &Scc = *It;
- for (MachineBasicBlock *MBB : Scc) {
- if (MBB->empty())
- continue;
+ bool Changed = false;
- Scavenger.enterBasicBlock(MBB);
- Scavenger.forward();
-
- LocallySpilled.clear();
-
- // Traverse the basic block.
- MachineBasicBlock::iterator NextII;
- for (auto MII = MBB->begin(); MII != MBB->end(); MII = NextII) {
- MachineInstr *MI = MII;
- NextII = std::next(MII);
-
- assert(Scavenger.getCurrentPosition() == MII &&
- "Unexpected scavenger position");
-
- unsigned Opc = MI->getOpcode();
- DebugLoc DL = MI->getDebugLoc();
-
- if (Opc == TargetOpcode::COPY) {
- unsigned DestReg = MI->getOperand(0).getReg();
- unsigned SrcReg = MI->getOperand(1).getReg();
- MachineInstr *EraseMI = nullptr;
- if (Hexagon::ModRegsRegClass.contains(DestReg) &&
- Hexagon::ModRegsRegClass.contains(SrcReg)) {
- unsigned T = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
- BuildMI(*MBB, MII, DL, HII.get(TargetOpcode::COPY), T)
- .addOperand(MI->getOperand(1));
- BuildMI(*MBB, MII, DL, HII.get(TargetOpcode::COPY), DestReg)
- .addReg(T, RegState::Kill);
- EraseMI = &*MII;
- HasReplacedPseudoInst = true;
- }
- if (NextII != MBB->end())
- Scavenger.forward(); // Move to next instruction
- if (EraseMI)
- MBB->erase(EraseMI);
- } else if (Opc == Hexagon::STriw_pred || Opc == Hexagon::STriw_mod) {
- // STriw_pred FI, 0, SrcReg
- unsigned SrcReg = MI->getOperand(2).getReg();
- bool IsOrigSrcRegKilled = MI->getOperand(2).isKill();
-
- assert(MI->getOperand(0).isFI() && "Expect a frame index");
- assert((Hexagon::PredRegsRegClass.contains(SrcReg) ||
- Hexagon::ModRegsRegClass.contains(SrcReg)) &&
- "Not a predicate or modifier register");
- int FI = MI->getOperand(0).getIndex();
-
- assert(!FItoRegUses.count(FI) &&
- "Still expecting a load of this spilled predicate register!");
-
- // Check whether we have an available GPR here and all the way to the
- // reload(s) of this spill
- unsigned AvailReg, NumUses = 0;
- if (!AlwaysSpill.count(FI) && findAvailableReg(FI, MII, MBB->end(),
- &AvailReg, &NumUses, &HRI, &Scavenger)) {
- // Found a register we can move this into instead of spilling
- if (Opc == Hexagon::STriw_pred)
- BuildMI(*MBB, MII, MI->getDebugLoc(), HII.get(Hexagon::C2_tfrpr),
- AvailReg).addReg(SrcReg, getKillRegState(IsOrigSrcRegKilled));
- else
- BuildMI(*MBB, MII, MI->getDebugLoc(), HII.get(Hexagon::A2_tfrcrr),
- AvailReg).addReg(SrcReg, getKillRegState(IsOrigSrcRegKilled));
-
- // Mark the register as used in the function (important for callee
- // saved registers).
- BitVector UsedPhysRegsMask = MRI.getUsedPhysRegsMask();
- UsedPhysRegsMask.set(AvailReg);
- MRI.setUsedPhysRegMask(UsedPhysRegsMask);
-
- Scavenger.setRegUsed(AvailReg);
- if (NextII != MBB->end())
- Scavenger.forward();
-
- FItoRegUses[FI] = std::make_pair(AvailReg, NumUses);
- LocallySpilled.erase(FI);
-
- MBB->erase(MII);
- } else {
- // No register available. Insert actual spill.
- // VirtReg = C2_tfrpr SrcPredReg
- unsigned VirtReg =
- MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
- if (Opc == Hexagon::STriw_pred)
- BuildMI(*MBB, MII, MI->getDebugLoc(), HII.get(Hexagon::C2_tfrpr),
- VirtReg).addReg(SrcReg, getKillRegState(IsOrigSrcRegKilled));
- else
- BuildMI(*MBB, MII, MI->getDebugLoc(), HII.get(Hexagon::A2_tfrcrr),
- VirtReg).addReg(SrcReg, getKillRegState(IsOrigSrcRegKilled));
-
- // Change instruction to S2_storeri_io.
- // S2_storeri_io FI, 0, VirtReg
- MI->setDesc(HII.get(Hexagon::S2_storeri_io));
- MI->getOperand(2).setReg(VirtReg);
- MI->getOperand(2).setIsKill();
-
- HasReplacedPseudoInst = true;
-
- if (NextII != MBB->end())
- Scavenger.forward();
-
- if (!AlwaysSpill.count(FI))
- LocallySpilled.insert(FI);
- }
- } else if (Opc == Hexagon::LDriw_pred || Opc == Hexagon::LDriw_mod) {
- // DstReg = LDriw_pred FI, 0
- unsigned DestReg = MI->getOperand(0).getReg();
- assert(MI->getOperand(1).isFI() && "Expect a frame index");
- assert((Hexagon::PredRegsRegClass.contains(DestReg) ||
- Hexagon::ModRegsRegClass.contains(DestReg)) &&
- "Not a predicate or modifier register");
-
- int FI = MI->getOperand(1).getIndex();
-
- MachineOperand &M0 = MI->getOperand(0);
- if (M0.isDead()) {
- if (NextII != MBB->end())
- Scavenger.forward();
- MBB->erase(MII);
- continue;
- }
-
- if (FItoRegUses.count(FI)) {
- // Reload from GPR
- std::pair<unsigned,unsigned> &SpillInfo = FItoRegUses[FI];
-
- --SpillInfo.second;
- bool IsKill = SpillInfo.second == 0;
- if (Opc == Hexagon::LDriw_pred)
- BuildMI(*MBB, std::next(MII), MI->getDebugLoc(),
- HII.get(Hexagon::C2_tfrrp), DestReg).addReg(SpillInfo.first,
- getKillRegState(IsKill));
- else
- BuildMI(*MBB, std::next(MII), MI->getDebugLoc(),
- HII.get(Hexagon::A2_tfrrcr), DestReg).addReg(SpillInfo.first,
- getKillRegState(IsKill));
-
- if (IsKill)
- FItoRegUses.erase(FI);
-
- Scavenger.forward(); // Process the newly inserted instruction
- if (NextII != MBB->end())
- Scavenger.forward(); // Move to next instruction
-
- MBB->erase(MII);
- } else {
- // Reload from memory
-
- // If this wasn't spilled previously in this block, the PredReg in
- // this FI is live across blocks. Make sure it never ends up in a
- // register.
- if (!LocallySpilled.count(FI))
- AlwaysSpill.insert(FI);
-
- unsigned VirtReg =
- MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
-
- // Change instruction to L2_loadri_io.
- // VirtReg = L2_loadri_io FI, 0
- MI->setDesc(HII.get(Hexagon::L2_loadri_io));
- MI->getOperand(0).setReg(VirtReg);
-
- // Insert transfer to general purpose register.
- // DestReg = C2_tfrrp VirtReg
- if (Opc == Hexagon::LDriw_pred)
- BuildMI(*MBB, std::next(MII), MI->getDebugLoc(),
- HII.get(Hexagon::C2_tfrrp), DestReg).addReg(VirtReg,
- getKillRegState(true));
- else
- BuildMI(*MBB, std::next(MII), MI->getDebugLoc(),
- HII.get(Hexagon::A2_tfrrcr), DestReg).addReg(VirtReg,
- getKillRegState(true));
-
- Scavenger.forward(); // Process newly inserted instruction
- if (NextII != MBB->end())
- Scavenger.forward(); // Move to next instruction
-
- HasReplacedPseudoInst = true;
- }
- } else if (NextII != MBB->end())
- Scavenger.forward();
- }
+ for (auto &B : MF) {
+ // Traverse the basic block.
+ MachineBasicBlock::iterator NextI;
+ for (auto I = B.begin(), E = B.end(); I != E; I = NextI) {
+ MachineInstr *MI = &*I;
+ NextI = std::next(I);
+ unsigned Opc = MI->getOpcode();
- assert(FItoRegUses.empty() && "PredRegs in GPRs outlast this block!");
+ switch (Opc) {
+ case TargetOpcode::COPY:
+ Changed = expandCopy(B, I, MRI, HII, NewRegs);
+ break;
+ case Hexagon::STriw_pred:
+ case Hexagon::STriw_mod:
+ Changed = expandStoreInt(B, I, MRI, HII, NewRegs);
+ break;
+ case Hexagon::LDriw_pred:
+ case Hexagon::LDriw_mod:
+ Changed = expandLoadInt(B, I, MRI, HII, NewRegs);
+ break;
+ case Hexagon::STriq_pred_V6:
+ case Hexagon::STriq_pred_V6_128B:
+ Changed = expandStoreVecPred(B, I, MRI, HII, NewRegs);
+ break;
+ case Hexagon::LDriq_pred_V6:
+ case Hexagon::LDriq_pred_V6_128B:
+ Changed = expandLoadVecPred(B, I, MRI, HII, NewRegs);
+ break;
+ case Hexagon::LDrivv_pseudo_V6:
+ case Hexagon::LDrivv_pseudo_V6_128B:
+ Changed = expandLoadVec2(B, I, MRI, HII, NewRegs);
+ break;
+ case Hexagon::STrivv_pseudo_V6:
+ case Hexagon::STrivv_pseudo_V6_128B:
+ Changed = expandStoreVec2(B, I, MRI, HII, NewRegs);
+ break;
+ case Hexagon::STriv_pseudo_V6:
+ case Hexagon::STriv_pseudo_V6_128B:
+ Changed = expandStoreVec(B, I, MRI, HII, NewRegs);
+ break;
+ case Hexagon::LDriv_pseudo_V6:
+ case Hexagon::LDriv_pseudo_V6_128B:
+ Changed = expandLoadVec(B, I, MRI, HII, NewRegs);
+ break;
+ }
}
}
- return HasReplacedPseudoInst;
+ return Changed;
}
+void HexagonFrameLowering::determineCalleeSaves(MachineFunction &MF,
+ BitVector &SavedRegs,
+ RegScavenger *RS) const {
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
+ auto &HRI = *HST.getRegisterInfo();
+
+ SavedRegs.resize(HRI.getNumRegs());
+
+ // If we have a function containing __builtin_eh_return we want to spill and
+ // restore all callee saved registers. Pretend that they are used.
+ if (MF.getInfo<HexagonMachineFunctionInfo>()->hasEHReturn())
+ for (const MCPhysReg *R = HRI.getCalleeSavedRegs(&MF); *R; ++R)
+ SavedRegs.set(*R);
+
+ // Replace predicate register pseudo spill code.
+ SmallVector<unsigned,8> NewRegs;
+ expandSpillMacros(MF, NewRegs);
+
+
+ // We need to reserve a a spill slot if scavenging could potentially require
+ // spilling a scavenged register.
+ if (!NewRegs.empty() && needToReserveScavengingSpillSlots(MF, HRI)) {
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+ SetVector<const TargetRegisterClass*> SpillRCs;
+ for (unsigned VR : NewRegs)
+ SpillRCs.insert(MRI.getRegClass(VR));
+
+ MachineFrameInfo &MFI = *MF.getFrameInfo();
+ const TargetRegisterClass &IntRC = Hexagon::IntRegsRegClass;
+ if (SpillRCs.count(&IntRC)) {
+ for (int i = 0; i < NumberScavengerSlots; i++) {
+ int NewFI = MFI.CreateSpillStackObject(IntRC.getSize(),
+ IntRC.getAlignment());
+ RS->addScavengingFrameIndex(NewFI);
+ }
+ }
+ for (auto *RC : SpillRCs) {
+ if (RC == &IntRC)
+ continue;
+ int NewFI = MFI.CreateSpillStackObject(RC->getSize(), RC->getAlignment());
+ RS->addScavengingFrameIndex(NewFI);
+ }
+ }
+
+ TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
+}
+
void HexagonFrameLowering::expandAlloca(MachineInstr *AI,
const HexagonInstrInfo &HII, unsigned SP, unsigned CF) const {