-
Notifications
You must be signed in to change notification settings - Fork 7
Frame lowering optimizations #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: nanomips-llvm13-submission
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -432,19 +432,61 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, | |
| MachineModuleInfo &MMI = MF.getMMI(); | ||
| const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); | ||
|
|
||
| // Adjust stack. | ||
| TII.adjustStackPtr(SP, -StackSize, MBB, MBBI); | ||
| const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); | ||
|
|
||
| int64_t CalleeSavedStackSize; | ||
| int64_t LoaclStackSize; | ||
| // If we have two-step stack setup MBBI_2 will point to the | ||
| // first instruction after calle-saves store sequence | ||
| MachineBasicBlock::iterator MBBI_2 = MBBI; | ||
|
|
||
| if (MipsFI->isTwoStepStackSetup(MF)) { | ||
|
|
||
| CalleeSavedStackSize = MipsFI->getCalleeSavedStackSize(); | ||
| unsigned NumOfCSI = MFI.getCalleeSavedInfo().size(); | ||
|
|
||
| // Move MBBI_2 to point to the first instruction after | ||
| // calle-saves store sequence. That's the place for the second | ||
| // steck pointer adjustment. | ||
nikolaperic marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| std::advance(MBBI_2, NumOfCSI); | ||
|
||
|
|
||
| // The first stack pointer adjustment to cover space needed | ||
| // to spill callee-saved registers on stack. | ||
| TII.adjustStackPtr(SP, -CalleeSavedStackSize, MBB, MBBI); | ||
|
|
||
| LoaclStackSize = StackSize - CalleeSavedStackSize; | ||
|
|
||
| // emit ".cfi_def_cfa_offset StackSize" | ||
| unsigned CFIIndex = | ||
| MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize)); | ||
| BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | ||
| .addCFIIndex(CFIIndex); | ||
| // The second stack pointer adjustment to cover space needed | ||
| // to spill local objects on stack. | ||
| TII.adjustStackPtr(SP, -LoaclStackSize, MBB, MBBI_2); | ||
|
|
||
| } else | ||
| // Adjust stack. | ||
| TII.adjustStackPtr(SP, -StackSize, MBB, MBBI); | ||
|
|
||
| if (MipsFI->isTwoStepStackSetup(MF)) { | ||
nikolaperic marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // emit ".cfi_def_cfa_offset CalleeSavedStackSize" | ||
| // emit ".cfi_def_cfa_offset StackSize = CalleeSavedStackSize + | ||
| // LoaclStackSize" | ||
| unsigned CFIIndex_1 = MF.addFrameInst( | ||
| MCCFIInstruction::cfiDefCfaOffset(nullptr, CalleeSavedStackSize)); | ||
| unsigned CFIIndex_2 = | ||
| MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize)); | ||
| BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | ||
| .addCFIIndex(CFIIndex_1); | ||
| BuildMI(MBB, MBBI_2, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | ||
| .addCFIIndex(CFIIndex_2); | ||
| } else { | ||
| // emit ".cfi_def_cfa_offset StackSize" | ||
| unsigned CFIIndex = | ||
| MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize)); | ||
| BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | ||
| .addCFIIndex(CFIIndex); | ||
| } | ||
|
|
||
| if (MF.getFunction().hasFnAttribute("interrupt")) | ||
| emitInterruptPrologueStub(MF, MBB); | ||
|
|
||
| const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); | ||
|
|
||
| if (!CSI.empty()) { | ||
| // Find the instruction past the last instruction that saves a callee-saved | ||
|
|
@@ -527,15 +569,40 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, | |
|
|
||
| // if framepointer enabled, set it to point to the stack pointer. | ||
| if (hasFP(MF)) { | ||
| // Insert instruction "move $fp, $sp" at this location. | ||
| BuildMI(MBB, MBBI, dl, TII.get(MOVE), FP).addReg(SP).addReg(ZERO) | ||
| .setMIFlag(MachineInstr::FrameSetup); | ||
|
|
||
| // emit ".cfi_def_cfa_register $fp" | ||
| unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister( | ||
| nullptr, MRI->getDwarfRegNum(FP, true))); | ||
| BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | ||
| .addCFIIndex(CFIIndex); | ||
| if (STI.hasNanoMips()) { | ||
|
|
||
| BuildMI(MBB, MBBI_2, dl, TII.get(ADDiu), FP) | ||
| .addReg(SP) | ||
| .addImm(-4096 + StackSize); | ||
|
|
||
| // emit ".cfi_def_cfa_register $fp" | ||
| unsigned CFIIndex = | ||
| MF.addFrameInst(MCCFIInstruction::createDefCfaRegister( | ||
| nullptr, MRI->getDwarfRegNum(FP, true))); | ||
| BuildMI(MBB, MBBI_2, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | ||
| .addCFIIndex(CFIIndex); | ||
|
|
||
| // emit ".cfi_def_cfa_offset 4096" | ||
| unsigned CFIIndex_1 = | ||
| MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 4096)); | ||
| BuildMI(MBB, MBBI_2, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | ||
| .addCFIIndex(CFIIndex_1); | ||
|
|
||
| } else { | ||
| // Insert instruction "move $fp, $sp" at this location. | ||
| BuildMI(MBB, MBBI, dl, TII.get(MOVE), FP) | ||
| .addReg(SP) | ||
| .addReg(ZERO) | ||
| .setMIFlag(MachineInstr::FrameSetup); | ||
|
|
||
| // emit ".cfi_def_cfa_register $fp" | ||
| unsigned CFIIndex = | ||
| MF.addFrameInst(MCCFIInstruction::createDefCfaRegister( | ||
| nullptr, MRI->getDwarfRegNum(FP, true))); | ||
| BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | ||
| .addCFIIndex(CFIIndex); | ||
| } | ||
|
|
||
| if (RegInfo.hasStackRealignment(MF)) { | ||
| // addiu $Reg, $zero, -MaxAlignment | ||
|
|
@@ -545,13 +612,19 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, | |
| "Function's alignment size requirement is not supported."); | ||
| int64_t MaxAlign = -(int64_t)MFI.getMaxAlign().value(); | ||
|
|
||
| if (ABI.IsP32()) | ||
| BuildMI(MBB, MBBI, dl, TII.get(Mips::Li_NM), VR).addImm(MaxAlign); | ||
| else | ||
| if (ABI.IsP32()) { | ||
| uint64_t MaxAlignment = MFI.getMaxAlign().value(); | ||
| BuildMI(MBB, MBBI, dl, TII.get(Mips::INS_NM), SP) | ||
| .addReg(ZERO) | ||
| .addImm(0) | ||
| .addImm(Log2_64(MaxAlignment)) | ||
| .addReg(SP); | ||
| } else { | ||
| BuildMI(MBB, MBBI, dl, TII.get(ADDiu), VR) | ||
| .addReg(ZERO) | ||
| .addImm(MaxAlign); | ||
| BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR); | ||
| BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR); | ||
| } | ||
|
|
||
| if (hasBP(MF)) { | ||
| // move $s7, $sp | ||
|
|
@@ -709,7 +782,7 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, | |
| unsigned MOVE = ABI.GetGPRMoveOp(); | ||
|
|
||
| // if framepointer enabled, restore the stack pointer. | ||
| if (hasFP(MF)) { | ||
| if (hasFP(MF) && !STI.hasNanoMips()) { | ||
| // Find the first instruction that restores a callee-saved register. | ||
| MachineBasicBlock::iterator I = MBBI; | ||
|
|
||
|
|
@@ -747,8 +820,26 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, | |
| if (!StackSize) | ||
| return; | ||
|
|
||
| // Adjust stack. | ||
| TII.adjustStackPtr(SP, StackSize, MBB, MBBI); | ||
| if (MipsFI->isTwoStepStackSetup(MF)) { | ||
|
|
||
| int64_t CalleeSavedStackSize = MipsFI->getCalleeSavedStackSize(); | ||
| int64_t LoaclStackSize = StackSize - CalleeSavedStackSize; | ||
|
|
||
| int64_t NumOfCSI = MFI.getCalleeSavedInfo().size(); | ||
|
|
||
| MachineBasicBlock::iterator MBBI_2 = MBBI; | ||
| // Move MBBI_2 to point to the first instruction in | ||
| // calle-saved load sequence. That's the place where we | ||
| // need to undo the second stack adjustment | ||
| std::advance(MBBI_2, (-1) * NumOfCSI); | ||
|
|
||
| // Undo the second stack pointer adjustment | ||
| TII.adjustStackPtr(SP, LoaclStackSize, MBB, MBBI_2); | ||
| // Undo the first stack pointer adjustment | ||
| TII.adjustStackPtr(SP, CalleeSavedStackSize, MBB, MBBI); | ||
| } else | ||
| // Adjust stack. | ||
| TII.adjustStackPtr(SP, StackSize, MBB, MBBI); | ||
| } | ||
|
|
||
| void MipsSEFrameLowering::emitInterruptEpilogueStub( | ||
|
|
@@ -935,22 +1026,60 @@ bool MipsSEFrameLowering::assignCalleeSavedSpillSlots( | |
| if (!STI.hasNanoMips()) | ||
| return false; | ||
|
|
||
| static const std::unordered_map<unsigned, unsigned> Regs = { | ||
| {Mips::GP_NM, 0}, {Mips::FP_NM, 1}, {Mips::RA_NM, 2}, {Mips::S0_NM, 3}, | ||
| {Mips::S1_NM, 4}, {Mips::S2_NM, 5}, {Mips::S3_NM, 6}, {Mips::S4_NM, 7}, | ||
| {Mips::S5_NM, 8}, {Mips::S6_NM, 9}, {Mips::S7_NM, 10}, | ||
| }; | ||
|
|
||
| static const std::unordered_map<unsigned, unsigned> CSNumToReg = { | ||
| {0, Mips::GP_NM}, {1, Mips::FP_NM}, {2, Mips::RA_NM}, {3, Mips::S0_NM}, | ||
| {4, Mips::S1_NM}, {5, Mips::S2_NM}, {6, Mips::S3_NM}, {7, Mips::S4_NM}, | ||
| {8, Mips::S5_NM}, {9, Mips::S6_NM}, {10, Mips::S7_NM}, | ||
| }; | ||
|
|
||
| // nanoMIPS save and restore instructions require callee-saved registers to be | ||
| // saved in particular order on the stack. | ||
| auto SortCalleeSaves = [](CalleeSavedInfo First, CalleeSavedInfo Second) { | ||
| std::unordered_map<unsigned, unsigned> Regs{ | ||
| {Mips::GP_NM, 0}, {Mips::FP_NM, 1}, {Mips::RA_NM, 2}, {Mips::S0_NM, 3}, | ||
| {Mips::S1_NM, 4}, {Mips::S2_NM, 5}, {Mips::S3_NM, 6}, {Mips::S4_NM, 7}, | ||
| {Mips::S5_NM, 8}, {Mips::S6_NM, 9}, {Mips::S7_NM, 10}, | ||
| }; | ||
|
|
||
| auto CompareCalleeSaves = [](CalleeSavedInfo First, CalleeSavedInfo Second) { | ||
| // There should be no callee-saved registers that are not part of the list. | ||
| assert(Regs.find(First.getReg()) != Regs.end() && | ||
| Regs.find(Second.getReg()) != Regs.end()); | ||
|
|
||
| return Regs[First.getReg()] < Regs[Second.getReg()]; | ||
| return Regs.at(First.getReg()) < Regs.at(Second.getReg()); | ||
| }; | ||
| std::sort(CSI.begin(), CSI.end(), SortCalleeSaves); | ||
|
|
||
| // If CSI list has less than two callee-saved registers | ||
| // no insertions nor sorting is needed | ||
| if (CSI.size() >= 2) { | ||
|
|
||
| SmallBitVector CSNumBitVector(11); | ||
| for (CalleeSavedInfo &CS : CSI) | ||
| CSNumBitVector.set(Regs.at(CS.getReg())); | ||
|
|
||
| int MinCSNum = CSNumBitVector.find_first(); | ||
| int MaxCSNum = CSNumBitVector.find_last(); | ||
|
|
||
| // Inserting all of the missing callee-saved registers between min and max | ||
| // in order to allow further load-store optimizations | ||
| for (int i = MinCSNum + 1; i < MaxCSNum; ++i) | ||
| if (!CSNumBitVector.test(i)) | ||
| CSI.push_back(CalleeSavedInfo(CSNumToReg.at(i))); | ||
|
|
||
| std::sort(CSI.begin(), CSI.end(), CompareCalleeSaves); | ||
| } | ||
|
|
||
| MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); | ||
| const MachineRegisterInfo &MRI = MF.getRegInfo(); | ||
|
|
||
| unsigned CalleeSavedOffsetSize = 0; | ||
| for (CalleeSavedInfo &CS : CSI) { | ||
| Register Reg = CS.getReg(); | ||
| auto RegSize = TRI->getRegSizeInBits(Reg, MRI) / 8; | ||
| CalleeSavedOffsetSize += RegSize; | ||
| } | ||
| uint64_t AlignedCSStackSize = alignTo(CalleeSavedOffsetSize, 16); | ||
| MipsFI->setCalleeSavedStackSize(AlignedCSStackSize); | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.