LLVM 24.0.0git
SIShrinkInstructions.cpp
Go to the documentation of this file.
1//===-- SIShrinkInstructions.cpp - Shrink Instructions --------------------===//
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/// The pass tries to use the 32-bit encoding for instructions when possible.
8//===----------------------------------------------------------------------===//
9//
10
12#include "AMDGPU.h"
13#include "GCNSubtarget.h"
15#include "llvm/ADT/Statistic.h"
17
18#define DEBUG_TYPE "si-shrink-instructions"
19
20STATISTIC(NumInstructionsShrunk,
21 "Number of 64-bit instruction reduced to 32-bit.");
22STATISTIC(NumLiteralConstantsFolded,
23 "Number of literal constants folded into 32-bit instructions.");
24
25using namespace llvm;
26
27namespace {
28
29enum ChangeKind { None, UpdateHint, UpdateInst };
30
31class SIShrinkInstructions {
33 MachineRegisterInfo *MRI;
34 const GCNSubtarget *ST;
35 const SIInstrInfo *TII;
36 const SIRegisterInfo *TRI;
37 bool IsPostRA;
38
39 bool foldImmediates(MachineInstr &MI, bool TryToCommute = true) const;
40 bool shouldShrinkTrue16(MachineInstr &MI) const;
41 bool isKImmOperand(const MachineInstr &MI, const MachineOperand &Src) const;
42 bool isKUImmOperand(const MachineInstr &MI, const MachineOperand &Src) const;
43 bool isKImmOrKUImmOperand(const MachineOperand &Src, bool &IsUnsigned) const;
44 void copyExtraImplicitOps(MachineInstr &NewMI, MachineInstr &MI) const;
45 bool shrinkScalarCompare(MachineInstr &MI) const;
46 bool shrinkMIMG(MachineInstr &MI) const;
47 bool shrinkMadFma(MachineInstr &MI) const;
48 ChangeKind shrinkScalarLogicOp(MachineInstr &MI) const;
49 bool tryReplaceDeadSDST(MachineInstr &MI) const;
51 unsigned SubReg) const;
52 bool instReadsReg(const MachineInstr *MI, unsigned Reg,
53 unsigned SubReg) const;
54 bool instModifiesReg(const MachineInstr *MI, unsigned Reg,
55 unsigned SubReg) const;
56 TargetInstrInfo::RegSubRegPair getSubRegForIndex(Register Reg, unsigned Sub,
57 unsigned I) const;
58 void dropInstructionKeepingImpDefs(MachineInstr &MI) const;
59 MachineInstr *matchSwap(MachineInstr &MovT) const;
60
61public:
62 SIShrinkInstructions() = default;
63 bool run(MachineFunction &MF);
64};
65
66class SIShrinkInstructionsLegacy : public MachineFunctionPass {
67
68public:
69 static char ID;
70
71 SIShrinkInstructionsLegacy() : MachineFunctionPass(ID) {}
72
73 bool runOnMachineFunction(MachineFunction &MF) override;
74
75 StringRef getPassName() const override { return "SI Shrink Instructions"; }
76
77 void getAnalysisUsage(AnalysisUsage &AU) const override {
78 AU.setPreservesCFG();
80 }
81};
82
83} // End anonymous namespace.
84
85INITIALIZE_PASS(SIShrinkInstructionsLegacy, DEBUG_TYPE,
86 "SI Shrink Instructions", false, false)
87
88char SIShrinkInstructionsLegacy::ID = 0;
89
91 return new SIShrinkInstructionsLegacy();
92}
93
94/// This function checks \p MI for operands defined by a move immediate
95/// instruction and then folds the literal constant into the instruction if it
96/// can. This function assumes that \p MI is a VOP1, VOP2, or VOPC instructions.
97bool SIShrinkInstructions::foldImmediates(MachineInstr &MI,
98 bool TryToCommute) const {
99 assert(TII->isVOP1(MI) || TII->isVOP2(MI) || TII->isVOPC(MI));
100
101 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
102
103 // Try to fold Src0
104 MachineOperand &Src0 = MI.getOperand(Src0Idx);
105 if (Src0.isReg()) {
106 Register Reg = Src0.getReg();
107 if (Reg.isVirtual()) {
108 MachineInstr *Def = MRI->getUniqueVRegDef(Reg);
109 if (Def && Def->isMoveImmediate()) {
110 const MachineOperand &MovSrc = Def->getOperand(1);
111 bool ConstantFolded = false;
112
113 if (MovSrc.isImm()) {
114 if (std::optional<int64_t> Imm = SIInstrInfo::extractSubregFromImm(
115 MovSrc.getImm(), Src0.getSubReg())) {
116 MachineOperand ImmOp = MachineOperand::CreateImm(*Imm);
117 if (TII->isOperandLegal(MI, Src0Idx, &ImmOp)) {
118 Src0.ChangeToImmediate(*Imm);
119 ConstantFolded = true;
120 }
121 }
122 } else if (MovSrc.isGlobal()) {
123 if (std::optional<unsigned> Flags =
125 MovSrc.getTargetFlags(), Src0.getSubReg())) {
126 MachineOperand GAOp = MachineOperand::CreateGA(
127 MovSrc.getGlobal(), MovSrc.getOffset(), *Flags);
128 if (TII->isOperandLegal(MI, Src0Idx, &GAOp)) {
129 Src0.ChangeToGA(MovSrc.getGlobal(), MovSrc.getOffset(), *Flags);
130 ConstantFolded = true;
131 }
132 }
133 } else if (MovSrc.isFI() && !Src0.getSubReg() &&
134 TII->isOperandLegal(MI, Src0Idx, &MovSrc)) {
135 Src0.ChangeToFrameIndex(MovSrc.getIndex());
136 ConstantFolded = true;
137 }
138
139 if (ConstantFolded) {
140 if (MRI->use_nodbg_empty(Reg))
141 Def->eraseFromParent();
142 ++NumLiteralConstantsFolded;
143 return true;
144 }
145 }
146 }
147 }
148
149 // We have failed to fold src0, so commute the instruction and try again.
150 if (TryToCommute && MI.isCommutable()) {
151 if (TII->commuteInstruction(MI)) {
152 if (foldImmediates(MI, false))
153 return true;
154
155 // Commute back.
156 TII->commuteInstruction(MI);
157 }
158 }
159
160 return false;
161}
162
163/// Do not shrink the instruction if its registers are not expressible in the
164/// shrunk encoding.
165bool SIShrinkInstructions::shouldShrinkTrue16(MachineInstr &MI) const {
166 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
167 const MachineOperand &MO = MI.getOperand(I);
168 if (MO.isReg()) {
169 Register Reg = MO.getReg();
170 assert(!Reg.isVirtual() && "Prior checks should ensure we only shrink "
171 "True16 Instructions post-RA");
172 if (AMDGPU::VGPR_32RegClass.contains(Reg) &&
173 !AMDGPU::VGPR_32_Lo128RegClass.contains(Reg))
174 return false;
175
176 if (AMDGPU::VGPR_16RegClass.contains(Reg) &&
177 !AMDGPU::VGPR_16_Lo128RegClass.contains(Reg))
178 return false;
179 }
180 }
181 return true;
182}
183
184bool SIShrinkInstructions::isKImmOperand(const MachineInstr &MI,
185 const MachineOperand &Src) const {
186 return isInt<16>(SignExtend64(Src.getImm(), 32)) &&
187 !TII->isInlineConstant(MI, MI.getOperandNo(&Src));
188}
189
190bool SIShrinkInstructions::isKUImmOperand(const MachineInstr &MI,
191 const MachineOperand &Src) const {
192 return isUInt<16>(Src.getImm()) &&
193 !TII->isInlineConstant(MI, MI.getOperandNo(&Src));
194}
195
196bool SIShrinkInstructions::isKImmOrKUImmOperand(const MachineOperand &Src,
197 bool &IsUnsigned) const {
198 if (isInt<16>(SignExtend64(Src.getImm(), 32))) {
199 IsUnsigned = false;
200 return !TII->isInlineConstant(Src);
201 }
202
203 if (isUInt<16>(Src.getImm())) {
204 IsUnsigned = true;
205 return !TII->isInlineConstant(Src);
206 }
207
208 return false;
209}
210
211/// \returns the opcode of an instruction a move immediate of the constant \p
212/// Src can be replaced with if the constant is replaced with \p ModifiedImm.
213/// i.e.
214///
215/// If the bitreverse of a constant is an inline immediate, reverse the
216/// immediate and return the bitreverse opcode.
217///
218/// If the bitwise negation of a constant is an inline immediate, reverse the
219/// immediate and return the bitwise not opcode.
221 const MachineOperand &Src,
222 int32_t &ModifiedImm, bool Scalar) {
223 if (TII->isInlineConstant(Src))
224 return 0;
225 int32_t SrcImm = static_cast<int32_t>(Src.getImm());
226
227 if (!Scalar) {
228 // We could handle the scalar case with here, but we would need to check
229 // that SCC is not live as S_NOT_B32 clobbers it. It's probably not worth
230 // it, as the reasonable values are already covered by s_movk_i32.
231 ModifiedImm = ~SrcImm;
232 if (TII->isInlineConstant(APInt(32, ModifiedImm, true)))
233 return AMDGPU::V_NOT_B32_e32;
234 }
235
236 ModifiedImm = reverseBits<int32_t>(SrcImm);
237 if (TII->isInlineConstant(APInt(32, ModifiedImm, true)))
238 return Scalar ? AMDGPU::S_BREV_B32 : AMDGPU::V_BFREV_B32_e32;
239
240 return 0;
241}
242
243/// Copy implicit register operands from specified instruction to this
244/// instruction that are not part of the instruction definition.
245void SIShrinkInstructions::copyExtraImplicitOps(MachineInstr &NewMI,
246 MachineInstr &MI) const {
247 MachineFunction &MF = *MI.getMF();
248 for (unsigned i = MI.getDesc().getNumOperands() +
249 MI.getDesc().implicit_uses().size() +
250 MI.getDesc().implicit_defs().size(),
251 e = MI.getNumOperands();
252 i != e; ++i) {
253 const MachineOperand &MO = MI.getOperand(i);
254 if ((MO.isReg() && MO.isImplicit()) || MO.isRegMask())
255 NewMI.addOperand(MF, MO);
256 }
257}
258
259bool SIShrinkInstructions::shrinkScalarCompare(MachineInstr &MI) const {
260 if (!ST->hasSCmpK())
261 return false;
262
263 // cmpk instructions do scc = dst <cc op> imm16, so commute the instruction to
264 // get constants on the RHS.
265 bool Changed = false;
266 if (!MI.getOperand(0).isReg()) {
267 if (TII->commuteInstruction(MI, false, 0, 1))
268 Changed = true;
269 }
270
271 // cmpk requires src0 to be a register
272 const MachineOperand &Src0 = MI.getOperand(0);
273 if (!Src0.isReg())
274 return Changed;
275
276 MachineOperand &Src1 = MI.getOperand(1);
277 if (!Src1.isImm())
278 return Changed;
279
280 int SOPKOpc = AMDGPU::getSOPKOp(MI.getOpcode());
281 if (SOPKOpc == -1)
282 return Changed;
283
284 // eq/ne is special because the imm16 can be treated as signed or unsigned,
285 // and initially selected to the unsigned versions.
286 if (SOPKOpc == AMDGPU::S_CMPK_EQ_U32 || SOPKOpc == AMDGPU::S_CMPK_LG_U32) {
287 bool HasUImm;
288 if (isKImmOrKUImmOperand(Src1, HasUImm)) {
289 if (!HasUImm) {
290 SOPKOpc = (SOPKOpc == AMDGPU::S_CMPK_EQ_U32) ?
291 AMDGPU::S_CMPK_EQ_I32 : AMDGPU::S_CMPK_LG_I32;
292 Src1.setImm(SignExtend32(Src1.getImm(), 32));
293 }
294
295 MI.setDesc(TII->get(SOPKOpc));
296 Changed = true;
297 }
298
299 return Changed;
300 }
301
302 const MCInstrDesc &NewDesc = TII->get(SOPKOpc);
303
304 if ((SIInstrInfo::sopkIsZext(SOPKOpc) && isKUImmOperand(MI, Src1)) ||
305 (!SIInstrInfo::sopkIsZext(SOPKOpc) && isKImmOperand(MI, Src1))) {
306 if (!SIInstrInfo::sopkIsZext(SOPKOpc))
307 Src1.setImm(SignExtend64(Src1.getImm(), 32));
308 MI.setDesc(NewDesc);
309 Changed = true;
310 }
311 return Changed;
312}
313
314// Shrink NSA encoded instructions with contiguous VGPRs to non-NSA encoding.
315bool SIShrinkInstructions::shrinkMIMG(MachineInstr &MI) const {
316 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(MI.getOpcode());
317 if (!Info)
318 return false;
319
320 uint8_t NewEncoding;
321 switch (Info->MIMGEncoding) {
322 case AMDGPU::MIMGEncGfx10NSA:
323 NewEncoding = AMDGPU::MIMGEncGfx10Default;
324 break;
325 case AMDGPU::MIMGEncGfx11NSA:
326 NewEncoding = AMDGPU::MIMGEncGfx11Default;
327 break;
328 default:
329 return false;
330 }
331
332 int VAddr0Idx =
333 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0);
334 unsigned NewAddrDwords = Info->VAddrDwords;
335 const TargetRegisterClass *RC;
336
337 if (Info->VAddrDwords == 2) {
338 RC = &AMDGPU::VReg_64RegClass;
339 } else if (Info->VAddrDwords == 3) {
340 RC = &AMDGPU::VReg_96RegClass;
341 } else if (Info->VAddrDwords == 4) {
342 RC = &AMDGPU::VReg_128RegClass;
343 } else if (Info->VAddrDwords == 5) {
344 RC = &AMDGPU::VReg_160RegClass;
345 } else if (Info->VAddrDwords == 6) {
346 RC = &AMDGPU::VReg_192RegClass;
347 } else if (Info->VAddrDwords == 7) {
348 RC = &AMDGPU::VReg_224RegClass;
349 } else if (Info->VAddrDwords == 8) {
350 RC = &AMDGPU::VReg_256RegClass;
351 } else if (Info->VAddrDwords == 9) {
352 RC = &AMDGPU::VReg_288RegClass;
353 } else if (Info->VAddrDwords == 10) {
354 RC = &AMDGPU::VReg_320RegClass;
355 } else if (Info->VAddrDwords == 11) {
356 RC = &AMDGPU::VReg_352RegClass;
357 } else if (Info->VAddrDwords == 12) {
358 RC = &AMDGPU::VReg_384RegClass;
359 } else {
360 RC = &AMDGPU::VReg_512RegClass;
361 NewAddrDwords = 16;
362 }
363
364 unsigned VgprBase = 0;
365 unsigned NextVgpr = 0;
366 bool IsUndef = true;
367 bool IsKill = NewAddrDwords == Info->VAddrDwords;
368 const unsigned NSAMaxSize = ST->getNSAMaxSize();
369 const bool IsPartialNSA = NewAddrDwords > NSAMaxSize;
370 const unsigned EndVAddr = IsPartialNSA ? NSAMaxSize : Info->VAddrOperands;
371 for (unsigned Idx = 0; Idx < EndVAddr; ++Idx) {
372 const MachineOperand &Op = MI.getOperand(VAddr0Idx + Idx);
373 unsigned Vgpr = TRI->getHWRegIndex(Op.getReg());
374 unsigned Dwords = TRI->getRegSizeInBits(Op.getReg(), *MRI) / 32;
375 assert(Dwords > 0 && "Un-implemented for less than 32 bit regs");
376
377 if (Idx == 0) {
378 VgprBase = Vgpr;
379 NextVgpr = Vgpr + Dwords;
380 } else if (Vgpr == NextVgpr) {
381 NextVgpr = Vgpr + Dwords;
382 } else {
383 return false;
384 }
385
386 if (!Op.isUndef())
387 IsUndef = false;
388 if (!Op.isKill())
389 IsKill = false;
390 }
391
392 if (VgprBase + NewAddrDwords > 256)
393 return false;
394
395 // Further check for implicit tied operands - this may be present if TFE is
396 // enabled
397 int TFEIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::tfe);
398 int LWEIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::lwe);
399 unsigned TFEVal = (TFEIdx == -1) ? 0 : MI.getOperand(TFEIdx).getImm();
400 unsigned LWEVal = (LWEIdx == -1) ? 0 : MI.getOperand(LWEIdx).getImm();
401 int ToUntie = -1;
402 if (TFEVal || LWEVal) {
403 // TFE/LWE is enabled so we need to deal with an implicit tied operand
404 for (unsigned i = LWEIdx + 1, e = MI.getNumOperands(); i != e; ++i) {
405 if (MI.getOperand(i).isReg() && MI.getOperand(i).isTied() &&
406 MI.getOperand(i).isImplicit()) {
407 // This is the tied operand
408 assert(
409 ToUntie == -1 &&
410 "found more than one tied implicit operand when expecting only 1");
411 ToUntie = i;
412 MI.untieRegOperand(ToUntie);
413 }
414 }
415 }
416
417 unsigned NewOpcode = AMDGPU::getMIMGOpcode(Info->BaseOpcode, NewEncoding,
418 Info->VDataDwords, NewAddrDwords);
419 MI.setDesc(TII->get(NewOpcode));
420 MI.getOperand(VAddr0Idx).setReg(RC->getRegister(VgprBase));
421 MI.getOperand(VAddr0Idx).setIsUndef(IsUndef);
422 MI.getOperand(VAddr0Idx).setIsKill(IsKill);
423
424 for (unsigned i = 1; i < EndVAddr; ++i)
425 MI.removeOperand(VAddr0Idx + 1);
426
427 if (ToUntie >= 0) {
428 MI.tieOperands(
429 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata),
430 ToUntie - (EndVAddr - 1));
431 }
432 return true;
433}
434
435// Shrink MAD to MADAK/MADMK and FMA to FMAAK/FMAMK.
436bool SIShrinkInstructions::shrinkMadFma(MachineInstr &MI) const {
437 // Pre-GFX10 VOP3 instructions like MAD/FMA cannot take a literal operand so
438 // there is no reason to try to shrink them.
439 if (!ST->hasVOP3Literal())
440 return false;
441
442 // There is no advantage to doing this pre-RA.
443 if (!IsPostRA)
444 return false;
445
446 if (TII->hasAnyModifiersSet(MI))
447 return false;
448
449 const unsigned Opcode = MI.getOpcode();
450 MachineOperand &Src0 = *TII->getNamedOperand(MI, AMDGPU::OpName::src0);
451 MachineOperand &Src1 = *TII->getNamedOperand(MI, AMDGPU::OpName::src1);
452 MachineOperand &Src2 = *TII->getNamedOperand(MI, AMDGPU::OpName::src2);
453 unsigned NewOpcode = AMDGPU::INSTRUCTION_LIST_END;
454
455 bool Swap;
456
457 // Detect "Dst = VSrc * VGPR + Imm" and convert to AK form.
458 if (Src2.isImm() && !TII->isInlineConstant(Src2)) {
459 if (Src1.isReg() && TRI->isVGPR(*MRI, Src1.getReg()))
460 Swap = false;
461 else if (Src0.isReg() && TRI->isVGPR(*MRI, Src0.getReg()))
462 Swap = true;
463 else
464 return false;
465
466 switch (Opcode) {
467 default:
468 llvm_unreachable("Unexpected mad/fma opcode!");
469 case AMDGPU::V_MAD_F32_e64:
470 NewOpcode = AMDGPU::V_MADAK_F32;
471 break;
472 case AMDGPU::V_FMA_F32_e64:
473 NewOpcode = AMDGPU::V_FMAAK_F32;
474 break;
475 case AMDGPU::V_MAD_F16_e64:
476 NewOpcode = AMDGPU::V_MADAK_F16;
477 break;
478 case AMDGPU::V_FMA_F16_e64:
479 case AMDGPU::V_FMA_F16_gfx9_e64:
480 NewOpcode = AMDGPU::V_FMAAK_F16;
481 break;
482 case AMDGPU::V_FMA_F16_gfx9_t16_e64:
483 NewOpcode = AMDGPU::V_FMAAK_F16_t16;
484 break;
485 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
486 NewOpcode = AMDGPU::V_FMAAK_F16_fake16;
487 break;
488 case AMDGPU::V_FMA_F64_e64:
489 if (ST->hasFmaakFmamkF64Insts())
490 NewOpcode = AMDGPU::V_FMAAK_F64;
491 break;
492 }
493 }
494
495 // Detect "Dst = VSrc * Imm + VGPR" and convert to MK form.
496 if (Src2.isReg() && TRI->isVGPR(*MRI, Src2.getReg())) {
497 if (Src1.isImm() && !TII->isInlineConstant(Src1))
498 Swap = false;
499 else if (Src0.isImm() && !TII->isInlineConstant(Src0))
500 Swap = true;
501 else
502 return false;
503
504 switch (Opcode) {
505 default:
506 llvm_unreachable("Unexpected mad/fma opcode!");
507 case AMDGPU::V_MAD_F32_e64:
508 NewOpcode = AMDGPU::V_MADMK_F32;
509 break;
510 case AMDGPU::V_FMA_F32_e64:
511 NewOpcode = AMDGPU::V_FMAMK_F32;
512 break;
513 case AMDGPU::V_MAD_F16_e64:
514 NewOpcode = AMDGPU::V_MADMK_F16;
515 break;
516 case AMDGPU::V_FMA_F16_e64:
517 case AMDGPU::V_FMA_F16_gfx9_e64:
518 NewOpcode = AMDGPU::V_FMAMK_F16;
519 break;
520 case AMDGPU::V_FMA_F16_gfx9_t16_e64:
521 NewOpcode = AMDGPU::V_FMAMK_F16_t16;
522 break;
523 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
524 NewOpcode = AMDGPU::V_FMAMK_F16_fake16;
525 break;
526 case AMDGPU::V_FMA_F64_e64:
527 if (ST->hasFmaakFmamkF64Insts())
528 NewOpcode = AMDGPU::V_FMAMK_F64;
529 break;
530 }
531 }
532
533 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END)
534 return false;
535
536 if (AMDGPU::isTrue16Inst(NewOpcode) && !shouldShrinkTrue16(MI))
537 return false;
538
539 if (Swap) {
540 // Swap Src0 and Src1 by building a new instruction.
541 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(NewOpcode),
542 MI.getOperand(0).getReg())
543 .add(Src1)
544 .add(Src0)
545 .add(Src2)
546 .setMIFlags(MI.getFlags());
547 MI.eraseFromParent();
548 } else {
549 TII->removeModOperands(MI);
550 MI.setDesc(TII->get(NewOpcode));
551 }
552 return true;
553}
554
555/// Attempt to shrink AND/OR/XOR operations requiring non-inlineable literals.
556/// For AND or OR, try using S_BITSET{0,1} to clear or set bits.
557/// If the inverse of the immediate is legal, use ANDN2, ORN2 or
558/// XNOR (as a ^ b == ~(a ^ ~b)).
559/// \return ChangeKind::None if no changes were made.
560/// ChangeKind::UpdateHint if regalloc hints were updated.
561/// ChangeKind::UpdateInst if the instruction was modified.
562ChangeKind SIShrinkInstructions::shrinkScalarLogicOp(MachineInstr &MI) const {
563 unsigned Opc = MI.getOpcode();
564 const MachineOperand *Dest = &MI.getOperand(0);
565 MachineOperand *Src0 = &MI.getOperand(1);
566 MachineOperand *Src1 = &MI.getOperand(2);
567 MachineOperand *SrcReg = Src0;
568 MachineOperand *SrcImm = Src1;
569
570 if (!SrcImm->isImm() ||
571 AMDGPU::isInlinableLiteral32(SrcImm->getImm(), ST->hasInv2PiInlineImm()))
572 return ChangeKind::None;
573
574 uint32_t Imm = static_cast<uint32_t>(SrcImm->getImm());
575 uint32_t NewImm = 0;
576
577 if (Opc == AMDGPU::S_AND_B32) {
578 if (isPowerOf2_32(~Imm) &&
579 MI.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr)->isDead()) {
580 NewImm = llvm::countr_one(Imm);
581 Opc = AMDGPU::S_BITSET0_B32;
582 } else if (AMDGPU::isInlinableLiteral32(~Imm, ST->hasInv2PiInlineImm())) {
583 NewImm = ~Imm;
584 Opc = AMDGPU::S_ANDN2_B32;
585 }
586 } else if (Opc == AMDGPU::S_OR_B32) {
587 if (isPowerOf2_32(Imm) &&
588 MI.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr)->isDead()) {
589 NewImm = llvm::countr_zero(Imm);
590 Opc = AMDGPU::S_BITSET1_B32;
591 } else if (AMDGPU::isInlinableLiteral32(~Imm, ST->hasInv2PiInlineImm())) {
592 NewImm = ~Imm;
593 Opc = AMDGPU::S_ORN2_B32;
594 }
595 } else if (Opc == AMDGPU::S_XOR_B32) {
596 if (AMDGPU::isInlinableLiteral32(~Imm, ST->hasInv2PiInlineImm())) {
597 NewImm = ~Imm;
598 Opc = AMDGPU::S_XNOR_B32;
599 }
600 } else {
601 llvm_unreachable("unexpected opcode");
602 }
603
604 if (NewImm != 0) {
605 if (Dest->getReg().isVirtual() && SrcReg->isReg()) {
606 MRI->setRegAllocationHint(Dest->getReg(), 0, SrcReg->getReg());
607 MRI->setRegAllocationHint(SrcReg->getReg(), 0, Dest->getReg());
608 return ChangeKind::UpdateHint;
609 }
610
611 if (SrcReg->isReg() && SrcReg->getReg() == Dest->getReg()) {
612 const bool IsUndef = SrcReg->isUndef();
613 const bool IsKill = SrcReg->isKill();
614 TII->mutateAndCleanupImplicit(MI, TII->get(Opc));
615 if (Opc == AMDGPU::S_BITSET0_B32 ||
616 Opc == AMDGPU::S_BITSET1_B32) {
617 Src0->ChangeToImmediate(NewImm);
618 // Remove the immediate and add the tied input.
619 MI.getOperand(2).ChangeToRegister(Dest->getReg(), /*IsDef*/ false,
620 /*isImp*/ false, IsKill,
621 /*isDead*/ false, IsUndef);
622 MI.tieOperands(0, 2);
623 } else {
624 SrcImm->setImm(NewImm);
625 }
626 return ChangeKind::UpdateInst;
627 }
628 }
629
630 return ChangeKind::None;
631}
632
633// This is the same as MachineInstr::readsRegister/modifiesRegister except
634// it takes subregs into account.
635bool SIShrinkInstructions::instAccessReg(
637 unsigned SubReg) const {
638 for (const MachineOperand &MO : R) {
639 if (Reg.isPhysical() && MO.getReg().isPhysical()) {
640 if (TRI->regsOverlap(Reg, MO.getReg()))
641 return true;
642 } else if (MO.getReg() == Reg && Reg.isVirtual()) {
643 LaneBitmask Overlap = TRI->getSubRegIndexLaneMask(SubReg) &
644 TRI->getSubRegIndexLaneMask(MO.getSubReg());
645 if (Overlap.any())
646 return true;
647 }
648 }
649 return false;
650}
651
652bool SIShrinkInstructions::instReadsReg(const MachineInstr *MI, unsigned Reg,
653 unsigned SubReg) const {
654 return instAccessReg(MI->all_uses(), Reg, SubReg);
655}
656
657bool SIShrinkInstructions::instModifiesReg(const MachineInstr *MI, unsigned Reg,
658 unsigned SubReg) const {
659 return instAccessReg(MI->all_defs(), Reg, SubReg);
660}
661
662TargetInstrInfo::RegSubRegPair
663SIShrinkInstructions::getSubRegForIndex(Register Reg, unsigned Sub,
664 unsigned I) const {
665 if (TRI->getRegSizeInBits(Reg, *MRI) != 32) {
666 if (Reg.isPhysical()) {
667 Reg = TRI->getSubReg(Reg, TRI->getSubRegFromChannel(I));
668 } else {
669 Sub = TRI->getSubRegFromChannel(I + TRI->getChannelFromSubReg(Sub));
670 }
671 }
672 return TargetInstrInfo::RegSubRegPair(Reg, Sub);
673}
674
675void SIShrinkInstructions::dropInstructionKeepingImpDefs(
676 MachineInstr &MI) const {
677 for (unsigned i = MI.getDesc().getNumOperands() +
678 MI.getDesc().implicit_uses().size() +
679 MI.getDesc().implicit_defs().size(),
680 e = MI.getNumOperands();
681 i != e; ++i) {
682 const MachineOperand &Op = MI.getOperand(i);
683 if (!Op.isDef())
684 continue;
685 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
686 TII->get(AMDGPU::IMPLICIT_DEF), Op.getReg());
687 }
688
689 MI.eraseFromParent();
690}
691
692// Match:
693// mov t, x
694// mov x, y
695// mov y, t
696//
697// =>
698//
699// mov t, x (t is potentially dead and move eliminated)
700// v_swap_b32 x, y
701//
702// Returns next valid instruction pointer if was able to create v_swap_b32.
703//
704// This shall not be done too early not to prevent possible folding which may
705// remove matched moves, and this should preferably be done before RA to
706// release saved registers and also possibly after RA which can insert copies
707// too.
708//
709// This is really just a generic peephole that is not a canonical shrinking,
710// although requirements match the pass placement and it reduces code size too.
711MachineInstr *SIShrinkInstructions::matchSwap(MachineInstr &MovT) const {
712 assert(MovT.getOpcode() == AMDGPU::V_MOV_B32_e32 ||
713 MovT.getOpcode() == AMDGPU::V_MOV_B16_t16_e32 ||
714 MovT.getOpcode() == AMDGPU::COPY);
715
716 Register T = MovT.getOperand(0).getReg();
717 unsigned Tsub = MovT.getOperand(0).getSubReg();
718 MachineOperand &Xop = MovT.getOperand(1);
719
720 if (!Xop.isReg())
721 return nullptr;
722 Register X = Xop.getReg();
723 unsigned Xsub = Xop.getSubReg();
724 Register Y;
725 unsigned Ysub;
726
727 unsigned Size = TII->getOpSize(MovT, 0);
728
729 // We can't match v_swap_b16 pre-RA, because VGPR_16_Lo128 registers
730 // are not allocatble.
731 if (Size == 2 && X.isVirtual())
732 return nullptr;
733
734 if (!TRI->isVGPR(*MRI, X))
735 return nullptr;
736
737 const unsigned SearchLimit = 16;
738 unsigned Count = 0;
739
740 MachineInstr *MovX = nullptr;
741 MachineInstr *InsertionPt = nullptr;
742 MachineInstr *MovY = nullptr;
743
744 for (auto Iter = std::next(MovT.getIterator()),
745 E = MovT.getParent()->instr_end();
746 Iter != E && Count < SearchLimit; ++Iter) {
747 if (Iter->isDebugInstr())
748 continue;
749 ++Count;
750
751 if (!MovX) {
752 // Search for mov x, y.
753 if ((Iter->getOpcode() == AMDGPU::V_MOV_B32_e32 ||
754 Iter->getOpcode() == AMDGPU::V_MOV_B16_t16_e32 ||
755 Iter->getOpcode() == AMDGPU::COPY) &&
756 Iter->getOperand(0).getReg() == X &&
757 Iter->getOperand(0).getSubReg() == Xsub &&
758 Iter->getOperand(1).isReg()) {
759 MovX = &*Iter;
760 Y = MovX->getOperand(1).getReg();
761 Ysub = MovX->getOperand(1).getSubReg();
762 } else if (instModifiesReg(&*Iter, X, Xsub)) {
763 // Writes to x are not allowed until mov x, y has been found
764 return nullptr;
765 }
766 } else {
767 // mov x, y has been found.
768 // Search for mov y, t.
769 if ((Iter->getOpcode() == AMDGPU::V_MOV_B32_e32 ||
770 Iter->getOpcode() == AMDGPU::V_MOV_B16_t16_e32 ||
771 Iter->getOpcode() == AMDGPU::COPY) &&
772 Iter->getOperand(0).getReg() == Y &&
773 Iter->getOperand(0).getSubReg() == Ysub &&
774 Iter->getOperand(1).isReg() && Iter->getOperand(1).getReg() == T &&
775 Iter->getOperand(1).getSubReg() == Tsub) {
776 MovY = &*Iter;
777 break;
778 }
779
780 // Effectively, mov x, y must be moved downward
781 // and mov y, t must be moved upward so that they can be fused into a
782 // swap. A write to y creates a barrier that prevents the two moves from
783 // being moved adjacent to each other.
784 if (instModifiesReg(&*Iter, Y, Ysub))
785 return nullptr;
786
787 // Reads or writes to x prevent mov x, y from being moved farther
788 // downward. Select this to be the insertion point.
789 if (!InsertionPt &&
790 (instReadsReg(&*Iter, X, Xsub) || instModifiesReg(&*Iter, X, Xsub))) {
791 InsertionPt = &*Iter;
792 }
793 // If the insertion point has been found, then mov y, t must be moved
794 // upward past all subsequent instructions. A read of y will block this
795 // movement.
796 if (InsertionPt) {
797 if (instReadsReg(&*Iter, Y, Ysub))
798 return nullptr;
799 }
800 }
801
802 if (instModifiesReg(&*Iter, T, Tsub))
803 return nullptr;
804 }
805 if (MovY) {
806 LLVM_DEBUG(dbgs() << "Matched v_swap:\n" << MovT << *MovX << *MovY);
807
808 MachineBasicBlock &MBB = *MovT.getParent();
809 SmallVector<MachineInstr *, 4> Swaps;
810
811 if (!InsertionPt)
812 InsertionPt = MovY;
813 if (Size == 2) {
814 auto *MIB = BuildMI(MBB, InsertionPt->getIterator(), MovT.getDebugLoc(),
815 TII->get(AMDGPU::V_SWAP_B16))
816 .addDef(X)
817 .addDef(Y)
818 .addReg(Y)
819 .addReg(X)
820 .getInstr();
821 Swaps.push_back(MIB);
822 } else {
823 assert(Size > 0 && Size % 4 == 0);
824 for (unsigned I = 0; I < Size / 4; ++I) {
825 TargetInstrInfo::RegSubRegPair X1, Y1;
826 X1 = getSubRegForIndex(X, Xsub, I);
827 Y1 = getSubRegForIndex(Y, Ysub, I);
828 auto *MIB = BuildMI(MBB, InsertionPt->getIterator(), MovT.getDebugLoc(),
829 TII->get(AMDGPU::V_SWAP_B32))
830 .addDef(X1.Reg, {}, X1.SubReg)
831 .addDef(Y1.Reg, {}, Y1.SubReg)
832 .addReg(Y1.Reg, {}, Y1.SubReg)
833 .addReg(X1.Reg, {}, X1.SubReg)
834 .getInstr();
835 Swaps.push_back(MIB);
836 }
837 }
838 // Drop implicit EXEC.
839 if (MovX->hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
840 for (MachineInstr *Swap : Swaps) {
841 Swap->removeOperand(Swap->getNumExplicitOperands());
842 Swap->copyImplicitOps(*MBB.getParent(), *MovX);
843 }
844 }
845 MovX->eraseFromParent();
846 dropInstructionKeepingImpDefs(*MovY);
847 MachineInstr *Next = &*std::next(MovT.getIterator());
848
849 if (T.isVirtual() && MRI->use_nodbg_empty(T)) {
850 dropInstructionKeepingImpDefs(MovT);
851 } else {
852 Xop.setIsKill(false);
853 for (int I = MovT.getNumImplicitOperands() - 1; I >= 0; --I ) {
854 unsigned OpNo = MovT.getNumExplicitOperands() + I;
855 const MachineOperand &Op = MovT.getOperand(OpNo);
856 if (Op.isKill() && TRI->regsOverlap(X, Op.getReg()))
857 MovT.removeOperand(OpNo);
858 }
859 }
860
861 return Next;
862 }
863 return nullptr;
864}
865
866// If an instruction has dead sdst replace it with NULL register on gfx1030+
867bool SIShrinkInstructions::tryReplaceDeadSDST(MachineInstr &MI) const {
868 if (!ST->hasGFX10_3Insts())
869 return false;
870
871 MachineOperand *Op = TII->getNamedOperand(MI, AMDGPU::OpName::sdst);
872 if (!Op)
873 return false;
874 Register SDstReg = Op->getReg();
875 if (SDstReg.isPhysical() || !MRI->use_nodbg_empty(SDstReg))
876 return false;
877
878 Op->setReg(ST->isWave32() ? AMDGPU::SGPR_NULL : AMDGPU::SGPR_NULL64);
879 return true;
880}
881
882bool SIShrinkInstructions::run(MachineFunction &MF) {
883
884 this->MF = &MF;
885 MRI = &MF.getRegInfo();
886 ST = &MF.getSubtarget<GCNSubtarget>();
887 TII = ST->getInstrInfo();
888 TRI = &TII->getRegisterInfo();
889 IsPostRA = MF.getProperties().hasNoVRegs();
890
891 unsigned VCCReg = ST->isWave32() ? AMDGPU::VCC_LO : AMDGPU::VCC;
892 bool Changed = false;
893
894 for (MachineBasicBlock &MBB : MF) {
896 for (I = MBB.begin(); I != MBB.end(); I = Next) {
897 Next = std::next(I);
898 MachineInstr &MI = *I;
899
900 if (MI.getOpcode() == AMDGPU::V_MOV_B32_e32) {
901 // If this has a literal constant source that is the same as the
902 // reversed bits of an inline immediate, replace with a bitreverse of
903 // that constant. This saves 4 bytes in the common case of materializing
904 // sign bits.
905
906 // Test if we are after regalloc. We only want to do this after any
907 // optimizations happen because this will confuse them.
908 MachineOperand &Src = MI.getOperand(1);
909 if (Src.isImm() && IsPostRA) {
910 int32_t ModImm;
911 unsigned ModOpcode =
912 canModifyToInlineImmOp32(TII, Src, ModImm, /*Scalar=*/false);
913 if (ModOpcode != 0) {
914 MI.setDesc(TII->get(ModOpcode));
915 Src.setImm(static_cast<int64_t>(ModImm));
916 Changed = true;
917 continue;
918 }
919 }
920 }
921
922 if (ST->hasSwap() && (MI.getOpcode() == AMDGPU::V_MOV_B32_e32 ||
923 MI.getOpcode() == AMDGPU::V_MOV_B16_t16_e32 ||
924 MI.getOpcode() == AMDGPU::COPY)) {
925 if (auto *NextMI = matchSwap(MI)) {
926 Next = NextMI->getIterator();
927 Changed = true;
928 continue;
929 }
930 }
931
932 // Shrink scalar logic operations.
933 if (MI.getOpcode() == AMDGPU::S_AND_B32 ||
934 MI.getOpcode() == AMDGPU::S_OR_B32 ||
935 MI.getOpcode() == AMDGPU::S_XOR_B32) {
936 ChangeKind CK = shrinkScalarLogicOp(MI);
937 if (CK == ChangeKind::UpdateHint)
938 continue;
939 Changed |= (CK == ChangeKind::UpdateInst);
940 }
941
942 // Try to use S_ADDK_I32 and S_MULK_I32.
943 // S_OR_B32 sets SCC to (result != 0), but S_ADDK_I32 sets it to
944 // signed overflow, so only shrink the OR when SCC is dead.
945 if (MI.getOpcode() == AMDGPU::S_ADD_I32 ||
946 MI.getOpcode() == AMDGPU::S_MUL_I32 ||
947 (MI.getOpcode() == AMDGPU::S_OR_B32 &&
948 MI.getFlag(MachineInstr::MIFlag::Disjoint) &&
949 MI.allImplicitDefsAreDead())) {
950 const MachineOperand *Dest = &MI.getOperand(0);
951 MachineOperand *Src0 = &MI.getOperand(1);
952 MachineOperand *Src1 = &MI.getOperand(2);
953
954 if (!Src0->isReg() && Src1->isReg()) {
955 if (TII->commuteInstruction(MI, false, 1, 2)) {
956 std::swap(Src0, Src1);
957 Changed = true;
958 }
959 }
960
961 // FIXME: This could work better if hints worked with subregisters. If
962 // we have a vector add of a constant, we usually don't get the correct
963 // allocation due to the subregister usage.
964 if (Dest->getReg().isVirtual() && Src0->isReg()) {
965 MRI->setRegAllocationHint(Dest->getReg(), 0, Src0->getReg());
966 MRI->setRegAllocationHint(Src0->getReg(), 0, Dest->getReg());
967 continue;
968 }
969 if (Src0->isReg() && Src0->getReg() == Dest->getReg()) {
970 if (Src1->isImm() && isKImmOperand(MI, *Src1)) {
971 unsigned Opc = (MI.getOpcode() == AMDGPU::S_MUL_I32)
972 ? AMDGPU::S_MULK_I32
973 : AMDGPU::S_ADDK_I32;
974 Src1->setImm(SignExtend64(Src1->getImm(), 32));
975 MI.setDesc(TII->get(Opc));
976 MI.tieOperands(0, 1);
977 Changed = true;
978 }
979 }
980 }
981
982 // Try to use s_cmpk_*
983 if (MI.isCompare() && TII->isSOPC(MI)) {
984 Changed |= shrinkScalarCompare(MI);
985 continue;
986 }
987
988 // Try to use S_MOVK_I32, which will save 4 bytes for small immediates.
989 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
990 const MachineOperand &Dst = MI.getOperand(0);
991 MachineOperand &Src = MI.getOperand(1);
992
993 if (Src.isImm() && Dst.getReg().isPhysical()) {
994 unsigned ModOpc;
995 int32_t ModImm;
996 if (isKImmOperand(MI, Src)) {
997 MI.setDesc(TII->get(AMDGPU::S_MOVK_I32));
998 Src.setImm(SignExtend64(Src.getImm(), 32));
999 Changed = true;
1000 } else if ((ModOpc = canModifyToInlineImmOp32(TII, Src, ModImm,
1001 /*Scalar=*/true))) {
1002 MI.setDesc(TII->get(ModOpc));
1003 Src.setImm(static_cast<int64_t>(ModImm));
1004 Changed = true;
1005 }
1006 }
1007
1008 continue;
1009 }
1010
1011 if (IsPostRA && TII->isMIMG(MI.getOpcode()) &&
1012 ST->getGeneration() >= AMDGPUSubtarget::GFX10) {
1013 Changed |= shrinkMIMG(MI);
1014 continue;
1015 }
1016
1017 if (!TII->isVOP3(MI))
1018 continue;
1019
1020 if (MI.getOpcode() == AMDGPU::V_MAD_F32_e64 ||
1021 MI.getOpcode() == AMDGPU::V_FMA_F32_e64 ||
1022 MI.getOpcode() == AMDGPU::V_MAD_F16_e64 ||
1023 MI.getOpcode() == AMDGPU::V_FMA_F16_e64 ||
1024 MI.getOpcode() == AMDGPU::V_FMA_F16_gfx9_e64 ||
1025 MI.getOpcode() == AMDGPU::V_FMA_F16_gfx9_t16_e64 ||
1026 MI.getOpcode() == AMDGPU::V_FMA_F16_gfx9_fake16_e64 ||
1027 (MI.getOpcode() == AMDGPU::V_FMA_F64_e64 &&
1028 ST->hasFmaakFmamkF64Insts())) {
1029 Changed |= shrinkMadFma(MI);
1030 continue;
1031 }
1032
1033 // If there is no chance we will shrink it and use VCC as sdst to get
1034 // a 32 bit form try to replace dead sdst with NULL.
1035 Changed |= tryReplaceDeadSDST(MI);
1036 if (!TII->hasVALU32BitEncoding(MI.getOpcode()))
1037 continue;
1038
1039 if (!TII->canShrink(MI, *MRI)) {
1040 // Try commuting the instruction and see if that enables us to shrink
1041 // it.
1042 if (!MI.isCommutable() || !TII->commuteInstruction(MI) ||
1043 !TII->canShrink(MI, *MRI)) {
1044 Changed |= tryReplaceDeadSDST(MI);
1045 continue;
1046 }
1047
1048 // Operands were commuted.
1049 Changed = true;
1050 }
1051
1052 int Op32 = AMDGPU::getVOPe32(MI.getOpcode());
1053
1054 if (Op32 == AMDGPU::V_CNDMASK_B32_e32) {
1055 // We shrink V_CNDMASK_B32_e64 using regalloc hints like we do for VOPC
1056 // instructions.
1057 const MachineOperand *Src2 =
1058 TII->getNamedOperand(MI, AMDGPU::OpName::src2);
1059 if (!Src2->isReg())
1060 continue;
1061 Register SReg = Src2->getReg();
1062 if (SReg.isVirtual()) {
1063 MRI->setRegAllocationHint(SReg, 0, VCCReg);
1064 continue;
1065 }
1066 if (SReg != VCCReg)
1067 continue;
1068 }
1069
1070 // Check for the bool flag output for instructions like V_ADD_I32_e64.
1071 // For VOPC e64 this is also the dst operand. VOPCX (nosdst) variants
1072 // have no sdst, so they fall through to be shrunk directly.
1073 const MachineOperand *SDst =
1074 TII->getNamedOperand(MI, AMDGPU::OpName::sdst);
1075
1076 if (SDst) {
1077 bool Next = false;
1078
1079 if (SDst->getReg() != VCCReg) {
1080 // VOPC instructions can only write to the VCC register. We can't
1081 // force them to use VCC here, because this is only one register and
1082 // cannot deal with sequences which would require multiple copies of
1083 // VCC, e.g. S_AND_B64 (vcc = V_CMP_...), (vcc = V_CMP_...)
1084 //
1085 // So, instead of forcing the instruction to write to VCC, we
1086 // provide a hint to the register allocator to use VCC and then we
1087 // will run this pass again after RA and shrink it if it outputs to
1088 // VCC.
1089 if (SDst->getReg().isVirtual())
1090 MRI->setRegAllocationHint(SDst->getReg(), 0, VCCReg);
1091 Next = true;
1092 }
1093
1094 // All of the instructions with carry outs also have an SGPR input in
1095 // src2.
1096 const MachineOperand *Src2 = TII->getNamedOperand(MI,
1097 AMDGPU::OpName::src2);
1098 if (Src2 && Src2->getReg() != VCCReg) {
1099 if (Src2->getReg().isVirtual())
1100 MRI->setRegAllocationHint(Src2->getReg(), 0, VCCReg);
1101 Next = true;
1102 }
1103
1104 if (Next)
1105 continue;
1106 }
1107
1108 // Pre-GFX10, shrinking VOP3 instructions pre-RA gave us the chance to
1109 // fold an immediate into the shrunk instruction as a literal operand. In
1110 // GFX10 VOP3 instructions can take a literal operand anyway, so there is
1111 // no advantage to doing this.
1112 // However, if 64-bit literals are allowed we still need to shrink it
1113 // for such literal to be able to fold.
1114 if (ST->hasVOP3Literal() &&
1115 (!ST->has64BitLiterals() || AMDGPU::isTrue16Inst(MI.getOpcode())) &&
1116 !IsPostRA)
1117 continue;
1118
1119 if (ST->hasTrue16BitInsts() && AMDGPU::isTrue16Inst(MI.getOpcode()) &&
1120 !shouldShrinkTrue16(MI))
1121 continue;
1122
1123 // We can shrink this instruction
1124 LLVM_DEBUG(dbgs() << "Shrinking " << MI);
1125
1126 MachineInstr *Inst32 = TII->buildShrunkInst(MI, Op32);
1127 ++NumInstructionsShrunk;
1128
1129 // Copy extra operands not present in the instruction definition.
1130 copyExtraImplicitOps(*Inst32, MI);
1131
1132 MI.eraseFromParent();
1133 foldImmediates(*Inst32);
1134
1135 LLVM_DEBUG(dbgs() << "e32 MI = " << *Inst32 << '\n');
1136 Changed = true;
1137 }
1138 }
1139 return Changed;
1140}
1141
1142bool SIShrinkInstructionsLegacy::runOnMachineFunction(MachineFunction &MF) {
1143 if (skipFunction(MF.getFunction()))
1144 return false;
1145
1146 return SIShrinkInstructions().run(MF);
1147}
1148
1149PreservedAnalyses
1152 if (MF.getFunction().hasOptNone() || !SIShrinkInstructions().run(MF))
1153 return PreservedAnalyses::all();
1154
1156 PA.preserveSet<CFGAnalyses>();
1157 return PA;
1158}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t Imm
MachineBasicBlock & MBB
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
MachineRegisterInfo & MRI
static unsigned canModifyToInlineImmOp32(const SIInstrInfo *TII, const MachineOperand &Src, int32_t &ModifiedImm, bool Scalar)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:479
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
Class for arbitrary precision integers.
Definition APInt.h:78
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
bool hasOptNone() const
Do not optimize this function (-O0).
Definition Function.h:686
bool hasSwap() const
bool hasFmaakFmamkF64Insts() const
const SIInstrInfo * getInstrInfo() const override
bool isWave32() const
unsigned getNSAMaxSize(bool HasSampler=false) const
bool hasSCmpK() const
Generation getGeneration() const
const HexagonRegisterInfo & getRegisterInfo() const
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineFunctionProperties & getProperties() const
Get the function properties.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getNumImplicitOperands() const
Returns the implicit operands number.
iterator_range< filter_iterator< const_mop_iterator, bool(*)(const MachineOperand &)> > filtered_const_mop_range
const MachineBasicBlock * getParent() const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI bool hasRegisterImplicitUseOperand(Register Reg) const
Returns true if the MachineInstr has an implicit-use operand of exactly the given register (not consi...
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const GlobalValue * getGlobal() const
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
static std::optional< unsigned > extractSubregFromGlobalAddressFlags(unsigned TargetFlags, unsigned SubRegIndex)
Return the target flags for a global address operand reading subregister SubRegIndex of a 64-bit glob...
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
static bool sopkIsZext(unsigned Opcode)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &)
void push_back(const T &Elt)
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
LLVM_READONLY int32_t getSOPKOp(uint32_t Opcode)
bool isKImmOperand(const MCInstrDesc &Desc, unsigned OpNo)
Is this a KImm operand?
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
bool isTrue16Inst(unsigned Opc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
Definition bit.h:315
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
@ Sub
Subtraction of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
DWARFExpression::Operation Op
constexpr int32_t SignExtend32(uint32_t X)
Sign-extend the number in the bottom B bits of X to a 32-bit integer.
Definition MathExtras.h:554
constexpr T reverseBits(T Val)
Reverse the bits in Val.
Definition MathExtras.h:119
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:572
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
FunctionPass * createSIShrinkInstructionsLegacyPass()
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:881
constexpr bool any() const
Definition LaneBitmask.h:53