summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp')
-rw-r--r--contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp333
1 files changed, 213 insertions, 120 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
index a3f6273..e5e7519 100644
--- a/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
+++ b/contrib/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
@@ -8,10 +8,8 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "hexagon-pei"
-
-#include "HexagonBlockRanges.h"
#include "HexagonFrameLowering.h"
+#include "HexagonBlockRanges.h"
#include "HexagonInstrInfo.h"
#include "HexagonMachineFunctionInfo.h"
#include "HexagonRegisterInfo.h"
@@ -63,6 +61,8 @@
#include <utility>
#include <vector>
+#define DEBUG_TYPE "hexagon-pei"
+
// Hexagon stack frame layout as defined by the ABI:
//
// Incoming arguments
@@ -178,8 +178,8 @@ static cl::opt<bool> EnableSaveRestoreLong("enable-save-restore-long",
cl::Hidden, cl::desc("Enable long calls for save-restore stubs."),
cl::init(false), cl::ZeroOrMore);
-static cl::opt<bool> UseAllocframe("use-allocframe", cl::init(true),
- cl::Hidden, cl::desc("Use allocframe more conservatively"));
+static cl::opt<bool> EliminateFramePointer("hexagon-fp-elim", cl::init(true),
+ cl::Hidden, cl::desc("Refrain from using FP whenever possible"));
static cl::opt<bool> OptimizeSpillSlots("hexagon-opt-spill", cl::Hidden,
cl::init(true), cl::desc("Optimize spill slots"));
@@ -301,16 +301,30 @@ static bool needsStackFrame(const MachineBasicBlock &MBB, const BitVector &CSR,
// the frame creation/destruction instructions.
if (MO.isFI())
return true;
- if (!MO.isReg())
- continue;
- unsigned R = MO.getReg();
- // Virtual registers will need scavenging, which then may require
- // a stack slot.
- if (TargetRegisterInfo::isVirtualRegister(R))
- return true;
- for (MCSubRegIterator S(R, &HRI, true); S.isValid(); ++S)
- if (CSR[*S])
+ if (MO.isReg()) {
+ unsigned R = MO.getReg();
+ // Virtual registers will need scavenging, which then may require
+ // a stack slot.
+ if (TargetRegisterInfo::isVirtualRegister(R))
return true;
+ for (MCSubRegIterator S(R, &HRI, true); S.isValid(); ++S)
+ if (CSR[*S])
+ return true;
+ continue;
+ }
+ if (MO.isRegMask()) {
+ // A regmask would normally have all callee-saved registers marked
+ // as preserved, so this check would not be needed, but in case of
+ // ever having other regmasks (for other calling conventions),
+ // make sure they would be processed correctly.
+ const uint32_t *BM = MO.getRegMask();
+ for (int x = CSR.find_first(); x >= 0; x = CSR.find_next(x)) {
+ unsigned R = x;
+ // If this regmask does not preserve a CSR, a frame will be needed.
+ if (!(BM[R/32] & (1u << (R%32))))
+ return true;
+ }
+ }
}
}
return false;
@@ -536,7 +550,6 @@ void HexagonFrameLowering::insertPrologueInBlock(MachineBasicBlock &MBB,
auto &HST = MF.getSubtarget<HexagonSubtarget>();
auto &HII = *HST.getInstrInfo();
auto &HRI = *HST.getRegisterInfo();
- DebugLoc dl;
unsigned MaxAlign = std::max(MFI.getMaxAlignment(), getStackAlignment());
@@ -570,77 +583,56 @@ void HexagonFrameLowering::insertPrologueInBlock(MachineBasicBlock &MBB,
MI->eraseFromParent();
}
- if (!hasFP(MF))
- return;
-
- // Check for overflow.
- // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used?
- const unsigned int ALLOCFRAME_MAX = 16384;
-
- // Create a dummy memory operand to avoid allocframe from being treated as
- // a volatile memory reference.
- MachineMemOperand *MMO =
- MF.getMachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOStore,
- 4, 4);
-
- if (NumBytes >= ALLOCFRAME_MAX) {
- // Emit allocframe(#0).
- BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
- .addImm(0)
- .addMemOperand(MMO);
+ DebugLoc dl = MBB.findDebugLoc(InsertPt);
- // Subtract offset from frame pointer.
- // We use a caller-saved non-parameter register for that.
- unsigned CallerSavedReg = HRI.getFirstCallerSavedNonParamReg();
- BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::CONST32),
- CallerSavedReg).addImm(NumBytes);
- BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_sub), SP)
+ if (hasFP(MF)) {
+ insertAllocframe(MBB, InsertPt, NumBytes);
+ if (AlignStack) {
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_andir), SP)
+ .addReg(SP)
+ .addImm(-int64_t(MaxAlign));
+ }
+ // If the stack-checking is enabled, and we spilled the callee-saved
+ // registers inline (i.e. did not use a spill function), then call
+ // the stack checker directly.
+ if (EnableStackOVFSanitizer && !PrologueStubs)
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::PS_call_stk))
+ .addExternalSymbol("__runtime_stack_check");
+ } else if (NumBytes > 0) {
+ assert(alignTo(NumBytes, 8) == NumBytes);
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
.addReg(SP)
- .addReg(CallerSavedReg);
- } else {
- BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
- .addImm(NumBytes)
- .addMemOperand(MMO);
- }
-
- if (AlignStack) {
- BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_andir), SP)
- .addReg(SP)
- .addImm(-int64_t(MaxAlign));
+ .addImm(-int(NumBytes));
}
-
- // If the stack-checking is enabled, and we spilled the callee-saved
- // registers inline (i.e. did not use a spill function), then call
- // the stack checker directly.
- if (EnableStackOVFSanitizer && !PrologueStubs)
- BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::PS_call_stk))
- .addExternalSymbol("__runtime_stack_check");
}
void HexagonFrameLowering::insertEpilogueInBlock(MachineBasicBlock &MBB) const {
MachineFunction &MF = *MBB.getParent();
- if (!hasFP(MF))
- return;
-
auto &HST = MF.getSubtarget<HexagonSubtarget>();
auto &HII = *HST.getInstrInfo();
auto &HRI = *HST.getRegisterInfo();
unsigned SP = HRI.getStackRegister();
+ MachineBasicBlock::iterator InsertPt = MBB.getFirstTerminator();
+ DebugLoc dl = MBB.findDebugLoc(InsertPt);
+
+ if (!hasFP(MF)) {
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ if (unsigned NumBytes = MFI.getStackSize()) {
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
+ .addReg(SP)
+ .addImm(NumBytes);
+ }
+ return;
+ }
+
MachineInstr *RetI = getReturn(MBB);
unsigned RetOpc = RetI ? RetI->getOpcode() : 0;
- MachineBasicBlock::iterator InsertPt = MBB.getFirstTerminator();
- DebugLoc DL;
- if (InsertPt != MBB.end())
- DL = InsertPt->getDebugLoc();
- else if (!MBB.empty())
- DL = std::prev(MBB.end())->getDebugLoc();
-
// Handle EH_RETURN.
if (RetOpc == Hexagon::EH_RETURN_JMPR) {
- BuildMI(MBB, InsertPt, DL, HII.get(Hexagon::L2_deallocframe));
- BuildMI(MBB, InsertPt, DL, HII.get(Hexagon::A2_add), SP)
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe));
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_add), SP)
.addReg(SP)
.addReg(Hexagon::R28);
return;
@@ -685,16 +677,52 @@ void HexagonFrameLowering::insertEpilogueInBlock(MachineBasicBlock &MBB) const {
// otherwise just add deallocframe. The function could be returning via a
// tail call.
if (RetOpc != Hexagon::PS_jmpret || DisableDeallocRet) {
- BuildMI(MBB, InsertPt, DL, HII.get(Hexagon::L2_deallocframe));
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe));
return;
}
unsigned NewOpc = Hexagon::L4_return;
- MachineInstr *NewI = BuildMI(MBB, RetI, DL, HII.get(NewOpc));
+ MachineInstr *NewI = BuildMI(MBB, RetI, dl, HII.get(NewOpc));
// Transfer the function live-out registers.
NewI->copyImplicitOps(MF, *RetI);
MBB.erase(RetI);
}
+void HexagonFrameLowering::insertAllocframe(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator InsertPt, unsigned NumBytes) const {
+ MachineFunction &MF = *MBB.getParent();
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
+ auto &HII = *HST.getInstrInfo();
+ auto &HRI = *HST.getRegisterInfo();
+
+ // Check for overflow.
+ // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used?
+ const unsigned int ALLOCFRAME_MAX = 16384;
+
+ // Create a dummy memory operand to avoid allocframe from being treated as
+ // a volatile memory reference.
+ auto *MMO = MF.getMachineMemOperand(MachinePointerInfo::getStack(MF, 0),
+ MachineMemOperand::MOStore, 4, 4);
+
+ DebugLoc dl = MBB.findDebugLoc(InsertPt);
+
+ if (NumBytes >= ALLOCFRAME_MAX) {
+ // Emit allocframe(#0).
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
+ .addImm(0)
+ .addMemOperand(MMO);
+
+ // Subtract the size from the stack pointer.
+ unsigned SP = HRI.getStackRegister();
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
+ .addReg(SP)
+ .addImm(-int(NumBytes));
+ } else {
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))
+ .addImm(NumBytes)
+ .addMemOperand(MMO);
+ }
+}
+
void HexagonFrameLowering::updateEntryPaths(MachineFunction &MF,
MachineBasicBlock &SaveB) const {
SetVector<unsigned> Worklist;
@@ -914,12 +942,11 @@ void HexagonFrameLowering::insertCFIInstructionsAt(MachineBasicBlock &MBB,
}
bool HexagonFrameLowering::hasFP(const MachineFunction &MF) const {
+ if (MF.getFunction()->hasFnAttribute(Attribute::Naked))
+ return false;
+
auto &MFI = MF.getFrameInfo();
auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
-
- bool HasFixed = MFI.getNumFixedObjects();
- bool HasPrealloc = const_cast<MachineFrameInfo&>(MFI)
- .getLocalFrameObjectCount();
bool HasExtraAlign = HRI.needsStackRealignment(MF);
bool HasAlloca = MFI.hasVarSizedObjects();
@@ -933,18 +960,23 @@ bool HexagonFrameLowering::hasFP(const MachineFunction &MF) const {
// By default we want to use SP (since it's always there). FP requires
// some setup (i.e. ALLOCFRAME).
- // Fixed and preallocated objects need FP if the distance from them to
- // the SP is unknown (as is with alloca or aligna).
- if ((HasFixed || HasPrealloc) && (HasAlloca || HasExtraAlign))
+ // Both, alloca and stack alignment modify the stack pointer by an
+ // undetermined value, so we need to save it at the entry to the function
+ // (i.e. use allocframe).
+ if (HasAlloca || HasExtraAlign)
return true;
if (MFI.getStackSize() > 0) {
- if (EnableStackOVFSanitizer || UseAllocframe)
+ // If FP-elimination is disabled, we have to use FP at this point.
+ const TargetMachine &TM = MF.getTarget();
+ if (TM.Options.DisableFramePointerElim(MF) || !EliminateFramePointer)
+ return true;
+ if (EnableStackOVFSanitizer)
return true;
}
- if (MFI.hasCalls() ||
- MF.getInfo<HexagonMachineFunctionInfo>()->hasClobberLR())
+ const auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>();
+ if (MFI.hasCalls() || HMFI.hasClobberLR())
return true;
return false;
@@ -1037,10 +1069,27 @@ int HexagonFrameLowering::getFrameIndexReference(const MachineFunction &MF,
bool HasExtraAlign = HRI.needsStackRealignment(MF);
bool NoOpt = MF.getTarget().getOptLevel() == CodeGenOpt::None;
- unsigned SP = HRI.getStackRegister(), FP = HRI.getFrameRegister();
auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>();
- unsigned AP = HMFI.getStackAlignBasePhysReg();
unsigned FrameSize = MFI.getStackSize();
+ unsigned SP = HRI.getStackRegister();
+ unsigned FP = HRI.getFrameRegister();
+ unsigned AP = HMFI.getStackAlignBasePhysReg();
+ // It may happen that AP will be absent even HasAlloca && HasExtraAlign
+ // is true. HasExtraAlign may be set because of vector spills, without
+ // aligned locals or aligned outgoing function arguments. Since vector
+ // spills will ultimately be "unaligned", it is safe to use FP as the
+ // base register.
+ // In fact, in such a scenario the stack is actually not required to be
+ // aligned, although it may end up being aligned anyway, since this
+ // particular case is not easily detectable. The alignment will be
+ // unnecessary, but not incorrect.
+ // Unfortunately there is no quick way to verify that the above is
+ // indeed the case (and that it's not a result of an error), so just
+ // assume that missing AP will be replaced by FP.
+ // (A better fix would be to rematerialize AP from FP and always align
+ // vector spills.)
+ if (AP == 0)
+ AP = FP;
bool UseFP = false, UseAP = false; // Default: use SP (except at -O0).
// Use FP at -O0, except when there are objects with extra alignment.
@@ -1105,7 +1154,7 @@ int HexagonFrameLowering::getFrameIndexReference(const MachineFunction &MF,
// there will be no SP -= FrameSize), so the frame size should not be
// added to the calculated offset.
int RealOffset = Offset;
- if (!UseFP && !UseAP && HasFP)
+ if (!UseFP && !UseAP)
RealOffset = FrameSize+Offset;
return RealOffset;
}
@@ -1411,7 +1460,7 @@ bool HexagonFrameLowering::assignCalleeSavedSpillSlots(MachineFunction &MF,
if (!SRegs[S->Reg])
continue;
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(S->Reg);
- int FI = MFI.CreateFixedSpillStackObject(RC->getSize(), S->Offset);
+ int FI = MFI.CreateFixedSpillStackObject(TRI->getSpillSize(*RC), S->Offset);
MinOffset = std::min(MinOffset, S->Offset);
CSI.push_back(CalleeSavedInfo(S->Reg, FI));
SRegs[S->Reg] = false;
@@ -1423,11 +1472,12 @@ bool HexagonFrameLowering::assignCalleeSavedSpillSlots(MachineFunction &MF,
for (int x = SRegs.find_first(); x >= 0; x = SRegs.find_next(x)) {
unsigned R = x;
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(R);
- int Off = MinOffset - RC->getSize();
- unsigned Align = std::min(RC->getAlignment(), getStackAlignment());
+ unsigned Size = TRI->getSpillSize(*RC);
+ int Off = MinOffset - Size;
+ unsigned Align = std::min(TRI->getSpillAlignment(*RC), getStackAlignment());
assert(isPowerOf2_32(Align));
Off &= -Align;
- int FI = MFI.CreateFixedSpillStackObject(RC->getSize(), Off);
+ int FI = MFI.CreateFixedSpillStackObject(Size, Off);
MinOffset = std::min(MinOffset, Off);
CSI.push_back(CalleeSavedInfo(R, FI));
SRegs[R] = false;
@@ -1473,8 +1523,7 @@ bool HexagonFrameLowering::expandCopy(MachineBasicBlock &B,
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), TmpR).add(MI->getOperand(1));
BuildMI(B, It, DL, HII.get(TargetOpcode::COPY), DstR)
.addReg(TmpR, RegState::Kill);
@@ -1643,11 +1692,18 @@ bool HexagonFrameLowering::expandStoreVec2(MachineBasicBlock &B,
// defined. From the point of view of the liveness tracking, it is ok to
// store it as a whole, but if we break it up we may end up storing a
// register that is entirely undefined.
- LivePhysRegs LPR(&HRI);
+ LivePhysRegs LPR(HRI);
LPR.addLiveIns(B);
SmallVector<std::pair<unsigned, const MachineOperand*>,2> Clobbers;
- for (auto R = B.begin(); R != It; ++R)
+ for (auto R = B.begin(); R != It; ++R) {
+ Clobbers.clear();
LPR.stepForward(*R, Clobbers);
+ // Dead defs are recorded in Clobbers, but are not automatically removed
+ // from the live set.
+ for (auto &C : Clobbers)
+ if (C.second->isReg() && C.second->isDead())
+ LPR.removeReg(C.first);
+ }
DebugLoc DL = MI->getDebugLoc();
unsigned SrcR = MI->getOperand(2).getReg();
@@ -1657,10 +1713,10 @@ bool HexagonFrameLowering::expandStoreVec2(MachineBasicBlock &B,
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();
+ const auto &RC = !Is128B ? Hexagon::VectorRegsRegClass
+ : Hexagon::VectorRegs128BRegClass;
+ unsigned Size = HRI.getSpillSize(RC);
+ unsigned NeedAlign = HRI.getSpillAlignment(RC);
unsigned HasAlign = MFI.getObjectAlignment(FI);
unsigned StoreOpc;
@@ -1714,10 +1770,10 @@ bool HexagonFrameLowering::expandLoadVec2(MachineBasicBlock &B,
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();
+ const auto &RC = !Is128B ? Hexagon::VectorRegsRegClass
+ : Hexagon::VectorRegs128BRegClass;
+ unsigned Size = HRI.getSpillSize(RC);
+ unsigned NeedAlign = HRI.getSpillAlignment(RC);
unsigned HasAlign = MFI.getObjectAlignment(FI);
unsigned LoadOpc;
@@ -1757,16 +1813,16 @@ bool HexagonFrameLowering::expandStoreVec(MachineBasicBlock &B,
if (!MI->getOperand(0).isFI())
return false;
+ auto &HRI = *HST.getRegisterInfo();
DebugLoc DL = MI->getDebugLoc();
unsigned SrcR = MI->getOperand(2).getReg();
bool IsKill = MI->getOperand(2).isKill();
int FI = MI->getOperand(0).getIndex();
bool Is128B = HST.useHVXDblOps();
- auto *RC = !Is128B ? &Hexagon::VectorRegsRegClass
- : &Hexagon::VectorRegs128BRegClass;
-
- unsigned NeedAlign = RC->getAlignment();
+ const auto &RC = !Is128B ? Hexagon::VectorRegsRegClass
+ : Hexagon::VectorRegs128BRegClass;
+ unsigned NeedAlign = HRI.getSpillAlignment(RC);
unsigned HasAlign = MFI.getObjectAlignment(FI);
unsigned StoreOpc;
@@ -1795,15 +1851,15 @@ bool HexagonFrameLowering::expandLoadVec(MachineBasicBlock &B,
if (!MI->getOperand(1).isFI())
return false;
+ auto &HRI = *HST.getRegisterInfo();
DebugLoc DL = MI->getDebugLoc();
unsigned DstR = MI->getOperand(0).getReg();
int FI = MI->getOperand(1).getIndex();
bool Is128B = HST.useHVXDblOps();
- auto *RC = !Is128B ? &Hexagon::VectorRegsRegClass
- : &Hexagon::VectorRegs128BRegClass;
-
- unsigned NeedAlign = RC->getAlignment();
+ const auto &RC = !Is128B ? Hexagon::VectorRegsRegClass
+ : Hexagon::VectorRegs128BRegClass;
+ unsigned NeedAlign = HRI.getSpillAlignment(RC);
unsigned HasAlign = MFI.getObjectAlignment(FI);
unsigned LoadOpc;
@@ -1912,7 +1968,7 @@ void HexagonFrameLowering::determineCalleeSaves(MachineFunction &MF,
if (!needToReserveScavengingSpillSlots(MF, HRI, RC))
continue;
unsigned Num = RC == &Hexagon::IntRegsRegClass ? NumberScavengerSlots : 1;
- unsigned S = RC->getSize(), A = RC->getAlignment();
+ unsigned S = HRI.getSpillSize(*RC), A = HRI.getSpillAlignment(*RC);
for (unsigned i = 0; i < Num; i++) {
int NewFI = MFI.CreateSpillStackObject(S, A);
RS->addScavengingFrameIndex(NewFI);
@@ -1985,9 +2041,9 @@ void HexagonFrameLowering::optimizeSpillSlots(MachineFunction &MF,
// class HaveRC and a new class NewRC. Return nullptr if a common class
// cannot be found, otherwise return the resulting class. If HaveRC is
// nullptr, assume that it is still unset.
- auto getCommonRC = [&HRI] (const TargetRegisterClass *HaveRC,
- const TargetRegisterClass *NewRC)
- -> const TargetRegisterClass* {
+ auto getCommonRC =
+ [](const TargetRegisterClass *HaveRC,
+ const TargetRegisterClass *NewRC) -> const TargetRegisterClass * {
if (HaveRC == nullptr || HaveRC == NewRC)
return NewRC;
// Different classes, both non-null. Pick the more general one.
@@ -2221,7 +2277,7 @@ void HexagonFrameLowering::optimizeSpillSlots(MachineFunction &MF,
if (SrcRR.Reg != FoundR || SrcRR.Sub != 0) {
const DebugLoc &DL = SI.getDebugLoc();
CopyIn = BuildMI(B, StartIt, DL, HII.get(TargetOpcode::COPY), FoundR)
- .addOperand(SrcOp);
+ .add(SrcOp);
}
++StartIt;
@@ -2365,10 +2421,12 @@ void HexagonFrameLowering::addCalleeSaveRegistersAsImpOperand(MachineInstr *MI,
/// be generated via inline code. If this function returns "true", inline
/// code will be generated. If this function returns "false", additional
/// checks are performed, which may still lead to the inline code.
-bool HexagonFrameLowering::shouldInlineCSR(MachineFunction &MF,
+bool HexagonFrameLowering::shouldInlineCSR(const MachineFunction &MF,
const CSIVect &CSI) const {
if (MF.getInfo<HexagonMachineFunctionInfo>()->hasEHReturn())
return true;
+ if (!hasFP(MF))
+ return true;
if (!isOptSize(MF) && !isMinSize(MF))
if (MF.getTarget().getOptLevel() > CodeGenOpt::Default)
return true;
@@ -2395,7 +2453,7 @@ bool HexagonFrameLowering::shouldInlineCSR(MachineFunction &MF,
return false;
}
-bool HexagonFrameLowering::useSpillFunction(MachineFunction &MF,
+bool HexagonFrameLowering::useSpillFunction(const MachineFunction &MF,
const CSIVect &CSI) const {
if (shouldInlineCSR(MF, CSI))
return false;
@@ -2408,7 +2466,7 @@ bool HexagonFrameLowering::useSpillFunction(MachineFunction &MF,
return Threshold < NumCSI;
}
-bool HexagonFrameLowering::useRestoreFunction(MachineFunction &MF,
+bool HexagonFrameLowering::useRestoreFunction(const MachineFunction &MF,
const CSIVect &CSI) const {
if (shouldInlineCSR(MF, CSI))
return false;
@@ -2433,9 +2491,44 @@ bool HexagonFrameLowering::mayOverflowFrameOffset(MachineFunction &MF) const {
unsigned StackSize = MF.getFrameInfo().estimateStackSize(MF);
auto &HST = MF.getSubtarget<HexagonSubtarget>();
// A fairly simplistic guess as to whether a potential load/store to a
- // stack location could require an extra register. It does not account
- // for store-immediate instructions.
- if (HST.useHVXOps())
- return StackSize > 256;
+ // stack location could require an extra register.
+ if (HST.useHVXOps() && StackSize > 256)
+ return true;
+
+ // Check if the function has store-immediate instructions that access
+ // the stack. Since the offset field is not extendable, if the stack
+ // size exceeds the offset limit (6 bits, shifted), the stores will
+ // require a new base register.
+ bool HasImmStack = false;
+ unsigned MinLS = ~0u; // Log_2 of the memory access size.
+
+ for (const MachineBasicBlock &B : MF) {
+ for (const MachineInstr &MI : B) {
+ unsigned LS = 0;
+ switch (MI.getOpcode()) {
+ case Hexagon::S4_storeirit_io:
+ case Hexagon::S4_storeirif_io:
+ case Hexagon::S4_storeiri_io:
+ ++LS;
+ LLVM_FALLTHROUGH;
+ case Hexagon::S4_storeirht_io:
+ case Hexagon::S4_storeirhf_io:
+ case Hexagon::S4_storeirh_io:
+ ++LS;
+ LLVM_FALLTHROUGH;
+ case Hexagon::S4_storeirbt_io:
+ case Hexagon::S4_storeirbf_io:
+ case Hexagon::S4_storeirb_io:
+ if (MI.getOperand(0).isFI())
+ HasImmStack = true;
+ MinLS = std::min(MinLS, LS);
+ break;
+ }
+ }
+ }
+
+ if (HasImmStack)
+ return !isUInt<6>(StackSize >> MinLS);
+
return false;
}
OpenPOWER on IntegriCloud