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