LLVM  3.7.0
SystemZShortenInst.cpp
Go to the documentation of this file.
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"
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 
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));
94  return true;
95  }
96  if (SystemZ::isImmLH(Imm)) {
97  MI.setDesc(TII->get(LLIxH));
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));
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 }
const MachineFunction * getParent() const
getParent - Return the MachineFunction containing this basic block.
mop_iterator operands_end()
Definition: MachineInstr.h:290
const unsigned GR32Regs[16]
unsigned getFirstReg(unsigned Reg)
F(f)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Reg
All possible values of the reg field in the ModR/M byte.
bool isUndef() const
const unsigned GRH32Regs[16]
void RemoveOperand(unsigned i)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
FunctionPass * createSystemZShortenInstPass(SystemZTargetMachine &TM)
int64_t getImm() const
reverse_iterator rend()
reverse_iterator rbegin()
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:267
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:120
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:273
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:294
static bool isImmLH(uint64_t Val)
Definition: SystemZ.h:110
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
MachineOperand class - Representation of each machine instruction operand.
const unsigned GR128Regs[16]
unsigned getRegAsGR64(unsigned Reg)
const unsigned GR64Regs[16]
Representation of each machine instruction.
Definition: MachineInstr.h:51
void setReg(unsigned Reg)
Change the register this operand corresponds to.
#define I(x, y, z)
Definition: MD5.cpp:54
unsigned getReg() const
getReg - Returns the register number.
virtual const TargetInstrInfo * getInstrInfo() const
mop_iterator operands_begin()
Definition: MachineInstr.h:289
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
static bool isImmLL(uint64_t Val)
Definition: SystemZ.h:105