1*5f613dfdSUlrich Weigand //===-- SystemZRegisterInfo.cpp - SystemZ register information ------------===//
2*5f613dfdSUlrich Weigand //
3*5f613dfdSUlrich Weigand //                     The LLVM Compiler Infrastructure
4*5f613dfdSUlrich Weigand //
5*5f613dfdSUlrich Weigand // This file is distributed under the University of Illinois Open Source
6*5f613dfdSUlrich Weigand // License. See LICENSE.TXT for details.
7*5f613dfdSUlrich Weigand //
8*5f613dfdSUlrich Weigand //===----------------------------------------------------------------------===//
9*5f613dfdSUlrich Weigand 
10*5f613dfdSUlrich Weigand #include "SystemZRegisterInfo.h"
11*5f613dfdSUlrich Weigand #include "SystemZTargetMachine.h"
12*5f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineInstrBuilder.h"
13*5f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineRegisterInfo.h"
14*5f613dfdSUlrich Weigand 
15*5f613dfdSUlrich Weigand #define GET_REGINFO_TARGET_DESC
16*5f613dfdSUlrich Weigand #include "SystemZGenRegisterInfo.inc"
17*5f613dfdSUlrich Weigand 
18*5f613dfdSUlrich Weigand using namespace llvm;
19*5f613dfdSUlrich Weigand 
20*5f613dfdSUlrich Weigand SystemZRegisterInfo::SystemZRegisterInfo(SystemZTargetMachine &tm,
21*5f613dfdSUlrich Weigand                                          const SystemZInstrInfo &tii)
22*5f613dfdSUlrich Weigand   : SystemZGenRegisterInfo(SystemZ::R14D), TM(tm), TII(tii) {}
23*5f613dfdSUlrich Weigand 
24*5f613dfdSUlrich Weigand const uint16_t*
25*5f613dfdSUlrich Weigand SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
26*5f613dfdSUlrich Weigand   static const uint16_t CalleeSavedRegs[] = {
27*5f613dfdSUlrich Weigand     SystemZ::R6D,  SystemZ::R7D,  SystemZ::R8D,  SystemZ::R9D,
28*5f613dfdSUlrich Weigand     SystemZ::R10D, SystemZ::R11D, SystemZ::R12D, SystemZ::R13D,
29*5f613dfdSUlrich Weigand     SystemZ::R14D, SystemZ::R15D,
30*5f613dfdSUlrich Weigand     SystemZ::F8D,  SystemZ::F9D,  SystemZ::F10D, SystemZ::F11D,
31*5f613dfdSUlrich Weigand     SystemZ::F12D, SystemZ::F13D, SystemZ::F14D, SystemZ::F15D,
32*5f613dfdSUlrich Weigand     0
33*5f613dfdSUlrich Weigand   };
34*5f613dfdSUlrich Weigand 
35*5f613dfdSUlrich Weigand   return CalleeSavedRegs;
36*5f613dfdSUlrich Weigand }
37*5f613dfdSUlrich Weigand 
38*5f613dfdSUlrich Weigand BitVector
39*5f613dfdSUlrich Weigand SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
40*5f613dfdSUlrich Weigand   BitVector Reserved(getNumRegs());
41*5f613dfdSUlrich Weigand   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
42*5f613dfdSUlrich Weigand 
43*5f613dfdSUlrich Weigand   if (TFI->hasFP(MF)) {
44*5f613dfdSUlrich Weigand     // R11D is the frame pointer.  Reserve all aliases.
45*5f613dfdSUlrich Weigand     Reserved.set(SystemZ::R11D);
46*5f613dfdSUlrich Weigand     Reserved.set(SystemZ::R11W);
47*5f613dfdSUlrich Weigand     Reserved.set(SystemZ::R10Q);
48*5f613dfdSUlrich Weigand   }
49*5f613dfdSUlrich Weigand 
50*5f613dfdSUlrich Weigand   // R15D is the stack pointer.  Reserve all aliases.
51*5f613dfdSUlrich Weigand   Reserved.set(SystemZ::R15D);
52*5f613dfdSUlrich Weigand   Reserved.set(SystemZ::R15W);
53*5f613dfdSUlrich Weigand   Reserved.set(SystemZ::R14Q);
54*5f613dfdSUlrich Weigand   return Reserved;
55*5f613dfdSUlrich Weigand }
56*5f613dfdSUlrich Weigand 
57*5f613dfdSUlrich Weigand bool
58*5f613dfdSUlrich Weigand SystemZRegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB,
59*5f613dfdSUlrich Weigand 					   MachineBasicBlock::iterator SaveMBBI,
60*5f613dfdSUlrich Weigand 					   MachineBasicBlock::iterator &UseMBBI,
61*5f613dfdSUlrich Weigand 					   const TargetRegisterClass *RC,
62*5f613dfdSUlrich Weigand 					   unsigned Reg) const {
63*5f613dfdSUlrich Weigand   MachineFunction &MF = *MBB.getParent();
64*5f613dfdSUlrich Weigand   const SystemZFrameLowering *TFI =
65*5f613dfdSUlrich Weigand     static_cast<const SystemZFrameLowering *>(TM.getFrameLowering());
66*5f613dfdSUlrich Weigand   unsigned Base = getFrameRegister(MF);
67*5f613dfdSUlrich Weigand   uint64_t Offset = TFI->getEmergencySpillSlotOffset(MF);
68*5f613dfdSUlrich Weigand   DebugLoc DL;
69*5f613dfdSUlrich Weigand 
70*5f613dfdSUlrich Weigand   unsigned LoadOpcode, StoreOpcode;
71*5f613dfdSUlrich Weigand   TII.getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode);
72*5f613dfdSUlrich Weigand 
73*5f613dfdSUlrich Weigand   // The offset must always be in range of a 12-bit unsigned displacement.
74*5f613dfdSUlrich Weigand   BuildMI(MBB, SaveMBBI, DL, TII.get(StoreOpcode))
75*5f613dfdSUlrich Weigand     .addReg(Reg, RegState::Kill).addReg(Base).addImm(Offset).addReg(0);
76*5f613dfdSUlrich Weigand   BuildMI(MBB, UseMBBI, DL, TII.get(LoadOpcode), Reg)
77*5f613dfdSUlrich Weigand     .addReg(Base).addImm(Offset).addReg(0);
78*5f613dfdSUlrich Weigand   return true;
79*5f613dfdSUlrich Weigand }
80*5f613dfdSUlrich Weigand 
81*5f613dfdSUlrich Weigand void
82*5f613dfdSUlrich Weigand SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
83*5f613dfdSUlrich Weigand                                          int SPAdj, unsigned FIOperandNum,
84*5f613dfdSUlrich Weigand                                          RegScavenger *RS) const {
85*5f613dfdSUlrich Weigand   assert(SPAdj == 0 && "Outgoing arguments should be part of the frame");
86*5f613dfdSUlrich Weigand 
87*5f613dfdSUlrich Weigand   MachineBasicBlock &MBB = *MI->getParent();
88*5f613dfdSUlrich Weigand   MachineFunction &MF = *MBB.getParent();
89*5f613dfdSUlrich Weigand   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
90*5f613dfdSUlrich Weigand   DebugLoc DL = MI->getDebugLoc();
91*5f613dfdSUlrich Weigand 
92*5f613dfdSUlrich Weigand   // Decompose the frame index into a base and offset.
93*5f613dfdSUlrich Weigand   int FrameIndex = MI->getOperand(FIOperandNum).getIndex();
94*5f613dfdSUlrich Weigand   unsigned BasePtr = getFrameRegister(MF);
95*5f613dfdSUlrich Weigand   int64_t Offset = (TFI->getFrameIndexOffset(MF, FrameIndex) +
96*5f613dfdSUlrich Weigand                     MI->getOperand(FIOperandNum + 1).getImm());
97*5f613dfdSUlrich Weigand 
98*5f613dfdSUlrich Weigand   // Special handling of dbg_value instructions.
99*5f613dfdSUlrich Weigand   if (MI->isDebugValue()) {
100*5f613dfdSUlrich Weigand     MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false);
101*5f613dfdSUlrich Weigand     MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
102*5f613dfdSUlrich Weigand     return;
103*5f613dfdSUlrich Weigand   }
104*5f613dfdSUlrich Weigand 
105*5f613dfdSUlrich Weigand   // See if the offset is in range, or if an equivalent instruction that
106*5f613dfdSUlrich Weigand   // accepts the offset exists.
107*5f613dfdSUlrich Weigand   unsigned Opcode = MI->getOpcode();
108*5f613dfdSUlrich Weigand   unsigned OpcodeForOffset = TII.getOpcodeForOffset(Opcode, Offset);
109*5f613dfdSUlrich Weigand   if (OpcodeForOffset)
110*5f613dfdSUlrich Weigand     MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
111*5f613dfdSUlrich Weigand   else {
112*5f613dfdSUlrich Weigand     // Create an anchor point that is in range.  Start at 0xffff so that
113*5f613dfdSUlrich Weigand     // can use LLILH to load the immediate.
114*5f613dfdSUlrich Weigand     int64_t OldOffset = Offset;
115*5f613dfdSUlrich Weigand     int64_t Mask = 0xffff;
116*5f613dfdSUlrich Weigand     do {
117*5f613dfdSUlrich Weigand       Offset = OldOffset & Mask;
118*5f613dfdSUlrich Weigand       OpcodeForOffset = TII.getOpcodeForOffset(Opcode, Offset);
119*5f613dfdSUlrich Weigand       Mask >>= 1;
120*5f613dfdSUlrich Weigand       assert(Mask && "One offset must be OK");
121*5f613dfdSUlrich Weigand     } while (!OpcodeForOffset);
122*5f613dfdSUlrich Weigand 
123*5f613dfdSUlrich Weigand     unsigned ScratchReg =
124*5f613dfdSUlrich Weigand       MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass);
125*5f613dfdSUlrich Weigand     int64_t HighOffset = OldOffset - Offset;
126*5f613dfdSUlrich Weigand 
127*5f613dfdSUlrich Weigand     if (MI->getDesc().TSFlags & SystemZII::HasIndex
128*5f613dfdSUlrich Weigand         && MI->getOperand(FIOperandNum + 2).getReg() == 0) {
129*5f613dfdSUlrich Weigand       // Load the offset into the scratch register and use it as an index.
130*5f613dfdSUlrich Weigand       // The scratch register then dies here.
131*5f613dfdSUlrich Weigand       TII.loadImmediate(MBB, MI, ScratchReg, HighOffset);
132*5f613dfdSUlrich Weigand       MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
133*5f613dfdSUlrich Weigand       MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg,
134*5f613dfdSUlrich Weigand                                                         false, false, true);
135*5f613dfdSUlrich Weigand     } else {
136*5f613dfdSUlrich Weigand       // Load the anchor address into a scratch register.
137*5f613dfdSUlrich Weigand       unsigned LAOpcode = TII.getOpcodeForOffset(SystemZ::LA, HighOffset);
138*5f613dfdSUlrich Weigand       if (LAOpcode)
139*5f613dfdSUlrich Weigand         BuildMI(MBB, MI, DL, TII.get(LAOpcode),ScratchReg)
140*5f613dfdSUlrich Weigand           .addReg(BasePtr).addImm(HighOffset).addReg(0);
141*5f613dfdSUlrich Weigand       else {
142*5f613dfdSUlrich Weigand         // Load the high offset into the scratch register and use it as
143*5f613dfdSUlrich Weigand         // an index.
144*5f613dfdSUlrich Weigand         TII.loadImmediate(MBB, MI, ScratchReg, HighOffset);
145*5f613dfdSUlrich Weigand         BuildMI(MBB, MI, DL, TII.get(SystemZ::AGR),ScratchReg)
146*5f613dfdSUlrich Weigand           .addReg(ScratchReg, RegState::Kill).addReg(BasePtr);
147*5f613dfdSUlrich Weigand       }
148*5f613dfdSUlrich Weigand 
149*5f613dfdSUlrich Weigand       // Use the scratch register as the base.  It then dies here.
150*5f613dfdSUlrich Weigand       MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg,
151*5f613dfdSUlrich Weigand                                                     false, false, true);
152*5f613dfdSUlrich Weigand     }
153*5f613dfdSUlrich Weigand   }
154*5f613dfdSUlrich Weigand   MI->setDesc(TII.get(OpcodeForOffset));
155*5f613dfdSUlrich Weigand   MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
156*5f613dfdSUlrich Weigand }
157*5f613dfdSUlrich Weigand 
158*5f613dfdSUlrich Weigand unsigned
159*5f613dfdSUlrich Weigand SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
160*5f613dfdSUlrich Weigand   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
161*5f613dfdSUlrich Weigand   return TFI->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D;
162*5f613dfdSUlrich Weigand }
163