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