LLVM  3.7.0
SIMCCodeEmitter.cpp
Go to the documentation of this file.
1 //===-- SIMCCodeEmitter.cpp - SI Code Emitter -------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 /// \file
11 /// \brief The SI code emitter produces machine code that can be executed
12 /// directly on the GPU device.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "AMDGPU.h"
20 #include "SIDefines.h"
21 #include "llvm/MC/MCCodeEmitter.h"
22 #include "llvm/MC/MCContext.h"
23 #include "llvm/MC/MCFixup.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/MCInstrInfo.h"
26 #include "llvm/MC/MCRegisterInfo.h"
29 
30 using namespace llvm;
31 
32 namespace {
33 
34 class SIMCCodeEmitter : public AMDGPUMCCodeEmitter {
35  SIMCCodeEmitter(const SIMCCodeEmitter &) = delete;
36  void operator=(const SIMCCodeEmitter &) = delete;
37  const MCInstrInfo &MCII;
38  const MCRegisterInfo &MRI;
39  MCContext &Ctx;
40 
41  /// \brief Can this operand also contain immediate values?
42  bool isSrcOperand(const MCInstrDesc &Desc, unsigned OpNo) const;
43 
44  /// \brief Encode an fp or int literal
45  uint32_t getLitEncoding(const MCOperand &MO, unsigned OpSize) const;
46 
47 public:
48  SIMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri,
49  MCContext &ctx)
50  : MCII(mcii), MRI(mri), Ctx(ctx) { }
51 
52  ~SIMCCodeEmitter() override {}
53 
54  /// \brief Encode the instruction and write it to the OS.
55  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
57  const MCSubtargetInfo &STI) const override;
58 
59  /// \returns the encoding for an MCOperand.
60  uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
62  const MCSubtargetInfo &STI) const override;
63 
64  /// \brief Use a fixup to encode the simm16 field for SOPP branch
65  /// instructions.
66  unsigned getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
68  const MCSubtargetInfo &STI) const override;
69 };
70 
71 } // End anonymous namespace
72 
74  const MCRegisterInfo &MRI,
75  MCContext &Ctx) {
76  return new SIMCCodeEmitter(MCII, MRI, Ctx);
77 }
78 
79 bool SIMCCodeEmitter::isSrcOperand(const MCInstrDesc &Desc,
80  unsigned OpNo) const {
81  unsigned OpType = Desc.OpInfo[OpNo].OperandType;
82 
83  return OpType == AMDGPU::OPERAND_REG_IMM32 ||
85 }
86 
87 // Returns the encoding value to use if the given integer is an integer inline
88 // immediate value, or 0 if it is not.
89 template <typename IntTy>
90 static uint32_t getIntInlineImmEncoding(IntTy Imm) {
91  if (Imm >= 0 && Imm <= 64)
92  return 128 + Imm;
93 
94  if (Imm >= -16 && Imm <= -1)
95  return 192 + std::abs(Imm);
96 
97  return 0;
98 }
99 
100 static uint32_t getLit32Encoding(uint32_t Val) {
101  uint32_t IntImm = getIntInlineImmEncoding(static_cast<int32_t>(Val));
102  if (IntImm != 0)
103  return IntImm;
104 
105  if (Val == FloatToBits(0.5f))
106  return 240;
107 
108  if (Val == FloatToBits(-0.5f))
109  return 241;
110 
111  if (Val == FloatToBits(1.0f))
112  return 242;
113 
114  if (Val == FloatToBits(-1.0f))
115  return 243;
116 
117  if (Val == FloatToBits(2.0f))
118  return 244;
119 
120  if (Val == FloatToBits(-2.0f))
121  return 245;
122 
123  if (Val == FloatToBits(4.0f))
124  return 246;
125 
126  if (Val == FloatToBits(-4.0f))
127  return 247;
128 
129  return 255;
130 }
131 
132 static uint32_t getLit64Encoding(uint64_t Val) {
133  uint32_t IntImm = getIntInlineImmEncoding(static_cast<int64_t>(Val));
134  if (IntImm != 0)
135  return IntImm;
136 
137  if (Val == DoubleToBits(0.5))
138  return 240;
139 
140  if (Val == DoubleToBits(-0.5))
141  return 241;
142 
143  if (Val == DoubleToBits(1.0))
144  return 242;
145 
146  if (Val == DoubleToBits(-1.0))
147  return 243;
148 
149  if (Val == DoubleToBits(2.0))
150  return 244;
151 
152  if (Val == DoubleToBits(-2.0))
153  return 245;
154 
155  if (Val == DoubleToBits(4.0))
156  return 246;
157 
158  if (Val == DoubleToBits(-4.0))
159  return 247;
160 
161  return 255;
162 }
163 
164 uint32_t SIMCCodeEmitter::getLitEncoding(const MCOperand &MO,
165  unsigned OpSize) const {
166  if (MO.isExpr())
167  return 255;
168 
169  assert(!MO.isFPImm());
170 
171  if (!MO.isImm())
172  return ~0;
173 
174  if (OpSize == 4)
175  return getLit32Encoding(static_cast<uint32_t>(MO.getImm()));
176 
177  assert(OpSize == 8);
178 
179  return getLit64Encoding(static_cast<uint64_t>(MO.getImm()));
180 }
181 
182 void SIMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
184  const MCSubtargetInfo &STI) const {
185 
186  uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups, STI);
187  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
188  unsigned bytes = Desc.getSize();
189 
190  for (unsigned i = 0; i < bytes; i++) {
191  OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff));
192  }
193 
194  if (bytes > 4)
195  return;
196 
197  // Check for additional literals in SRC0/1/2 (Op 1/2/3)
198  for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) {
199 
200  // Check if this operand should be encoded as [SV]Src
201  if (!isSrcOperand(Desc, i))
202  continue;
203 
204  int RCID = Desc.OpInfo[i].RegClass;
205  const MCRegisterClass &RC = MRI.getRegClass(RCID);
206 
207  // Is this operand a literal immediate?
208  const MCOperand &Op = MI.getOperand(i);
209  if (getLitEncoding(Op, RC.getSize()) != 255)
210  continue;
211 
212  // Yes! Encode it
213  int64_t Imm = 0;
214 
215  if (Op.isImm())
216  Imm = Op.getImm();
217  else if (!Op.isExpr()) // Exprs will be replaced with a fixup value.
218  llvm_unreachable("Must be immediate or expr");
219 
220  for (unsigned j = 0; j < 4; j++) {
221  OS.write((uint8_t) ((Imm >> (8 * j)) & 0xff));
222  }
223 
224  // Only one literal value allowed
225  break;
226  }
227 }
228 
229 unsigned SIMCCodeEmitter::getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
230  SmallVectorImpl<MCFixup> &Fixups,
231  const MCSubtargetInfo &STI) const {
232  const MCOperand &MO = MI.getOperand(OpNo);
233 
234  if (MO.isExpr()) {
235  const MCExpr *Expr = MO.getExpr();
237  Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
238  return 0;
239  }
240 
241  return getMachineOpValue(MI, MO, Fixups, STI);
242 }
243 
244 uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI,
245  const MCOperand &MO,
246  SmallVectorImpl<MCFixup> &Fixups,
247  const MCSubtargetInfo &STI) const {
248  if (MO.isReg())
249  return MRI.getEncodingValue(MO.getReg());
250 
251  if (MO.isExpr()) {
252  const MCSymbolRefExpr *Expr = cast<MCSymbolRefExpr>(MO.getExpr());
254  const MCSymbol *Sym =
255  Ctx.getOrCreateSymbol(StringRef(END_OF_TEXT_LABEL_NAME));
256 
257  if (&Expr->getSymbol() == Sym) {
258  // Add the offset to the beginning of the constant values.
260  } else {
261  // This is used for constant data stored in .rodata.
263  }
264  Fixups.push_back(MCFixup::create(4, Expr, Kind, MI.getLoc()));
265  }
266 
267  // Figure out the operand number, needed for isSrcOperand check
268  unsigned OpNo = 0;
269  for (unsigned e = MI.getNumOperands(); OpNo < e; ++OpNo) {
270  if (&MO == &MI.getOperand(OpNo))
271  break;
272  }
273 
274  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
275  if (isSrcOperand(Desc, OpNo)) {
276  int RCID = Desc.OpInfo[OpNo].RegClass;
277  const MCRegisterClass &RC = MRI.getRegClass(RCID);
278 
279  uint32_t Enc = getLitEncoding(MO, RC.getSize());
280  if (Enc != ~0U && (Enc != 255 || Desc.getSize() == 4))
281  return Enc;
282 
283  } else if (MO.isImm())
284  return MO.getImm();
285 
286  llvm_unreachable("Encoding of this operand type is not supported yet.");
287  return 0;
288 }
289 
fixup for offset from instruction to end of text section
MCCodeEmitter * createSIMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx)
const MCSymbol & getSymbol() const
Definition: MCExpr.h:328
bool isReg() const
Definition: MCInst.h:56
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:39
#define END_OF_TEXT_LABEL_NAME
Definition: AMDGPU.h:88
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:138
fixup for global addresses with constant initializers
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APInt.h:33
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:33
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:159
Context object for machine code objects.
Definition: MCContext.h:48
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:68
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:63
Operand with register or inline constant.
Definition: SIDefines.h:50
MCRegisterClass - Base class of TargetRegisterClass.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:150
uint32_t FloatToBits(float Float)
FloatToBits - This function takes a float and returns the bit equivalent 32-bit integer.
Definition: MathExtras.h:541
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
bool isImm() const
Definition: MCInst.h:57
const MCExpr * getExpr() const
Definition: MCInst.h:93
bool isFPImm() const
Definition: MCInst.h:58
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:23
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:532
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:24
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:23
static uint32_t getIntInlineImmEncoding(IntTy Imm)
unsigned getSize() const
getSize - Return the size of the register in bytes, which is also the size of a stack slot allocated ...
bool isExpr() const
Definition: MCInst.h:59
SMLoc getLoc() const
Definition: MCInst.h:162
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:78
raw_ostream & write(unsigned char C)
uint64_t DoubleToBits(double Double)
DoubleToBits - This function takes a double and returns the bit equivalent 64-bit integer...
Definition: MathExtras.h:528
unsigned getOpcode() const
Definition: MCInst.h:159
int64_t getImm() const
Definition: MCInst.h:74
Provides AMDGPU specific target descriptions.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition: MCInstrDesc.h:62
unsigned getNumOperands() const
Definition: MCInst.h:166
16-bit PC relative fixup for SOPP branch instructions.
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Definition: APFloat.h:651
MCSubtargetInfo - Generic base class for all target subtargets.
CodeEmitter interface for R600 and SI codegen.
Operand with register or 32-bit immediate.
Definition: SIDefines.h:48
static uint32_t getLit64Encoding(uint64_t Val)
static uint32_t getLit32Encoding(uint32_t Val)
const ARM::ArchExtKind Kind
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:149
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:38
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:33
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:164