LLVM 24.0.0git
SystemZShortenInst.cpp
Go to the documentation of this file.
1//===-- SystemZShortenInst.cpp - Instruction-shortening pass --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This pass tries to replace instructions with shorter forms. For example,
10// IILF can be replaced with LLILL or LLILH if the constant fits and if the
11// other 32 bits of the GR64 destination are not live.
12//
13//===----------------------------------------------------------------------===//
14
15#include "SystemZInstrInfo.h"
23#include "llvm/IR/Analysis.h"
24#include "llvm/Pass.h"
25
26using namespace llvm;
27
28#define DEBUG_TYPE "systemz-shorten-inst"
29
30namespace {
31class SystemZShortenInstLegacy : public MachineFunctionPass {
32public:
33 static char ID;
34 SystemZShortenInstLegacy();
35
37 bool runOnMachineFunction(MachineFunction &F) override;
38 MachineFunctionProperties getRequiredProperties() const override {
39 return MachineFunctionProperties().setNoVRegs();
40 }
41 void getAnalysisUsage(AnalysisUsage &AU) const override {
42 AU.setPreservesCFG();
44 }
45};
46
47char SystemZShortenInstLegacy::ID = 0;
48} // end anonymous namespace
49
50INITIALIZE_PASS(SystemZShortenInstLegacy, DEBUG_TYPE,
51 "SystemZ Instruction Shortening", false, false)
52
55 return new SystemZShortenInstLegacy();
56}
57
58SystemZShortenInstLegacy::SystemZShortenInstLegacy()
59 : MachineFunctionPass(ID) {}
60
61// Tie operands if MI has become a two-address instruction.
63 if (MI.getDesc().getOperandConstraint(1, MCOI::TIED_TO) == 0 &&
64 !MI.getOperand(0).isTied())
65 MI.tieOperands(0, 1);
66}
67
68// MI loads one word of a GPR using an IIxF instruction and LLIxL and LLIxH
69// are the halfword immediate loads for the same word. Try to use one of them
70// instead of IIxF.
71static bool shortenIIF(MachineInstr &MI, unsigned LLIxL, unsigned LLIxH,
72 const SystemZInstrInfo *TII,
74 Register Reg = MI.getOperand(0).getReg();
75 // The new opcode will clear the other half of the GR64 reg, so
76 // cancel if that is live.
77 unsigned thisSubRegIdx =
78 (SystemZ::GRH32BitRegClass.contains(Reg) ? SystemZ::subreg_h32
79 : SystemZ::subreg_l32);
80 unsigned otherSubRegIdx =
81 (thisSubRegIdx == SystemZ::subreg_l32 ? SystemZ::subreg_h32
82 : SystemZ::subreg_l32);
83 unsigned GR64BitReg =
84 TRI->getMatchingSuperReg(Reg, thisSubRegIdx, &SystemZ::GR64BitRegClass);
85 Register OtherReg = TRI->getSubReg(GR64BitReg, otherSubRegIdx);
86 if (!LiveRegs.available(OtherReg))
87 return false;
88
89 uint64_t Imm = MI.getOperand(1).getImm();
90 if (SystemZ::isImmLL(Imm)) {
91 MI.setDesc(TII->get(LLIxL));
92 MI.getOperand(0).setReg(SystemZMC::getRegAsGR64(Reg));
93 return true;
94 }
95 if (SystemZ::isImmLH(Imm)) {
96 MI.setDesc(TII->get(LLIxH));
97 MI.getOperand(0).setReg(SystemZMC::getRegAsGR64(Reg));
98 MI.getOperand(1).setImm(Imm >> 16);
99 return true;
100 }
101 return false;
102}
103
104// Change MI's opcode to Opcode if register operand 0 has a 4-bit encoding.
105static bool shortenOn0(MachineInstr &MI, unsigned Opcode,
106 const SystemZInstrInfo *TII) {
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.
116static bool shortenOn01(MachineInstr &MI, unsigned Opcode,
117 const SystemZInstrInfo *TII) {
118 if (SystemZMC::getFirstReg(MI.getOperand(0).getReg()) < 16 &&
119 SystemZMC::getFirstReg(MI.getOperand(1).getReg()) < 16) {
120 MI.setDesc(TII->get(Opcode));
121 return true;
122 }
123 return false;
124}
125
126// Change MI's opcode to Opcode if register operands 0, 1 and 2 have a
127// 4-bit encoding and if operands 0 and 1 are tied. Also ties op 0
128// with op 1, if MI becomes 2-address.
129static bool shortenOn001(MachineInstr &MI, unsigned Opcode,
130 const SystemZInstrInfo *TII) {
131 if (SystemZMC::getFirstReg(MI.getOperand(0).getReg()) < 16 &&
132 MI.getOperand(1).getReg() == MI.getOperand(0).getReg() &&
133 SystemZMC::getFirstReg(MI.getOperand(2).getReg()) < 16) {
134 MI.setDesc(TII->get(Opcode));
136 return true;
137 }
138 return false;
139}
140
141// Calls shortenOn001 if CCLive is false. CC def operand is added in
142// case of success.
143static bool shortenOn001AddCC(MachineInstr &MI, unsigned Opcode,
144 const SystemZInstrInfo *TII,
146 if (LiveRegs.available(SystemZ::CC) && shortenOn001(MI, Opcode, TII)) {
147 MachineInstrBuilder(*MI.getParent()->getParent(), &MI)
149 return true;
150 }
151 return false;
152}
153
154// MI is a vector-style conversion instruction with the operand order:
155// destination, source, exact-suppress, rounding-mode. If both registers
156// have a 4-bit encoding then change it to Opcode, which has operand order:
157// destination, rouding-mode, source, exact-suppress.
158static bool shortenFPConv(MachineInstr &MI, unsigned Opcode,
159 const SystemZInstrInfo *TII) {
160 if (SystemZMC::getFirstReg(MI.getOperand(0).getReg()) < 16 &&
161 SystemZMC::getFirstReg(MI.getOperand(1).getReg()) < 16) {
162 MachineOperand Dest(MI.getOperand(0));
163 MachineOperand Src(MI.getOperand(1));
164 MachineOperand Suppress(MI.getOperand(2));
165 MachineOperand Mode(MI.getOperand(3));
166 MI.removeOperand(3);
167 MI.removeOperand(2);
168 MI.removeOperand(1);
169 MI.removeOperand(0);
170 MI.setDesc(TII->get(Opcode));
171 MachineInstrBuilder(*MI.getParent()->getParent(), &MI)
172 .add(Dest)
173 .add(Mode)
174 .add(Src)
175 .add(Suppress);
176 return true;
177 }
178 return false;
179}
180
181static bool shortenFusedFPOp(MachineInstr &MI, unsigned Opcode,
182 const SystemZInstrInfo *TII) {
183 MachineOperand &DstMO = MI.getOperand(0);
184 MachineOperand &LHSMO = MI.getOperand(1);
185 MachineOperand &RHSMO = MI.getOperand(2);
186 MachineOperand &AccMO = MI.getOperand(3);
187 if (SystemZMC::getFirstReg(DstMO.getReg()) < 16 &&
188 SystemZMC::getFirstReg(LHSMO.getReg()) < 16 &&
189 SystemZMC::getFirstReg(RHSMO.getReg()) < 16 &&
190 SystemZMC::getFirstReg(AccMO.getReg()) < 16 &&
191 DstMO.getReg() == AccMO.getReg()) {
192 MachineOperand Lhs(LHSMO);
193 MachineOperand Rhs(RHSMO);
194 MachineOperand Src(AccMO);
195 MI.removeOperand(3);
196 MI.removeOperand(2);
197 MI.removeOperand(1);
198 MI.setDesc(TII->get(Opcode));
199 MachineInstrBuilder(*MI.getParent()->getParent(), &MI)
200 .add(Src)
201 .add(Lhs)
202 .add(Rhs);
203 return true;
204 }
205 return false;
206}
207
208// Process all instructions in MBB. Return true if something changed.
210 const SystemZInstrInfo *TII,
211 const TargetRegisterInfo *TRI) {
212 bool Changed = false;
213
214 // Set up the set of live registers at the end of MBB (live out)
215 LiveRegs.clear();
216 LiveRegs.addLiveOuts(MBB);
217
218 // Iterate backwards through the block looking for instructions to change.
219 for (MachineInstr &MI : llvm::reverse(MBB)) {
220 switch (MI.getOpcode()) {
221 case SystemZ::IILF:
222 Changed |=
223 shortenIIF(MI, SystemZ::LLILL, SystemZ::LLILH, TII, TRI, LiveRegs);
224 break;
225
226 case SystemZ::IIHF:
227 Changed |=
228 shortenIIF(MI, SystemZ::LLIHL, SystemZ::LLIHH, TII, TRI, LiveRegs);
229 break;
230
231 case SystemZ::WFADB:
232 Changed |= shortenOn001AddCC(MI, SystemZ::ADBR, TII, LiveRegs);
233 break;
234
235 case SystemZ::WFASB:
236 Changed |= shortenOn001AddCC(MI, SystemZ::AEBR, TII, LiveRegs);
237 break;
238
239 case SystemZ::WFDDB:
240 Changed |= shortenOn001(MI, SystemZ::DDBR, TII);
241 break;
242
243 case SystemZ::WFDSB:
244 Changed |= shortenOn001(MI, SystemZ::DEBR, TII);
245 break;
246
247 case SystemZ::WFIDB:
248 Changed |= shortenFPConv(MI, SystemZ::FIDBRA, TII);
249 break;
250
251 case SystemZ::WFISB:
252 Changed |= shortenFPConv(MI, SystemZ::FIEBRA, TII);
253 break;
254
255 case SystemZ::WLDEB:
256 Changed |= shortenOn01(MI, SystemZ::LDEBR, TII);
257 break;
258
259 case SystemZ::WLEDB:
260 Changed |= shortenFPConv(MI, SystemZ::LEDBRA, TII);
261 break;
262
263 case SystemZ::WFMDB:
264 Changed |= shortenOn001(MI, SystemZ::MDBR, TII);
265 break;
266
267 case SystemZ::WFMSB:
268 Changed |= shortenOn001(MI, SystemZ::MEEBR, TII);
269 break;
270
271 case SystemZ::WFMADB:
272 Changed |= shortenFusedFPOp(MI, SystemZ::MADBR, TII);
273 break;
274
275 case SystemZ::WFMASB:
276 Changed |= shortenFusedFPOp(MI, SystemZ::MAEBR, TII);
277 break;
278
279 case SystemZ::WFMSDB:
280 Changed |= shortenFusedFPOp(MI, SystemZ::MSDBR, TII);
281 break;
282
283 case SystemZ::WFMSSB:
284 Changed |= shortenFusedFPOp(MI, SystemZ::MSEBR, TII);
285 break;
286
287 case SystemZ::WFLCDB:
288 Changed |= shortenOn01(MI, SystemZ::LCDFR, TII);
289 break;
290
291 case SystemZ::WFLCSB:
292 Changed |= shortenOn01(MI, SystemZ::LCDFR_32, TII);
293 break;
294
295 case SystemZ::WFLNDB:
296 Changed |= shortenOn01(MI, SystemZ::LNDFR, TII);
297 break;
298
299 case SystemZ::WFLNSB:
300 Changed |= shortenOn01(MI, SystemZ::LNDFR_32, TII);
301 break;
302
303 case SystemZ::WFLPDB:
304 Changed |= shortenOn01(MI, SystemZ::LPDFR, TII);
305 break;
306
307 case SystemZ::WFLPSB:
308 Changed |= shortenOn01(MI, SystemZ::LPDFR_32, TII);
309 break;
310
311 case SystemZ::WFSQDB:
312 Changed |= shortenOn01(MI, SystemZ::SQDBR, TII);
313 break;
314
315 case SystemZ::WFSQSB:
316 Changed |= shortenOn01(MI, SystemZ::SQEBR, TII);
317 break;
318
319 case SystemZ::WFSDB:
320 Changed |= shortenOn001AddCC(MI, SystemZ::SDBR, TII, LiveRegs);
321 break;
322
323 case SystemZ::WFSSB:
324 Changed |= shortenOn001AddCC(MI, SystemZ::SEBR, TII, LiveRegs);
325 break;
326
327 case SystemZ::WFCDB:
328 Changed |= shortenOn01(MI, SystemZ::CDBR, TII);
329 break;
330
331 case SystemZ::WFCSB:
332 Changed |= shortenOn01(MI, SystemZ::CEBR, TII);
333 break;
334
335 case SystemZ::WFKDB:
336 Changed |= shortenOn01(MI, SystemZ::KDBR, TII);
337 break;
338
339 case SystemZ::WFKSB:
340 Changed |= shortenOn01(MI, SystemZ::KEBR, TII);
341 break;
342
343 case SystemZ::VL32:
344 // For z13 we prefer LDE over LE to avoid partial register dependencies.
345 Changed |= shortenOn0(MI, SystemZ::LDE32, TII);
346 break;
347
348 case SystemZ::VST32:
349 Changed |= shortenOn0(MI, SystemZ::STE, TII);
350 break;
351
352 case SystemZ::VL64:
353 Changed |= shortenOn0(MI, SystemZ::LD, TII);
354 break;
355
356 case SystemZ::VST64:
357 Changed |= shortenOn0(MI, SystemZ::STD, TII);
358 break;
359
360 default: {
361 int TwoOperandOpcode = SystemZ::getTwoOperandOpcode(MI.getOpcode());
362 if (TwoOperandOpcode == -1)
363 break;
364
365 if ((MI.getOperand(0).getReg() != MI.getOperand(1).getReg()) &&
366 (!MI.isCommutable() ||
367 MI.getOperand(0).getReg() != MI.getOperand(2).getReg() ||
368 !TII->commuteInstruction(MI, false, 1, 2)))
369 break;
370
371 MI.setDesc(TII->get(TwoOperandOpcode));
372 MI.tieOperands(0, 1);
373 if (TwoOperandOpcode == SystemZ::SLL ||
374 TwoOperandOpcode == SystemZ::SLA ||
375 TwoOperandOpcode == SystemZ::SRL ||
376 TwoOperandOpcode == SystemZ::SRA) {
377 // These shifts only use the low 6 bits of the shift count.
378 MachineOperand &ImmMO = MI.getOperand(3);
379 ImmMO.setImm(ImmMO.getImm() & 0xfff);
380 }
381 Changed = true;
382 break;
383 }
384 }
385 if (!MI.isDebugInstr())
386 LiveRegs.stepBackward(MI);
387 }
388
389 return Changed;
390}
391
393 const SystemZSubtarget &ST = F.getSubtarget<SystemZSubtarget>();
394 const SystemZInstrInfo *TII = ST.getInstrInfo();
395 const TargetRegisterInfo *TRI = ST.getRegisterInfo();
397 LiveRegs.init(*TRI);
398
399 bool Changed = false;
400 for (auto &MBB : F)
402
403 return Changed;
404}
405
406bool SystemZShortenInstLegacy::runOnMachineFunction(MachineFunction &MF) {
407 if (skipFunction(MF.getFunction()))
408 return false;
409 return shortenInstructionsInMF(MF);
410}
411
412PreservedAnalyses
uint64_t uint64_t
uint64_t Imm
MachineBasicBlock & MBB
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
A set of register units.
#define F(x, y, z)
Definition MD5.cpp:54
Register Reg
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool shortenFPConv(MachineInstr &MI, unsigned Opcode, const SystemZInstrInfo *TII)
static bool processBlock(MachineBasicBlock &MBB, LiveRegUnits &LiveRegs, const SystemZInstrInfo *TII, const TargetRegisterInfo *TRI)
static bool shortenOn01(MachineInstr &MI, unsigned Opcode, const SystemZInstrInfo *TII)
static bool shortenIIF(MachineInstr &MI, unsigned LLIxL, unsigned LLIxH, const SystemZInstrInfo *TII, const TargetRegisterInfo *TRI, LiveRegUnits &LiveRegs)
static void tieOpsIfNeeded(MachineInstr &MI)
static bool shortenFusedFPOp(MachineInstr &MI, unsigned Opcode, const SystemZInstrInfo *TII)
static bool shortenOn001(MachineInstr &MI, unsigned Opcode, const SystemZInstrInfo *TII)
static bool shortenOn0(MachineInstr &MI, unsigned Opcode, const SystemZInstrInfo *TII)
static bool shortenOn001AddCC(MachineInstr &MI, unsigned Opcode, const SystemZInstrInfo *TII, LiveRegUnits &LiveRegs)
static bool shortenInstructionsInMF(MachineFunction &F)
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:280
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
A set of register units used to track register liveness.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Properties which a MachineFunction may have at a given point in time.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
void setImm(int64_t immVal)
int64_t getImm() const
Register getReg() const
getReg - Returns the register number.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
Wrapper class representing virtual and physical registers.
Definition Register.h:20
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Pass manager infrastructure for declaring and invalidating analyses.
unsigned getFirstReg(unsigned Reg)
unsigned getRegAsGR64(unsigned Reg)
static bool isImmLL(uint64_t Val)
Definition SystemZ.h:167
static bool isImmLH(uint64_t Val)
Definition SystemZ.h:172
int32_t getTwoOperandOpcode(uint32_t Opcode)
This is an optimization pass for GlobalISel generic memory operations.
@ Dead
Unused definition.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
FunctionPass * createSystemZShortenInstLegacyPass(SystemZTargetMachine &TM)