1 //=====- SystemZFrameLowering.cpp - SystemZ Frame Information ------*- C++ -*-====// 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 // 10 // This file contains the SystemZ implementation of TargetFrameLowering class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "SystemZFrameLowering.h" 15 #include "SystemZInstrBuilder.h" 16 #include "SystemZInstrInfo.h" 17 #include "SystemZMachineFunctionInfo.h" 18 #include "llvm/Function.h" 19 #include "llvm/CodeGen/MachineFrameInfo.h" 20 #include "llvm/CodeGen/MachineFunction.h" 21 #include "llvm/CodeGen/MachineInstrBuilder.h" 22 #include "llvm/CodeGen/MachineModuleInfo.h" 23 #include "llvm/CodeGen/MachineRegisterInfo.h" 24 #include "llvm/Target/TargetData.h" 25 #include "llvm/Target/TargetOptions.h" 26 #include "llvm/Support/CommandLine.h" 27 28 using namespace llvm; 29 30 SystemZFrameLowering::SystemZFrameLowering(const SystemZSubtarget &sti) 31 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 8, -160), STI(sti) { 32 // Fill the spill offsets map 33 static const unsigned SpillOffsTab[][2] = { 34 { SystemZ::R2D, 0x10 }, 35 { SystemZ::R3D, 0x18 }, 36 { SystemZ::R4D, 0x20 }, 37 { SystemZ::R5D, 0x28 }, 38 { SystemZ::R6D, 0x30 }, 39 { SystemZ::R7D, 0x38 }, 40 { SystemZ::R8D, 0x40 }, 41 { SystemZ::R9D, 0x48 }, 42 { SystemZ::R10D, 0x50 }, 43 { SystemZ::R11D, 0x58 }, 44 { SystemZ::R12D, 0x60 }, 45 { SystemZ::R13D, 0x68 }, 46 { SystemZ::R14D, 0x70 }, 47 { SystemZ::R15D, 0x78 } 48 }; 49 50 RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS); 51 52 for (unsigned i = 0, e = array_lengthof(SpillOffsTab); i != e; ++i) 53 RegSpillOffsets[SpillOffsTab[i][0]] = SpillOffsTab[i][1]; 54 } 55 56 /// needsFP - Return true if the specified function should have a dedicated 57 /// frame pointer register. This is true if the function has variable sized 58 /// allocas or if frame pointer elimination is disabled. 59 bool SystemZFrameLowering::hasFP(const MachineFunction &MF) const { 60 const MachineFrameInfo *MFI = MF.getFrameInfo(); 61 return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects(); 62 } 63 64 /// emitSPUpdate - Emit a series of instructions to increment / decrement the 65 /// stack pointer by a constant value. 66 static 67 void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, 68 int64_t NumBytes, const TargetInstrInfo &TII) { 69 unsigned Opc; uint64_t Chunk; 70 bool isSub = NumBytes < 0; 71 uint64_t Offset = isSub ? -NumBytes : NumBytes; 72 73 if (Offset >= (1LL << 15) - 1) { 74 Opc = SystemZ::ADD64ri32; 75 Chunk = (1LL << 31) - 1; 76 } else { 77 Opc = SystemZ::ADD64ri16; 78 Chunk = (1LL << 15) - 1; 79 } 80 81 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 82 83 while (Offset) { 84 uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset; 85 MachineInstr *MI = 86 BuildMI(MBB, MBBI, DL, TII.get(Opc), SystemZ::R15D) 87 .addReg(SystemZ::R15D).addImm(isSub ? -ThisVal : ThisVal); 88 // The PSW implicit def is dead. 89 MI->getOperand(3).setIsDead(); 90 Offset -= ThisVal; 91 } 92 } 93 94 void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const { 95 MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB 96 MachineFrameInfo *MFI = MF.getFrameInfo(); 97 const SystemZInstrInfo &TII = 98 *static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo()); 99 SystemZMachineFunctionInfo *SystemZMFI = 100 MF.getInfo<SystemZMachineFunctionInfo>(); 101 MachineBasicBlock::iterator MBBI = MBB.begin(); 102 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 103 104 // Get the number of bytes to allocate from the FrameInfo. 105 // Note that area for callee-saved stuff is already allocated, thus we need to 106 // 'undo' the stack movement. 107 uint64_t StackSize = MFI->getStackSize(); 108 StackSize -= SystemZMFI->getCalleeSavedFrameSize(); 109 110 uint64_t NumBytes = StackSize - getOffsetOfLocalArea(); 111 112 // Skip the callee-saved push instructions. 113 while (MBBI != MBB.end() && 114 (MBBI->getOpcode() == SystemZ::MOV64mr || 115 MBBI->getOpcode() == SystemZ::MOV64mrm)) 116 ++MBBI; 117 118 if (MBBI != MBB.end()) 119 DL = MBBI->getDebugLoc(); 120 121 // adjust stack pointer: R15 -= numbytes 122 if (StackSize || MFI->hasCalls()) { 123 assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) && 124 "Invalid stack frame calculation!"); 125 emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, TII); 126 } 127 128 if (hasFP(MF)) { 129 // Update R11 with the new base value... 130 BuildMI(MBB, MBBI, DL, TII.get(SystemZ::MOV64rr), SystemZ::R11D) 131 .addReg(SystemZ::R15D); 132 133 // Mark the FramePtr as live-in in every block except the entry. 134 for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end(); 135 I != E; ++I) 136 I->addLiveIn(SystemZ::R11D); 137 138 } 139 } 140 141 void SystemZFrameLowering::emitEpilogue(MachineFunction &MF, 142 MachineBasicBlock &MBB) const { 143 const MachineFrameInfo *MFI = MF.getFrameInfo(); 144 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 145 const SystemZInstrInfo &TII = 146 *static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo()); 147 SystemZMachineFunctionInfo *SystemZMFI = 148 MF.getInfo<SystemZMachineFunctionInfo>(); 149 unsigned RetOpcode = MBBI->getOpcode(); 150 151 switch (RetOpcode) { 152 case SystemZ::RET: break; // These are ok 153 default: 154 assert(0 && "Can only insert epilog into returning blocks"); 155 } 156 157 // Get the number of bytes to allocate from the FrameInfo 158 // Note that area for callee-saved stuff is already allocated, thus we need to 159 // 'undo' the stack movement. 160 uint64_t StackSize = 161 MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize(); 162 uint64_t NumBytes = StackSize - getOffsetOfLocalArea(); 163 164 // Skip the final terminator instruction. 165 while (MBBI != MBB.begin()) { 166 MachineBasicBlock::iterator PI = prior(MBBI); 167 --MBBI; 168 if (!PI->getDesc().isTerminator()) 169 break; 170 } 171 172 // During callee-saved restores emission stack frame was not yet finialized 173 // (and thus - the stack size was unknown). Tune the offset having full stack 174 // size in hands. 175 if (StackSize || MFI->hasCalls()) { 176 assert((MBBI->getOpcode() == SystemZ::MOV64rmm || 177 MBBI->getOpcode() == SystemZ::MOV64rm) && 178 "Expected to see callee-save register restore code"); 179 assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) && 180 "Invalid stack frame calculation!"); 181 182 unsigned i = 0; 183 MachineInstr &MI = *MBBI; 184 while (!MI.getOperand(i).isImm()) { 185 ++i; 186 assert(i < MI.getNumOperands() && "Unexpected restore code!"); 187 } 188 189 uint64_t Offset = NumBytes + MI.getOperand(i).getImm(); 190 // If Offset does not fit into 20-bit signed displacement field we need to 191 // emit some additional code... 192 if (Offset > 524287) { 193 // Fold the displacement into load instruction as much as possible. 194 NumBytes = Offset - 524287; 195 Offset = 524287; 196 emitSPUpdate(MBB, MBBI, NumBytes, TII); 197 } 198 199 MI.getOperand(i).ChangeToImmediate(Offset); 200 } 201 } 202 203 int SystemZFrameLowering::getFrameIndexOffset(const MachineFunction &MF, 204 int FI) const { 205 const MachineFrameInfo *MFI = MF.getFrameInfo(); 206 const SystemZMachineFunctionInfo *SystemZMFI = 207 MF.getInfo<SystemZMachineFunctionInfo>(); 208 int Offset = MFI->getObjectOffset(FI) + MFI->getOffsetAdjustment(); 209 uint64_t StackSize = MFI->getStackSize(); 210 211 // Fixed objects are really located in the "previous" frame. 212 if (FI < 0) 213 StackSize -= SystemZMFI->getCalleeSavedFrameSize(); 214 215 Offset += StackSize - getOffsetOfLocalArea(); 216 217 // Skip the register save area if we generated the stack frame. 218 if (StackSize || MFI->hasCalls()) 219 Offset -= getOffsetOfLocalArea(); 220 221 return Offset; 222 } 223 224 bool 225 SystemZFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, 226 MachineBasicBlock::iterator MI, 227 const std::vector<CalleeSavedInfo> &CSI, 228 const TargetRegisterInfo *TRI) const { 229 if (CSI.empty()) 230 return false; 231 232 DebugLoc DL; 233 if (MI != MBB.end()) DL = MI->getDebugLoc(); 234 235 MachineFunction &MF = *MBB.getParent(); 236 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 237 SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); 238 unsigned CalleeFrameSize = 0; 239 240 // Scan the callee-saved and find the bounds of register spill area. 241 unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0; 242 for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 243 unsigned Reg = CSI[i].getReg(); 244 if (!SystemZ::FP64RegClass.contains(Reg)) { 245 unsigned Offset = RegSpillOffsets[Reg]; 246 CalleeFrameSize += 8; 247 if (StartOffset > Offset) { 248 LowReg = Reg; StartOffset = Offset; 249 } 250 if (EndOffset < Offset) { 251 HighReg = Reg; EndOffset = RegSpillOffsets[Reg]; 252 } 253 } 254 } 255 256 // Save information for epilogue inserter. 257 MFI->setCalleeSavedFrameSize(CalleeFrameSize); 258 MFI->setLowReg(LowReg); MFI->setHighReg(HighReg); 259 260 // Save GPRs 261 if (StartOffset) { 262 // Build a store instruction. Use STORE MULTIPLE instruction if there are many 263 // registers to store, otherwise - just STORE. 264 MachineInstrBuilder MIB = 265 BuildMI(MBB, MI, DL, TII.get((LowReg == HighReg ? 266 SystemZ::MOV64mr : SystemZ::MOV64mrm))); 267 268 // Add store operands. 269 MIB.addReg(SystemZ::R15D).addImm(StartOffset); 270 if (LowReg == HighReg) 271 MIB.addReg(0); 272 MIB.addReg(LowReg, RegState::Kill); 273 if (LowReg != HighReg) 274 MIB.addReg(HighReg, RegState::Kill); 275 276 // Do a second scan adding regs as being killed by instruction 277 for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 278 unsigned Reg = CSI[i].getReg(); 279 // Add the callee-saved register as live-in. It's killed at the spill. 280 MBB.addLiveIn(Reg); 281 if (Reg != LowReg && Reg != HighReg) 282 MIB.addReg(Reg, RegState::ImplicitKill); 283 } 284 } 285 286 // Save FPRs 287 for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 288 unsigned Reg = CSI[i].getReg(); 289 if (SystemZ::FP64RegClass.contains(Reg)) { 290 MBB.addLiveIn(Reg); 291 TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), 292 &SystemZ::FP64RegClass, TRI); 293 } 294 } 295 296 return true; 297 } 298 299 bool 300 SystemZFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 301 MachineBasicBlock::iterator MI, 302 const std::vector<CalleeSavedInfo> &CSI, 303 const TargetRegisterInfo *TRI) const { 304 if (CSI.empty()) 305 return false; 306 307 DebugLoc DL; 308 if (MI != MBB.end()) DL = MI->getDebugLoc(); 309 310 MachineFunction &MF = *MBB.getParent(); 311 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); 312 SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); 313 314 // Restore FP registers 315 for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 316 unsigned Reg = CSI[i].getReg(); 317 if (SystemZ::FP64RegClass.contains(Reg)) 318 TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), 319 &SystemZ::FP64RegClass, TRI); 320 } 321 322 // Restore GP registers 323 unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg(); 324 unsigned StartOffset = RegSpillOffsets[LowReg]; 325 326 if (StartOffset) { 327 // Build a load instruction. Use LOAD MULTIPLE instruction if there are many 328 // registers to load, otherwise - just LOAD. 329 MachineInstrBuilder MIB = 330 BuildMI(MBB, MI, DL, TII.get((LowReg == HighReg ? 331 SystemZ::MOV64rm : SystemZ::MOV64rmm))); 332 // Add store operands. 333 MIB.addReg(LowReg, RegState::Define); 334 if (LowReg != HighReg) 335 MIB.addReg(HighReg, RegState::Define); 336 337 MIB.addReg(hasFP(MF) ? SystemZ::R11D : SystemZ::R15D); 338 MIB.addImm(StartOffset); 339 if (LowReg == HighReg) 340 MIB.addReg(0); 341 342 // Do a second scan adding regs as being defined by instruction 343 for (unsigned i = 0, e = CSI.size(); i != e; ++i) { 344 unsigned Reg = CSI[i].getReg(); 345 if (Reg != LowReg && Reg != HighReg) 346 MIB.addReg(Reg, RegState::ImplicitDefine); 347 } 348 } 349 350 return true; 351 } 352 353 void 354 SystemZFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, 355 RegScavenger *RS) const { 356 // Determine whether R15/R14 will ever be clobbered inside the function. And 357 // if yes - mark it as 'callee' saved. 358 MachineFrameInfo *FFI = MF.getFrameInfo(); 359 MachineRegisterInfo &MRI = MF.getRegInfo(); 360 361 // Check whether high FPRs are ever used, if yes - we need to save R15 as 362 // well. 363 static const unsigned HighFPRs[] = { 364 SystemZ::F8L, SystemZ::F9L, SystemZ::F10L, SystemZ::F11L, 365 SystemZ::F12L, SystemZ::F13L, SystemZ::F14L, SystemZ::F15L, 366 SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S, 367 SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S, 368 }; 369 370 bool HighFPRsUsed = false; 371 for (unsigned i = 0, e = array_lengthof(HighFPRs); i != e; ++i) 372 HighFPRsUsed |= MRI.isPhysRegUsed(HighFPRs[i]); 373 374 if (FFI->hasCalls()) 375 /* FIXME: function is varargs */ 376 /* FIXME: function grabs RA */ 377 /* FIXME: function calls eh_return */ 378 MRI.setPhysRegUsed(SystemZ::R14D); 379 380 if (HighFPRsUsed || 381 FFI->hasCalls() || 382 FFI->getObjectIndexEnd() != 0 || // Contains automatic variables 383 FFI->hasVarSizedObjects() // Function calls dynamic alloca's 384 /* FIXME: function is varargs */) 385 MRI.setPhysRegUsed(SystemZ::R15D); 386 } 387