mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-02 00:35:27 +00:00
[Hexagon] Replace expansion of spill pseudo-instructions in frame lowering
Rewrite the code to handle all pseudo-instructions in a single pass. This temporarily reverts spill slot optimization that used general- purpose registers to hold values of spilled predicate registers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@260696 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e049aa6ae3
commit
c006b1e101
@ -11,7 +11,6 @@
|
||||
#define DEBUG_TYPE "hexagon-pei"
|
||||
|
||||
#include "HexagonFrameLowering.h"
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonInstrInfo.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include "HexagonRegisterInfo.h"
|
||||
@ -19,13 +18,11 @@
|
||||
#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"
|
||||
@ -127,7 +124,6 @@ using namespace llvm;
|
||||
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);
|
||||
@ -397,7 +393,6 @@ void HexagonFrameLowering::emitPrologue(MachineFunction &MF,
|
||||
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();
|
||||
|
||||
@ -831,7 +826,6 @@ int HexagonFrameLowering::getFrameIndexReference(const MachineFunction &MF,
|
||||
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);
|
||||
@ -1073,99 +1067,6 @@ static bool needToReserveScavengingSpillSlots(MachineFunction &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() << '{';
|
||||
@ -1313,230 +1214,456 @@ bool HexagonFrameLowering::assignCalleeSavedSpillSlots(MachineFunction &MF,
|
||||
}
|
||||
|
||||
|
||||
/// 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;
|
||||
bool Changed = false;
|
||||
|
||||
// We use the register scavenger purely for tracking of available registers
|
||||
// here, but do the 'scavenging' on our own.
|
||||
RegScavenger Scavenger;
|
||||
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();
|
||||
|
||||
// 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;
|
||||
|
||||
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();
|
||||
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;
|
||||
}
|
||||
|
||||
assert(FItoRegUses.empty() && "PredRegs in GPRs outlast this block!");
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -44,19 +44,19 @@ public:
|
||||
void eliminateCallFramePseudoInstr(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override;
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF,
|
||||
RegScavenger *RS = nullptr) const override;
|
||||
RegScavenger *RS = nullptr) const override;
|
||||
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
|
||||
RegScavenger *RS) const override;
|
||||
RegScavenger *RS) const override;
|
||||
|
||||
bool targetHandlesStackFrameRounding() const override {
|
||||
return true;
|
||||
}
|
||||
int getFrameIndexReference(const MachineFunction &MF, int FI,
|
||||
unsigned &FrameReg) const override;
|
||||
unsigned &FrameReg) const override;
|
||||
bool hasFP(const MachineFunction &MF) const override;
|
||||
|
||||
const SpillSlot *getCalleeSavedSpillSlots(unsigned &NumEntries)
|
||||
const override {
|
||||
const override {
|
||||
static const SpillSlot Offsets[] = {
|
||||
{ Hexagon::R17, -4 }, { Hexagon::R16, -8 }, { Hexagon::D8, -8 },
|
||||
{ Hexagon::R19, -12 }, { Hexagon::R18, -16 }, { Hexagon::D9, -16 },
|
||||
@ -93,8 +93,36 @@ private:
|
||||
MachineBasicBlock::iterator At) const;
|
||||
|
||||
void adjustForCalleeSavedRegsSpillCall(MachineFunction &MF) const;
|
||||
bool replacePseudoRegTransferCode(MachineFunction &MF) const;
|
||||
bool replaceVecPredRegPseudoSpillCode(MachineFunction &MF) const;
|
||||
|
||||
bool expandCopy(MachineBasicBlock &B, MachineBasicBlock::iterator It,
|
||||
MachineRegisterInfo &MRI, const HexagonInstrInfo &HII,
|
||||
SmallVectorImpl<unsigned> &NewRegs) const;
|
||||
bool expandStoreInt(MachineBasicBlock &B, MachineBasicBlock::iterator It,
|
||||
MachineRegisterInfo &MRI, const HexagonInstrInfo &HII,
|
||||
SmallVectorImpl<unsigned> &NewRegs) const;
|
||||
bool expandLoadInt(MachineBasicBlock &B, MachineBasicBlock::iterator It,
|
||||
MachineRegisterInfo &MRI, const HexagonInstrInfo &HII,
|
||||
SmallVectorImpl<unsigned> &NewRegs) const;
|
||||
bool expandStoreVecPred(MachineBasicBlock &B, MachineBasicBlock::iterator It,
|
||||
MachineRegisterInfo &MRI, const HexagonInstrInfo &HII,
|
||||
SmallVectorImpl<unsigned> &NewRegs) const;
|
||||
bool expandLoadVecPred(MachineBasicBlock &B, MachineBasicBlock::iterator It,
|
||||
MachineRegisterInfo &MRI, const HexagonInstrInfo &HII,
|
||||
SmallVectorImpl<unsigned> &NewRegs) const;
|
||||
bool expandStoreVec2(MachineBasicBlock &B, MachineBasicBlock::iterator It,
|
||||
MachineRegisterInfo &MRI, const HexagonInstrInfo &HII,
|
||||
SmallVectorImpl<unsigned> &NewRegs) const;
|
||||
bool expandLoadVec2(MachineBasicBlock &B, MachineBasicBlock::iterator It,
|
||||
MachineRegisterInfo &MRI, const HexagonInstrInfo &HII,
|
||||
SmallVectorImpl<unsigned> &NewRegs) const;
|
||||
bool expandStoreVec(MachineBasicBlock &B, MachineBasicBlock::iterator It,
|
||||
MachineRegisterInfo &MRI, const HexagonInstrInfo &HII,
|
||||
SmallVectorImpl<unsigned> &NewRegs) const;
|
||||
bool expandLoadVec(MachineBasicBlock &B, MachineBasicBlock::iterator It,
|
||||
MachineRegisterInfo &MRI, const HexagonInstrInfo &HII,
|
||||
SmallVectorImpl<unsigned> &NewRegs) const;
|
||||
bool expandSpillMacros(MachineFunction &MF,
|
||||
SmallVectorImpl<unsigned> &NewRegs) const;
|
||||
|
||||
void findShrunkPrologEpilog(MachineFunction &MF, MachineBasicBlock *&PrologB,
|
||||
MachineBasicBlock *&EpilogB) const;
|
||||
|
@ -1,3 +1,6 @@
|
||||
; This functionality will be restored shortly.
|
||||
; XFAIL: *
|
||||
|
||||
; RUN: llc -march=hexagon -O2 < %s | FileCheck %s
|
||||
;
|
||||
; This checks that predicate registers are moved to GPRs instead of spilling
|
||||
|
Loading…
x
Reference in New Issue
Block a user