MC: Clean up method names in MCContext.
[oota-llvm.git] / lib / Target / SystemZ / SystemZShortenInst.cpp
1 //===-- SystemZShortenInst.cpp - Instruction-shortening pass --------------===//
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 // This pass tries to replace instructions with shorter forms.  For example,
11 // IILF can be replaced with LLILL or LLILH if the constant fits and if the
12 // other 32 bits of the GR64 destination are not live.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "SystemZTargetMachine.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19
20 using namespace llvm;
21
22 #define DEBUG_TYPE "systemz-shorten-inst"
23
24 namespace {
25 class SystemZShortenInst : public MachineFunctionPass {
26 public:
27   static char ID;
28   SystemZShortenInst(const SystemZTargetMachine &tm);
29
30   const char *getPassName() const override {
31     return "SystemZ Instruction Shortening";
32   }
33
34   bool processBlock(MachineBasicBlock &MBB);
35   bool runOnMachineFunction(MachineFunction &F) override;
36
37 private:
38   bool shortenIIF(MachineInstr &MI, unsigned *GPRMap, unsigned LiveOther,
39                   unsigned LLIxL, unsigned LLIxH);
40   bool shortenOn0(MachineInstr &MI, unsigned Opcode);
41   bool shortenOn01(MachineInstr &MI, unsigned Opcode);
42   bool shortenOn001(MachineInstr &MI, unsigned Opcode);
43   bool shortenFPConv(MachineInstr &MI, unsigned Opcode);
44
45   const SystemZInstrInfo *TII;
46
47   // LowGPRs[I] has bit N set if LLVM register I includes the low
48   // word of GPR N.  HighGPRs is the same for the high word.
49   unsigned LowGPRs[SystemZ::NUM_TARGET_REGS];
50   unsigned HighGPRs[SystemZ::NUM_TARGET_REGS];
51 };
52
53 char SystemZShortenInst::ID = 0;
54 } // end anonymous namespace
55
56 FunctionPass *llvm::createSystemZShortenInstPass(SystemZTargetMachine &TM) {
57   return new SystemZShortenInst(TM);
58 }
59
60 SystemZShortenInst::SystemZShortenInst(const SystemZTargetMachine &tm)
61   : MachineFunctionPass(ID), TII(nullptr), LowGPRs(), HighGPRs() {
62   // Set up LowGPRs and HighGPRs.
63   for (unsigned I = 0; I < 16; ++I) {
64     LowGPRs[SystemZMC::GR32Regs[I]] |= 1 << I;
65     LowGPRs[SystemZMC::GR64Regs[I]] |= 1 << I;
66     HighGPRs[SystemZMC::GRH32Regs[I]] |= 1 << I;
67     HighGPRs[SystemZMC::GR64Regs[I]] |= 1 << I;
68     if (unsigned GR128 = SystemZMC::GR128Regs[I]) {
69       LowGPRs[GR128] |= 3 << I;
70       HighGPRs[GR128] |= 3 << I;
71     }
72   }
73 }
74
75 // MI loads one word of a GPR using an IIxF instruction and LLIxL and LLIxH
76 // are the halfword immediate loads for the same word.  Try to use one of them
77 // instead of IIxF.  If MI loads the high word, GPRMap[X] is the set of high
78 // words referenced by LLVM register X while LiveOther is the mask of low
79 // words that are currently live, and vice versa.
80 bool SystemZShortenInst::shortenIIF(MachineInstr &MI, unsigned *GPRMap,
81                                     unsigned LiveOther, unsigned LLIxL,
82                                     unsigned LLIxH) {
83   unsigned Reg = MI.getOperand(0).getReg();
84   assert(Reg < SystemZ::NUM_TARGET_REGS && "Invalid register number");
85   unsigned GPRs = GPRMap[Reg];
86   assert(GPRs != 0 && "Register must be a GPR");
87   if (GPRs & LiveOther)
88     return false;
89
90   uint64_t Imm = MI.getOperand(1).getImm();
91   if (SystemZ::isImmLL(Imm)) {
92     MI.setDesc(TII->get(LLIxL));
93     MI.getOperand(0).setReg(SystemZMC::getRegAsGR64(Reg));
94     return true;
95   }
96   if (SystemZ::isImmLH(Imm)) {
97     MI.setDesc(TII->get(LLIxH));
98     MI.getOperand(0).setReg(SystemZMC::getRegAsGR64(Reg));
99     MI.getOperand(1).setImm(Imm >> 16);
100     return true;
101   }
102   return false;
103 }
104
105 // Change MI's opcode to Opcode if register operand 0 has a 4-bit encoding.
106 bool SystemZShortenInst::shortenOn0(MachineInstr &MI, unsigned Opcode) {
107   if (SystemZMC::getFirstReg(MI.getOperand(0).getReg()) < 16) {
108     MI.setDesc(TII->get(Opcode));
109     return true;
110   }
111   return false;
112 }
113
114 // Change MI's opcode to Opcode if register operands 0 and 1 have a
115 // 4-bit encoding.
116 bool SystemZShortenInst::shortenOn01(MachineInstr &MI, unsigned Opcode) {
117   if (SystemZMC::getFirstReg(MI.getOperand(0).getReg()) < 16 &&
118       SystemZMC::getFirstReg(MI.getOperand(1).getReg()) < 16) {
119     MI.setDesc(TII->get(Opcode));
120     return true;
121   }
122   return false;
123 }
124
125 // Change MI's opcode to Opcode if register operands 0, 1 and 2 have a
126 // 4-bit encoding and if operands 0 and 1 are tied.
127 bool SystemZShortenInst::shortenOn001(MachineInstr &MI, unsigned Opcode) {
128   if (SystemZMC::getFirstReg(MI.getOperand(0).getReg()) < 16 &&
129       MI.getOperand(1).getReg() == MI.getOperand(0).getReg() &&
130       SystemZMC::getFirstReg(MI.getOperand(2).getReg()) < 16) {
131     MI.setDesc(TII->get(Opcode));
132     return true;
133   }
134   return false;
135 }
136
137 // MI is a vector-style conversion instruction with the operand order:
138 // destination, source, exact-suppress, rounding-mode.  If both registers
139 // have a 4-bit encoding then change it to Opcode, which has operand order:
140 // destination, rouding-mode, source, exact-suppress.
141 bool SystemZShortenInst::shortenFPConv(MachineInstr &MI, unsigned Opcode) {
142   if (SystemZMC::getFirstReg(MI.getOperand(0).getReg()) < 16 &&
143       SystemZMC::getFirstReg(MI.getOperand(1).getReg()) < 16) {
144     MachineOperand Dest(MI.getOperand(0));
145     MachineOperand Src(MI.getOperand(1));
146     MachineOperand Suppress(MI.getOperand(2));
147     MachineOperand Mode(MI.getOperand(3));
148     MI.RemoveOperand(3);
149     MI.RemoveOperand(2);
150     MI.RemoveOperand(1);
151     MI.RemoveOperand(0);
152     MI.setDesc(TII->get(Opcode));
153     MachineInstrBuilder(*MI.getParent()->getParent(), &MI)
154       .addOperand(Dest)
155       .addOperand(Mode)
156       .addOperand(Src)
157       .addOperand(Suppress);
158     return true;
159   }
160   return false;
161 }
162
163 // Process all instructions in MBB.  Return true if something changed.
164 bool SystemZShortenInst::processBlock(MachineBasicBlock &MBB) {
165   bool Changed = false;
166
167   // Work out which words are live on exit from the block.
168   unsigned LiveLow = 0;
169   unsigned LiveHigh = 0;
170   for (auto SI = MBB.succ_begin(), SE = MBB.succ_end(); SI != SE; ++SI) {
171     for (auto LI = (*SI)->livein_begin(), LE = (*SI)->livein_end();
172          LI != LE; ++LI) {
173       unsigned Reg = *LI;
174       assert(Reg < SystemZ::NUM_TARGET_REGS && "Invalid register number");
175       LiveLow |= LowGPRs[Reg];
176       LiveHigh |= HighGPRs[Reg];
177     }
178   }
179
180   // Iterate backwards through the block looking for instructions to change.
181   for (auto MBBI = MBB.rbegin(), MBBE = MBB.rend(); MBBI != MBBE; ++MBBI) {
182     MachineInstr &MI = *MBBI;
183     switch (MI.getOpcode()) {
184     case SystemZ::IILF:
185       Changed |= shortenIIF(MI, LowGPRs, LiveHigh, SystemZ::LLILL,
186                             SystemZ::LLILH);
187       break;
188
189     case SystemZ::IIHF:
190       Changed |= shortenIIF(MI, HighGPRs, LiveLow, SystemZ::LLIHL,
191                             SystemZ::LLIHH);
192       break;
193
194     case SystemZ::WFADB:
195       Changed |= shortenOn001(MI, SystemZ::ADBR);
196       break;
197
198     case SystemZ::WFDDB:
199       Changed |= shortenOn001(MI, SystemZ::DDBR);
200       break;
201
202     case SystemZ::WFIDB:
203       Changed |= shortenFPConv(MI, SystemZ::FIDBRA);
204       break;
205
206     case SystemZ::WLDEB:
207       Changed |= shortenOn01(MI, SystemZ::LDEBR);
208       break;
209
210     case SystemZ::WLEDB:
211       Changed |= shortenFPConv(MI, SystemZ::LEDBRA);
212       break;
213
214     case SystemZ::WFMDB:
215       Changed |= shortenOn001(MI, SystemZ::MDBR);
216       break;
217
218     case SystemZ::WFLCDB:
219       Changed |= shortenOn01(MI, SystemZ::LCDBR);
220       break;
221
222     case SystemZ::WFLNDB:
223       Changed |= shortenOn01(MI, SystemZ::LNDBR);
224       break;
225
226     case SystemZ::WFLPDB:
227       Changed |= shortenOn01(MI, SystemZ::LPDBR);
228       break;
229
230     case SystemZ::WFSQDB:
231       Changed |= shortenOn01(MI, SystemZ::SQDBR);
232       break;
233
234     case SystemZ::WFSDB:
235       Changed |= shortenOn001(MI, SystemZ::SDBR);
236       break;
237
238     case SystemZ::WFCDB:
239       Changed |= shortenOn01(MI, SystemZ::CDBR);
240       break;
241
242     case SystemZ::VL32:
243       // For z13 we prefer LDE over LE to avoid partial register dependencies.
244       Changed |= shortenOn0(MI, SystemZ::LDE32);
245       break;
246
247     case SystemZ::VST32:
248       Changed |= shortenOn0(MI, SystemZ::STE);
249       break;
250
251     case SystemZ::VL64:
252       Changed |= shortenOn0(MI, SystemZ::LD);
253       break;
254
255     case SystemZ::VST64:
256       Changed |= shortenOn0(MI, SystemZ::STD);
257       break;
258     }
259
260     unsigned UsedLow = 0;
261     unsigned UsedHigh = 0;
262     for (auto MOI = MI.operands_begin(), MOE = MI.operands_end();
263          MOI != MOE; ++MOI) {
264       MachineOperand &MO = *MOI;
265       if (MO.isReg()) {
266         if (unsigned Reg = MO.getReg()) {
267           assert(Reg < SystemZ::NUM_TARGET_REGS && "Invalid register number");
268           if (MO.isDef()) {
269             LiveLow &= ~LowGPRs[Reg];
270             LiveHigh &= ~HighGPRs[Reg];
271           } else if (!MO.isUndef()) {
272             UsedLow |= LowGPRs[Reg];
273             UsedHigh |= HighGPRs[Reg];
274           }
275         }
276       }
277     }
278     LiveLow |= UsedLow;
279     LiveHigh |= UsedHigh;
280   }
281
282   return Changed;
283 }
284
285 bool SystemZShortenInst::runOnMachineFunction(MachineFunction &F) {
286   TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo());
287
288   bool Changed = false;
289   for (auto &MBB : F)
290     Changed |= processBlock(MBB);
291
292   return Changed;
293 }