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