diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
commit | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch) | |
tree | 4adf86a776049cbf7f69a1929c4babcbbef925eb /llvm/lib/Target/VE/VEFrameLowering.cpp | |
parent | 7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff) |
Notes
Diffstat (limited to 'llvm/lib/Target/VE/VEFrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/VE/VEFrameLowering.cpp | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/llvm/lib/Target/VE/VEFrameLowering.cpp b/llvm/lib/Target/VE/VEFrameLowering.cpp new file mode 100644 index 0000000000000..ef5b5f0559111 --- /dev/null +++ b/llvm/lib/Target/VE/VEFrameLowering.cpp @@ -0,0 +1,325 @@ +//===-- VEFrameLowering.cpp - VE Frame Information ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the VE implementation of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#include "VEFrameLowering.h" +#include "VEInstrInfo.h" +#include "VESubtarget.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/MathExtras.h" + +using namespace llvm; + +VEFrameLowering::VEFrameLowering(const VESubtarget &ST) + : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(16), 0, + Align(16)) {} + +void VEFrameLowering::emitPrologueInsns(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + int NumBytes, + bool RequireFPUpdate) const { + + DebugLoc dl; + const VEInstrInfo &TII = + *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); + // Insert following codes here as prologue + // + // st %fp, 0(,%sp) + // st %lr, 8(,%sp) + // st %got, 24(,%sp) + // st %plt, 32(,%sp) + // or %fp, 0, %sp + + BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) + .addReg(VE::SX11) + .addImm(0) + .addReg(VE::SX9); + BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) + .addReg(VE::SX11) + .addImm(8) + .addReg(VE::SX10); + BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) + .addReg(VE::SX11) + .addImm(24) + .addReg(VE::SX15); + BuildMI(MBB, MBBI, dl, TII.get(VE::STSri)) + .addReg(VE::SX11) + .addImm(32) + .addReg(VE::SX16); + BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX9) + .addReg(VE::SX11) + .addImm(0); +} + +void VEFrameLowering::emitEpilogueInsns(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + int NumBytes, + bool RequireFPUpdate) const { + + DebugLoc dl; + const VEInstrInfo &TII = + *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); + // Insert following codes here as epilogue + // + // or %sp, 0, %fp + // ld %got, 32(,%sp) + // ld %plt, 24(,%sp) + // ld %lr, 8(,%sp) + // ld %fp, 0(,%sp) + + BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX11) + .addReg(VE::SX9) + .addImm(0); + BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX16) + .addReg(VE::SX11) + .addImm(32); + BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX15) + .addReg(VE::SX11) + .addImm(24); + BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX10) + .addReg(VE::SX11) + .addImm(8); + BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX9) + .addReg(VE::SX11) + .addImm(0); +} + +void VEFrameLowering::emitSPAdjustment(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + int NumBytes) const { + DebugLoc dl; + const VEInstrInfo &TII = + *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); + + if (NumBytes >= -64 && NumBytes < 63) { + BuildMI(MBB, MBBI, dl, TII.get(VE::ADXri), VE::SX11) + .addReg(VE::SX11) + .addImm(NumBytes); + return; + } + + // Emit following codes. This clobbers SX13 which we always know is + // available here. + // lea %s13,%lo(NumBytes) + // and %s13,%s13,(32)0 + // lea.sl %sp,%hi(NumBytes)(%sp, %s13) + BuildMI(MBB, MBBI, dl, TII.get(VE::LEAzzi), VE::SX13) + .addImm(LO32(NumBytes)); + BuildMI(MBB, MBBI, dl, TII.get(VE::ANDrm0), VE::SX13) + .addReg(VE::SX13) + .addImm(32); + BuildMI(MBB, MBBI, dl, TII.get(VE::LEASLrri), VE::SX11) + .addReg(VE::SX11) + .addReg(VE::SX13) + .addImm(HI32(NumBytes)); +} + +void VEFrameLowering::emitSPExtend(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + int NumBytes) const { + DebugLoc dl; + const VEInstrInfo &TII = + *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo()); + + // Emit following codes. It is not possible to insert multiple + // BasicBlocks in PEI pass, so we emit two pseudo instructions here. + // + // EXTEND_STACK // pseudo instrcution + // EXTEND_STACK_GUARD // pseudo instrcution + // + // EXTEND_STACK pseudo will be converted by ExpandPostRA pass into + // following instructions with multiple basic blocks later. + // + // thisBB: + // brge.l.t %sp, %sl, sinkBB + // syscallBB: + // ld %s61, 0x18(, %tp) // load param area + // or %s62, 0, %s0 // spill the value of %s0 + // lea %s63, 0x13b // syscall # of grow + // shm.l %s63, 0x0(%s61) // store syscall # at addr:0 + // shm.l %sl, 0x8(%s61) // store old limit at addr:8 + // shm.l %sp, 0x10(%s61) // store new limit at addr:16 + // monc // call monitor + // or %s0, 0, %s62 // restore the value of %s0 + // sinkBB: + // + // EXTEND_STACK_GUARD pseudo will be simply eliminated by ExpandPostRA + // pass. This pseudo is required to be at the next of EXTEND_STACK + // pseudo in order to protect iteration loop in ExpandPostRA. + + BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK)); + BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK_GUARD)); +} + +void VEFrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); + MachineFrameInfo &MFI = MF.getFrameInfo(); + const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>(); + const VEInstrInfo &TII = + *static_cast<const VEInstrInfo *>(Subtarget.getInstrInfo()); + const VERegisterInfo &RegInfo = + *static_cast<const VERegisterInfo *>(Subtarget.getRegisterInfo()); + MachineBasicBlock::iterator MBBI = MBB.begin(); + // Debug location must be unknown since the first debug location is used + // to determine the end of the prologue. + DebugLoc dl; + bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF); + + // FIXME: unfortunately, returning false from canRealignStack + // actually just causes needsStackRealignment to return false, + // rather than reporting an error, as would be sensible. This is + // poor, but fixing that bogosity is going to be a large project. + // For now, just see if it's lied, and report an error here. + if (!NeedsStackRealignment && MFI.getMaxAlignment() > getStackAlignment()) + report_fatal_error("Function \"" + Twine(MF.getName()) + + "\" required " + "stack re-alignment, but LLVM couldn't handle it " + "(probably because it has a dynamic alloca)."); + + // Get the number of bytes to allocate from the FrameInfo + int NumBytes = (int)MFI.getStackSize(); + // The VE ABI requires a reserved 176-byte area in the user's stack, starting + // at %sp + 16. This is for the callee Register Save Area (RSA). + // + // We therefore need to add that offset to the total stack size + // after all the stack objects are placed by + // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack + // needs to be aligned *after* the extra size is added, we need to disable + // calculateFrameObjectOffsets's built-in stack alignment, by having + // targetHandlesStackFrameRounding return true. + + // Add the extra call frame stack size, if needed. (This is the same + // code as in PrologEpilogInserter, but also gets disabled by + // targetHandlesStackFrameRounding) + if (MFI.adjustsStack() && hasReservedCallFrame(MF)) + NumBytes += MFI.getMaxCallFrameSize(); + + // Adds the VE subtarget-specific spill area to the stack + // size. Also ensures target-required alignment. + NumBytes = Subtarget.getAdjustedFrameSize(NumBytes); + + // Finally, ensure that the size is sufficiently aligned for the + // data on the stack. + if (MFI.getMaxAlignment() > 0) { + NumBytes = alignTo(NumBytes, MFI.getMaxAlignment()); + } + + // Update stack size with corrected value. + MFI.setStackSize(NumBytes); + + // Emit Prologue instructions to save %lr + emitPrologueInsns(MF, MBB, MBBI, NumBytes, true); + + // Emit stack adjust instructions + emitSPAdjustment(MF, MBB, MBBI, -NumBytes); + + // Emit stack extend instructions + emitSPExtend(MF, MBB, MBBI, -NumBytes); + + unsigned regFP = RegInfo.getDwarfRegNum(VE::SX9, true); + + // Emit ".cfi_def_cfa_register 30". + unsigned CFIIndex = + MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP)); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); + + // Emit ".cfi_window_save". + CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr)); + BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); +} + +MachineBasicBlock::iterator VEFrameLowering::eliminateCallFramePseudoInstr( + MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + if (!hasReservedCallFrame(MF)) { + MachineInstr &MI = *I; + int Size = MI.getOperand(0).getImm(); + if (MI.getOpcode() == VE::ADJCALLSTACKDOWN) + Size = -Size; + + if (Size) + emitSPAdjustment(MF, MBB, I, Size); + } + return MBB.erase(I); +} + +void VEFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + DebugLoc dl = MBBI->getDebugLoc(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + + int NumBytes = (int)MFI.getStackSize(); + + // Emit Epilogue instructions to restore %lr + emitEpilogueInsns(MF, MBB, MBBI, NumBytes, true); +} + +bool VEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { + // Reserve call frame if there are no variable sized objects on the stack. + return !MF.getFrameInfo().hasVarSizedObjects(); +} + +// hasFP - Return true if the specified function should have a dedicated frame +// pointer register. This is true if the function has variable sized allocas or +// if frame pointer elimination is disabled. +bool VEFrameLowering::hasFP(const MachineFunction &MF) const { + const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); + + const MachineFrameInfo &MFI = MF.getFrameInfo(); + return MF.getTarget().Options.DisableFramePointerElim(MF) || + RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || + MFI.isFrameAddressTaken(); +} + +int VEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const { + // Addressable stack objects are accessed using neg. offsets from + // %fp, or positive offsets from %sp. + int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI); + FrameReg = VE::SX11; // %sp + return FrameOffset + MF.getFrameInfo().getStackSize(); +} + +bool VEFrameLowering::isLeafProc(MachineFunction &MF) const { + + MachineRegisterInfo &MRI = MF.getRegInfo(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + + return !MFI.hasCalls() // No calls + && !MRI.isPhysRegUsed(VE::SX18) // Registers within limits + // (s18 is first CSR) + && !MRI.isPhysRegUsed(VE::SX11) // %sp un-used + && !hasFP(MF); // Don't need %fp +} + +void VEFrameLowering::determineCalleeSaves(MachineFunction &MF, + BitVector &SavedRegs, + RegScavenger *RS) const { + TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); + + assert(isLeafProc(MF) && "TODO implement for non-leaf procs"); +} |