aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.td2
-rw-r--r--lib/Target/SystemZ/SystemZRegisterInfo.cpp92
-rw-r--r--test/CodeGen/SystemZ/06-LocalFrame.ll1
3 files changed, 92 insertions, 3 deletions
diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td
index 978562e9c3..7ceb948a35 100644
--- a/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -178,7 +178,7 @@ def laaddr : Operand<i64>,
//
// FIXME: Provide proper encoding!
-let isReturn = 1, isTerminator = 1 in {
+let isReturn = 1, isTerminator = 1, Uses = [R14D] in {
def RET : Pseudo<(outs), (ins), "br\t%r14", [(SystemZretflag)]>;
}
diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp
index 3773a2a496..74633769bf 100644
--- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp
+++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp
@@ -18,6 +18,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Target/TargetFrameInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/BitVector.h"
@@ -120,13 +121,100 @@ void SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
MI.getOperand(i+1).ChangeToImmediate(Offset);
}
+/// emitSPUpdate - Emit a series of instructions to increment / decrement the
+/// stack pointer by a constant value.
+static
+void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
+ int64_t NumBytes, const TargetInstrInfo &TII) {
+ // FIXME: Handle different stack sizes here.
+ bool isSub = NumBytes < 0;
+ uint64_t Offset = isSub ? -NumBytes : NumBytes;
+ unsigned Opc = SystemZ::ADD64ri16;
+ uint64_t Chunk = (1LL << 15) - 1;
+ DebugLoc DL = (MBBI != MBB.end() ? MBBI->getDebugLoc() :
+ DebugLoc::getUnknownLoc());
+
+ while (Offset) {
+ uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset;
+ MachineInstr *MI =
+ BuildMI(MBB, MBBI, DL, TII.get(Opc), SystemZ::R15D)
+ .addReg(SystemZ::R15D).addImm((isSub ? -(int64_t)ThisVal : ThisVal));
+ // The PSW implicit def is dead.
+ MI->getOperand(3).setIsDead();
+ Offset -= ThisVal;
+ }
+}
+
void SystemZRegisterInfo::emitPrologue(MachineFunction &MF) const {
- // Nothing here yet
+ MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
+ const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ MachineBasicBlock::iterator MBBI = MBB.begin();
+ DebugLoc DL = (MBBI != MBB.end() ? MBBI->getDebugLoc() :
+ DebugLoc::getUnknownLoc());
+
+ // Get the number of bytes to allocate from the FrameInfo.
+ uint64_t StackSize = MFI->getStackSize();
+
+ // FIXME: Skip the callee-saved push instructions.
+
+ if (MBBI != MBB.end())
+ DL = MBBI->getDebugLoc();
+
+ uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
+
+ if (StackSize) // adjust stack pointer: R15 -= numbytes
+ emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, TII);
+
+ if (hasFP(MF)) {
+ // Update R11 with the new base value...
+ BuildMI(MBB, MBBI, DL, TII.get(SystemZ::MOV64rr), SystemZ::R11D)
+ .addReg(SystemZ::R15D);
+
+ // Mark the FramePtr as live-in in every block except the entry.
+ for (MachineFunction::iterator I = next(MF.begin()), E = MF.end();
+ I != E; ++I)
+ I->addLiveIn(SystemZ::R11D);
+
+ }
}
void SystemZRegisterInfo::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
- // Nothing here yet
+ const MachineFrameInfo *MFI = MF.getFrameInfo();
+ const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
+ MachineBasicBlock::iterator MBBI = prior(MBB.end());
+ unsigned RetOpcode = MBBI->getOpcode();
+ DebugLoc DL = MBBI->getDebugLoc();
+
+ switch (RetOpcode) {
+ case SystemZ::RET: break; // These are ok
+ default:
+ assert(0 && "Can only insert epilog into returning blocks");
+ }
+
+ // Get the number of bytes to allocate from the FrameInfo
+ uint64_t StackSize = MFI->getStackSize();
+ uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
+
+ // Skip the callee-saved regs load instructions.
+ MachineBasicBlock::iterator LastCSPop = MBBI;
+ while (MBBI != MBB.begin()) {
+ MachineBasicBlock::iterator PI = prior(MBBI);
+ if (!PI->getDesc().isTerminator())
+ break;
+ --MBBI;
+ }
+
+ DL = MBBI->getDebugLoc();
+
+ if (MFI->hasVarSizedObjects()) {
+ assert(0 && "Not implemented yet!");
+ } else {
+ // adjust stack pointer back: R15 += numbytes
+ if (StackSize)
+ emitSPUpdate(MBB, MBBI, NumBytes, TII);
+ }
}
unsigned SystemZRegisterInfo::getRARegister() const {
diff --git a/test/CodeGen/SystemZ/06-LocalFrame.ll b/test/CodeGen/SystemZ/06-LocalFrame.ll
index 8c627db00f..588c46d645 100644
--- a/test/CodeGen/SystemZ/06-LocalFrame.ll
+++ b/test/CodeGen/SystemZ/06-LocalFrame.ll
@@ -1,5 +1,6 @@
; RUN: llvm-as < %s | llc | grep 160 | count 1
; RUN: llvm-as < %s | llc | grep 328 | count 1
+; RUN: llvm-as < %s | llc | grep 168 | count 2
target datalayout = "E-p:64:64:64-i1:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128"
target triple = "s390x-unknown-linux-gnu"