]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r306956, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / SystemZ / SystemZRegisterInfo.cpp
1 //===-- SystemZRegisterInfo.cpp - SystemZ register information ------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "SystemZRegisterInfo.h"
11 #include "SystemZInstrInfo.h"
12 #include "SystemZSubtarget.h"
13 #include "llvm/CodeGen/MachineInstrBuilder.h"
14 #include "llvm/CodeGen/MachineRegisterInfo.h"
15 #include "llvm/Target/TargetFrameLowering.h"
16
17 using namespace llvm;
18
19 #define GET_REGINFO_TARGET_DESC
20 #include "SystemZGenRegisterInfo.inc"
21
22 SystemZRegisterInfo::SystemZRegisterInfo()
23     : SystemZGenRegisterInfo(SystemZ::R14D) {}
24
25 const MCPhysReg *
26 SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
27   if (MF->getSubtarget().getTargetLowering()->supportSwiftError() &&
28       MF->getFunction()->getAttributes().hasAttrSomewhere(
29           Attribute::SwiftError))
30     return CSR_SystemZ_SwiftError_SaveList;
31   return CSR_SystemZ_SaveList;
32 }
33
34 const uint32_t *
35 SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
36                                           CallingConv::ID CC) const {
37   if (MF.getSubtarget().getTargetLowering()->supportSwiftError() &&
38       MF.getFunction()->getAttributes().hasAttrSomewhere(
39           Attribute::SwiftError))
40     return CSR_SystemZ_SwiftError_RegMask;
41   return CSR_SystemZ_RegMask;
42 }
43
44 BitVector
45 SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
46   BitVector Reserved(getNumRegs());
47   const SystemZFrameLowering *TFI = getFrameLowering(MF);
48
49   if (TFI->hasFP(MF)) {
50     // R11D is the frame pointer.  Reserve all aliases.
51     Reserved.set(SystemZ::R11D);
52     Reserved.set(SystemZ::R11L);
53     Reserved.set(SystemZ::R11H);
54     Reserved.set(SystemZ::R10Q);
55   }
56
57   // R15D is the stack pointer.  Reserve all aliases.
58   Reserved.set(SystemZ::R15D);
59   Reserved.set(SystemZ::R15L);
60   Reserved.set(SystemZ::R15H);
61   Reserved.set(SystemZ::R14Q);
62
63   // A0 and A1 hold the thread pointer.
64   Reserved.set(SystemZ::A0);
65   Reserved.set(SystemZ::A1);
66
67   return Reserved;
68 }
69
70 void
71 SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
72                                          int SPAdj, unsigned FIOperandNum,
73                                          RegScavenger *RS) const {
74   assert(SPAdj == 0 && "Outgoing arguments should be part of the frame");
75
76   MachineBasicBlock &MBB = *MI->getParent();
77   MachineFunction &MF = *MBB.getParent();
78   auto *TII =
79       static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
80   const SystemZFrameLowering *TFI = getFrameLowering(MF);
81   DebugLoc DL = MI->getDebugLoc();
82
83   // Decompose the frame index into a base and offset.
84   int FrameIndex = MI->getOperand(FIOperandNum).getIndex();
85   unsigned BasePtr;
86   int64_t Offset = (TFI->getFrameIndexReference(MF, FrameIndex, BasePtr) +
87                     MI->getOperand(FIOperandNum + 1).getImm());
88
89   // Special handling of dbg_value instructions.
90   if (MI->isDebugValue()) {
91     MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false);
92     MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
93     return;
94   }
95
96   // See if the offset is in range, or if an equivalent instruction that
97   // accepts the offset exists.
98   unsigned Opcode = MI->getOpcode();
99   unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset);
100   if (OpcodeForOffset) {
101     if (OpcodeForOffset == SystemZ::LE &&
102         MF.getSubtarget<SystemZSubtarget>().hasVector()) {
103       // If LE is ok for offset, use LDE instead on z13.
104       OpcodeForOffset = SystemZ::LDE32;
105     }
106     MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
107   }
108   else {
109     // Create an anchor point that is in range.  Start at 0xffff so that
110     // can use LLILH to load the immediate.
111     int64_t OldOffset = Offset;
112     int64_t Mask = 0xffff;
113     do {
114       Offset = OldOffset & Mask;
115       OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset);
116       Mask >>= 1;
117       assert(Mask && "One offset must be OK");
118     } while (!OpcodeForOffset);
119
120     unsigned ScratchReg =
121       MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass);
122     int64_t HighOffset = OldOffset - Offset;
123
124     if (MI->getDesc().TSFlags & SystemZII::HasIndex
125         && MI->getOperand(FIOperandNum + 2).getReg() == 0) {
126       // Load the offset into the scratch register and use it as an index.
127       // The scratch register then dies here.
128       TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);
129       MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);
130       MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg,
131                                                         false, false, true);
132     } else {
133       // Load the anchor address into a scratch register.
134       unsigned LAOpcode = TII->getOpcodeForOffset(SystemZ::LA, HighOffset);
135       if (LAOpcode)
136         BuildMI(MBB, MI, DL, TII->get(LAOpcode),ScratchReg)
137           .addReg(BasePtr).addImm(HighOffset).addReg(0);
138       else {
139         // Load the high offset into the scratch register and use it as
140         // an index.
141         TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);
142         BuildMI(MBB, MI, DL, TII->get(SystemZ::AGR),ScratchReg)
143           .addReg(ScratchReg, RegState::Kill).addReg(BasePtr);
144       }
145
146       // Use the scratch register as the base.  It then dies here.
147       MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg,
148                                                     false, false, true);
149     }
150   }
151   MI->setDesc(TII->get(OpcodeForOffset));
152   MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
153 }
154
155 unsigned
156 SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
157   const SystemZFrameLowering *TFI = getFrameLowering(MF);
158   return TFI->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D;
159 }