[llvm-commits] [llvm] r75943 - in /llvm/trunk: lib/Target/SystemZ/SystemZInstrInfo.cpp lib/Target/SystemZ/SystemZInstrInfo.h lib/Target/SystemZ/SystemZInstrInfo.td lib/Target/SystemZ/SystemZMachineFunctionInfo.h lib/Target/SystemZ/SystemZRegisterInfo.cpp lib/Target/SystemZ/SystemZRegisterInfo.h test/CodeGen/SystemZ/06-CallViaStack.ll test/CodeGen/SystemZ/06-LocalFrame.ll
Anton Korobeynikov
asl at math.spbu.ru
Thu Jul 16 06:51:17 PDT 2009
Author: asl
Date: Thu Jul 16 08:51:12 2009
New Revision: 75943
URL: http://llvm.org/viewvc/llvm-project?rev=75943&view=rev
Log:
Emit callee-saved regs spills / restores
Modified:
llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp
llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.h
llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td
llvm/trunk/lib/Target/SystemZ/SystemZMachineFunctionInfo.h
llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.cpp
llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.h
llvm/trunk/test/CodeGen/SystemZ/06-CallViaStack.ll
llvm/trunk/test/CodeGen/SystemZ/06-LocalFrame.ll
Modified: llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp?rev=75943&r1=75942&r2=75943&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp Thu Jul 16 08:51:12 2009
@@ -26,7 +26,30 @@
SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm)
: TargetInstrInfoImpl(SystemZInsts, array_lengthof(SystemZInsts)),
- RI(tm, *this), TM(tm) {}
+ RI(tm, *this), TM(tm) {
+ // Fill the spill offsets map
+ static const unsigned SpillOffsTab[][2] = {
+ { SystemZ::R2D, 0x10 },
+ { SystemZ::R3D, 0x18 },
+ { SystemZ::R4D, 0x20 },
+ { SystemZ::R5D, 0x28 },
+ { SystemZ::R6D, 0x30 },
+ { SystemZ::R7D, 0x38 },
+ { SystemZ::R8D, 0x40 },
+ { SystemZ::R9D, 0x48 },
+ { SystemZ::R10D, 0x50 },
+ { SystemZ::R11D, 0x58 },
+ { SystemZ::R12D, 0x60 },
+ { SystemZ::R13D, 0x68 },
+ { SystemZ::R14D, 0x70 },
+ { SystemZ::R15D, 0x78 }
+ };
+
+ RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
+
+ for (unsigned i = 0, e = array_lengthof(SpillOffsTab); i != e; ++i)
+ RegSpillOffsets[SpillOffsTab[i][0]] = SpillOffsTab[i][1];
+}
void SystemZInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
@@ -117,13 +140,52 @@
SystemZInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI) const {
- if (CSI.empty())
- return false;
+ DebugLoc DL = DebugLoc::getUnknownLoc();
+ if (MI != MBB.end()) DL = MI->getDebugLoc();
MachineFunction &MF = *MBB.getParent();
SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
MFI->setCalleeSavedFrameSize(CSI.size() * 8);
+ // Scan the callee-saved and find the bounds of register spill area.
+ unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0;
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ unsigned Reg = CSI[i].getReg();
+ unsigned Offset = RegSpillOffsets[Reg];
+ if (StartOffset > Offset) {
+ LowReg = Reg; StartOffset = Offset;
+ }
+ if (EndOffset < Offset) {
+ HighReg = Reg; EndOffset = RegSpillOffsets[Reg];
+ }
+ }
+
+ // Save information for epilogue inserter.
+ MFI->setLowReg(LowReg); MFI->setHighReg(HighReg);
+
+ // Build a store instruction. Use STORE MULTIPLE instruction if there are many
+ // registers to store, otherwise - just STORE.
+ MachineInstrBuilder MIB =
+ BuildMI(MBB, MI, DL, get((LowReg == HighReg ?
+ SystemZ::MOV64mr : SystemZ::MOV64mrm)));
+
+ // Add store operands.
+ MIB.addReg(SystemZ::R15D).addImm(StartOffset);
+ if (LowReg == HighReg)
+ MIB.addReg(0);
+ MIB.addReg(LowReg, RegState::Kill);
+ if (LowReg != HighReg)
+ MIB.addReg(HighReg, RegState::Kill);
+
+ // Do a second scan adding regs as being killed by instruction
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ unsigned Reg = CSI[i].getReg();
+ // Add the callee-saved register as live-in. It's killed at the spill.
+ MBB.addLiveIn(Reg);
+ if (Reg != LowReg && Reg != HighReg)
+ MIB.addReg(Reg, RegState::ImplicitKill);
+ }
+
return true;
}
@@ -131,6 +193,41 @@
SystemZInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI) const {
+ if (CSI.empty())
+ return false;
+
+ DebugLoc DL = DebugLoc::getUnknownLoc();
+ if (MI != MBB.end()) DL = MI->getDebugLoc();
+
+ MachineFunction &MF = *MBB.getParent();
+ const TargetRegisterInfo *RegInfo= MF.getTarget().getRegisterInfo();
+ SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
+
+ unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg();
+ unsigned StartOffset = RegSpillOffsets[LowReg];
+
+ // Build a load instruction. Use LOAD MULTIPLE instruction if there are many
+ // registers to load, otherwise - just LOAD.
+ MachineInstrBuilder MIB =
+ BuildMI(MBB, MI, DL, get((LowReg == HighReg ?
+ SystemZ::MOV64rm : SystemZ::MOV64rmm)));
+ // Add store operands.
+ MIB.addReg(LowReg, RegState::Define);
+ if (LowReg != HighReg)
+ MIB.addReg(HighReg, RegState::Define);
+
+ MIB.addReg((RegInfo->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D));
+ MIB.addImm(StartOffset);
+ if (LowReg == HighReg)
+ MIB.addReg(0);
+
+ // Do a second scan adding regs as being defined by instruction
+ for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+ unsigned Reg = CSI[i].getReg();
+ if (Reg != LowReg && Reg != HighReg)
+ MIB.addReg(Reg, RegState::ImplicitDefine);
+ }
+
return true;
}
Modified: llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.h?rev=75943&r1=75942&r2=75943&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.h (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.h Thu Jul 16 08:51:12 2009
@@ -14,8 +14,9 @@
#ifndef LLVM_TARGET_SYSTEMZINSTRINFO_H
#define LLVM_TARGET_SYSTEMZINSTRINFO_H
-#include "llvm/Target/TargetInstrInfo.h"
#include "SystemZRegisterInfo.h"
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/Target/TargetInstrInfo.h"
namespace llvm {
@@ -24,6 +25,7 @@
class SystemZInstrInfo : public TargetInstrInfoImpl {
const SystemZRegisterInfo RI;
SystemZTargetMachine &TM;
+ IndexedMap<unsigned> RegSpillOffsets;
public:
explicit SystemZInstrInfo(SystemZTargetMachine &TM);
Modified: llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td?rev=75943&r1=75942&r2=75943&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td Thu Jul 16 08:51:12 2009
@@ -195,19 +195,12 @@
//===----------------------------------------------------------------------===//
// Instruction list..
-// ADJCALLSTACKDOWN/UP implicitly use/def SP because they may be expanded into
-// a stack adjustment and the codegen must know that they may modify the stack
-// pointer before prolog-epilog rewriting occurs.
-// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
-// sub / add which can clobber R15D.
-let Defs = [R15D], Uses = [R15D] in {
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt),
"#ADJCALLSTACKDOWN",
[(SystemZcallseq_start timm:$amt)]>;
def ADJCALLSTACKUP : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2),
"#ADJCALLSTACKUP",
[(SystemZcallseq_end timm:$amt1, timm:$amt2)]>;
-}
//===----------------------------------------------------------------------===//
@@ -215,7 +208,7 @@
//
// FIXME: Provide proper encoding!
-let isReturn = 1, isTerminator = 1, Uses = [R14D] in {
+let isReturn = 1, isTerminator = 1 in {
def RET : Pseudo<(outs), (ins), "br\t%r14", [(SystemZretflag)]>;
}
@@ -224,12 +217,9 @@
//
let isCall = 1 in
- // All calls clobber the non-callee saved registers. R15 is marked as
- // a use to prevent stack-pointer assignments that appear immediately
- // before calls from potentially appearing dead. Uses for argument
- // registers are added manually.
- let Defs = [R0D, R1D, R3D, R4D, R5D, R14D, R15D],
- Uses = [R15D] in {
+ // All calls clobber the non-callee saved registers (except R14 which we
+ // handle separately). Uses for argument registers are added manually.
+ let Defs = [R0D, R1D, R3D, R4D, R5D] in {
def CALLi : Pseudo<(outs), (ins i64imm:$dst, variable_ops),
"brasl\t%r14, $dst", [(SystemZcall imm:$dst)]>;
def CALLr : Pseudo<(outs), (ins ADDR64:$dst, variable_ops),
@@ -370,6 +360,22 @@
"sty\t{$src, $dst}",
[(truncstorei32 GR64:$src, rriaddr:$dst)]>;
+// multiple regs moves
+// FIXME: should we use multiple arg nodes?
+def MOV32mrm : Pseudo<(outs), (ins riaddr:$dst, GR32:$from, GR32:$to),
+ "stmy\t{$from, $to, $dst}",
+ []>;
+def MOV64mrm : Pseudo<(outs), (ins riaddr:$dst, GR64:$from, GR64:$to),
+ "stmg\t{$from, $to, $dst}",
+ []>;
+def MOV32rmm : Pseudo<(outs GR32:$from, GR32:$to), (ins riaddr:$dst),
+ "lmy\t{$from, $to, $dst}",
+ []>;
+def MOV64rmm : Pseudo<(outs GR64:$from, GR64:$to), (ins riaddr:$dst),
+ "lmg\t{$from, $to, $dst}",
+ []>;
+
+
//===----------------------------------------------------------------------===//
// Arithmetic Instructions
Modified: llvm/trunk/lib/Target/SystemZ/SystemZMachineFunctionInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZMachineFunctionInfo.h?rev=75943&r1=75942&r2=75943&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZMachineFunctionInfo.h (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZMachineFunctionInfo.h Thu Jul 16 08:51:12 2009
@@ -25,6 +25,11 @@
/// stack frame in bytes.
unsigned CalleeSavedFrameSize;
+ /// LowReg - Low register of range of callee-saved registers to store.
+ unsigned LowReg;
+
+ /// HighReg - High register of range of callee-saved registers to store.
+ unsigned HighReg;
public:
SystemZMachineFunctionInfo() : CalleeSavedFrameSize(0) {}
@@ -32,6 +37,12 @@
unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; }
void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; }
+
+ unsigned getLowReg() const { return LowReg; }
+ void setLowReg(unsigned Reg) { LowReg = Reg; }
+
+ unsigned getHighReg() const { return HighReg; }
+ void setHighReg(unsigned Reg) { HighReg = Reg; }
};
} // End llvm namespace
Modified: llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.cpp?rev=75943&r1=75942&r2=75943&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.cpp Thu Jul 16 08:51:12 2009
@@ -18,6 +18,7 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
@@ -35,7 +36,8 @@
SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
static const unsigned CalleeSavedRegs[] = {
SystemZ::R6D, SystemZ::R7D, SystemZ::R8D, SystemZ::R9D,
- SystemZ::R10D, SystemZ::R11D, SystemZ::R12D, SystemZ::R13D, SystemZ::R14D,
+ SystemZ::R10D, SystemZ::R11D, SystemZ::R12D, SystemZ::R13D,
+ SystemZ::R14D, SystemZ::R15D,
SystemZ::F1, SystemZ::F3, SystemZ::F5, SystemZ::F7,
0
};
@@ -50,7 +52,7 @@
&SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
&SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
&SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
- &SystemZ::GR64RegClass,
+ &SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
&SystemZ::FP64RegClass, &SystemZ::FP64RegClass,
&SystemZ::FP64RegClass, &SystemZ::FP64RegClass, 0
};
@@ -66,16 +68,16 @@
return Reserved;
}
-// needsFP - 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.
-//
+/// needsFP - 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 SystemZRegisterInfo::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
return NoFramePointerElim || MFI->hasVarSizedObjects();
}
bool SystemZRegisterInfo::hasReservedCallFrame(MachineFunction &MF) const {
+ // FIXME: Should we always have reserved call frame?
return !MF.getFrameInfo()->hasVarSizedObjects();
}
@@ -137,6 +139,25 @@
MI.getOperand(i+1).ChangeToImmediate(Offset);
}
+void
+SystemZRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
+ RegScavenger *RS) const {
+ // Determine whether R15/R14 will ever be clobbered inside the function. And
+ // if yes - mark it as 'callee' saved.
+ MachineFrameInfo *FFI = MF.getFrameInfo();
+
+ if (FFI->hasCalls()
+ /* FIXME: function is varargs */
+ /* FIXME: function grabs RA */
+ /* FIXME: function calls eh_return */)
+ MF.getRegInfo().setPhysRegUsed(SystemZ::R14D);
+
+ if (FFI->getObjectIndexEnd() != 0 || // Contains automatic variables
+ FFI->hasVarSizedObjects() // Function calls dynamic alloca's
+ /* FIXME: function is varargs */)
+ MF.getRegInfo().setPhysRegUsed(SystemZ::R15D);
+}
+
/// emitSPUpdate - Emit a series of instructions to increment / decrement the
/// stack pointer by a constant value.
static
@@ -177,7 +198,11 @@
uint64_t StackSize =
MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize();
- // FIXME: Skip the callee-saved push instructions.
+ // Skip the callee-saved push instructions.
+ while (MBBI != MBB.end() &&
+ (MBBI->getOpcode() == SystemZ::MOV64mr ||
+ MBBI->getOpcode() == SystemZ::MOV64mrm))
+ ++MBBI;
if (MBBI != MBB.end())
DL = MBBI->getDebugLoc();
@@ -223,23 +248,30 @@
MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize();
uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
- // Skip the callee-saved regs load instructions.
- MachineBasicBlock::iterator LastCSPop = MBBI;
+ // Skip the final terminator instruction.
while (MBBI != MBB.begin()) {
MachineBasicBlock::iterator PI = prior(MBBI);
+ --MBBI;
if (!PI->getDesc().isTerminator())
break;
- --MBBI;
}
- DL = MBBI->getDebugLoc();
+ // During callee-saved restores emission stack frame was not yet finialized
+ // (and thus - the stack size was unknown). Tune the offset having full stack
+ // size in hands.
+ if (SystemZMFI->getCalleeSavedFrameSize()) {
+ assert((MBBI->getOpcode() == SystemZ::MOV64rmm ||
+ MBBI->getOpcode() == SystemZ::MOV64rm) &&
+ "Expected to see callee-save register restore code");
+
+ unsigned i = 0;
+ MachineInstr &MI = *MBBI;
+ while (!MI.getOperand(i).isImm()) {
+ ++i;
+ assert(i < MI.getNumOperands() && "Unexpected restore code!");
+ }
- if (MFI->hasVarSizedObjects()) {
- assert(0 && "Not implemented yet!");
- } else {
- // adjust stack pointer back: R15 += numbytes
- if (StackSize)
- emitSPUpdate(MBB, MBBI, NumBytes, TII);
+ MI.getOperand(i).ChangeToImmediate(NumBytes + MI.getOperand(i).getImm());
}
}
Modified: llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.h?rev=75943&r1=75942&r2=75943&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.h (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.h Thu Jul 16 08:51:12 2009
@@ -49,6 +49,10 @@
void eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, RegScavenger *RS = NULL) const;
+
+ void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
+ RegScavenger *RS) const;
+
void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
Modified: llvm/trunk/test/CodeGen/SystemZ/06-CallViaStack.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/06-CallViaStack.ll?rev=75943&r1=75942&r2=75943&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/06-CallViaStack.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/06-CallViaStack.ll Thu Jul 16 08:51:12 2009
@@ -1,4 +1,4 @@
-; RUN: llvm-as < %s | llc | grep 168 | count 2
+; RUN: llvm-as < %s | llc | grep 168 | count 1
; RUN: llvm-as < %s | llc | grep 160 | count 3
; RUN: llvm-as < %s | llc | grep 328 | count 1
Modified: llvm/trunk/test/CodeGen/SystemZ/06-LocalFrame.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/06-LocalFrame.ll?rev=75943&r1=75942&r2=75943&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/06-LocalFrame.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/06-LocalFrame.ll Thu Jul 16 08:51:12 2009
@@ -1,6 +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
+; RUN: llvm-as < %s | llc | grep 168 | count 1
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"
More information about the llvm-commits
mailing list