LLVM  9.0.0svn
SIMCCodeEmitter.cpp
Go to the documentation of this file.
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.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "AMDGPU.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"
29 #include "llvm/MC/MCSymbol.h"
30 #include "llvm/Support/Casting.h"
34 #include <cassert>
35 #include <cstdint>
36 #include <cstdlib>
37 
38 using namespace llvm;
39 
40 namespace {
41 
42 class SIMCCodeEmitter : public AMDGPUMCCodeEmitter {
43  const MCRegisterInfo &MRI;
44 
45  /// Encode an fp or int literal
46  uint32_t getLitEncoding(const MCOperand &MO, const MCOperandInfo &OpInfo,
47  const MCSubtargetInfo &STI) const;
48 
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;
55 
56  /// Encode the instruction and write it to the OS.
57  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
59  const MCSubtargetInfo &STI) const override;
60 
61  /// \returns the encoding for an MCOperand.
62  uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
64  const MCSubtargetInfo &STI) const override;
65 
66  /// Use a fixup to encode the simm16 field for SOPP branch
67  /// instructions.
68  unsigned getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
70  const MCSubtargetInfo &STI) const override;
71 
72  unsigned getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
74  const MCSubtargetInfo &STI) const override;
75 
76  unsigned getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo,
78  const MCSubtargetInfo &STI) const override;
79 };
80 
81 } // end anonymous namespace
82 
84  const MCRegisterInfo &MRI,
85  MCContext &Ctx) {
86  return new SIMCCodeEmitter(MCII, MRI, Ctx);
87 }
88 
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;
95 
96  if (Imm >= -16 && Imm <= -1)
97  return 192 + std::abs(Imm);
98 
99  return 0;
100 }
101 
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;
106 
107  if (Val == 0x3800) // 0.5
108  return 240;
109 
110  if (Val == 0xB800) // -0.5
111  return 241;
112 
113  if (Val == 0x3C00) // 1.0
114  return 242;
115 
116  if (Val == 0xBC00) // -1.0
117  return 243;
118 
119  if (Val == 0x4000) // 2.0
120  return 244;
121 
122  if (Val == 0xC000) // -2.0
123  return 245;
124 
125  if (Val == 0x4400) // 4.0
126  return 246;
127 
128  if (Val == 0xC400) // -4.0
129  return 247;
130 
131  if (Val == 0x3118 && // 1.0 / (2.0 * pi)
132  STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
133  return 248;
134 
135  return 255;
136 }
137 
139  uint32_t IntImm = getIntInlineImmEncoding(static_cast<int32_t>(Val));
140  if (IntImm != 0)
141  return IntImm;
142 
143  if (Val == FloatToBits(0.5f))
144  return 240;
145 
146  if (Val == FloatToBits(-0.5f))
147  return 241;
148 
149  if (Val == FloatToBits(1.0f))
150  return 242;
151 
152  if (Val == FloatToBits(-1.0f))
153  return 243;
154 
155  if (Val == FloatToBits(2.0f))
156  return 244;
157 
158  if (Val == FloatToBits(-2.0f))
159  return 245;
160 
161  if (Val == FloatToBits(4.0f))
162  return 246;
163 
164  if (Val == FloatToBits(-4.0f))
165  return 247;
166 
167  if (Val == 0x3e22f983 && // 1.0 / (2.0 * pi)
168  STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
169  return 248;
170 
171  return 255;
172 }
173 
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;
178 
179  if (Val == DoubleToBits(0.5))
180  return 240;
181 
182  if (Val == DoubleToBits(-0.5))
183  return 241;
184 
185  if (Val == DoubleToBits(1.0))
186  return 242;
187 
188  if (Val == DoubleToBits(-1.0))
189  return 243;
190 
191  if (Val == DoubleToBits(2.0))
192  return 244;
193 
194  if (Val == DoubleToBits(-2.0))
195  return 245;
196 
197  if (Val == DoubleToBits(4.0))
198  return 246;
199 
200  if (Val == DoubleToBits(-4.0))
201  return 247;
202 
203  if (Val == 0x3fc45f306dc9c882 && // 1.0 / (2.0 * pi)
204  STI.getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm])
205  return 248;
206 
207  return 255;
208 }
209 
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;
218 
219  Imm = C->getValue();
220  } else {
221 
222  assert(!MO.isFPImm());
223 
224  if (!MO.isImm())
225  return ~0;
226 
227  Imm = MO.getImm();
228  }
229 
230  switch (OpInfo.OperandType) {
235  return getLit32Encoding(static_cast<uint32_t>(Imm), STI);
236 
241  return getLit64Encoding(static_cast<uint64_t>(Imm), STI);
242 
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);
250 
253  uint16_t Lo16 = static_cast<uint16_t>(Imm);
254  uint32_t Encoding = getLit16Encoding(Lo16, STI);
255  return Encoding;
256  }
257  default:
258  llvm_unreachable("invalid operand size");
259  }
260 }
261 
262 void SIMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
264  const MCSubtargetInfo &STI) const {
265  verifyInstructionPredicates(MI,
266  computeAvailableFeatures(STI.getFeatureBits()));
267 
268  uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups, STI);
269  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
270  unsigned bytes = Desc.getSize();
271 
272  for (unsigned i = 0; i < bytes; i++) {
273  OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff));
274  }
275 
276  if (bytes > 4)
277  return;
278 
279  // Check for additional literals in SRC0/1/2 (Op 1/2/3)
280  for (unsigned i = 0, e = Desc.getNumOperands(); i < e; ++i) {
281 
282  // Check if this operand should be encoded as [SV]Src
283  if (!AMDGPU::isSISrcOperand(Desc, i))
284  continue;
285 
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;
290 
291  // Yes! Encode it
292  int64_t Imm = 0;
293 
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();
299 
300  } else if (!Op.isExpr()) // Exprs will be replaced with a fixup value.
301  llvm_unreachable("Must be immediate or expr");
302 
303  for (unsigned j = 0; j < 4; j++) {
304  OS.write((uint8_t) ((Imm >> (8 * j)) & 0xff));
305  }
306 
307  // Only one literal value allowed
308  break;
309  }
310 }
311 
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);
316 
317  if (MO.isExpr()) {
318  const MCExpr *Expr = MO.getExpr();
320  Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
321  return 0;
322  }
323 
324  return getMachineOpValue(MI, MO, Fixups, STI);
325 }
326 
327 unsigned
328 SIMCCodeEmitter::getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
329  SmallVectorImpl<MCFixup> &Fixups,
330  const MCSubtargetInfo &STI) const {
331  using namespace AMDGPU::SDWA;
332 
333  uint64_t RegEnc = 0;
334 
335  const MCOperand &MO = MI.getOperand(OpNo);
336 
337  if (MO.isReg()) {
338  unsigned Reg = MO.getReg();
339  RegEnc |= MRI.getEncodingValue(Reg);
343  }
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;
350  }
351  }
352 
353  llvm_unreachable("Unsupported operand kind");
354  return 0;
355 }
356 
357 unsigned
358 SIMCCodeEmitter::getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo,
359  SmallVectorImpl<MCFixup> &Fixups,
360  const MCSubtargetInfo &STI) const {
361  using namespace AMDGPU::SDWA;
362 
363  uint64_t RegEnc = 0;
364 
365  const MCOperand &MO = MI.getOperand(OpNo);
366 
367  unsigned Reg = MO.getReg();
368  if (Reg != AMDGPU::VCC) {
369  RegEnc |= MRI.getEncodingValue(Reg);
372  }
373  return RegEnc;
374 }
375 
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());
385  }
386  case MCExpr::Unary:
387  return needsPCRel(cast<MCUnaryExpr>(Expr)->getSubExpr());
388  case MCExpr::Target:
389  case MCExpr::Constant:
390  return false;
391  }
392  llvm_unreachable("invalid kind");
393 }
394 
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());
401 
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
406  //
407  // s_add_u32 s2, s2, (extern_const_addrspace+16
408  //
409  // And expecting a PCRel should instead produce
410  //
411  // .Ltmp1:
412  // s_add_u32 s2, s2, (extern_const_addrspace+16)-.Ltmp1
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()));
419  }
420 
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;
426  }
427 
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;
433 
434  } else if (MO.isImm())
435  return MO.getImm();
436 
437  llvm_unreachable("Encoding of this operand type is not supported yet.");
438  return 0;
439 }
440 
441 #define ENABLE_INSTR_PREDICATE_VERIFIER
442 #include "AMDGPUGenMCCodeEmitter.inc"
uint64_t CallInst * C
bool isImm() const
Definition: MCInst.h:58
unsigned mc2PseudoReg(unsigned Reg)
Convert hardware register Reg to a pseudo register.
MCCodeEmitter * createSIMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:163
unsigned Reg
bool isReg() const
Definition: MCInst.h:57
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:210
const FeatureBitset & getFeatureBits() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:41
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:64
A four-byte fixup.
Definition: MCFixup.h:25
Context object for machine code objects.
Definition: MCContext.h:62
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:78
static uint32_t getLit64Encoding(uint64_t Val, const MCSubtargetInfo &STI)
const MCExpr * getExpr() const
Definition: MCInst.h:95
Unary expressions.
Definition: MCExpr.h:41
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
uint32_t FloatToBits(float Float)
This function takes a float and returns the bit equivalent 32-bit integer.
Definition: MathExtras.h:600
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
int64_t getImm() const
Definition: MCInst.h:75
unsigned const MachineRegisterInfo * MRI
static uint32_t getLit32Encoding(uint32_t Val, const MCSubtargetInfo &STI)
bool isFPImm() const
Definition: MCInst.h:59
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:23
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:22
static uint32_t getIntInlineImmEncoding(IntTy Imm)
static bool needsPCRel(const MCExpr *Expr)
bool isExpr() const
Definition: MCInst.h:60
unsigned getNumOperands() const
Definition: MCInst.h:181
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:89
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Operands with register or inline constant.
Definition: SIDefines.h:123
raw_ostream & write(unsigned char C)
static uint32_t getLit16Encoding(uint16_t Val, const MCSubtargetInfo &STI)
A four-byte pc relative fixup.
Definition: MCFixup.h:29
ExprKind getKind() const
Definition: MCExpr.h:72
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:179
uint64_t DoubleToBits(double Double)
This function takes a double and returns the bit equivalent 64-bit integer.
Definition: MathExtras.h:590
SMLoc getLoc() const
Definition: MCInst.h:177
Provides AMDGPU specific target descriptions.
16-bit PC relative fixup for SOPP branch instructions.
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Definition: APFloat.h:1212
Generic base class for all target subtargets.
CodeEmitter interface for R600 and SI codegen.
References to labels and assigned expressions.
Definition: MCExpr.h:40
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:322
Operands with register or 32-bit immediate.
Definition: SIDefines.h:115
const unsigned Kind
bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo)
Can this operand also contain immediate values?
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Constant expressions.
Definition: MCExpr.h:39
Binary expressions.
Definition: MCExpr.h:38
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:174
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
Subtraction.
Definition: MCExpr.h:440
IRTranslator LLVM IR MI
Target specific expression.
Definition: MCExpr.h:42
bool isSGPR(unsigned Reg, const MCRegisterInfo *TRI)
Is Reg - scalar register.
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:66
unsigned getOpcode() const
Definition: MCInst.h:171
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:34
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
Definition: MCInstrDesc.h:580