1//===-- AMDGPUMCTargetDesc.cpp - AMDGPU Target Descriptions ---------------===//
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/// This file provides AMDGPU specific target descriptions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AMDGPUMCTargetDesc.h"
15#include "AMDGPUELFStreamer.h"
16#include "AMDGPUInstPrinter.h"
17#include "AMDGPUMCAsmInfo.h"
18#include "AMDGPUTargetStreamer.h"
19#include "R600InstPrinter.h"
20#include "R600MCTargetDesc.h"
21#include "TargetInfo/AMDGPUTargetInfo.h"
22#include "llvm/MC/MCAsmBackend.h"
23#include "llvm/MC/MCCodeEmitter.h"
24#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCELFStreamer.h"
26#include "llvm/MC/MCInstPrinter.h"
27#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCInstrInfo.h"
29#include "llvm/MC/MCObjectWriter.h"
30#include "llvm/MC/MCRegisterInfo.h"
31#include "llvm/MC/MCStreamer.h"
32#include "llvm/MC/MCSubtargetInfo.h"
33#include "llvm/MC/TargetRegistry.h"
34#include "llvm/Support/Compiler.h"
35
36using namespace llvm;
37
38#define GET_INSTRINFO_MC_DESC
39#define ENABLE_INSTR_PREDICATE_VERIFIER
40#include "AMDGPUGenInstrInfo.inc"
41
42#define GET_SUBTARGETINFO_MC_DESC
43#include "AMDGPUGenSubtargetInfo.inc"
44
45#define NoSchedModel NoSchedModelR600
46#define GET_SUBTARGETINFO_MC_DESC
47#include "R600GenSubtargetInfo.inc"
48#undef NoSchedModelR600
49
50#define GET_REGINFO_MC_DESC
51#include "AMDGPUGenRegisterInfo.inc"
52
53#define GET_REGINFO_MC_DESC
54#include "R600GenRegisterInfo.inc"
55
56static MCInstrInfo *createAMDGPUMCInstrInfo() {
57 MCInstrInfo *X = new MCInstrInfo();
58 InitAMDGPUMCInstrInfo(II: X);
59 return X;
60}
61
62static MCRegisterInfo *createAMDGPUMCRegisterInfo(const Triple &TT) {
63 MCRegisterInfo *X = new MCRegisterInfo();
64 if (TT.getArch() == Triple::r600)
65 InitR600MCRegisterInfo(RI: X, RA: 0);
66 else
67 InitAMDGPUMCRegisterInfo(RI: X, RA: AMDGPU::PC_REG);
68 return X;
69}
70
71MCRegisterInfo *llvm::createGCNMCRegisterInfo(AMDGPUDwarfFlavour DwarfFlavour) {
72 MCRegisterInfo *X = new MCRegisterInfo();
73 InitAMDGPUMCRegisterInfo(RI: X, RA: AMDGPU::PC_REG, DwarfFlavour, EHFlavour: DwarfFlavour);
74 return X;
75}
76
77static MCSubtargetInfo *
78createAMDGPUMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
79 if (TT.getArch() == Triple::r600)
80 return createR600MCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
81
82 MCSubtargetInfo *STI =
83 createAMDGPUMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
84
85 bool IsWave64 = STI->hasFeature(Feature: AMDGPU::FeatureWavefrontSize64);
86 bool IsWave32 = STI->hasFeature(Feature: AMDGPU::FeatureWavefrontSize32);
87
88 // FIXME: We should error for the default target.
89 if (STI->getFeatureBits().none())
90 STI->ToggleFeature(FB: AMDGPU::FeatureSouthernIslands);
91
92 if (!IsWave64 && !IsWave32) {
93 // If there is no default wave size it must be a generation before gfx10,
94 // these have FeatureWavefrontSize64 in their definition already. For gfx10+
95 // set wave32 as a default.
96 STI->ToggleFeature(FB: AMDGPU::isGFX10Plus(STI: *STI)
97 ? AMDGPU::FeatureWavefrontSize32
98 : AMDGPU::FeatureWavefrontSize64);
99 } else if (IsWave64 && IsWave32) {
100 // The wave size is mutually exclusive. If both somehow end up set, wave32
101 // wins if supported.
102 STI->ToggleFeature(FB: AMDGPU::supportsWave32(STI: *STI)
103 ? AMDGPU::FeatureWavefrontSize64
104 : AMDGPU::FeatureWavefrontSize32);
105
106 // If both wavesizes were manually requested, hack in a feature to permit
107 // assembling modules with mixed wavesizes.
108 STI->ToggleFeature(FB: AMDGPU::FeatureAssemblerPermissiveWavesize);
109 }
110
111 assert((STI->hasFeature(AMDGPU::FeatureWavefrontSize64) !=
112 STI->hasFeature(AMDGPU::FeatureWavefrontSize32)) &&
113 "wavesize features are mutually exclusive");
114
115 return STI;
116}
117
118static MCInstPrinter *createAMDGPUMCInstPrinter(const Triple &T,
119 unsigned SyntaxVariant,
120 const MCAsmInfo &MAI,
121 const MCInstrInfo &MII,
122 const MCRegisterInfo &MRI) {
123 if (T.getArch() == Triple::r600)
124 return new R600InstPrinter(MAI, MII, MRI);
125 return new AMDGPUInstPrinter(MAI, MII, MRI);
126}
127
128static MCTargetStreamer *
129createAMDGPUAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
130 MCInstPrinter *InstPrint) {
131 return new AMDGPUTargetAsmStreamer(S, OS);
132}
133
134static MCTargetStreamer * createAMDGPUObjectTargetStreamer(
135 MCStreamer &S,
136 const MCSubtargetInfo &STI) {
137 return new AMDGPUTargetELFStreamer(S, STI);
138}
139
140static MCTargetStreamer *createAMDGPUNullTargetStreamer(MCStreamer &S) {
141 return new AMDGPUTargetStreamer(S);
142}
143
144static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context,
145 std::unique_ptr<MCAsmBackend> &&MAB,
146 std::unique_ptr<MCObjectWriter> &&OW,
147 std::unique_ptr<MCCodeEmitter> &&Emitter) {
148 return createAMDGPUELFStreamer(T, Context, MAB: std::move(MAB), OW: std::move(OW),
149 Emitter: std::move(Emitter));
150}
151
152namespace llvm {
153namespace AMDGPU {
154
155bool AMDGPUMCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
156 uint64_t Size,
157 uint64_t &Target) const {
158 if (Inst.getNumOperands() == 0 || !Inst.getOperand(i: 0).isImm() ||
159 Info->get(Opcode: Inst.getOpcode()).operands()[0].OperandType !=
160 MCOI::OPERAND_PCREL)
161 return false;
162
163 int64_t Imm = Inst.getOperand(i: 0).getImm();
164 // Our branches take a simm16.
165 Target = SignExtend64<16>(x: Imm) * 4 + Addr + Size;
166 return true;
167}
168
169void AMDGPUMCInstrAnalysis::updateState(const MCInst &Inst,
170 const MCSubtargetInfo *STI,
171 uint64_t Addr) {
172 if (Inst.getOpcode() == AMDGPU::S_SET_VGPR_MSB_gfx12)
173 VgprMSBs = Inst.getOperand(i: 0).getImm() & 0xff;
174 else if (Inst.getOpcode() == AMDGPU::S_SETREG_IMM32_B32_gfx12 &&
175 STI->hasFeature(Feature: AMDGPU::Feature1024AddressableVGPRs)) {
176 VgprMSBs = AMDGPU::convertSetRegImmToVgprMSBs(
177 MI: Inst, HasSetregVGPRMSBFixup: STI->hasFeature(Feature: AMDGPU::FeatureSetregVGPRMSBFixup))
178 .value_or(u: 0);
179 } else if (isTerminator(Inst))
180 VgprMSBs = 0;
181}
182
183} // end namespace AMDGPU
184} // end namespace llvm
185
186static MCInstrAnalysis *createAMDGPUMCInstrAnalysis(const MCInstrInfo *Info) {
187 return new AMDGPU::AMDGPUMCInstrAnalysis(Info);
188}
189
190extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
191LLVMInitializeAMDGPUTargetMC() {
192
193 TargetRegistry::RegisterMCInstrInfo(T&: getTheGCNTarget(), Fn: createAMDGPUMCInstrInfo);
194 TargetRegistry::RegisterMCInstrInfo(T&: getTheR600Target(),
195 Fn: createR600MCInstrInfo);
196 for (Target *T : {&getTheR600Target(), &getTheGCNTarget()}) {
197 RegisterMCAsmInfo<AMDGPUMCAsmInfo> X(*T);
198
199 TargetRegistry::RegisterMCRegInfo(T&: *T, Fn: createAMDGPUMCRegisterInfo);
200 TargetRegistry::RegisterMCSubtargetInfo(T&: *T, Fn: createAMDGPUMCSubtargetInfo);
201 TargetRegistry::RegisterMCInstPrinter(T&: *T, Fn: createAMDGPUMCInstPrinter);
202 TargetRegistry::RegisterMCInstrAnalysis(T&: *T, Fn: createAMDGPUMCInstrAnalysis);
203 TargetRegistry::RegisterMCAsmBackend(T&: *T, Fn: createAMDGPUAsmBackend);
204 TargetRegistry::RegisterELFStreamer(T&: *T, Fn: createMCStreamer);
205 }
206
207 // R600 specific registration
208 TargetRegistry::RegisterMCCodeEmitter(T&: getTheR600Target(),
209 Fn: createR600MCCodeEmitter);
210 TargetRegistry::RegisterObjectTargetStreamer(
211 T&: getTheR600Target(), Fn: createAMDGPUObjectTargetStreamer);
212
213 // GCN specific registration
214 TargetRegistry::RegisterMCCodeEmitter(T&: getTheGCNTarget(),
215 Fn: createAMDGPUMCCodeEmitter);
216
217 TargetRegistry::RegisterAsmTargetStreamer(T&: getTheGCNTarget(),
218 Fn: createAMDGPUAsmTargetStreamer);
219 TargetRegistry::RegisterObjectTargetStreamer(
220 T&: getTheGCNTarget(), Fn: createAMDGPUObjectTargetStreamer);
221 TargetRegistry::RegisterNullTargetStreamer(T&: getTheGCNTarget(),
222 Fn: createAMDGPUNullTargetStreamer);
223}
224