LLVM 22.0.0git
AMDGPUMCCodeEmitter.cpp
Go to the documentation of this file.
1//===-- AMDGPUMCCodeEmitter.cpp - AMDGPU Code Emitter ---------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// The AMDGPU code emitter produces machine code that can be executed
11/// directly on the GPU device.
12//
13//===----------------------------------------------------------------------===//
14
18#include "SIDefines.h"
20#include "llvm/ADT/APInt.h"
22#include "llvm/MC/MCContext.h"
23#include "llvm/MC/MCExpr.h"
24#include "llvm/MC/MCInstrInfo.h"
29#include <optional>
30
31using namespace llvm;
32
33namespace {
34
35class AMDGPUMCCodeEmitter : public MCCodeEmitter {
36 const MCRegisterInfo &MRI;
37 const MCInstrInfo &MCII;
38
39public:
40 AMDGPUMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI)
41 : MRI(MRI), MCII(MCII) {}
42
43 /// Encode the instruction and write it to the OS.
46 const MCSubtargetInfo &STI) const override;
47
48 void getMachineOpValue(const MCInst &MI, const MCOperand &MO, APInt &Op,
50 const MCSubtargetInfo &STI) const;
51
52 void getMachineOpValueT16(const MCInst &MI, unsigned OpNo, APInt &Op,
54 const MCSubtargetInfo &STI) const;
55
56 void getMachineOpValueT16Lo128(const MCInst &MI, unsigned OpNo, APInt &Op,
58 const MCSubtargetInfo &STI) const;
59
60 /// Use a fixup to encode the simm16 field for SOPP branch
61 /// instructions.
62 void getSOPPBrEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
64 const MCSubtargetInfo &STI) const;
65
66 void getSMEMOffsetEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
68 const MCSubtargetInfo &STI) const;
69
70 void getSDWASrcEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
72 const MCSubtargetInfo &STI) const;
73
74 void getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
76 const MCSubtargetInfo &STI) const;
77
78 void getAVOperandEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
80 const MCSubtargetInfo &STI) const;
81
82private:
83 uint64_t getImplicitOpSelHiEncoding(int Opcode) const;
84 void getMachineOpValueCommon(const MCInst &MI, const MCOperand &MO,
85 unsigned OpNo, APInt &Op,
87 const MCSubtargetInfo &STI) const;
88
89 /// Encode an fp or int literal.
90 std::optional<uint64_t>
91 getLitEncoding(const MCOperand &MO, const MCOperandInfo &OpInfo,
92 const MCSubtargetInfo &STI,
93 bool HasMandatoryLiteral = false) const;
94
95 void getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups,
96 APInt &Inst, APInt &Scratch,
97 const MCSubtargetInfo &STI) const;
98};
99
100} // end anonymous namespace
101
103 MCContext &Ctx) {
104 return new AMDGPUMCCodeEmitter(MCII, *Ctx.getRegisterInfo());
105}
106
108 const MCExpr *Value, uint16_t Kind, bool PCRel = false) {
109 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));
110}
111
112// Returns the encoding value to use if the given integer is an integer inline
113// immediate value, or 0 if it is not.
114template <typename IntTy>
116 if (Imm >= 0 && Imm <= 64)
117 return 128 + Imm;
118
119 if (Imm >= -16 && Imm <= -1)
120 return 192 + std::abs(Imm);
121
122 return 0;
123}
124
126 uint16_t IntImm = getIntInlineImmEncoding(static_cast<int16_t>(Val));
127 if (IntImm != 0)
128 return IntImm;
129
130 if (Val == 0x3800) // 0.5
131 return 240;
132
133 if (Val == 0xB800) // -0.5
134 return 241;
135
136 if (Val == 0x3C00) // 1.0
137 return 242;
138
139 if (Val == 0xBC00) // -1.0
140 return 243;
141
142 if (Val == 0x4000) // 2.0
143 return 244;
144
145 if (Val == 0xC000) // -2.0
146 return 245;
147
148 if (Val == 0x4400) // 4.0
149 return 246;
150
151 if (Val == 0xC400) // -4.0
152 return 247;
153
154 if (Val == 0x3118 && // 1.0 / (2.0 * pi)
155 STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
156 return 248;
157
158 return 255;
159}
160
162 uint16_t IntImm = getIntInlineImmEncoding(static_cast<int16_t>(Val));
163 if (IntImm != 0)
164 return IntImm;
165
166 // clang-format off
167 switch (Val) {
168 case 0x3F00: return 240; // 0.5
169 case 0xBF00: return 241; // -0.5
170 case 0x3F80: return 242; // 1.0
171 case 0xBF80: return 243; // -1.0
172 case 0x4000: return 244; // 2.0
173 case 0xC000: return 245; // -2.0
174 case 0x4080: return 246; // 4.0
175 case 0xC080: return 247; // -4.0
176 case 0x3E22: return 248; // 1.0 / (2.0 * pi)
177 default: return 255;
178 }
179 // clang-format on
180}
181
183 uint32_t IntImm = getIntInlineImmEncoding(static_cast<int32_t>(Val));
184 if (IntImm != 0)
185 return IntImm;
186
187 if (Val == llvm::bit_cast<uint32_t>(0.5f))
188 return 240;
189
190 if (Val == llvm::bit_cast<uint32_t>(-0.5f))
191 return 241;
192
193 if (Val == llvm::bit_cast<uint32_t>(1.0f))
194 return 242;
195
196 if (Val == llvm::bit_cast<uint32_t>(-1.0f))
197 return 243;
198
199 if (Val == llvm::bit_cast<uint32_t>(2.0f))
200 return 244;
201
202 if (Val == llvm::bit_cast<uint32_t>(-2.0f))
203 return 245;
204
205 if (Val == llvm::bit_cast<uint32_t>(4.0f))
206 return 246;
207
208 if (Val == llvm::bit_cast<uint32_t>(-4.0f))
209 return 247;
210
211 if (Val == 0x3e22f983 && // 1.0 / (2.0 * pi)
212 STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
213 return 248;
214
215 return 255;
216}
217
219 return getLit32Encoding(Val, STI);
220}
221
223 bool IsFP) {
224 uint32_t IntImm = getIntInlineImmEncoding(static_cast<int64_t>(Val));
225 if (IntImm != 0)
226 return IntImm;
227
228 if (Val == llvm::bit_cast<uint64_t>(0.5))
229 return 240;
230
231 if (Val == llvm::bit_cast<uint64_t>(-0.5))
232 return 241;
233
234 if (Val == llvm::bit_cast<uint64_t>(1.0))
235 return 242;
236
237 if (Val == llvm::bit_cast<uint64_t>(-1.0))
238 return 243;
239
240 if (Val == llvm::bit_cast<uint64_t>(2.0))
241 return 244;
242
243 if (Val == llvm::bit_cast<uint64_t>(-2.0))
244 return 245;
245
246 if (Val == llvm::bit_cast<uint64_t>(4.0))
247 return 246;
248
249 if (Val == llvm::bit_cast<uint64_t>(-4.0))
250 return 247;
251
252 if (Val == 0x3fc45f306dc9c882 && // 1.0 / (2.0 * pi)
253 STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
254 return 248;
255
256 // The rest part needs to align with AMDGPUInstPrinter::printLiteral64.
257
258 if (IsFP) {
259 return STI.hasFeature(AMDGPU::Feature64BitLiterals) && Lo_32(Val) ? 254
260 : 255;
261 }
262
263 return STI.hasFeature(AMDGPU::Feature64BitLiterals) &&
264 (!isInt<32>(Val) || !isUInt<32>(Val))
265 ? 254
266 : 255;
267}
268
269std::optional<uint64_t> AMDGPUMCCodeEmitter::getLitEncoding(
270 const MCOperand &MO, const MCOperandInfo &OpInfo,
271 const MCSubtargetInfo &STI, bool HasMandatoryLiteral) const {
272 int64_t Imm;
273 if (MO.isExpr()) {
274 if (!MO.getExpr()->evaluateAsAbsolute(Imm))
275 return AMDGPU::getOperandSize(OpInfo) == 8 ? 254 : 255;
276 } else {
277 assert(!MO.isDFPImm());
278
279 if (!MO.isImm())
280 return {};
281
282 Imm = MO.getImm();
283 }
284
285 switch (OpInfo.OperandType) {
295 return getLit32Encoding(static_cast<uint32_t>(Imm), STI);
296
299 return getLit64Encoding(static_cast<uint64_t>(Imm), STI, false);
300
303 return getLit64Encoding(static_cast<uint64_t>(Imm), STI, true);
304
306 auto Enc = getLit64Encoding(static_cast<uint64_t>(Imm), STI, true);
307 return (HasMandatoryLiteral && Enc == 255) ? 254 : Enc;
308 }
309
312 return getLit16IntEncoding(static_cast<uint32_t>(Imm), STI);
313
316 // FIXME Is this correct? What do inline immediates do on SI for f16 src
317 // which does not have f16 support?
318 return getLit16Encoding(static_cast<uint16_t>(Imm), STI);
319
322 // We don't actually need to check Inv2Pi here because BF16 instructions can
323 // only be emitted for targets that already support the feature.
324 return getLitBF16Encoding(static_cast<uint16_t>(Imm));
325
328 return AMDGPU::getInlineEncodingV2I16(static_cast<uint32_t>(Imm))
329 .value_or(255);
330
333 return AMDGPU::getInlineEncodingV2F16(static_cast<uint32_t>(Imm))
334 .value_or(255);
335
338 return AMDGPU::getInlineEncodingV2BF16(static_cast<uint32_t>(Imm))
339 .value_or(255);
340
342 return 255;
343
347 return MO.getImm();
348 default:
349 llvm_unreachable("invalid operand size");
350 }
351}
352
353uint64_t AMDGPUMCCodeEmitter::getImplicitOpSelHiEncoding(int Opcode) const {
354 using namespace AMDGPU::VOP3PEncoding;
355
356 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::op_sel_hi)) {
357 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src2))
358 return 0;
359 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src1))
360 return OP_SEL_HI_2;
361 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0))
362 return OP_SEL_HI_1 | OP_SEL_HI_2;
363 }
365}
366
367static bool isVCMPX64(const MCInstrDesc &Desc) {
368 return (Desc.TSFlags & SIInstrFlags::VOP3) &&
369 Desc.hasImplicitDefOfPhysReg(AMDGPU::EXEC);
370}
371
372void AMDGPUMCCodeEmitter::encodeInstruction(const MCInst &MI,
375 const MCSubtargetInfo &STI) const {
376 int Opcode = MI.getOpcode();
377 APInt Encoding, Scratch;
378 getBinaryCodeForInstr(MI, Fixups, Encoding, Scratch, STI);
379 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
380 unsigned bytes = Desc.getSize();
381
382 // Set unused op_sel_hi bits to 1 for VOP3P and MAI instructions.
383 // Note that accvgpr_read/write are MAI, have src0, but do not use op_sel.
384 if (((Desc.TSFlags & SIInstrFlags::VOP3P) ||
385 Opcode == AMDGPU::V_ACCVGPR_READ_B32_vi ||
386 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_vi) &&
387 // Matrix B format operand reuses op_sel_hi.
388 !AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::matrix_b_fmt) &&
389 // Matrix B scale operand reuses op_sel_hi.
390 !AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::matrix_b_scale) &&
391 // Matrix B reuse operand reuses op_sel_hi.
392 !AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::matrix_b_reuse)) {
393 Encoding |= getImplicitOpSelHiEncoding(Opcode);
394 }
395
396 // GFX10+ v_cmpx opcodes promoted to VOP3 have implied dst=EXEC.
397 // Documentation requires dst to be encoded as EXEC (0x7E),
398 // but it looks like the actual value encoded for dst operand
399 // is ignored by HW. It was decided to define dst as "do not care"
400 // in td files to allow disassembler accept any dst value.
401 // However, dst is encoded as EXEC for compatibility with SP3.
402 if (AMDGPU::isGFX10Plus(STI) && isVCMPX64(Desc)) {
403 assert((Encoding & 0xFF) == 0);
404 Encoding |= MRI.getEncodingValue(AMDGPU::EXEC_LO) &
406 }
407
408 for (unsigned i = 0; i < bytes; i++) {
409 CB.push_back((uint8_t)Encoding.extractBitsAsZExtValue(8, 8 * i));
410 }
411
412 // NSA encoding.
413 if (AMDGPU::isGFX10Plus(STI) && Desc.TSFlags & SIInstrFlags::MIMG) {
414 int vaddr0 = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
415 AMDGPU::OpName::vaddr0);
416 int srsrc = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
417 AMDGPU::OpName::srsrc);
418 assert(vaddr0 >= 0 && srsrc > vaddr0);
419 unsigned NumExtraAddrs = srsrc - vaddr0 - 1;
420 unsigned NumPadding = (-NumExtraAddrs) & 3;
421
422 for (unsigned i = 0; i < NumExtraAddrs; ++i) {
423 getMachineOpValue(MI, MI.getOperand(vaddr0 + 1 + i), Encoding, Fixups,
424 STI);
425 CB.push_back((uint8_t)Encoding.getLimitedValue());
426 }
427 CB.append(NumPadding, 0);
428 }
429
430 if ((bytes > 8 && STI.hasFeature(AMDGPU::FeatureVOP3Literal)) ||
431 (bytes > 4 && !STI.hasFeature(AMDGPU::FeatureVOP3Literal)))
432 return;
433
434 // Do not print literals from SISrc Operands for insts with mandatory literals
435 if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::imm))
436 return;
437
438 // Check for additional literals
439 for (unsigned i = 0, e = Desc.getNumOperands(); i < e; ++i) {
440
441 // Check if this operand should be encoded as [SV]Src
443 continue;
444
445 // Is this operand a literal immediate?
446 const MCOperand &Op = MI.getOperand(i);
447 auto Enc = getLitEncoding(Op, Desc.operands()[i], STI);
448 if (!Enc || (*Enc != 255 && *Enc != 254))
449 continue;
450
451 // Yes! Encode it
452 int64_t Imm = 0;
453
454 if (Op.isImm())
455 Imm = Op.getImm();
456 else if (Op.isExpr()) {
457 if (const auto *C = dyn_cast<MCConstantExpr>(Op.getExpr()))
458 Imm = C->getValue();
459 } else // Exprs will be replaced with a fixup value.
460 llvm_unreachable("Must be immediate or expr");
461
462 if (*Enc == 254) {
463 assert(STI.hasFeature(AMDGPU::Feature64BitLiterals));
464 support::endian::write<uint64_t>(CB, Imm, llvm::endianness::little);
465 } else {
466 if (Desc.operands()[i].OperandType == AMDGPU::OPERAND_REG_IMM_FP64)
467 Imm = Hi_32(Imm);
468 support::endian::write<uint32_t>(CB, Imm, llvm::endianness::little);
469 }
470
471 // Only one literal value allowed
472 break;
473 }
474}
475
476void AMDGPUMCCodeEmitter::getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
477 APInt &Op,
479 const MCSubtargetInfo &STI) const {
480 const MCOperand &MO = MI.getOperand(OpNo);
481
482 if (MO.isExpr()) {
483 const MCExpr *Expr = MO.getExpr();
484 addFixup(Fixups, 0, Expr, AMDGPU::fixup_si_sopp_br, true);
485 Op = APInt::getZero(96);
486 } else {
487 getMachineOpValue(MI, MO, Op, Fixups, STI);
488 }
489}
490
491void AMDGPUMCCodeEmitter::getSMEMOffsetEncoding(
492 const MCInst &MI, unsigned OpNo, APInt &Op,
493 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
494 auto Offset = MI.getOperand(OpNo).getImm();
495 // VI only supports 20-bit unsigned offsets.
496 assert(!AMDGPU::isVI(STI) || isUInt<20>(Offset));
497 Op = Offset;
498}
499
500void AMDGPUMCCodeEmitter::getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
501 APInt &Op,
503 const MCSubtargetInfo &STI) const {
504 using namespace AMDGPU::SDWA;
505
506 uint64_t RegEnc = 0;
507
508 const MCOperand &MO = MI.getOperand(OpNo);
509
510 if (MO.isReg()) {
511 MCRegister Reg = MO.getReg();
512 RegEnc |= MRI.getEncodingValue(Reg);
513 RegEnc &= SDWA9EncValues::SRC_VGPR_MASK;
515 RegEnc |= SDWA9EncValues::SRC_SGPR_MASK;
516 }
517 Op = RegEnc;
518 return;
519 } else {
520 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
521 auto Enc = getLitEncoding(MO, Desc.operands()[OpNo], STI);
522 if (Enc && *Enc != 255) {
523 Op = *Enc | SDWA9EncValues::SRC_SGPR_MASK;
524 return;
525 }
526 }
527
528 llvm_unreachable("Unsupported operand kind");
529}
530
531void AMDGPUMCCodeEmitter::getSDWAVopcDstEncoding(
532 const MCInst &MI, unsigned OpNo, APInt &Op,
533 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
534 using namespace AMDGPU::SDWA;
535
536 uint64_t RegEnc = 0;
537
538 const MCOperand &MO = MI.getOperand(OpNo);
539
540 MCRegister Reg = MO.getReg();
541 if (Reg != AMDGPU::VCC && Reg != AMDGPU::VCC_LO) {
542 RegEnc |= MRI.getEncodingValue(Reg);
543 RegEnc &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
544 RegEnc |= SDWA9EncValues::VOPC_DST_VCC_MASK;
545 }
546 Op = RegEnc;
547}
548
549void AMDGPUMCCodeEmitter::getAVOperandEncoding(
550 const MCInst &MI, unsigned OpNo, APInt &Op,
551 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
552 MCRegister Reg = MI.getOperand(OpNo).getReg();
553 unsigned Enc = MRI.getEncodingValue(Reg);
554 unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
555 bool IsVGPROrAGPR =
557
558 // VGPR and AGPR have the same encoding, but SrcA and SrcB operands of mfma
559 // instructions use acc[0:1] modifier bits to distinguish. These bits are
560 // encoded as a virtual 9th bit of the register for these operands.
561 bool IsAGPR = Enc & AMDGPU::HWEncoding::IS_AGPR;
562
563 Op = Idx | (IsVGPROrAGPR << 8) | (IsAGPR << 9);
564}
565
566static bool needsPCRel(const MCExpr *Expr) {
567 switch (Expr->getKind()) {
568 case MCExpr::SymbolRef: {
569 auto *SE = cast<MCSymbolRefExpr>(Expr);
570 auto Spec = AMDGPU::getSpecifier(SE);
571 return Spec != AMDGPUMCExpr::S_ABS32_LO &&
573 }
574 case MCExpr::Binary: {
575 auto *BE = cast<MCBinaryExpr>(Expr);
576 if (BE->getOpcode() == MCBinaryExpr::Sub)
577 return false;
578 return needsPCRel(BE->getLHS()) || needsPCRel(BE->getRHS());
579 }
580 case MCExpr::Unary:
581 return needsPCRel(cast<MCUnaryExpr>(Expr)->getSubExpr());
583 case MCExpr::Target:
584 case MCExpr::Constant:
585 return false;
586 }
587 llvm_unreachable("invalid kind");
588}
589
590void AMDGPUMCCodeEmitter::getMachineOpValue(const MCInst &MI,
591 const MCOperand &MO, APInt &Op,
593 const MCSubtargetInfo &STI) const {
594 if (MO.isReg()){
595 unsigned Enc = MRI.getEncodingValue(MO.getReg());
596 unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
597 bool IsVGPROrAGPR =
599 Op = Idx | (IsVGPROrAGPR << 8);
600 return;
601 }
602 unsigned OpNo = &MO - MI.begin();
603 getMachineOpValueCommon(MI, MO, OpNo, Op, Fixups, STI);
604}
605
606void AMDGPUMCCodeEmitter::getMachineOpValueT16(
607 const MCInst &MI, unsigned OpNo, APInt &Op,
608 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
609 const MCOperand &MO = MI.getOperand(OpNo);
610 if (MO.isReg()) {
611 unsigned Enc = MRI.getEncodingValue(MO.getReg());
612 unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
613 bool IsVGPR = Enc & AMDGPU::HWEncoding::IS_VGPR;
614 Op = Idx | (IsVGPR << 8);
615 return;
616 }
617 getMachineOpValueCommon(MI, MO, OpNo, Op, Fixups, STI);
618 // VGPRs include the suffix/op_sel bit in the register encoding, but
619 // immediates and SGPRs include it in src_modifiers. Therefore, copy the
620 // op_sel bit from the src operands into src_modifier operands if Op is
621 // src_modifiers and the corresponding src is a VGPR
622 int SrcMOIdx = -1;
623 assert(OpNo < INT_MAX);
624 if ((int)OpNo == AMDGPU::getNamedOperandIdx(MI.getOpcode(),
625 AMDGPU::OpName::src0_modifiers)) {
626 SrcMOIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
627 int VDstMOIdx =
628 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdst);
629 if (VDstMOIdx != -1) {
630 auto DstReg = MI.getOperand(VDstMOIdx).getReg();
631 if (AMDGPU::isHi16Reg(DstReg, MRI))
633 }
634 } else if ((int)OpNo == AMDGPU::getNamedOperandIdx(
635 MI.getOpcode(), AMDGPU::OpName::src1_modifiers))
636 SrcMOIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);
637 else if ((int)OpNo == AMDGPU::getNamedOperandIdx(
638 MI.getOpcode(), AMDGPU::OpName::src2_modifiers))
639 SrcMOIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src2);
640 if (SrcMOIdx == -1)
641 return;
642
643 const MCOperand &SrcMO = MI.getOperand(SrcMOIdx);
644 if (!SrcMO.isReg())
645 return;
646 auto SrcReg = SrcMO.getReg();
647 if (AMDGPU::isSGPR(SrcReg, &MRI))
648 return;
649 if (AMDGPU::isHi16Reg(SrcReg, MRI))
651}
652
653void AMDGPUMCCodeEmitter::getMachineOpValueT16Lo128(
654 const MCInst &MI, unsigned OpNo, APInt &Op,
655 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
656 const MCOperand &MO = MI.getOperand(OpNo);
657 if (MO.isReg()) {
658 uint16_t Encoding = MRI.getEncodingValue(MO.getReg());
659 unsigned RegIdx = Encoding & AMDGPU::HWEncoding::REG_IDX_MASK;
660 bool IsHi = Encoding & AMDGPU::HWEncoding::IS_HI16;
661 bool IsVGPR = Encoding & AMDGPU::HWEncoding::IS_VGPR;
662 assert((!IsVGPR || isUInt<7>(RegIdx)) && "VGPR0-VGPR127 expected!");
663 Op = (IsVGPR ? 0x100 : 0) | (IsHi ? 0x80 : 0) | RegIdx;
664 return;
665 }
666 getMachineOpValueCommon(MI, MO, OpNo, Op, Fixups, STI);
667}
668
669void AMDGPUMCCodeEmitter::getMachineOpValueCommon(
670 const MCInst &MI, const MCOperand &MO, unsigned OpNo, APInt &Op,
671 SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
672 bool isLikeImm = false;
673 int64_t Val;
674
675 if (MO.isImm()) {
676 Val = MO.getImm();
677 isLikeImm = true;
678 } else if (MO.isExpr() && MO.getExpr()->evaluateAsAbsolute(Val)) {
679 isLikeImm = true;
680 } else if (MO.isExpr()) {
681 // FIXME: If this is expression is PCRel or not should not depend on what
682 // the expression looks like. Given that this is just a general expression,
683 // it should probably be FK_Data_4 and whatever is producing
684 //
685 // s_add_u32 s2, s2, (extern_const_addrspace+16
686 //
687 // And expecting a PCRel should instead produce
688 //
689 // .Ltmp1:
690 // s_add_u32 s2, s2, (extern_const_addrspace+16)-.Ltmp1
691 bool PCRel = needsPCRel(MO.getExpr());
692 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
693 uint32_t Offset = Desc.getSize();
694 assert(Offset == 4 || Offset == 8);
695 unsigned Size = AMDGPU::getOperandSize(Desc, OpNo);
697 addFixup(Fixups, Offset, MO.getExpr(), Kind, PCRel);
698 }
699
700 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
701 if (AMDGPU::isSISrcOperand(Desc, OpNo)) {
702 bool HasMandatoryLiteral =
703 AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::imm);
704 if (auto Enc = getLitEncoding(MO, Desc.operands()[OpNo], STI,
705 HasMandatoryLiteral)) {
706 Op = *Enc;
707 return;
708 }
709
710 llvm_unreachable("Operand not supported for SISrc");
711 }
712
713 if (isLikeImm) {
714 Op = Val;
715 return;
716 }
717
718 llvm_unreachable("Encoding of this operand type is not supported yet.");
719}
720
721#include "AMDGPUGenMCCodeEmitter.inc"
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint32_t getLit16IntEncoding(uint32_t Val, const MCSubtargetInfo &STI)
static uint32_t getLit64Encoding(uint64_t Val, const MCSubtargetInfo &STI, bool IsFP)
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind, bool PCRel=false)
static uint32_t getLitBF16Encoding(uint16_t Val)
static bool isVCMPX64(const MCInstrDesc &Desc)
static uint32_t getLit16Encoding(uint16_t Val, const MCSubtargetInfo &STI)
static uint32_t getIntInlineImmEncoding(IntTy Imm)
static bool needsPCRel(const MCExpr *Expr)
static uint32_t getLit32Encoding(uint32_t Val, const MCSubtargetInfo &STI)
Provides AMDGPU specific target descriptions.
This file implements a class to represent arbitrary precision integral constant values and operations...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
uint64_t Size
IRTranslator LLVM IR MI
Class for arbitrary precision integers.
Definition: APInt.h:78
LLVM_ABI uint64_t extractBitsAsZExtValue(unsigned numBits, unsigned bitPosition) const
Definition: APInt.cpp:520
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
Definition: APInt.h:475
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition: APInt.h:200
This class represents an Operation in the Expression.
@ Sub
Subtraction.
Definition: MCExpr.h:324
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:23
virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl< char > &CB, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
Encode the given Inst to bytes and append to CB.
Context object for machine code objects.
Definition: MCContext.h:83
const MCRegisterInfo * getRegisterInfo() const
Definition: MCContext.h:414
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
@ Unary
Unary expressions.
Definition: MCExpr.h:44
@ Constant
Constant expressions.
Definition: MCExpr.h:42
@ SymbolRef
References to labels and assigned expressions.
Definition: MCExpr.h:43
@ Target
Target specific expression.
Definition: MCExpr.h:46
@ Specifier
Expression with a relocation specifier.
Definition: MCExpr.h:45
@ Binary
Binary expressions.
Definition: MCExpr.h:41
ExprKind getKind() const
Definition: MCExpr.h:85
static MCFixupKind getDataKindForSize(unsigned Size)
Return the generic fixup kind for a value with the given size.
Definition: MCFixup.h:110
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Definition: MCFixup.h:86
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:188
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:199
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:27
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:86
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:98
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:40
int64_t getImm() const
Definition: MCInst.h:84
bool isImm() const
Definition: MCInst.h:66
bool isReg() const
Definition: MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition: MCInst.h:73
bool isDFPImm() const
Definition: MCInst.h:68
const MCExpr * getExpr() const
Definition: MCInst.h:118
bool isExpr() const
Definition: MCInst.h:69
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:684
void push_back(const T &Elt)
Definition: SmallVector.h:414
LLVM Value Representation.
Definition: Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isSGPR(MCRegister Reg, const MCRegisterInfo *TRI)
Is Reg - scalar register.
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
static AMDGPUMCExpr::Specifier getSpecifier(const MCSymbolRefExpr *SRE)
Definition: AMDGPUMCExpr.h:129
@ fixup_si_sopp_br
16-bit PC relative fixup for SOPP branch instructions.
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo)
Is this an AMDGPU specific source operand? These include registers, inline constants,...
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
bool isGFX10Plus(const MCSubtargetInfo &STI)
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition: SIDefines.h:231
@ OPERAND_REG_IMM_INT64
Definition: SIDefines.h:202
@ OPERAND_REG_IMM_V2FP16
Definition: SIDefines.h:209
@ OPERAND_REG_INLINE_C_FP64
Definition: SIDefines.h:222
@ OPERAND_REG_INLINE_C_BF16
Definition: SIDefines.h:219
@ OPERAND_REG_INLINE_C_V2BF16
Definition: SIDefines.h:224
@ OPERAND_REG_IMM_V2INT16
Definition: SIDefines.h:210
@ OPERAND_REG_IMM_BF16
Definition: SIDefines.h:206
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition: SIDefines.h:201
@ OPERAND_REG_IMM_V2BF16
Definition: SIDefines.h:208
@ OPERAND_REG_IMM_FP16
Definition: SIDefines.h:207
@ OPERAND_REG_INLINE_C_INT64
Definition: SIDefines.h:218
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition: SIDefines.h:216
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition: SIDefines.h:211
@ OPERAND_REG_IMM_FP64
Definition: SIDefines.h:205
@ OPERAND_REG_INLINE_C_V2FP16
Definition: SIDefines.h:225
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition: SIDefines.h:236
@ OPERAND_REG_INLINE_AC_FP32
Definition: SIDefines.h:237
@ OPERAND_REG_IMM_V2INT32
Definition: SIDefines.h:212
@ OPERAND_REG_IMM_FP32
Definition: SIDefines.h:204
@ OPERAND_REG_INLINE_C_FP32
Definition: SIDefines.h:221
@ OPERAND_REG_INLINE_C_INT32
Definition: SIDefines.h:217
@ OPERAND_REG_INLINE_C_V2INT16
Definition: SIDefines.h:223
@ OPERAND_REG_IMM_V2FP32
Definition: SIDefines.h:213
@ OPERAND_REG_INLINE_AC_FP64
Definition: SIDefines.h:238
@ OPERAND_REG_INLINE_C_FP16
Definition: SIDefines.h:220
@ OPERAND_REG_IMM_INT16
Definition: SIDefines.h:203
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition: SIDefines.h:228
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
bool isVI(const MCSubtargetInfo &STI)
MCRegister mc2PseudoReg(MCRegister Reg)
Convert hardware register Reg to a pseudo register.
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
LLVM_READNONE unsigned getOperandSize(const MCOperandInfo &OpInfo)
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition: MathExtras.h:159
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition: MathExtras.h:164
MCCodeEmitter * createAMDGPUMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
Description of the encoding of one expression Op.