Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- R600MCCodeEmitter.cpp - Code Emitter for R600->Cayman GPU families -===//
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
///
11
/// The R600 code emitter produces machine code that can be executed
12
/// directly on the GPU device.
13
//
14
//===----------------------------------------------------------------------===//
15
16
#include "MCTargetDesc/AMDGPUFixupKinds.h"
17
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
18
#include "R600Defines.h"
19
#include "llvm/MC/MCCodeEmitter.h"
20
#include "llvm/MC/MCContext.h"
21
#include "llvm/MC/MCFixup.h"
22
#include "llvm/MC/MCInst.h"
23
#include "llvm/MC/MCInstrDesc.h"
24
#include "llvm/MC/MCInstrInfo.h"
25
#include "llvm/MC/MCRegisterInfo.h"
26
#include "llvm/MC/MCSubtargetInfo.h"
27
#include "llvm/Support/Endian.h"
28
#include "llvm/Support/EndianStream.h"
29
#include "llvm/Support/raw_ostream.h"
30
#include <cassert>
31
#include <cstdint>
32
33
using namespace llvm;
34
35
namespace {
36
37
class R600MCCodeEmitter : public MCCodeEmitter {
38
  const MCRegisterInfo &MRI;
39
  const MCInstrInfo &MCII;
40
41
public:
42
  R600MCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri)
43
31
    : MRI(mri), MCII(mcii) {}
44
  R600MCCodeEmitter(const R600MCCodeEmitter &) = delete;
45
  R600MCCodeEmitter &operator=(const R600MCCodeEmitter &) = delete;
46
47
  /// Encode the instruction and write it to the OS.
48
  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
49
                         SmallVectorImpl<MCFixup> &Fixups,
50
                         const MCSubtargetInfo &STI) const;
51
52
  /// \returns the encoding for an MCOperand.
53
  uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
54
                             SmallVectorImpl<MCFixup> &Fixups,
55
                             const MCSubtargetInfo &STI) const;
56
57
private:
58
59
  void Emit(uint32_t value, raw_ostream &OS) const;
60
  void Emit(uint64_t value, raw_ostream &OS) const;
61
62
  unsigned getHWReg(unsigned regNo) const;
63
64
  uint64_t getBinaryCodeForInstr(const MCInst &MI,
65
                                 SmallVectorImpl<MCFixup> &Fixups,
66
                                 const MCSubtargetInfo &STI) const;
67
  FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const;
68
  void
69
  verifyInstructionPredicates(const MCInst &MI,
70
                              const FeatureBitset &AvailableFeatures) const;
71
72
};
73
74
} // end anonymous namespace
75
76
enum RegElement {
77
  ELEMENT_X = 0,
78
  ELEMENT_Y,
79
  ELEMENT_Z,
80
  ELEMENT_W
81
};
82
83
enum FCInstr {
84
  FC_IF_PREDICATE = 0,
85
  FC_ELSE,
86
  FC_ENDIF,
87
  FC_BGNLOOP,
88
  FC_ENDLOOP,
89
  FC_BREAK_PREDICATE,
90
  FC_CONTINUE
91
};
92
93
MCCodeEmitter *llvm::createR600MCCodeEmitter(const MCInstrInfo &MCII,
94
                                             const MCRegisterInfo &MRI,
95
31
                                             MCContext &Ctx) {
96
31
  return new R600MCCodeEmitter(MCII, MRI);
97
31
}
98
99
void R600MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
100
                                       SmallVectorImpl<MCFixup> &Fixups,
