aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp275
1 files changed, 213 insertions, 62 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
index aff8e57b0a94..010b7171ce17 100644
--- a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
@@ -261,20 +261,20 @@ static unsigned getMax32BitSubRegister(unsigned Reg,
}
/// Returns the callee saved register with the largest id in the vector.
-static unsigned getMaxCalleeSavedReg(const std::vector<CalleeSavedInfo> &CSI,
+static unsigned getMaxCalleeSavedReg(ArrayRef<CalleeSavedInfo> CSI,
const TargetRegisterInfo &TRI) {
- static_assert(Hexagon::R1 > 0,
- "Assume physical registers are encoded as positive integers");
- if (CSI.empty())
- return 0;
-
- unsigned Max = getMax32BitSubRegister(CSI[0].getReg(), TRI);
- for (unsigned I = 1, E = CSI.size(); I < E; ++I) {
- unsigned Reg = getMax32BitSubRegister(CSI[I].getReg(), TRI);
- if (Reg > Max)
- Max = Reg;
- }
- return Max;
+ static_assert(Hexagon::R1 > 0,
+ "Assume physical registers are encoded as positive integers");
+ if (CSI.empty())
+ return 0;
+
+ unsigned Max = getMax32BitSubRegister(CSI[0].getReg(), TRI);
+ for (unsigned I = 1, E = CSI.size(); I < E; ++I) {
+ unsigned Reg = getMax32BitSubRegister(CSI[I].getReg(), TRI);
+ if (Reg > Max)
+ Max = Reg;
+ }
+ return Max;
}
/// Checks if the basic block contains any instruction that needs a stack
@@ -395,6 +395,9 @@ void HexagonFrameLowering::findShrunkPrologEpilog(MachineFunction &MF,
MachineBasicBlock *&PrologB, MachineBasicBlock *&EpilogB) const {
static unsigned ShrinkCounter = 0;
+ if (MF.getSubtarget<HexagonSubtarget>().isEnvironmentMusl() &&
+ MF.getFunction().isVarArg())
+ return;
if (ShrinkLimit.getPosition()) {
if (ShrinkCounter >= ShrinkLimit)
return;
@@ -588,7 +591,7 @@ void HexagonFrameLowering::insertPrologueInBlock(MachineBasicBlock &MBB,
auto &HII = *HST.getInstrInfo();
auto &HRI = *HST.getRegisterInfo();
- unsigned MaxAlign = std::max(MFI.getMaxAlignment(), getStackAlignment());
+ Align MaxAlign = std::max(MFI.getMaxAlign(), getStackAlign());
// Calculate the total stack frame size.
// Get the number of bytes to allocate from the FrameInfo.
@@ -600,7 +603,7 @@ void HexagonFrameLowering::insertPrologueInBlock(MachineBasicBlock &MBB,
FrameSize = MaxCFA + alignTo(FrameSize, MaxAlign);
MFI.setStackSize(FrameSize);
- bool AlignStack = (MaxAlign > getStackAlignment());
+ bool AlignStack = (MaxAlign > getStackAlign());
// Get the number of bytes to allocate from the FrameInfo.
unsigned NumBytes = MFI.getStackSize();
@@ -622,12 +625,124 @@ void HexagonFrameLowering::insertPrologueInBlock(MachineBasicBlock &MBB,
DebugLoc dl = MBB.findDebugLoc(InsertPt);
+ if (MF.getFunction().isVarArg() &&
+ MF.getSubtarget<HexagonSubtarget>().isEnvironmentMusl()) {
+ // Calculate the size of register saved area.
+ int NumVarArgRegs = 6 - FirstVarArgSavedReg;
+ int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0)
+ ? NumVarArgRegs * 4
+ : NumVarArgRegs * 4 + 4;
+ if (RegisterSavedAreaSizePlusPadding > 0) {
+ // Decrement the stack pointer by size of register saved area plus
+ // padding if any.
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
+ .addReg(SP)
+ .addImm(-RegisterSavedAreaSizePlusPadding)
+ .setMIFlag(MachineInstr::FrameSetup);
+
+ int NumBytes = 0;
+ // Copy all the named arguments below register saved area.
+ auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>();
+ for (int i = HMFI.getFirstNamedArgFrameIndex(),
+ e = HMFI.getLastNamedArgFrameIndex(); i >= e; --i) {
+ uint64_t ObjSize = MFI.getObjectSize(i);
+ Align ObjAlign = MFI.getObjectAlign(i);
+
+ // Determine the kind of load/store that should be used.
+ unsigned LDOpc, STOpc;
+ uint64_t OpcodeChecker = ObjAlign.value();
+
+ // Handle cases where alignment of an object is > its size.
+ if (ObjAlign > ObjSize) {
+ if (ObjSize <= 1)
+ OpcodeChecker = 1;
+ else if (ObjSize <= 2)
+ OpcodeChecker = 2;
+ else if (ObjSize <= 4)
+ OpcodeChecker = 4;
+ else if (ObjSize > 4)
+ OpcodeChecker = 8;
+ }
+
+ switch (OpcodeChecker) {
+ case 1:
+ LDOpc = Hexagon::L2_loadrb_io;
+ STOpc = Hexagon::S2_storerb_io;
+ break;
+ case 2:
+ LDOpc = Hexagon::L2_loadrh_io;
+ STOpc = Hexagon::S2_storerh_io;
+ break;
+ case 4:
+ LDOpc = Hexagon::L2_loadri_io;
+ STOpc = Hexagon::S2_storeri_io;
+ break;
+ case 8:
+ default:
+ LDOpc = Hexagon::L2_loadrd_io;
+ STOpc = Hexagon::S2_storerd_io;
+ break;
+ }
+
+ unsigned RegUsed = LDOpc == Hexagon::L2_loadrd_io ? Hexagon::D3
+ : Hexagon::R6;
+ int LoadStoreCount = ObjSize / OpcodeChecker;
+
+ if (ObjSize % OpcodeChecker)
+ ++LoadStoreCount;
+
+ // Get the start location of the load. NumBytes is basically the
+ // offset from the stack pointer of previous function, which would be
+ // the caller in this case, as this function has variable argument
+ // list.
+ if (NumBytes != 0)
+ NumBytes = alignTo(NumBytes, ObjAlign);
+
+ int Count = 0;
+ while (Count < LoadStoreCount) {
+ // Load the value of the named argument on stack.
+ BuildMI(MBB, InsertPt, dl, HII.get(LDOpc), RegUsed)
+ .addReg(SP)
+ .addImm(RegisterSavedAreaSizePlusPadding +
+ ObjAlign.value() * Count + NumBytes)
+ .setMIFlag(MachineInstr::FrameSetup);
+
+ // Store it below the register saved area plus padding.
+ BuildMI(MBB, InsertPt, dl, HII.get(STOpc))
+ .addReg(SP)
+ .addImm(ObjAlign.value() * Count + NumBytes)
+ .addReg(RegUsed)
+ .setMIFlag(MachineInstr::FrameSetup);
+
+ Count++;
+ }
+ NumBytes += MFI.getObjectSize(i);
+ }
+
+ // Make NumBytes 8 byte aligned
+ NumBytes = alignTo(NumBytes, 8);
+
+ // If the number of registers having variable arguments is odd,
+ // leave 4 bytes of padding to get to the location where first
+ // variable argument which was passed through register was copied.
+ NumBytes = (NumVarArgRegs % 2 == 0) ? NumBytes : NumBytes + 4;
+
+ for (int j = FirstVarArgSavedReg, i = 0; j < 6; ++j, ++i) {
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::S2_storeri_io))
+ .addReg(SP)
+ .addImm(NumBytes + 4 * i)
+ .addReg(Hexagon::R0 + j)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
+ }
+ }
+
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));
+ .addImm(-int64_t(MaxAlign.value()));
}
// If the stack-checking is enabled, and we spilled the callee-saved
// registers inline (i.e. did not use a spill function), then call
@@ -655,7 +770,16 @@ void HexagonFrameLowering::insertEpilogueInBlock(MachineBasicBlock &MBB) const {
if (!hasFP(MF)) {
MachineFrameInfo &MFI = MF.getFrameInfo();
- if (unsigned NumBytes = MFI.getStackSize()) {
+ unsigned NumBytes = MFI.getStackSize();
+ if (MF.getFunction().isVarArg() &&
+ MF.getSubtarget<HexagonSubtarget>().isEnvironmentMusl()) {
+ // On Hexagon Linux, deallocate the stack for the register saved area.
+ int NumVarArgRegs = 6 - FirstVarArgSavedReg;
+ int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?
+ (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);
+ NumBytes += RegisterSavedAreaSizePlusPadding;
+ }
+ if (NumBytes) {
BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
.addReg(SP)
.addImm(NumBytes);
@@ -710,24 +834,49 @@ void HexagonFrameLowering::insertEpilogueInBlock(MachineBasicBlock &MBB) const {
NeedsDeallocframe = false;
}
- if (!NeedsDeallocframe)
- return;
- // If the returning instruction is PS_jmpret, replace it with dealloc_return,
- // 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))
+ if (!MF.getSubtarget<HexagonSubtarget>().isEnvironmentMusl() ||
+ !MF.getFunction().isVarArg()) {
+ if (!NeedsDeallocframe)
+ return;
+ // If the returning instruction is PS_jmpret, replace it with
+ // dealloc_return, 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))
.addDef(Hexagon::D15)
.addReg(Hexagon::R30);
- return;
- }
- unsigned NewOpc = Hexagon::L4_return;
- MachineInstr *NewI = BuildMI(MBB, RetI, dl, HII.get(NewOpc))
+ return;
+ }
+ unsigned NewOpc = Hexagon::L4_return;
+ MachineInstr *NewI = BuildMI(MBB, RetI, dl, HII.get(NewOpc))
.addDef(Hexagon::D15)
.addReg(Hexagon::R30);
- // Transfer the function live-out registers.
- NewI->copyImplicitOps(MF, *RetI);
- MBB.erase(RetI);
+ // Transfer the function live-out registers.
+ NewI->copyImplicitOps(MF, *RetI);
+ MBB.erase(RetI);
+ } else {
+ // L2_deallocframe instruction after it.
+ // Calculate the size of register saved area.
+ int NumVarArgRegs = 6 - FirstVarArgSavedReg;
+ int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?
+ (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);
+
+ MachineBasicBlock::iterator Term = MBB.getFirstTerminator();
+ MachineBasicBlock::iterator I = (Term == MBB.begin()) ? MBB.end()
+ : std::prev(Term);
+ if (I == MBB.end() ||
+ (I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT &&
+ I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC &&
+ I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4 &&
+ I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC))
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))
+ .addDef(Hexagon::D15)
+ .addReg(Hexagon::R30);
+ if (RegisterSavedAreaSizePlusPadding != 0)
+ BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)
+ .addReg(SP)
+ .addImm(RegisterSavedAreaSizePlusPadding);
+ }
}
void HexagonFrameLowering::insertAllocframe(MachineBasicBlock &MBB,
@@ -744,7 +893,7 @@ void HexagonFrameLowering::insertAllocframe(MachineBasicBlock &MBB,
// 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);
+ MachineMemOperand::MOStore, 4, Align(4));
DebugLoc dl = MBB.findDebugLoc(InsertPt);
unsigned SP = HRI.getStackRegister();
@@ -907,9 +1056,9 @@ void HexagonFrameLowering::insertCFIInstructionsAt(MachineBasicBlock &MBB,
// | +-- Old SP (before allocframe)
// +-- New FP (after allocframe)
//
- // MCCFIInstruction::createDefCfa subtracts the offset from the register.
+ // MCCFIInstruction::cfiDefCfa adds the offset from the register.
// MCCFIInstruction::createOffset takes the offset without sign change.
- auto DefCfa = MCCFIInstruction::createDefCfa(FrameLabel, DwFPReg, -8);
+ auto DefCfa = MCCFIInstruction::cfiDefCfa(FrameLabel, DwFPReg, 8);
BuildMI(MBB, At, DL, CFID)
.addCFIIndex(MF.addFrameInst(DefCfa));
// R31 (return addr) = CFA - 4
@@ -954,7 +1103,7 @@ void HexagonFrameLowering::insertCFIInstructionsAt(MachineBasicBlock &MBB,
// Instead, get the offset (relative to the FP) directly.
Offset = MFI.getObjectOffset(F->getFrameIdx());
} else {
- unsigned FrameReg;
+ Register FrameReg;
Offset = getFrameIndexReference(MF, F->getFrameIdx(), FrameReg);
}
// Subtract 8 to make room for R30 and R31, which are added above.
@@ -1108,7 +1257,8 @@ static const char *getSpillFunctionFor(unsigned MaxReg, SpillKind SpillType,
}
int HexagonFrameLowering::getFrameIndexReference(const MachineFunction &MF,
- int FI, unsigned &FrameReg) const {
+ int FI,
+ Register &FrameReg) const {
auto &MFI = MF.getFrameInfo();
auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
@@ -1119,9 +1269,9 @@ int HexagonFrameLowering::getFrameIndexReference(const MachineFunction &MF,
auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>();
unsigned FrameSize = MFI.getStackSize();
- unsigned SP = HRI.getStackRegister();
- unsigned FP = HRI.getFrameRegister();
- unsigned AP = HMFI.getStackAlignBasePhysReg();
+ Register SP = HRI.getStackRegister();
+ Register FP = HRI.getFrameRegister();
+ Register 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
@@ -1358,7 +1508,7 @@ void HexagonFrameLowering::processFunctionBeforeFrameFinalized(
// via AP, which may not be available at the particular place in the program.
MachineFrameInfo &MFI = MF.getFrameInfo();
bool HasAlloca = MFI.hasVarSizedObjects();
- bool NeedsAlign = (MFI.getMaxAlignment() > getStackAlignment());
+ bool NeedsAlign = (MFI.getMaxAlign() > getStackAlign());
if (!HasAlloca || !NeedsAlign)
return;
@@ -1371,8 +1521,8 @@ void HexagonFrameLowering::processFunctionBeforeFrameFinalized(
unsigned S = MFI.getObjectSize(i);
// Reduce the alignment to at most 8. This will require unaligned vector
// stores if they happen here.
- unsigned A = std::max(MFI.getObjectAlignment(i), 8U);
- MFI.setObjectAlignment(i, 8);
+ Align A = std::max(MFI.getObjectAlign(i), Align(8));
+ MFI.setObjectAlignment(i, Align(8));
LFS = alignTo(LFS+S, A);
MFI.mapLocalFrameObject(i, -static_cast<int64_t>(LFS));
DealignSlots.insert(i);
@@ -1398,12 +1548,11 @@ void HexagonFrameLowering::processFunctionBeforeFrameFinalized(
if (auto *FS = dyn_cast_or_null<FixedStackPseudoSourceValue>(PV)) {
int FI = FS->getFrameIndex();
if (DealignSlots.count(FI)) {
- unsigned A = MFI.getObjectAlignment(FI);
- auto *NewMMO = MF.getMachineMemOperand(MMO->getPointerInfo(),
- MMO->getFlags(), MMO->getSize(), A,
- MMO->getAAInfo(), MMO->getRanges(),
- MMO->getSyncScopeID(), MMO->getOrdering(),
- MMO->getFailureOrdering());
+ auto *NewMMO = MF.getMachineMemOperand(
+ MMO->getPointerInfo(), MMO->getFlags(), MMO->getSize(),
+ MFI.getObjectAlign(FI), MMO->getAAInfo(), MMO->getRanges(),
+ MMO->getSyncScopeID(), MMO->getOrdering(),
+ MMO->getFailureOrdering());
new_memops.push_back(NewMMO);
KeepOld = false;
continue;
@@ -1562,9 +1711,8 @@ bool HexagonFrameLowering::assignCalleeSavedSpillSlots(MachineFunction &MF,
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(R);
unsigned Size = TRI->getSpillSize(*RC);
int Off = MinOffset - Size;
- unsigned Align = std::min(TRI->getSpillAlignment(*RC), getStackAlignment());
- assert(isPowerOf2_32(Align));
- Off &= -Align;
+ Align Alignment = std::min(TRI->getSpillAlign(*RC), getStackAlign());
+ Off &= -Alignment.value();
int FI = MFI.CreateFixedSpillStackObject(Size, Off);
MinOffset = std::min(MinOffset, Off);
CSI.push_back(CalleeSavedInfo(R, FI));
@@ -1787,11 +1935,11 @@ bool HexagonFrameLowering::expandStoreVec2(MachineBasicBlock &B,
bool NeedsAligna = needsAligna(MF);
unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
- unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
- unsigned HasAlign = MFI.getObjectAlignment(FI);
+ Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
+ Align HasAlign = MFI.getObjectAlign(FI);
unsigned StoreOpc;
- auto UseAligned = [&] (unsigned NeedAlign, unsigned HasAlign) {
+ auto UseAligned = [&](Align NeedAlign, Align HasAlign) {
return !NeedsAligna && (NeedAlign <= HasAlign);
};
@@ -1839,11 +1987,11 @@ bool HexagonFrameLowering::expandLoadVec2(MachineBasicBlock &B,
bool NeedsAligna = needsAligna(MF);
unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
- unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
- unsigned HasAlign = MFI.getObjectAlignment(FI);
+ Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
+ Align HasAlign = MFI.getObjectAlign(FI);
unsigned LoadOpc;
- auto UseAligned = [&] (unsigned NeedAlign, unsigned HasAlign) {
+ auto UseAligned = [&](Align NeedAlign, Align HasAlign) {
return !NeedsAligna && (NeedAlign <= HasAlign);
};
@@ -1883,8 +2031,8 @@ bool HexagonFrameLowering::expandStoreVec(MachineBasicBlock &B,
bool IsKill = MI->getOperand(2).isKill();
int FI = MI->getOperand(0).getIndex();
- unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
- unsigned HasAlign = MFI.getObjectAlignment(FI);
+ Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
+ Align HasAlign = MFI.getObjectAlign(FI);
bool UseAligned = !NeedsAligna && (NeedAlign <= HasAlign);
unsigned StoreOpc = UseAligned ? Hexagon::V6_vS32b_ai
: Hexagon::V6_vS32Ub_ai;
@@ -1913,8 +2061,8 @@ bool HexagonFrameLowering::expandLoadVec(MachineBasicBlock &B,
Register DstR = MI->getOperand(0).getReg();
int FI = MI->getOperand(1).getIndex();
- unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
- unsigned HasAlign = MFI.getObjectAlignment(FI);
+ Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
+ Align HasAlign = MFI.getObjectAlign(FI);
bool UseAligned = !NeedsAligna && (NeedAlign <= HasAlign);
unsigned LoadOpc = UseAligned ? Hexagon::V6_vL32b_ai
: Hexagon::V6_vL32Ub_ai;
@@ -2016,7 +2164,8 @@ void HexagonFrameLowering::determineCalleeSaves(MachineFunction &MF,
Num = 2; // Vector predicate spills also need a vector register.
break;
}
- unsigned S = HRI.getSpillSize(*RC), A = HRI.getSpillAlignment(*RC);
+ unsigned S = HRI.getSpillSize(*RC);
+ Align A = HRI.getSpillAlign(*RC);
for (unsigned i = 0; i < Num; i++) {
int NewFI = MFI.CreateSpillStackObject(S, A);
RS->addScavengingFrameIndex(NewFI);
@@ -2473,6 +2622,8 @@ void HexagonFrameLowering::addCalleeSaveRegistersAsImpOperand(MachineInstr *MI,
/// checks are performed, which may still lead to the inline code.
bool HexagonFrameLowering::shouldInlineCSR(const MachineFunction &MF,
const CSIVect &CSI) const {
+ if (MF.getSubtarget<HexagonSubtarget>().isEnvironmentMusl())
+ return true;
if (MF.getInfo<HexagonMachineFunctionInfo>()->hasEHReturn())
return true;
if (!hasFP(MF))