diff options
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp | 275 |
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)) |