101
315
                                       const MCSubtargetInfo &STI) const {
102
315
  verifyInstructionPredicates(MI,
103
315
                              computeAvailableFeatures(STI.getFeatureBits()));
104
315
105
315
  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
106
315
  if (MI.getOpcode() == R600::RETURN ||
107
315
    MI.getOpcode() == R600::FETCH_CLAUSE ||
108
315
    
MI.getOpcode() == R600::ALU_CLAUSE300
||
109
315
    
MI.getOpcode() == R600::BUNDLE268
||
110
315
    
MI.getOpcode() == R600::KILL268
) {
111
47
    return;
112
268
  } else if (IS_VTX(Desc)) {
113
14
    uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups, STI);
114
14
    uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset
115
14
    if (!(STI.getFeatureBits()[R600::FeatureCaymanISA])) {
116
10
      InstWord2 |= 1 << 19; // Mega-Fetch bit
117
10
    }
118
14
119
14
    Emit(InstWord01, OS);
120
14
    Emit(InstWord2, OS);
121
14
    Emit((uint32_t) 0, OS);
122
254
  } else if (IS_TEX(Desc)) {
123
10
      int64_t Sampler = MI.getOperand(14).getImm();
124
10
125
10
      int64_t SrcSelect[4] = {
126
10
        MI.getOperand(2).getImm(),
127
10
        MI.getOperand(3).getImm(),
128
10
        MI.getOperand(4).getImm(),
129
10
        MI.getOperand(5).getImm()
130
10
      };
131
10
      int64_t Offsets[3] = {
132
10
        MI.getOperand(6).getImm() & 0x1F,
133
10
        MI.getOperand(7).getImm() & 0x1F,
134
10
        MI.getOperand(8).getImm() & 0x1F
135
10
      };
136
10
137
10
      uint64_t Word01 = getBinaryCodeForInstr(MI, Fixups, STI);
138
10
      uint32_t Word2 = Sampler << 15 | SrcSelect[ELEMENT_X] << 20 |
139
10
          SrcSelect[ELEMENT_Y] << 23 | SrcSelect[ELEMENT_Z] << 26 |
140
10
          SrcSelect[ELEMENT_W] << 29 | Offsets[0] << 0 | Offsets[1] << 5 |
141
10
          Offsets[2] << 10;
142
10
143
10
      Emit(Word01, OS);
144
10
      Emit(Word2, OS);
145
10
      Emit((uint32_t) 0, OS);
146
244
  } else {
147
244
    uint64_t Inst = getBinaryCodeForInstr(MI, Fixups, STI);
148
244
    if ((STI.getFeatureBits()[R600::FeatureR600ALUInst]) &&
149
244
       
(15
(Desc.TSFlags & R600_InstFlag::OP1)15
||
150
15
         Desc.TSFlags & R600_InstFlag::OP2)) {
151
1
      uint64_t ISAOpCode = Inst & (0x3FFULL << 39);
152
1
      Inst &= ~(0x3FFULL << 39);
153
1
      Inst |= ISAOpCode << 1;
154
1
    }
155
244
    Emit(Inst, OS);
156
244
  }
157
315
}
158
159
48
void R600MCCodeEmitter::Emit(uint32_t Value, raw_ostream &OS) const {
160
48
  support::endian::write(OS, Value, support::little);
161
48
}
162
163
268
void R600MCCodeEmitter::Emit(uint64_t Value, raw_ostream &OS) const {
164
268
  support::endian::write(OS, Value, support::little);
165
268
}
166
167
81
unsigned R600MCCodeEmitter::getHWReg(unsigned RegNo) const {
168
81
  return MRI.getEncodingValue(RegNo) & HW_REG_MASK;
169
81
}
170
171
uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI,
172
                                              const MCOperand &MO,
173
                                        SmallVectorImpl<MCFixup> &Fixups,
174
1.79k
                                        const MCSubtargetInfo &STI) const {
175
1.79k
  if (MO.isReg()) {
176
359
    if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags))
177
359
      
return MRI.getEncodingValue(MO.getReg())278
;
178
81
    return getHWReg(MO.getReg());
179
81
  }
180
1.43k
181
1.43k
  if (MO.isExpr()) {
182
5
    // We put rodata at the end of code section, then map the entire
183
5
    // code secetion as vtx buf. Thus the section relative address is the
184
5
    // correct one.
185
5
    // Each R600 literal instruction has two operands
186
5
    // We can't easily get the order of the current one, so compare against
187
5
    // the first one and adjust offset.
188
5
    const unsigned offset = (&MO == &MI.getOperand(0)) ? 0 : 
40
;
189
5
    Fixups.push_back(MCFixup::create(offset, MO.getExpr(), FK_SecRel_4, MI.getLoc()));
190
5
    return 0;
191
5
  }
192
1.42k
193
1.42k
  assert(MO.isImm());
194
1.42k
  return MO.getImm();
195
1.42k
}
196
197
#define ENABLE_INSTR_PREDICATE_VERIFIER
198
#include "R600GenMCCodeEmitter.inc"