Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / lib / Target / AMDGPU / MCTargetDesc / SIMCCodeEmitter.cpp
blob205e9b3b5849485a6e38948b98c9f34c64045cee
1 //===-- SIMCCodeEmitter.cpp - SI 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 SI code emitter produces machine code that can be executed
11 /// directly on the GPU device.
13 //===----------------------------------------------------------------------===//
15 #include "AMDGPU.h"
16 #include "MCTargetDesc/AMDGPUFixupKinds.h"
17 #include "MCTargetDesc/AMDGPUMCCodeEmitter.h"
18 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
19 #include "Utils/AMDGPUBaseInfo.h"
20 #include "llvm/MC/MCCodeEmitter.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCFixup.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/MCInstrDesc.h"
26 #include "llvm/MC/MCInstrInfo.h"
27 #include "llvm/MC/MCRegisterInfo.h"
28 #include "llvm/MC/MCSubtargetInfo.h"
29 #include "llvm/MC/MCSymbol.h"
30 #include "llvm/Support/Casting.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include "llvm/Support/MathExtras.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include <cassert>
35 #include <cstdint>
36 #include <cstdlib>
38 using namespace llvm;
40 namespace {
42 class SIMCCodeEmitter : public AMDGPUMCCodeEmitter {
43 const MCRegisterInfo &MRI;
45 /// Encode an fp or int literal
46 uint32_t getLitEncoding(const MCOperand &MO, const MCOperandInfo &OpInfo,
47 const MCSubtargetInfo &STI) const;
49 public:
50 SIMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri,
51 MCContext &ctx)
52 : AMDGPUMCCodeEmitter(mcii), MRI(mri) {}
53 SIMCCodeEmitter(const SIMCCodeEmitter &) = delete;
54 SIMCCodeEmitter &operator=(const SIMCCodeEmitter &) = delete;
56 /// Encode the instruction and write it to the OS.
57 void encodeInstruction(const MCInst &MI, raw_ostream &OS,
58 SmallVectorImpl<MCFixup> &Fixups,
59 const MCSubtargetInfo &STI) const override;
61 /// \returns the encoding for an MCOperand.
62 uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
63 SmallVectorImpl<MCFixup> &Fixups,
64 const MCSubtargetInfo &STI) const override;
66 /// Use a fixup to encode the simm16 field for SOPP branch
67 /// instructions.
68 unsigned getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
69 SmallVectorImpl<MCFixup> &Fixups,
70 const MCSubtargetInfo &STI) const override;
72 unsigned getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
73 SmallVectorImpl<MCFixup> &Fixups,
74 const MCSubtargetInfo &STI) const override;
76 unsigned getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo,
77 SmallVectorImpl<MCFixup> &Fixups,
78 const MCSubtargetInfo &STI) const override;
81 } // end anonymous namespace
83 MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII,
84 const MCRegisterInfo &MRI,
85 MCContext &Ctx) {
86 return new SIMCCodeEmitter(MCII, MRI, Ctx);
89 // Returns the encoding value to use if the given integer is an integer inline
90 // immediate value, or 0 if it is not.
91 template <typename IntTy>
92 static uint32_t getIntInlineImmEncoding(IntTy Imm) {
93 if (Imm >= 0 && Imm <= 64)
94 return 128 + Imm;
96 if (Imm >= -16 && Imm <= -1)
97 return 192 + std::abs(Imm);
99 return 0;
102 static uint32_t getLit16Encoding(uint16_t Val, const MCSubtargetInfo &STI) {
103 uint16_t IntImm = getIntInlineImmEncoding(static_cast<int16_t>(Val));
104 if (IntImm != 0)
105 return IntImm;
107 if (Val == 0x3800) // 0.5
108 return 240;
110 if (Val == 0xB800) // -0.5
111 return 241;
113 if (Val == 0x3C00) // 1.0
114 return 242;
116 if (Val == 0xBC00) // -1.0
117 return 243;
119 if (Val == 0x4000) // 2.0
120 return 244;
122 if (Val == 0xC000) // -2.0
123 return 245;
125 if (Val == 0x4400) // 4.0
126 return 246;
128 if (Val == 0xC400) // -4.0
129 return 247;
131 if (Val == 0x3118 && // 1.0 / (2.0 * pi)
132 STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
133 return 248;
135 return 255;
138 static uint32_t getLit32Encoding(uint32_t Val, const MCSubtargetInfo &STI) {
139 uint32_t IntImm = getIntInlineImmEncoding(static_cast<int32_t>(Val));
140 if (IntImm != 0)
141 return IntImm;
143 if (Val == FloatToBits(0.5f))
144 return 240;
146 if (Val == FloatToBits(-0.5f))
147 return 241;
149 if (Val == FloatToBits(1.0f))
150 return 242;
152 if (Val == FloatToBits(-1.0f))
153 return 243;
155 if (Val == FloatToBits(2.0f))
156 return 244;
158 if (Val == FloatToBits(-2.0f))
159 return 245;
161 if (Val == FloatToBits(4.0f))
162 return 246;
164 if (Val == FloatToBits(-4.0f))
165 return 247;
167 if (Val == 0x3e22f983 && // 1.0 / (2.0 * pi)
168 STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
169 return 248;
171 return 255;
174 static uint32_t getLit64Encoding(uint64_t Val, const MCSubtargetInfo &STI) {
175 uint32_t IntImm = getIntInlineImmEncoding(static_cast<int64_t>(Val));
176 if (IntImm != 0)
177 return IntImm;
179 if (Val == DoubleToBits(0.5))
180 return 240;
182 if (Val == DoubleToBits(-0.5))
183 return 241;
185 if (Val == DoubleToBits(1.0))
186 return 242;
188 if (Val == DoubleToBits(-1.0))
189 return 243;
191 if (Val == DoubleToBits(2.0))
192 return 244;
194 if (Val == DoubleToBits(-2.0))
195 return 245;
197 if (Val == DoubleToBits(4.0))
198 return 246;
200 if (Val == DoubleToBits(-4.0))
201 return 247;
203 if (Val == 0x3fc45f306dc9c882 && // 1.0 / (2.0 * pi)
204 STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
205 return 248;
207 return 255;
210 uint32_t SIMCCodeEmitter::getLitEncoding(const MCOperand &MO,
211 const MCOperandInfo &OpInfo,
212 const MCSubtargetInfo &STI) const {
213 int64_t Imm;
214 if (MO.isExpr()) {
215 const auto *C = dyn_cast<MCConstantExpr>(MO.getExpr());
216 if (!C)
217 return 255;
219 Imm = C->getValue();
220 } else {
222 assert(!MO.isFPImm());
224 if (!MO.isImm())
225 return ~0;
227 Imm = MO.getImm();
230 switch (OpInfo.OperandType) {
231 case AMDGPU::OPERAND_REG_IMM_INT32:
232 case AMDGPU::OPERAND_REG_IMM_FP32:
233 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
234 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
235 return getLit32Encoding(static_cast<uint32_t>(Imm), STI);
237 case AMDGPU::OPERAND_REG_IMM_INT64:
238 case AMDGPU::OPERAND_REG_IMM_FP64:
239 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
240 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
241 return getLit64Encoding(static_cast<uint64_t>(Imm), STI);
243 case AMDGPU::OPERAND_REG_IMM_INT16:
244 case AMDGPU::OPERAND_REG_IMM_FP16:
245 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
246 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
247 // FIXME Is this correct? What do inline immediates do on SI for f16 src
248 // which does not have f16 support?
249 return getLit16Encoding(static_cast<uint16_t>(Imm), STI);
251 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
252 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
253 uint16_t Lo16 = static_cast<uint16_t>(Imm);
254 uint32_t Encoding = getLit16Encoding(Lo16, STI);
255 return Encoding;
257 default:
258 llvm_unreachable("invalid operand size");
262 void SIMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
263 SmallVectorImpl<MCFixup> &Fixups,
264 const MCSubtargetInfo &STI) const {
265 verifyInstructionPredicates(MI,
266 computeAvailableFeatures(STI.getFeatureBits()));
268 uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups, STI);
269 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
270 unsigned bytes = Desc.getSize();
272 for (unsigned i = 0; i < bytes; i++) {
273 OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff));
276 if (bytes > 4)
277 return;
279 // Check for additional literals in SRC0/1/2 (Op 1/2/3)
280 for (unsigned i = 0, e = Desc.getNumOperands(); i < e; ++i) {
282 // Check if this operand should be encoded as [SV]Src
283 if (!AMDGPU::isSISrcOperand(Desc, i))
284 continue;
286 // Is this operand a literal immediate?
287 const MCOperand &Op = MI.getOperand(i);
288 if (getLitEncoding(Op, Desc.OpInfo[i], STI) != 255)
289 continue;
291 // Yes! Encode it
292 int64_t Imm = 0;
294 if (Op.isImm())
295 Imm = Op.getImm();
296 else if (Op.isExpr()) {
297 if (const auto *C = dyn_cast<MCConstantExpr>(Op.getExpr()))
298 Imm = C->getValue();
300 } else if (!Op.isExpr()) // Exprs will be replaced with a fixup value.
301 llvm_unreachable("Must be immediate or expr");
303 for (unsigned j = 0; j < 4; j++) {
304 OS.write((uint8_t) ((Imm >> (8 * j)) & 0xff));
307 // Only one literal value allowed
308 break;
312 unsigned SIMCCodeEmitter::getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
313 SmallVectorImpl<MCFixup> &Fixups,
314 const MCSubtargetInfo &STI) const {
315 const MCOperand &MO = MI.getOperand(OpNo);
317 if (MO.isExpr()) {
318 const MCExpr *Expr = MO.getExpr();
319 MCFixupKind Kind = (MCFixupKind)AMDGPU::fixup_si_sopp_br;
320 Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
321 return 0;
324 return getMachineOpValue(MI, MO, Fixups, STI);
327 unsigned
328 SIMCCodeEmitter::getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
329 SmallVectorImpl<MCFixup> &Fixups,
330 const MCSubtargetInfo &STI) const {
331 using namespace AMDGPU::SDWA;
333 uint64_t RegEnc = 0;
335 const MCOperand &MO = MI.getOperand(OpNo);
337 if (MO.isReg()) {
338 unsigned Reg = MO.getReg();
339 RegEnc |= MRI.getEncodingValue(Reg);
340 RegEnc &= SDWA9EncValues::SRC_VGPR_MASK;
341 if (AMDGPU::isSGPR(AMDGPU::mc2PseudoReg(Reg), &MRI)) {
342 RegEnc |= SDWA9EncValues::SRC_SGPR_MASK;
344 return RegEnc;
345 } else {
346 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
347 uint32_t Enc = getLitEncoding(MO, Desc.OpInfo[OpNo], STI);
348 if (Enc != ~0U && Enc != 255) {
349 return Enc | SDWA9EncValues::SRC_SGPR_MASK;
353 llvm_unreachable("Unsupported operand kind");
354 return 0;
357 unsigned
358 SIMCCodeEmitter::getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo,
359 SmallVectorImpl<MCFixup> &Fixups,
360 const MCSubtargetInfo &STI) const {
361 using namespace AMDGPU::SDWA;
363 uint64_t RegEnc = 0;
365 const MCOperand &MO = MI.getOperand(OpNo);
367 unsigned Reg = MO.getReg();
368 if (Reg != AMDGPU::VCC) {
369 RegEnc |= MRI.getEncodingValue(Reg);
370 RegEnc &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
371 RegEnc |= SDWA9EncValues::VOPC_DST_VCC_MASK;
373 return RegEnc;
376 static bool needsPCRel(const MCExpr *Expr) {
377 switch (Expr->getKind()) {
378 case MCExpr::SymbolRef:
379 return true;
380 case MCExpr::Binary: {
381 auto *BE = cast<MCBinaryExpr>(Expr);
382 if (BE->getOpcode() == MCBinaryExpr::Sub)
383 return false;
384 return needsPCRel(BE->getLHS()) || needsPCRel(BE->getRHS());
386 case MCExpr::Unary:
387 return needsPCRel(cast<MCUnaryExpr>(Expr)->getSubExpr());
388 case MCExpr::Target:
389 case MCExpr::Constant:
390 return false;
392 llvm_unreachable("invalid kind");
395 uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI,
396 const MCOperand &MO,
397 SmallVectorImpl<MCFixup> &Fixups,
398 const MCSubtargetInfo &STI) const {
399 if (MO.isReg())
400 return MRI.getEncodingValue(MO.getReg());
402 if (MO.isExpr() && MO.getExpr()->getKind() != MCExpr::Constant) {
403 // FIXME: If this is expression is PCRel or not should not depend on what
404 // the expression looks like. Given that this is just a general expression,
405 // it should probably be FK_Data_4 and whatever is producing
407 // s_add_u32 s2, s2, (extern_const_addrspace+16
409 // And expecting a PCRel should instead produce
411 // .Ltmp1:
412 // s_add_u32 s2, s2, (extern_const_addrspace+16)-.Ltmp1
413 MCFixupKind Kind;
414 if (needsPCRel(MO.getExpr()))
415 Kind = FK_PCRel_4;
416 else
417 Kind = FK_Data_4;
418 Fixups.push_back(MCFixup::create(4, MO.getExpr(), Kind, MI.getLoc()));
421 // Figure out the operand number, needed for isSrcOperand check
422 unsigned OpNo = 0;
423 for (unsigned e = MI.getNumOperands(); OpNo < e; ++OpNo) {
424 if (&MO == &MI.getOperand(OpNo))
425 break;
428 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
429 if (AMDGPU::isSISrcOperand(Desc, OpNo)) {
430 uint32_t Enc = getLitEncoding(MO, Desc.OpInfo[OpNo], STI);
431 if (Enc != ~0U && (Enc != 255 || Desc.getSize() == 4))
432 return Enc;
434 } else if (MO.isImm())
435 return MO.getImm();
437 llvm_unreachable("Encoding of this operand type is not supported yet.");
438 return 0;
441 #define ENABLE_INSTR_PREDICATE_VERIFIER
442 #include "AMDGPUGenMCCodeEmitter.inc"