1 //===-- VEFrameLowering.cpp - VE Frame Information ------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains the VE implementation of TargetFrameLowering class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "VEFrameLowering.h" 14 #include "VEInstrInfo.h" 15 #include "VEMachineFunctionInfo.h" 16 #include "VESubtarget.h" 17 #include "llvm/CodeGen/MachineFrameInfo.h" 18 #include "llvm/CodeGen/MachineFunction.h" 19 #include "llvm/CodeGen/MachineInstrBuilder.h" 20 #include "llvm/CodeGen/MachineModuleInfo.h" 21 #include "llvm/CodeGen/MachineRegisterInfo.h" 22 #include "llvm/CodeGen/RegisterScavenging.h" 23 #include "llvm/IR/DataLayout.h" 24 #include "llvm/IR/Function.h" 25 #include "llvm/Support/CommandLine.h" 26 #include "llvm/Target/TargetOptions.h" 27 #include "llvm/Support/MathExtras.h" 28 29 using namespace llvm; 30 31 VEFrameLowering::VEFrameLowering(const VESubtarget &ST) 32 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(16), 0, 33 Align(16)), 34 STI(ST) {} 35 36 void VEFrameLowering::emitPrologueInsns(MachineFunction &MF, 37 MachineBasicBlock &MBB, 38 MachineBasicBlock::iterator MBBI, 39 uint64_t NumBytes, 40 bool RequireFPUpdate) const { 41 42 DebugLoc dl; 43 const VEInstrInfo &TII = 44 *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); 45 // Insert following codes here as prologue 46 // 47 // st %fp, 0(,%sp) 48 // st %lr, 8(,%sp) 49 // st %got, 24(,%sp) 50 // st %plt, 32(,%sp) 51 // st %s17, 40(,%sp) iff this function is using s17 as BP 52 // or %fp, 0, %sp 53 54 BuildMI(MBB, MBBI, dl, TII.get(VE::STrii)) 55 .addReg(VE::SX11) 56 .addImm(0) 57 .addImm(0) 58 .addReg(VE::SX9); 59 BuildMI(MBB, MBBI, dl, TII.get(VE::STrii)) 60 .addReg(VE::SX11) 61 .addImm(0) 62 .addImm(8) 63 .addReg(VE::SX10); 64 BuildMI(MBB, MBBI, dl, TII.get(VE::STrii)) 65 .addReg(VE::SX11) 66 .addImm(0) 67 .addImm(24) 68 .addReg(VE::SX15); 69 BuildMI(MBB, MBBI, dl, TII.get(VE::STrii)) 70 .addReg(VE::SX11) 71 .addImm(0) 72 .addImm(32) 73 .addReg(VE::SX16); 74 if (hasBP(MF)) 75 BuildMI(MBB, MBBI, dl, TII.get(VE::STrii)) 76 .addReg(VE::SX11) 77 .addImm(0) 78 .addImm(40) 79 .addReg(VE::SX17); 80 BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX9) 81 .addReg(VE::SX11) 82 .addImm(0); 83 } 84 85 void VEFrameLowering::emitEpilogueInsns(MachineFunction &MF, 86 MachineBasicBlock &MBB, 87 MachineBasicBlock::iterator MBBI, 88 uint64_t NumBytes, 89 bool RequireFPUpdate) const { 90 91 DebugLoc dl; 92 const VEInstrInfo &TII = 93 *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); 94 // Insert following codes here as epilogue 95 // 96 // or %sp, 0, %fp 97 // ld %s17, 40(,%sp) iff this function is using s17 as BP 98 // ld %got, 32(,%sp) 99 // ld %plt, 24(,%sp) 100 // ld %lr, 8(,%sp) 101 // ld %fp, 0(,%sp) 102 103 BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX11) 104 .addReg(VE::SX9) 105 .addImm(0); 106 if (hasBP(MF)) 107 BuildMI(MBB, MBBI, dl, TII.get(VE::LDrii), VE::SX17) 108 .addReg(VE::SX11) 109 .addImm(0) 110 .addImm(40); 111 BuildMI(MBB, MBBI, dl, TII.get(VE::LDrii), VE::SX16) 112 .addReg(VE::SX11) 113 .addImm(0) 114 .addImm(32); 115 BuildMI(MBB, MBBI, dl, TII.get(VE::LDrii), VE::SX15) 116 .addReg(VE::SX11) 117 .addImm(0) 118 .addImm(24); 119 BuildMI(MBB, MBBI, dl, TII.get(VE::LDrii), VE::SX10) 120 .addReg(VE::SX11) 121 .addImm(0) 122 .addImm(8); 123 BuildMI(MBB, MBBI, dl, TII.get(VE::LDrii), VE::SX9) 124 .addReg(VE::SX11) 125 .addImm(0) 126 .addImm(0); 127 } 128 129 void VEFrameLowering::emitSPAdjustment(MachineFunction &MF, 130 MachineBasicBlock &MBB, 131 MachineBasicBlock::iterator MBBI, 132 int64_t NumBytes, 133 MaybeAlign MaybeAlign) const { 134 DebugLoc dl; 135 const VEInstrInfo &TII = 136 *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); 137 138 if (NumBytes >= -64 && NumBytes < 63) { 139 BuildMI(MBB, MBBI, dl, TII.get(VE::ADDSLri), VE::SX11) 140 .addReg(VE::SX11) 141 .addImm(NumBytes); 142 return; 143 } 144 145 // Emit following codes. This clobbers SX13 which we always know is 146 // available here. 147 // lea %s13,%lo(NumBytes) 148 // and %s13,%s13,(32)0 149 // lea.sl %sp,%hi(NumBytes)(%sp, %s13) 150 BuildMI(MBB, MBBI, dl, TII.get(VE::LEAzii), VE::SX13) 151 .addImm(0) 152 .addImm(0) 153 .addImm(Lo_32(NumBytes)); 154 BuildMI(MBB, MBBI, dl, TII.get(VE::ANDrm), VE::SX13) 155 .addReg(VE::SX13) 156 .addImm(M0(32)); 157 BuildMI(MBB, MBBI, dl, TII.get(VE::LEASLrri), VE::SX11) 158 .addReg(VE::SX11) 159 .addReg(VE::SX13) 160 .addImm(Hi_32(NumBytes)); 161 162 if (MaybeAlign) { 163 // and %sp, %sp, Align-1 164 BuildMI(MBB, MBBI, dl, TII.get(VE::ANDrm), VE::SX11) 165 .addReg(VE::SX11) 166 .addImm(M1(64 - Log2_64(MaybeAlign.valueOrOne().value()))); 167 } 168 } 169 170 void VEFrameLowering::emitSPExtend(MachineFunction &MF, MachineBasicBlock &MBB, 171 MachineBasicBlock::iterator MBBI) const { 172 DebugLoc dl; 173 const VEInstrInfo &TII = 174 *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); 175 176 // Emit following codes. It is not possible to insert multiple 177 // BasicBlocks in PEI pass, so we emit two pseudo instructions here. 178 // 179 // EXTEND_STACK // pseudo instrcution 180 // EXTEND_STACK_GUARD // pseudo instrcution 181 // 182 // EXTEND_STACK pseudo will be converted by ExpandPostRA pass into 183 // following instructions with multiple basic blocks later. 184 // 185 // thisBB: 186 // brge.l.t %sp, %sl, sinkBB 187 // syscallBB: 188 // ld %s61, 0x18(, %tp) // load param area 189 // or %s62, 0, %s0 // spill the value of %s0 190 // lea %s63, 0x13b // syscall # of grow 191 // shm.l %s63, 0x0(%s61) // store syscall # at addr:0 192 // shm.l %sl, 0x8(%s61) // store old limit at addr:8 193 // shm.l %sp, 0x10(%s61) // store new limit at addr:16 194 // monc // call monitor 195 // or %s0, 0, %s62 // restore the value of %s0 196 // sinkBB: 197 // 198 // EXTEND_STACK_GUARD pseudo will be simply eliminated by ExpandPostRA 199 // pass. This pseudo is required to be at the next of EXTEND_STACK 200 // pseudo in order to protect iteration loop in ExpandPostRA. 201 202 BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK)); 203 BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK_GUARD)); 204 } 205 206 void VEFrameLowering::emitPrologue(MachineFunction &MF, 207 MachineBasicBlock &MBB) const { 208 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); 209 MachineFrameInfo &MFI = MF.getFrameInfo(); 210 const VEInstrInfo &TII = *STI.getInstrInfo(); 211 const VERegisterInfo &RegInfo = *STI.getRegisterInfo(); 212 MachineBasicBlock::iterator MBBI = MBB.begin(); 213 // Debug location must be unknown since the first debug location is used 214 // to determine the end of the prologue. 215 DebugLoc dl; 216 bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF); 217 218 // FIXME: unfortunately, returning false from canRealignStack 219 // actually just causes needsStackRealignment to return false, 220 // rather than reporting an error, as would be sensible. This is 221 // poor, but fixing that bogosity is going to be a large project. 222 // For now, just see if it's lied, and report an error here. 223 if (!NeedsStackRealignment && MFI.getMaxAlign() > getStackAlign()) 224 report_fatal_error("Function \"" + Twine(MF.getName()) + 225 "\" required " 226 "stack re-alignment, but LLVM couldn't handle it " 227 "(probably because it has a dynamic alloca)."); 228 229 // Get the number of bytes to allocate from the FrameInfo 230 uint64_t NumBytes = MFI.getStackSize(); 231 232 // The VE ABI requires a reserved 176 bytes area at the top 233 // of stack as described in VESubtarget.cpp. So, we adjust it here. 234 NumBytes = STI.getAdjustedFrameSize(NumBytes); 235 236 // Finally, ensure that the size is sufficiently aligned for the 237 // data on the stack. 238 NumBytes = alignTo(NumBytes, MFI.getMaxAlign()); 239 240 // Update stack size with corrected value. 241 MFI.setStackSize(NumBytes); 242 243 // Emit Prologue instructions to save %lr 244 emitPrologueInsns(MF, MBB, MBBI, NumBytes, true); 245 246 // Emit stack adjust instructions 247 MaybeAlign RuntimeAlign = 248 NeedsStackRealignment ? MaybeAlign(MFI.getMaxAlign()) : None; 249 emitSPAdjustment(MF, MBB, MBBI, -(int64_t)NumBytes, RuntimeAlign); 250 251 if (hasBP(MF)) { 252 // Copy SP to BP. 253 BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX17) 254 .addReg(VE::SX11) 255 .addImm(0); 256 } 257 258 // Emit stack extend instructions 259 emitSPExtend(MF, MBB, MBBI); 260 261 Register RegFP = RegInfo.getDwarfRegNum(VE::SX9, true); 262 263 // Emit ".cfi_def_cfa_register 30". 264 unsigned CFIIndex = 265 MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, RegFP)); 266 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 267 .addCFIIndex(CFIIndex); 268 269 // Emit ".cfi_window_save". 270 CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr)); 271 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 272 .addCFIIndex(CFIIndex); 273 } 274 275 MachineBasicBlock::iterator VEFrameLowering::eliminateCallFramePseudoInstr( 276 MachineFunction &MF, MachineBasicBlock &MBB, 277 MachineBasicBlock::iterator I) const { 278 if (!hasReservedCallFrame(MF)) { 279 MachineInstr &MI = *I; 280 int64_t Size = MI.getOperand(0).getImm(); 281 if (MI.getOpcode() == VE::ADJCALLSTACKDOWN) 282 Size = -Size; 283 284 if (Size) 285 emitSPAdjustment(MF, MBB, I, Size); 286 } 287 return MBB.erase(I); 288 } 289 290 void VEFrameLowering::emitEpilogue(MachineFunction &MF, 291 MachineBasicBlock &MBB) const { 292 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 293 DebugLoc dl = MBBI->getDebugLoc(); 294 MachineFrameInfo &MFI = MF.getFrameInfo(); 295 296 uint64_t NumBytes = MFI.getStackSize(); 297 298 // Emit Epilogue instructions to restore %lr 299 emitEpilogueInsns(MF, MBB, MBBI, NumBytes, true); 300 } 301 302 // hasFP - Return true if the specified function should have a dedicated frame 303 // pointer register. This is true if the function has variable sized allocas 304 // or if frame pointer elimination is disabled. For the case of VE, we don't 305 // implement FP eliminator yet, but we returns false from this function to 306 // not refer fp from generated code. 307 bool VEFrameLowering::hasFP(const MachineFunction &MF) const { 308 const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 309 310 const MachineFrameInfo &MFI = MF.getFrameInfo(); 311 return MF.getTarget().Options.DisableFramePointerElim(MF) || 312 RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || 313 MFI.isFrameAddressTaken(); 314 } 315 316 bool VEFrameLowering::hasBP(const MachineFunction &MF) const { 317 const MachineFrameInfo &MFI = MF.getFrameInfo(); 318 const TargetRegisterInfo *TRI = STI.getRegisterInfo(); 319 320 return MFI.hasVarSizedObjects() && TRI->needsStackRealignment(MF); 321 } 322 323 int VEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, 324 Register &FrameReg) const { 325 const MachineFrameInfo &MFI = MF.getFrameInfo(); 326 const VERegisterInfo *RegInfo = STI.getRegisterInfo(); 327 const VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>(); 328 bool isFixed = MFI.isFixedObjectIndex(FI); 329 330 int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI); 331 332 if (FuncInfo->isLeafProc()) { 333 // If there's a leaf proc, all offsets need to be %sp-based, 334 // because we haven't caused %fp to actually point to our frame. 335 FrameReg = VE::SX11; // %sp 336 return FrameOffset + MF.getFrameInfo().getStackSize(); 337 } 338 if (RegInfo->needsStackRealignment(MF) && !isFixed) { 339 // If there is dynamic stack realignment, all local object 340 // references need to be via %sp or %s17 (bp), to take account 341 // of the re-alignment. 342 if (hasBP(MF)) 343 FrameReg = VE::SX17; // %bp 344 else 345 FrameReg = VE::SX11; // %sp 346 return FrameOffset + MF.getFrameInfo().getStackSize(); 347 } 348 // Finally, default to using %fp. 349 FrameReg = RegInfo->getFrameRegister(MF); 350 return FrameOffset; 351 } 352 353 bool VEFrameLowering::isLeafProc(MachineFunction &MF) const { 354 355 MachineRegisterInfo &MRI = MF.getRegInfo(); 356 MachineFrameInfo &MFI = MF.getFrameInfo(); 357 358 return !MFI.hasCalls() // No calls 359 && !MRI.isPhysRegUsed(VE::SX18) // Registers within limits 360 // (s18 is first CSR) 361 && !MRI.isPhysRegUsed(VE::SX11) // %sp un-used 362 && !hasFP(MF); // Don't need %fp 363 } 364 365 void VEFrameLowering::determineCalleeSaves(MachineFunction &MF, 366 BitVector &SavedRegs, 367 RegScavenger *RS) const { 368 TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 369 370 if (isLeafProc(MF)) { 371 VEMachineFunctionInfo *MFI = MF.getInfo<VEMachineFunctionInfo>(); 372 MFI->setLeafProc(true); 373 } 374 } 375