| Jia Liu | b22310f | 2012-02-18 12:03:15 +0000 | [diff] [blame] | 1 | //===-- Thumb1FrameLowering.cpp - Thumb1 Frame Information ----------------===// | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 10 | // This file contains the Thumb1 implementation of TargetFrameLowering class. | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 14 | #include "Thumb1FrameLowering.h" | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 15 | #include "ARMMachineFunctionInfo.h" | 
| Quentin Colombet | 71a7148 | 2015-07-20 21:42:14 +0000 | [diff] [blame] | 16 | #include "llvm/CodeGen/LivePhysRegs.h" | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 17 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
|  | 18 | #include "llvm/CodeGen/MachineFunction.h" | 
|  | 19 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 20 | #include "llvm/CodeGen/MachineModuleInfo.h" | 
| Evan Cheng | eb56dca | 2010-11-22 18:12:04 +0000 | [diff] [blame] | 21 | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 22 |  | 
|  | 23 | using namespace llvm; | 
|  | 24 |  | 
| Eric Christopher | 45fb7b6 | 2014-06-26 19:29:59 +0000 | [diff] [blame] | 25 | Thumb1FrameLowering::Thumb1FrameLowering(const ARMSubtarget &sti) | 
|  | 26 | : ARMFrameLowering(sti) {} | 
|  | 27 |  | 
| Jim Grosbach | e7e2aca | 2011-09-13 20:30:37 +0000 | [diff] [blame] | 28 | bool Thumb1FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const{ | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 29 | const MachineFrameInfo &MFI = MF.getFrameInfo(); | 
|  | 30 | unsigned CFSize = MFI.getMaxCallFrameSize(); | 
| Anton Korobeynikov | 0eecf5d | 2010-11-18 21:19:35 +0000 | [diff] [blame] | 31 | // It's not always a good idea to include the call frame as part of the | 
|  | 32 | // stack frame. ARM (especially Thumb) has small immediate offset to | 
|  | 33 | // address the stack frame. So a large call frame can cause poor codegen | 
|  | 34 | // and may even makes it impossible to scavenge a register. | 
|  | 35 | if (CFSize >= ((1 << 8) - 1) * 4 / 2) // Half of imm8 * 4 | 
|  | 36 | return false; | 
|  | 37 |  | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 38 | return !MFI.hasVarSizedObjects(); | 
| Anton Korobeynikov | 0eecf5d | 2010-11-18 21:19:35 +0000 | [diff] [blame] | 39 | } | 
|  | 40 |  | 
| Benjamin Kramer | bdc4956 | 2016-06-12 15:39:02 +0000 | [diff] [blame] | 41 | static void emitSPUpdate(MachineBasicBlock &MBB, | 
|  | 42 | MachineBasicBlock::iterator &MBBI, | 
|  | 43 | const TargetInstrInfo &TII, const DebugLoc &dl, | 
|  | 44 | const ThumbRegisterInfo &MRI, int NumBytes, | 
|  | 45 | unsigned MIFlags = MachineInstr::NoFlags) { | 
| Anton Korobeynikov | e7410dd | 2011-03-05 18:43:32 +0000 | [diff] [blame] | 46 | emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, TII, | 
| Anton Korobeynikov | a8d177b | 2011-03-05 18:43:50 +0000 | [diff] [blame] | 47 | MRI, MIFlags); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 48 | } | 
|  | 49 |  | 
| Eli Bendersky | 8da8716 | 2013-02-21 20:05:00 +0000 | [diff] [blame] | 50 |  | 
| Hans Wennborg | e1a2e90 | 2016-03-31 18:33:38 +0000 | [diff] [blame] | 51 | MachineBasicBlock::iterator Thumb1FrameLowering:: | 
| Eli Bendersky | 8da8716 | 2013-02-21 20:05:00 +0000 | [diff] [blame] | 52 | eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, | 
|  | 53 | MachineBasicBlock::iterator I) const { | 
|  | 54 | const Thumb1InstrInfo &TII = | 
| Eric Christopher | 1b21f00 | 2015-01-29 00:19:33 +0000 | [diff] [blame] | 55 | *static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo()); | 
| Eric Christopher | ae32649 | 2015-03-12 22:48:50 +0000 | [diff] [blame] | 56 | const ThumbRegisterInfo *RegInfo = | 
|  | 57 | static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); | 
| Eli Bendersky | 8da8716 | 2013-02-21 20:05:00 +0000 | [diff] [blame] | 58 | if (!hasReservedCallFrame(MF)) { | 
|  | 59 | // If we have alloca, convert as follows: | 
|  | 60 | // ADJCALLSTACKDOWN -> sub, sp, sp, amount | 
|  | 61 | // ADJCALLSTACKUP   -> add, sp, sp, amount | 
| Duncan P. N. Exon Smith | 29c5249 | 2016-07-08 20:21:17 +0000 | [diff] [blame] | 62 | MachineInstr &Old = *I; | 
|  | 63 | DebugLoc dl = Old.getDebugLoc(); | 
|  | 64 | unsigned Amount = Old.getOperand(0).getImm(); | 
| Eli Bendersky | 8da8716 | 2013-02-21 20:05:00 +0000 | [diff] [blame] | 65 | if (Amount != 0) { | 
|  | 66 | // We need to keep the stack aligned properly.  To do this, we round the | 
|  | 67 | // amount of space needed for the outgoing arguments up to the next | 
|  | 68 | // alignment boundary. | 
|  | 69 | unsigned Align = getStackAlignment(); | 
|  | 70 | Amount = (Amount+Align-1)/Align*Align; | 
|  | 71 |  | 
|  | 72 | // Replace the pseudo instruction with a new instruction... | 
| Duncan P. N. Exon Smith | 29c5249 | 2016-07-08 20:21:17 +0000 | [diff] [blame] | 73 | unsigned Opc = Old.getOpcode(); | 
| Eli Bendersky | 8da8716 | 2013-02-21 20:05:00 +0000 | [diff] [blame] | 74 | if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { | 
|  | 75 | emitSPUpdate(MBB, I, TII, dl, *RegInfo, -Amount); | 
|  | 76 | } else { | 
|  | 77 | assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); | 
|  | 78 | emitSPUpdate(MBB, I, TII, dl, *RegInfo, Amount); | 
|  | 79 | } | 
|  | 80 | } | 
|  | 81 | } | 
| Hans Wennborg | e1a2e90 | 2016-03-31 18:33:38 +0000 | [diff] [blame] | 82 | return MBB.erase(I); | 
| Eli Bendersky | 8da8716 | 2013-02-21 20:05:00 +0000 | [diff] [blame] | 83 | } | 
|  | 84 |  | 
| Quentin Colombet | 61b305e | 2015-05-05 17:38:16 +0000 | [diff] [blame] | 85 | void Thumb1FrameLowering::emitPrologue(MachineFunction &MF, | 
|  | 86 | MachineBasicBlock &MBB) const { | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 87 | MachineBasicBlock::iterator MBBI = MBB.begin(); | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 88 | MachineFrameInfo &MFI = MF.getFrameInfo(); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 89 | ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 90 | MachineModuleInfo &MMI = MF.getMMI(); | 
|  | 91 | const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); | 
| Eric Christopher | ae32649 | 2015-03-12 22:48:50 +0000 | [diff] [blame] | 92 | const ThumbRegisterInfo *RegInfo = | 
|  | 93 | static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 94 | const Thumb1InstrInfo &TII = | 
| Eric Christopher | 1b21f00 | 2015-01-29 00:19:33 +0000 | [diff] [blame] | 95 | *static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo()); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 96 |  | 
| Tim Northover | 8cda34f | 2015-03-11 18:54:22 +0000 | [diff] [blame] | 97 | unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 98 | unsigned NumBytes = MFI.getStackSize(); | 
| Tim Northover | 775aaeb | 2015-11-05 21:54:58 +0000 | [diff] [blame] | 99 | assert(NumBytes >= ArgRegsSaveSize && | 
|  | 100 | "ArgRegsSaveSize is included in NumBytes"); | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 101 | const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); | 
| Tim Northover | 775aaeb | 2015-11-05 21:54:58 +0000 | [diff] [blame] | 102 |  | 
|  | 103 | // Debug location must be unknown since the first debug location is used | 
|  | 104 | // to determine the end of the prologue. | 
|  | 105 | DebugLoc dl; | 
|  | 106 |  | 
|  | 107 | unsigned FramePtr = RegInfo->getFrameRegister(MF); | 
|  | 108 | unsigned BasePtr = RegInfo->getBaseRegister(); | 
|  | 109 | int CFAOffset = 0; | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 110 |  | 
|  | 111 | // Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4. | 
|  | 112 | NumBytes = (NumBytes + 3) & ~3; | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 113 | MFI.setStackSize(NumBytes); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 114 |  | 
|  | 115 | // Determine the sizes of each callee-save spill areas and record which frame | 
|  | 116 | // belongs to which callee-save spill areas. | 
|  | 117 | unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; | 
|  | 118 | int FramePtrSpillFI = 0; | 
|  | 119 |  | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 120 | if (ArgRegsSaveSize) { | 
| Stepan Dyatkovskiy | f5aa83d | 2013-04-30 07:19:58 +0000 | [diff] [blame] | 121 | emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -ArgRegsSaveSize, | 
| Anton Korobeynikov | a8d177b | 2011-03-05 18:43:50 +0000 | [diff] [blame] | 122 | MachineInstr::FrameSetup); | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 123 | CFAOffset -= ArgRegsSaveSize; | 
| Rafael Espindola | b1f25f1 | 2014-03-07 06:08:31 +0000 | [diff] [blame] | 124 | unsigned CFIIndex = MMI.addFrameInst( | 
|  | 125 | MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); | 
|  | 126 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | 
| Adrian Prantl | d9e64b6 | 2014-12-22 23:09:14 +0000 | [diff] [blame] | 127 | .addCFIIndex(CFIIndex) | 
|  | 128 | .setMIFlags(MachineInstr::FrameSetup); | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 129 | } | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 130 |  | 
|  | 131 | if (!AFI->hasStackFrame()) { | 
| Oliver Stannard | d55e115 | 2014-03-05 15:25:27 +0000 | [diff] [blame] | 132 | if (NumBytes - ArgRegsSaveSize != 0) { | 
|  | 133 | emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -(NumBytes - ArgRegsSaveSize), | 
| Anton Korobeynikov | a8d177b | 2011-03-05 18:43:50 +0000 | [diff] [blame] | 134 | MachineInstr::FrameSetup); | 
| Oliver Stannard | d55e115 | 2014-03-05 15:25:27 +0000 | [diff] [blame] | 135 | CFAOffset -= NumBytes - ArgRegsSaveSize; | 
| Rafael Espindola | b1f25f1 | 2014-03-07 06:08:31 +0000 | [diff] [blame] | 136 | unsigned CFIIndex = MMI.addFrameInst( | 
|  | 137 | MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); | 
|  | 138 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | 
| Adrian Prantl | d9e64b6 | 2014-12-22 23:09:14 +0000 | [diff] [blame] | 139 | .addCFIIndex(CFIIndex) | 
|  | 140 | .setMIFlags(MachineInstr::FrameSetup); | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 141 | } | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 142 | return; | 
|  | 143 | } | 
|  | 144 |  | 
|  | 145 | for (unsigned i = 0, e = CSI.size(); i != e; ++i) { | 
|  | 146 | unsigned Reg = CSI[i].getReg(); | 
|  | 147 | int FI = CSI[i].getFrameIdx(); | 
|  | 148 | switch (Reg) { | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 149 | case ARM::R8: | 
|  | 150 | case ARM::R9: | 
|  | 151 | case ARM::R10: | 
|  | 152 | case ARM::R11: | 
| Oliver Stannard | 9aa6f01 | 2016-08-23 09:19:22 +0000 | [diff] [blame] | 153 | if (STI.splitFramePushPop(MF)) { | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 154 | GPRCS2Size += 4; | 
|  | 155 | break; | 
|  | 156 | } | 
| Justin Bogner | b03fd12 | 2016-08-17 05:10:15 +0000 | [diff] [blame] | 157 | LLVM_FALLTHROUGH; | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 158 | case ARM::R4: | 
|  | 159 | case ARM::R5: | 
|  | 160 | case ARM::R6: | 
|  | 161 | case ARM::R7: | 
|  | 162 | case ARM::LR: | 
|  | 163 | if (Reg == FramePtr) | 
|  | 164 | FramePtrSpillFI = FI; | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 165 | GPRCS1Size += 4; | 
|  | 166 | break; | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 167 | default: | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 168 | DPRCSSize += 8; | 
|  | 169 | } | 
|  | 170 | } | 
| Tim Northover | 775aaeb | 2015-11-05 21:54:58 +0000 | [diff] [blame] | 171 |  | 
|  | 172 | if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH) { | 
|  | 173 | ++MBBI; | 
|  | 174 | } | 
|  | 175 |  | 
|  | 176 | // Determine starting offsets of spill areas. | 
| Oliver Stannard | d55e115 | 2014-03-05 15:25:27 +0000 | [diff] [blame] | 177 | unsigned DPRCSOffset  = NumBytes - ArgRegsSaveSize - (GPRCS1Size + GPRCS2Size + DPRCSSize); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 178 | unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; | 
|  | 179 | unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; | 
| Logan Chien | 53c18d8 | 2013-02-20 12:21:33 +0000 | [diff] [blame] | 180 | bool HasFP = hasFP(MF); | 
|  | 181 | if (HasFP) | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 182 | AFI->setFramePtrSpillOffset(MFI.getObjectOffset(FramePtrSpillFI) + | 
| Logan Chien | 53c18d8 | 2013-02-20 12:21:33 +0000 | [diff] [blame] | 183 | NumBytes); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 184 | AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); | 
|  | 185 | AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); | 
|  | 186 | AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 187 | NumBytes = DPRCSOffset; | 
| Evan Cheng | eb56dca | 2010-11-22 18:12:04 +0000 | [diff] [blame] | 188 |  | 
| Tim Northover | 93bcc66 | 2013-11-08 17:18:07 +0000 | [diff] [blame] | 189 | int FramePtrOffsetInBlock = 0; | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 190 | unsigned adjustedGPRCS1Size = GPRCS1Size; | 
| Duncan P. N. Exon Smith | 29c5249 | 2016-07-08 20:21:17 +0000 | [diff] [blame] | 191 | if (tryFoldSPUpdateIntoPushPop(STI, MF, &*std::prev(MBBI), NumBytes)) { | 
| Tim Northover | 93bcc66 | 2013-11-08 17:18:07 +0000 | [diff] [blame] | 192 | FramePtrOffsetInBlock = NumBytes; | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 193 | adjustedGPRCS1Size += NumBytes; | 
| Tim Northover | 93bcc66 | 2013-11-08 17:18:07 +0000 | [diff] [blame] | 194 | NumBytes = 0; | 
|  | 195 | } | 
|  | 196 |  | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 197 | if (adjustedGPRCS1Size) { | 
|  | 198 | CFAOffset -= adjustedGPRCS1Size; | 
| Rafael Espindola | b1f25f1 | 2014-03-07 06:08:31 +0000 | [diff] [blame] | 199 | unsigned CFIIndex = MMI.addFrameInst( | 
|  | 200 | MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); | 
|  | 201 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | 
| Adrian Prantl | d9e64b6 | 2014-12-22 23:09:14 +0000 | [diff] [blame] | 202 | .addCFIIndex(CFIIndex) | 
|  | 203 | .setMIFlags(MachineInstr::FrameSetup); | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 204 | } | 
|  | 205 | for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), | 
|  | 206 | E = CSI.end(); I != E; ++I) { | 
|  | 207 | unsigned Reg = I->getReg(); | 
|  | 208 | int FI = I->getFrameIdx(); | 
|  | 209 | switch (Reg) { | 
|  | 210 | case ARM::R8: | 
|  | 211 | case ARM::R9: | 
|  | 212 | case ARM::R10: | 
|  | 213 | case ARM::R11: | 
|  | 214 | case ARM::R12: | 
| Oliver Stannard | 9aa6f01 | 2016-08-23 09:19:22 +0000 | [diff] [blame] | 215 | if (STI.splitFramePushPop(MF)) | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 216 | break; | 
|  | 217 | // fallthough | 
|  | 218 | case ARM::R0: | 
|  | 219 | case ARM::R1: | 
|  | 220 | case ARM::R2: | 
|  | 221 | case ARM::R3: | 
|  | 222 | case ARM::R4: | 
|  | 223 | case ARM::R5: | 
|  | 224 | case ARM::R6: | 
|  | 225 | case ARM::R7: | 
|  | 226 | case ARM::LR: | 
| Rafael Espindola | b1f25f1 | 2014-03-07 06:08:31 +0000 | [diff] [blame] | 227 | unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset( | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 228 | nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI))); | 
| Rafael Espindola | b1f25f1 | 2014-03-07 06:08:31 +0000 | [diff] [blame] | 229 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | 
| Adrian Prantl | d9e64b6 | 2014-12-22 23:09:14 +0000 | [diff] [blame] | 230 | .addCFIIndex(CFIIndex) | 
|  | 231 | .setMIFlags(MachineInstr::FrameSetup); | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 232 | break; | 
|  | 233 | } | 
|  | 234 | } | 
|  | 235 |  | 
| Evan Cheng | eb56dca | 2010-11-22 18:12:04 +0000 | [diff] [blame] | 236 | // Adjust FP so it point to the stack slot that contains the previous FP. | 
| Logan Chien | 53c18d8 | 2013-02-20 12:21:33 +0000 | [diff] [blame] | 237 | if (HasFP) { | 
| NAKAMURA Takumi | 0a7d0ad | 2015-09-22 11:15:07 +0000 | [diff] [blame] | 238 | FramePtrOffsetInBlock += | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 239 | MFI.getObjectOffset(FramePtrSpillFI) + GPRCS1Size + ArgRegsSaveSize; | 
| Jim Grosbach | 1b8457a | 2011-08-24 17:46:13 +0000 | [diff] [blame] | 240 | AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr) | 
| Tim Northover | 93bcc66 | 2013-11-08 17:18:07 +0000 | [diff] [blame] | 241 | .addReg(ARM::SP).addImm(FramePtrOffsetInBlock / 4) | 
| Jim Grosbach | 1b8457a | 2011-08-24 17:46:13 +0000 | [diff] [blame] | 242 | .setMIFlags(MachineInstr::FrameSetup)); | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 243 | if(FramePtrOffsetInBlock) { | 
|  | 244 | CFAOffset += FramePtrOffsetInBlock; | 
| Rafael Espindola | b1f25f1 | 2014-03-07 06:08:31 +0000 | [diff] [blame] | 245 | unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createDefCfa( | 
|  | 246 | nullptr, MRI->getDwarfRegNum(FramePtr, true), CFAOffset)); | 
|  | 247 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | 
| Adrian Prantl | d9e64b6 | 2014-12-22 23:09:14 +0000 | [diff] [blame] | 248 | .addCFIIndex(CFIIndex) | 
|  | 249 | .setMIFlags(MachineInstr::FrameSetup); | 
| Rafael Espindola | b1f25f1 | 2014-03-07 06:08:31 +0000 | [diff] [blame] | 250 | } else { | 
|  | 251 | unsigned CFIIndex = | 
|  | 252 | MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister( | 
|  | 253 | nullptr, MRI->getDwarfRegNum(FramePtr, true))); | 
|  | 254 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | 
| Adrian Prantl | d9e64b6 | 2014-12-22 23:09:14 +0000 | [diff] [blame] | 255 | .addCFIIndex(CFIIndex) | 
|  | 256 | .setMIFlags(MachineInstr::FrameSetup); | 
| Rafael Espindola | b1f25f1 | 2014-03-07 06:08:31 +0000 | [diff] [blame] | 257 | } | 
| Jim Grosbach | dca8531 | 2011-06-13 21:18:25 +0000 | [diff] [blame] | 258 | if (NumBytes > 508) | 
|  | 259 | // If offset is > 508 then sp cannot be adjusted in a single instruction, | 
| Evan Cheng | eb56dca | 2010-11-22 18:12:04 +0000 | [diff] [blame] | 260 | // try restoring from fp instead. | 
|  | 261 | AFI->setShouldRestoreSPFromFP(true); | 
|  | 262 | } | 
|  | 263 |  | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 264 | if (NumBytes) { | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 265 | // Insert it after all the callee-save spills. | 
| Anton Korobeynikov | a8d177b | 2011-03-05 18:43:50 +0000 | [diff] [blame] | 266 | emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -NumBytes, | 
|  | 267 | MachineInstr::FrameSetup); | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 268 | if (!HasFP) { | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 269 | CFAOffset -= NumBytes; | 
| Rafael Espindola | b1f25f1 | 2014-03-07 06:08:31 +0000 | [diff] [blame] | 270 | unsigned CFIIndex = MMI.addFrameInst( | 
|  | 271 | MCCFIInstruction::createDefCfaOffset(nullptr, CFAOffset)); | 
|  | 272 | BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) | 
| Adrian Prantl | d9e64b6 | 2014-12-22 23:09:14 +0000 | [diff] [blame] | 273 | .addCFIIndex(CFIIndex) | 
|  | 274 | .setMIFlags(MachineInstr::FrameSetup); | 
| Artyom Skrobov | f6830f4 | 2014-02-14 17:19:07 +0000 | [diff] [blame] | 275 | } | 
|  | 276 | } | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 277 |  | 
| Logan Chien | 53c18d8 | 2013-02-20 12:21:33 +0000 | [diff] [blame] | 278 | if (STI.isTargetELF() && HasFP) | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 279 | MFI.setOffsetAdjustment(MFI.getOffsetAdjustment() - | 
|  | 280 | AFI->getFramePtrSpillOffset()); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 281 |  | 
|  | 282 | AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); | 
|  | 283 | AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); | 
|  | 284 | AFI->setDPRCalleeSavedAreaSize(DPRCSSize); | 
|  | 285 |  | 
| Chad Rosier | add38c1 | 2011-10-20 00:07:12 +0000 | [diff] [blame] | 286 | // Thumb1 does not currently support dynamic stack realignment.  Report a | 
|  | 287 | // fatal error rather then silently generate bad code. | 
|  | 288 | if (RegInfo->needsStackRealignment(MF)) | 
|  | 289 | report_fatal_error("Dynamic stack realignment not supported for thumb1."); | 
| Chad Rosier | 1809d6c | 2011-10-15 00:28:24 +0000 | [diff] [blame] | 290 |  | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 291 | // If we need a base pointer, set it up here. It's whatever the value | 
|  | 292 | // of the stack pointer is at this point. Any variable size objects | 
|  | 293 | // will be allocated after this, so we can still use the base pointer | 
|  | 294 | // to reference locals. | 
|  | 295 | if (RegInfo->hasBasePointer(MF)) | 
| Jim Grosbach | e9cc901 | 2011-06-30 23:38:17 +0000 | [diff] [blame] | 296 | AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), BasePtr) | 
| Jim Grosbach | b98ab91 | 2011-06-30 22:10:46 +0000 | [diff] [blame] | 297 | .addReg(ARM::SP)); | 
| Anton Korobeynikov | a8d177b | 2011-03-05 18:43:50 +0000 | [diff] [blame] | 298 |  | 
| Eric Christopher | 3904343 | 2011-01-11 00:16:04 +0000 | [diff] [blame] | 299 | // If the frame has variable sized objects then the epilogue must restore | 
|  | 300 | // the sp from fp. We can assume there's an FP here since hasFP already | 
|  | 301 | // checks for hasVarSizedObjects. | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 302 | if (MFI.hasVarSizedObjects()) | 
| Eric Christopher | 3904343 | 2011-01-11 00:16:04 +0000 | [diff] [blame] | 303 | AFI->setShouldRestoreSPFromFP(true); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 304 | } | 
|  | 305 |  | 
| Duncan P. N. Exon Smith | 29c5249 | 2016-07-08 20:21:17 +0000 | [diff] [blame] | 306 | static bool isCSRestore(MachineInstr &MI, const MCPhysReg *CSRegs) { | 
|  | 307 | if (MI.getOpcode() == ARM::tLDRspi && MI.getOperand(1).isFI() && | 
|  | 308 | isCalleeSavedRegister(MI.getOperand(0).getReg(), CSRegs)) | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 309 | return true; | 
| Duncan P. N. Exon Smith | 29c5249 | 2016-07-08 20:21:17 +0000 | [diff] [blame] | 310 | else if (MI.getOpcode() == ARM::tPOP) { | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 311 | // The first two operands are predicates. The last two are | 
|  | 312 | // imp-def and imp-use of SP. Check everything in between. | 
| Duncan P. N. Exon Smith | 29c5249 | 2016-07-08 20:21:17 +0000 | [diff] [blame] | 313 | for (int i = 2, e = MI.getNumOperands() - 2; i != e; ++i) | 
|  | 314 | if (!isCalleeSavedRegister(MI.getOperand(i).getReg(), CSRegs)) | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 315 | return false; | 
|  | 316 | return true; | 
|  | 317 | } | 
|  | 318 | return false; | 
|  | 319 | } | 
|  | 320 |  | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 321 | void Thumb1FrameLowering::emitEpilogue(MachineFunction &MF, | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 322 | MachineBasicBlock &MBB) const { | 
| Quentin Colombet | 71a7148 | 2015-07-20 21:42:14 +0000 | [diff] [blame] | 323 | MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); | 
|  | 324 | DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 325 | MachineFrameInfo &MFI = MF.getFrameInfo(); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 326 | ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); | 
| Eric Christopher | ae32649 | 2015-03-12 22:48:50 +0000 | [diff] [blame] | 327 | const ThumbRegisterInfo *RegInfo = | 
|  | 328 | static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 329 | const Thumb1InstrInfo &TII = | 
| Eric Christopher | 1b21f00 | 2015-01-29 00:19:33 +0000 | [diff] [blame] | 330 | *static_cast<const Thumb1InstrInfo *>(STI.getInstrInfo()); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 331 |  | 
| Tim Northover | 8cda34f | 2015-03-11 18:54:22 +0000 | [diff] [blame] | 332 | unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 333 | int NumBytes = (int)MFI.getStackSize(); | 
| David Blaikie | 7f4a52e | 2014-03-05 18:53:36 +0000 | [diff] [blame] | 334 | assert((unsigned)NumBytes >= ArgRegsSaveSize && | 
| Oliver Stannard | d55e115 | 2014-03-05 15:25:27 +0000 | [diff] [blame] | 335 | "ArgRegsSaveSize is included in NumBytes"); | 
| Eric Christopher | 7af95287 | 2015-03-11 21:41:28 +0000 | [diff] [blame] | 336 | const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 337 | unsigned FramePtr = RegInfo->getFrameRegister(MF); | 
|  | 338 |  | 
|  | 339 | if (!AFI->hasStackFrame()) { | 
| Oliver Stannard | d55e115 | 2014-03-05 15:25:27 +0000 | [diff] [blame] | 340 | if (NumBytes - ArgRegsSaveSize != 0) | 
|  | 341 | emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, NumBytes - ArgRegsSaveSize); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 342 | } else { | 
|  | 343 | // Unwind MBBI to point to first LDR / VLDRD. | 
|  | 344 | if (MBBI != MBB.begin()) { | 
|  | 345 | do | 
|  | 346 | --MBBI; | 
| Duncan P. N. Exon Smith | 29c5249 | 2016-07-08 20:21:17 +0000 | [diff] [blame] | 347 | while (MBBI != MBB.begin() && isCSRestore(*MBBI, CSRegs)); | 
|  | 348 | if (!isCSRestore(*MBBI, CSRegs)) | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 349 | ++MBBI; | 
|  | 350 | } | 
|  | 351 |  | 
|  | 352 | // Move SP to start of FP callee save spill area. | 
|  | 353 | NumBytes -= (AFI->getGPRCalleeSavedArea1Size() + | 
|  | 354 | AFI->getGPRCalleeSavedArea2Size() + | 
| Oliver Stannard | d55e115 | 2014-03-05 15:25:27 +0000 | [diff] [blame] | 355 | AFI->getDPRCalleeSavedAreaSize() + | 
|  | 356 | ArgRegsSaveSize); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 357 |  | 
|  | 358 | if (AFI->shouldRestoreSPFromFP()) { | 
|  | 359 | NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; | 
|  | 360 | // Reset SP based on frame pointer only if the stack frame extends beyond | 
| Eric Christopher | 3904343 | 2011-01-11 00:16:04 +0000 | [diff] [blame] | 361 | // frame pointer stack slot, the target is ELF and the function has FP, or | 
|  | 362 | // the target uses var sized objects. | 
| Evan Cheng | eb56dca | 2010-11-22 18:12:04 +0000 | [diff] [blame] | 363 | if (NumBytes) { | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 364 | assert(!MFI.getPristineRegs(MF).test(ARM::R4) && | 
| Evan Cheng | eb56dca | 2010-11-22 18:12:04 +0000 | [diff] [blame] | 365 | "No scratch register to restore SP from FP!"); | 
| Anton Korobeynikov | e7410dd | 2011-03-05 18:43:32 +0000 | [diff] [blame] | 366 | emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, | 
|  | 367 | TII, *RegInfo); | 
| Jim Grosbach | e9cc901 | 2011-06-30 23:38:17 +0000 | [diff] [blame] | 368 | AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), | 
| Jim Grosbach | b98ab91 | 2011-06-30 22:10:46 +0000 | [diff] [blame] | 369 | ARM::SP) | 
|  | 370 | .addReg(ARM::R4)); | 
| Evan Cheng | eb56dca | 2010-11-22 18:12:04 +0000 | [diff] [blame] | 371 | } else | 
| Jim Grosbach | e9cc901 | 2011-06-30 23:38:17 +0000 | [diff] [blame] | 372 | AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), | 
| Jim Grosbach | b98ab91 | 2011-06-30 22:10:46 +0000 | [diff] [blame] | 373 | ARM::SP) | 
|  | 374 | .addReg(FramePtr)); | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 375 | } else { | 
| Quentin Colombet | 71a7148 | 2015-07-20 21:42:14 +0000 | [diff] [blame] | 376 | if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tBX_RET && | 
| Duncan P. N. Exon Smith | 29c5249 | 2016-07-08 20:21:17 +0000 | [diff] [blame] | 377 | &MBB.front() != &*MBBI && std::prev(MBBI)->getOpcode() == ARM::tPOP) { | 
| Benjamin Kramer | b6d0bd4 | 2014-03-02 12:27:27 +0000 | [diff] [blame] | 378 | MachineBasicBlock::iterator PMBBI = std::prev(MBBI); | 
| Duncan P. N. Exon Smith | 29c5249 | 2016-07-08 20:21:17 +0000 | [diff] [blame] | 379 | if (!tryFoldSPUpdateIntoPushPop(STI, MF, &*PMBBI, NumBytes)) | 
| Tim Northover | 93bcc66 | 2013-11-08 17:18:07 +0000 | [diff] [blame] | 380 | emitSPUpdate(MBB, PMBBI, TII, dl, *RegInfo, NumBytes); | 
| Duncan P. N. Exon Smith | 29c5249 | 2016-07-08 20:21:17 +0000 | [diff] [blame] | 381 | } else if (!tryFoldSPUpdateIntoPushPop(STI, MF, &*MBBI, NumBytes)) | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 382 | emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, NumBytes); | 
|  | 383 | } | 
|  | 384 | } | 
|  | 385 |  | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 386 | if (needPopSpecialFixUp(MF)) { | 
|  | 387 | bool Done = emitPopSpecialFixUp(MBB, /* DoIt */ true); | 
|  | 388 | (void)Done; | 
|  | 389 | assert(Done && "Emission of the special fixup failed!?"); | 
|  | 390 | } | 
|  | 391 | } | 
|  | 392 |  | 
|  | 393 | bool Thumb1FrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const { | 
|  | 394 | if (!needPopSpecialFixUp(*MBB.getParent())) | 
|  | 395 | return true; | 
|  | 396 |  | 
|  | 397 | MachineBasicBlock *TmpMBB = const_cast<MachineBasicBlock *>(&MBB); | 
|  | 398 | return emitPopSpecialFixUp(*TmpMBB, /* DoIt */ false); | 
|  | 399 | } | 
|  | 400 |  | 
|  | 401 | bool Thumb1FrameLowering::needPopSpecialFixUp(const MachineFunction &MF) const { | 
|  | 402 | ARMFunctionInfo *AFI = | 
|  | 403 | const_cast<MachineFunction *>(&MF)->getInfo<ARMFunctionInfo>(); | 
|  | 404 | if (AFI->getArgRegsSaveSize()) | 
|  | 405 | return true; | 
|  | 406 |  | 
| Artyom Skrobov | 5d1f252 | 2015-12-01 19:25:11 +0000 | [diff] [blame] | 407 | // LR cannot be encoded with Thumb1, i.e., it requires a special fix-up. | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 408 | for (const CalleeSavedInfo &CSI : MF.getFrameInfo().getCalleeSavedInfo()) | 
| Jonathan Roelofs | ef84bda | 2014-08-05 21:32:21 +0000 | [diff] [blame] | 409 | if (CSI.getReg() == ARM::LR) | 
| Artyom Skrobov | 5d1f252 | 2015-12-01 19:25:11 +0000 | [diff] [blame] | 410 | return true; | 
|  | 411 |  | 
|  | 412 | return false; | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 413 | } | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 414 |  | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 415 | bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, | 
|  | 416 | bool DoIt) const { | 
|  | 417 | MachineFunction &MF = *MBB.getParent(); | 
|  | 418 | ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); | 
|  | 419 | unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); | 
|  | 420 | const TargetInstrInfo &TII = *STI.getInstrInfo(); | 
|  | 421 | const ThumbRegisterInfo *RegInfo = | 
|  | 422 | static_cast<const ThumbRegisterInfo *>(STI.getRegisterInfo()); | 
| Quentin Colombet | 71a7148 | 2015-07-20 21:42:14 +0000 | [diff] [blame] | 423 |  | 
| Artyom Skrobov | 5d1f252 | 2015-12-01 19:25:11 +0000 | [diff] [blame] | 424 | // If MBBI is a return instruction, or is a tPOP followed by a return | 
|  | 425 | // instruction in the successor BB, we may be able to directly restore | 
|  | 426 | // LR in the PC. | 
|  | 427 | // This is only possible with v5T ops (v4T can't change the Thumb bit via | 
|  | 428 | // a POP PC instruction), and only if we do not need to emit any SP update. | 
|  | 429 | // Otherwise, we need a temporary register to pop the value | 
|  | 430 | // and copy that value into LR. | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 431 | auto MBBI = MBB.getFirstTerminator(); | 
| Artyom Skrobov | 5d1f252 | 2015-12-01 19:25:11 +0000 | [diff] [blame] | 432 | bool CanRestoreDirectly = STI.hasV5TOps() && !ArgRegsSaveSize; | 
|  | 433 | if (CanRestoreDirectly) { | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 434 | if (MBBI != MBB.end() && MBBI->getOpcode() != ARM::tB) | 
| Artyom Skrobov | 5d1f252 | 2015-12-01 19:25:11 +0000 | [diff] [blame] | 435 | CanRestoreDirectly = (MBBI->getOpcode() == ARM::tBX_RET || | 
|  | 436 | MBBI->getOpcode() == ARM::tPOP_RET); | 
|  | 437 | else { | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 438 | auto MBBI_prev = MBBI; | 
|  | 439 | MBBI_prev--; | 
|  | 440 | assert(MBBI_prev->getOpcode() == ARM::tPOP); | 
| Artyom Skrobov | 5d1f252 | 2015-12-01 19:25:11 +0000 | [diff] [blame] | 441 | assert(MBB.succ_size() == 1); | 
|  | 442 | if ((*MBB.succ_begin())->begin()->getOpcode() == ARM::tBX_RET) | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 443 | MBBI = MBBI_prev; // Replace the final tPOP with a tPOP_RET. | 
| Artyom Skrobov | 5d1f252 | 2015-12-01 19:25:11 +0000 | [diff] [blame] | 444 | else | 
|  | 445 | CanRestoreDirectly = false; | 
|  | 446 | } | 
|  | 447 | } | 
|  | 448 |  | 
|  | 449 | if (CanRestoreDirectly) { | 
|  | 450 | if (!DoIt || MBBI->getOpcode() == ARM::tPOP_RET) | 
|  | 451 | return true; | 
|  | 452 | MachineInstrBuilder MIB = | 
|  | 453 | AddDefaultPred( | 
|  | 454 | BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP_RET))); | 
|  | 455 | // Copy implicit ops and popped registers, if any. | 
|  | 456 | for (auto MO: MBBI->operands()) | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 457 | if (MO.isReg() && (MO.isImplicit() || MO.isDef())) | 
| Artyom Skrobov | 5d1f252 | 2015-12-01 19:25:11 +0000 | [diff] [blame] | 458 | MIB.addOperand(MO); | 
|  | 459 | MIB.addReg(ARM::PC, RegState::Define); | 
|  | 460 | // Erase the old instruction (tBX_RET or tPOP). | 
|  | 461 | MBB.erase(MBBI); | 
|  | 462 | return true; | 
|  | 463 | } | 
| Quentin Colombet | 71a7148 | 2015-07-20 21:42:14 +0000 | [diff] [blame] | 464 |  | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 465 | // Look for a temporary register to use. | 
|  | 466 | // First, compute the liveness information. | 
|  | 467 | LivePhysRegs UsedRegs(STI.getRegisterInfo()); | 
| Matthias Braun | d1aabb2 | 2016-05-03 00:24:32 +0000 | [diff] [blame] | 468 | UsedRegs.addLiveOuts(MBB); | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 469 | // The semantic of pristines changed recently and now, | 
|  | 470 | // the callee-saved registers that are touched in the function | 
|  | 471 | // are not part of the pristines set anymore. | 
|  | 472 | // Add those callee-saved now. | 
|  | 473 | const TargetRegisterInfo *TRI = STI.getRegisterInfo(); | 
|  | 474 | const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF); | 
|  | 475 | for (unsigned i = 0; CSRegs[i]; ++i) | 
|  | 476 | UsedRegs.addReg(CSRegs[i]); | 
| Quentin Colombet | 71a7148 | 2015-07-20 21:42:14 +0000 | [diff] [blame] | 477 |  | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 478 | DebugLoc dl = DebugLoc(); | 
|  | 479 | if (MBBI != MBB.end()) { | 
|  | 480 | dl = MBBI->getDebugLoc(); | 
|  | 481 | auto InstUpToMBBI = MBB.end(); | 
| Artyom Skrobov | 5d1f252 | 2015-12-01 19:25:11 +0000 | [diff] [blame] | 482 | while (InstUpToMBBI != MBBI) | 
|  | 483 | // The pre-decrement is on purpose here. | 
|  | 484 | // We want to have the liveness right before MBBI. | 
|  | 485 | UsedRegs.stepBackward(*--InstUpToMBBI); | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 486 | } | 
|  | 487 |  | 
|  | 488 | // Look for a register that can be directly use in the POP. | 
|  | 489 | unsigned PopReg = 0; | 
|  | 490 | // And some temporary register, just in case. | 
|  | 491 | unsigned TemporaryReg = 0; | 
|  | 492 | BitVector PopFriendly = | 
|  | 493 | TRI->getAllocatableSet(MF, TRI->getRegClass(ARM::tGPRRegClassID)); | 
|  | 494 | assert(PopFriendly.any() && "No allocatable pop-friendly register?!"); | 
|  | 495 | // Rebuild the GPRs from the high registers because they are removed | 
|  | 496 | // form the GPR reg class for thumb1. | 
|  | 497 | BitVector GPRsNoLRSP = | 
|  | 498 | TRI->getAllocatableSet(MF, TRI->getRegClass(ARM::hGPRRegClassID)); | 
|  | 499 | GPRsNoLRSP |= PopFriendly; | 
|  | 500 | GPRsNoLRSP.reset(ARM::LR); | 
|  | 501 | GPRsNoLRSP.reset(ARM::SP); | 
|  | 502 | GPRsNoLRSP.reset(ARM::PC); | 
|  | 503 | for (int Register = GPRsNoLRSP.find_first(); Register != -1; | 
|  | 504 | Register = GPRsNoLRSP.find_next(Register)) { | 
|  | 505 | if (!UsedRegs.contains(Register)) { | 
|  | 506 | // Remember the first pop-friendly register and exit. | 
|  | 507 | if (PopFriendly.test(Register)) { | 
|  | 508 | PopReg = Register; | 
|  | 509 | TemporaryReg = 0; | 
|  | 510 | break; | 
| Quentin Colombet | 71a7148 | 2015-07-20 21:42:14 +0000 | [diff] [blame] | 511 | } | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 512 | // Otherwise, remember that the register will be available to | 
|  | 513 | // save a pop-friendly register. | 
|  | 514 | TemporaryReg = Register; | 
| Jonathan Roelofs | ef84bda | 2014-08-05 21:32:21 +0000 | [diff] [blame] | 515 | } | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 516 | } | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 517 |  | 
|  | 518 | if (!DoIt && !PopReg && !TemporaryReg) | 
|  | 519 | return false; | 
|  | 520 |  | 
|  | 521 | assert((PopReg || TemporaryReg) && "Cannot get LR"); | 
|  | 522 |  | 
|  | 523 | if (TemporaryReg) { | 
|  | 524 | assert(!PopReg && "Unnecessary MOV is about to be inserted"); | 
|  | 525 | PopReg = PopFriendly.find_first(); | 
|  | 526 | AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) | 
|  | 527 | .addReg(TemporaryReg, RegState::Define) | 
|  | 528 | .addReg(PopReg, RegState::Kill)); | 
|  | 529 | } | 
|  | 530 |  | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 531 | if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPOP_RET) { | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 532 | // We couldn't use the direct restoration above, so | 
|  | 533 | // perform the opposite conversion: tPOP_RET to tPOP. | 
|  | 534 | MachineInstrBuilder MIB = | 
|  | 535 | AddDefaultPred( | 
|  | 536 | BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.get(ARM::tPOP))); | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 537 | bool Popped = false; | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 538 | for (auto MO: MBBI->operands()) | 
|  | 539 | if (MO.isReg() && (MO.isImplicit() || MO.isDef()) && | 
|  | 540 | MO.getReg() != ARM::PC) { | 
|  | 541 | MIB.addOperand(MO); | 
|  | 542 | if (!MO.isImplicit()) | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 543 | Popped = true; | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 544 | } | 
|  | 545 | // Is there anything left to pop? | 
|  | 546 | if (!Popped) | 
|  | 547 | MBB.erase(MIB.getInstr()); | 
|  | 548 | // Erase the old instruction. | 
|  | 549 | MBB.erase(MBBI); | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 550 | MBBI = AddDefaultPred(BuildMI(MBB, MBB.end(), dl, TII.get(ARM::tBX_RET))); | 
| Artyom Skrobov | 5d1f252 | 2015-12-01 19:25:11 +0000 | [diff] [blame] | 551 | } | 
|  | 552 |  | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 553 | assert(PopReg && "Do not know how to get LR"); | 
|  | 554 | AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP))) | 
|  | 555 | .addReg(PopReg, RegState::Define); | 
|  | 556 |  | 
|  | 557 | emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, ArgRegsSaveSize); | 
|  | 558 |  | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 559 | AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) | 
|  | 560 | .addReg(ARM::LR, RegState::Define) | 
|  | 561 | .addReg(PopReg, RegState::Kill)); | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 562 |  | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 563 | if (TemporaryReg) | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 564 | AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr)) | 
|  | 565 | .addReg(PopReg, RegState::Define) | 
|  | 566 | .addReg(TemporaryReg, RegState::Kill)); | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 567 |  | 
|  | 568 | return true; | 
| Anton Korobeynikov | f7183ed | 2010-11-15 00:06:54 +0000 | [diff] [blame] | 569 | } | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 570 |  | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 571 | bool Thumb1FrameLowering:: | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 572 | spillCalleeSavedRegisters(MachineBasicBlock &MBB, | 
|  | 573 | MachineBasicBlock::iterator MI, | 
|  | 574 | const std::vector<CalleeSavedInfo> &CSI, | 
|  | 575 | const TargetRegisterInfo *TRI) const { | 
|  | 576 | if (CSI.empty()) | 
|  | 577 | return false; | 
|  | 578 |  | 
| Tim Northover | 775aaeb | 2015-11-05 21:54:58 +0000 | [diff] [blame] | 579 | DebugLoc DL; | 
|  | 580 | const TargetInstrInfo &TII = *STI.getInstrInfo(); | 
|  | 581 |  | 
|  | 582 | MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(ARM::tPUSH)); | 
|  | 583 | AddDefaultPred(MIB); | 
|  | 584 | for (unsigned i = CSI.size(); i != 0; --i) { | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 585 | unsigned Reg = CSI[i-1].getReg(); | 
|  | 586 | bool isKill = true; | 
|  | 587 |  | 
|  | 588 | // Add the callee-saved register as live-in unless it's LR and | 
|  | 589 | // @llvm.returnaddress is called. If LR is returned for @llvm.returnaddress | 
|  | 590 | // then it's already added to the function and entry block live-in sets. | 
|  | 591 | if (Reg == ARM::LR) { | 
|  | 592 | MachineFunction &MF = *MBB.getParent(); | 
| Matthias Braun | 941a705 | 2016-07-28 18:40:00 +0000 | [diff] [blame] | 593 | if (MF.getFrameInfo().isReturnAddressTaken() && | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 594 | MF.getRegInfo().isLiveIn(Reg)) | 
|  | 595 | isKill = false; | 
|  | 596 | } | 
|  | 597 |  | 
|  | 598 | if (isKill) | 
|  | 599 | MBB.addLiveIn(Reg); | 
|  | 600 |  | 
|  | 601 | MIB.addReg(Reg, getKillRegState(isKill)); | 
|  | 602 | } | 
| Anton Korobeynikov | a8d177b | 2011-03-05 18:43:50 +0000 | [diff] [blame] | 603 | MIB.setMIFlags(MachineInstr::FrameSetup); | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 604 | return true; | 
|  | 605 | } | 
|  | 606 |  | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 607 | bool Thumb1FrameLowering:: | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 608 | restoreCalleeSavedRegisters(MachineBasicBlock &MBB, | 
|  | 609 | MachineBasicBlock::iterator MI, | 
|  | 610 | const std::vector<CalleeSavedInfo> &CSI, | 
|  | 611 | const TargetRegisterInfo *TRI) const { | 
|  | 612 | if (CSI.empty()) | 
|  | 613 | return false; | 
|  | 614 |  | 
|  | 615 | MachineFunction &MF = *MBB.getParent(); | 
|  | 616 | ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); | 
| Eric Christopher | 1b21f00 | 2015-01-29 00:19:33 +0000 | [diff] [blame] | 617 | const TargetInstrInfo &TII = *STI.getInstrInfo(); | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 618 |  | 
| Stepan Dyatkovskiy | f5aa83d | 2013-04-30 07:19:58 +0000 | [diff] [blame] | 619 | bool isVarArg = AFI->getArgRegsSaveSize() > 0; | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 620 | DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(); | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 621 | MachineInstrBuilder MIB = BuildMI(MF, DL, TII.get(ARM::tPOP)); | 
|  | 622 | AddDefaultPred(MIB); | 
|  | 623 |  | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 624 | bool NeedsPop = false; | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 625 | for (unsigned i = CSI.size(); i != 0; --i) { | 
|  | 626 | unsigned Reg = CSI[i-1].getReg(); | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 627 | if (Reg == ARM::LR) { | 
|  | 628 | if (MBB.succ_empty()) { | 
|  | 629 | // Special epilogue for vararg functions. See emitEpilogue | 
|  | 630 | if (isVarArg) | 
|  | 631 | continue; | 
|  | 632 | // ARMv4T requires BX, see emitEpilogue | 
|  | 633 | if (!STI.hasV5TOps()) | 
|  | 634 | continue; | 
|  | 635 | Reg = ARM::PC; | 
|  | 636 | (*MIB).setDesc(TII.get(ARM::tPOP_RET)); | 
|  | 637 | if (MI != MBB.end()) | 
| Duncan P. N. Exon Smith | fd8cc23 | 2016-02-27 20:01:33 +0000 | [diff] [blame] | 638 | MIB.copyImplicitOps(*MI); | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 639 | MI = MBB.erase(MI); | 
|  | 640 | } else | 
|  | 641 | // LR may only be popped into PC, as part of return sequence. | 
|  | 642 | // If this isn't the return sequence, we'll need emitPopSpecialFixUp | 
|  | 643 | // to restore LR the hard way. | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 644 | continue; | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 645 | } | 
|  | 646 | MIB.addReg(Reg, getDefRegState(true)); | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 647 | NeedsPop = true; | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 648 | } | 
|  | 649 |  | 
|  | 650 | // It's illegal to emit pop instruction without operands. | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 651 | if (NeedsPop) | 
| Anton Korobeynikov | d08fbd1 | 2010-11-27 23:05:03 +0000 | [diff] [blame] | 652 | MBB.insert(MI, &*MIB); | 
|  | 653 | else | 
|  | 654 | MF.DeleteMachineInstr(MIB); | 
|  | 655 |  | 
|  | 656 | return true; | 
|  | 657 | } |