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 StringRef ResolvedCPU = CPU;
83 if (ResolvedCPU.empty())
84 ResolvedCPU = AMDGPU::getArchNameFromSubArch(SubArch: TT.getSubArch());
85
86 MCSubtargetInfo *STI = createAMDGPUMCSubtargetInfoImpl(
87 TT, CPU: ResolvedCPU, /*TuneCPU*/ ResolvedCPU, FS);
88
89 bool IsWave64 = STI->hasFeature(Feature: AMDGPU::FeatureWavefrontSize64);
90 bool IsWave32 = STI->hasFeature(Feature: AMDGPU::FeatureWavefrontSize32);
91
92 // FIXME: We should error for the default target.
93 if (STI->getFeatureBits().none())
94 STI->ToggleFeature(FB: AMDGPU::FeatureSouthernIslands);
95
96 if (!IsWave64 && !IsWave32) {
97 // If there is no default wave size it must be a generation before gfx10,
98 // these have FeatureWavefrontSize64 in their definition already. For gfx10+
99 // set wave32 as a default.
100 STI->ToggleFeature(FB: AMDGPU::isGFX10Plus(STI: *STI)
101 ? AMDGPU::FeatureWavefrontSize32
102 : AMDGPU::FeatureWavefrontSize64);
103 } else if (IsWave64 && IsWave32) {
104 // The wave size is mutually exclusive. If both somehow end up set, wave32
105 // wins if supported.
106 STI->ToggleFeature(FB: AMDGPU::supportsWave32(STI: *STI)
107 ? AMDGPU::FeatureWavefrontSize64
108 : AMDGPU::FeatureWavefrontSize32);
109
110 // If both wavesizes were manually requested, hack in a feature to permit
111 // assembling modules with mixed wavesizes.
112 STI->ToggleFeature(FB: AMDGPU::FeatureAssemblerPermissiveWavesize);
113 }
114
115 assert((STI->hasFeature(AMDGPU::FeatureWavefrontSize64) !=
116 STI->hasFeature(AMDGPU::FeatureWavefrontSize32)) &&
117 "wavesize features are mutually exclusive");
118
119 return STI;
120}
121
122static MCInstPrinter *createAMDGPUMCInstPrinter(const Triple &T,
123 unsigned SyntaxVariant,
124 const MCAsmInfo &MAI,
125 const MCInstrInfo &MII,
126 const MCRegisterInfo &MRI) {
127 if (T.getArch() == Triple::r600)
128 return new R600InstPrinter(MAI, MII, MRI);
129 return new AMDGPUInstPrinter(MAI, MII, MRI);
130}
131
132static MCTargetStreamer *
133createAMDGPUAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
134 MCInstPrinter *InstPrint) {
135 return new AMDGPUTargetAsmStreamer(S, OS);
136}
137
138static MCTargetStreamer * createAMDGPUObjectTargetStreamer(
139 MCStreamer &S,
140 const MCSubtargetInfo &STI) {
141 return new AMDGPUTargetELFStreamer(S, STI);
142}
143
144static MCTargetStreamer *createAMDGPUNullTargetStreamer(MCStreamer &S) {
145 return new AMDGPUTargetStreamer(S);
146}
147
148static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context,
149 std::unique_ptr<MCAsmBackend> &&MAB,
150 std::unique_ptr<MCObjectWriter> &&OW,
151 std::unique_ptr<MCCodeEmitter> &&Emitter) {
152 return createAMDGPUELFStreamer(T, Context, MAB: std::move(MAB), OW: std::move(OW),
153 Emitter: std::move(Emitter));
154}
155
156namespace llvm {
157namespace AMDGPU {
158
159bool AMDGPUMCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
160 uint64_t Size,
161 uint64_t &Target) const {
162 if (Inst.getNumOperands() == 0 || !Inst.getOperand(i: 0).isImm() ||
163 Info->get(Opcode: Inst.getOpcode()).operands()[0].OperandType !=
164 MCOI::OPERAND_PCREL)
165 return false;
166
167 int64_t Imm = Inst.getOperand(i: 0).getImm();
168 // Our branches take a simm16.
169 Target = SignExtend64<16>(x: Imm) * 4 + Addr + Size;
170 return true;
171}
172
173void AMDGPUMCInstrAnalysis::updateState(const MCInst &Inst,
174 const MCSubtargetInfo *STI,
175 uint64_t Addr) {
176 if (Inst.getOpcode() == AMDGPU::S_SET_VGPR_MSB_gfx12)
177 VgprMSBs = Inst.getOperand(i: 0).getImm() & 0xff;
178 else if (Inst.getOpcode() == AMDGPU::S_SETREG_IMM32_B32_gfx12 &&
179 STI->hasFeature(Feature: AMDGPU::Feature1024AddressableVGPRs)) {
180 VgprMSBs = AMDGPU::convertSetRegImmToVgprMSBs(
181 MI: Inst, HasSetregVGPRMSBFixup: STI->hasFeature(Feature: AMDGPU::FeatureSetregVGPRMSBFixup))
182 .value_or(u: 0);
183 } else if (isTerminator(Inst))
184 VgprMSBs = 0;
185}
186
187} // end namespace AMDGPU
188} // end namespace llvm
189
190static MCInstrAnalysis *createAMDGPUMCInstrAnalysis(const MCInstrInfo *Info) {
191 return new AMDGPU::AMDGPUMCInstrAnalysis(Info);
192}
193
194extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
195LLVMInitializeAMDGPUTargetMC() {
196
197 TargetRegistry::RegisterMCInstrInfo(T&: getTheGCNTarget(), Fn: createAMDGPUMCInstrInfo);
198 TargetRegistry::RegisterMCInstrInfo(T&: getTheGCNLegacyTarget(),
199 Fn: createAMDGPUMCInstrInfo);
200 TargetRegistry::RegisterMCInstrInfo(T&: getTheR600Target(),
201 Fn: createR600MCInstrInfo);
202 for (Target *T :
203 {&getTheR600Target(), &getTheGCNTarget(), &getTheGCNLegacyTarget()}) {
204 RegisterMCAsmInfo<AMDGPUMCAsmInfo> X(*T);
205
206 TargetRegistry::RegisterMCRegInfo(T&: *T, Fn: createAMDGPUMCRegisterInfo);
207 TargetRegistry::RegisterMCSubtargetInfo(T&: *T, Fn: createAMDGPUMCSubtargetInfo);
208 TargetRegistry::RegisterMCInstPrinter(T&: *T, Fn: createAMDGPUMCInstPrinter);
209 TargetRegistry::RegisterMCInstrAnalysis(T&: *T, Fn: createAMDGPUMCInstrAnalysis);
210 TargetRegistry::RegisterMCAsmBackend(T&: *T, Fn: createAMDGPUAsmBackend);
211 TargetRegistry::RegisterELFStreamer(T&: *T, Fn: createMCStreamer);
212 }
213
214 // R600 specific registration
215 TargetRegistry::RegisterMCCodeEmitter(T&: getTheR600Target(),
216 Fn: createR600MCCodeEmitter);
217 TargetRegistry::RegisterObjectTargetStreamer(
218 T&: getTheR600Target(), Fn: createAMDGPUObjectTargetStreamer);
219
220 // GCN specific registration
221 for (Target *T : {&getTheGCNTarget(), &getTheGCNLegacyTarget()}) {
222 TargetRegistry::RegisterMCCodeEmitter(T&: *T, Fn: createAMDGPUMCCodeEmitter);
223
224 TargetRegistry::RegisterAsmTargetStreamer(T&: *T,
225 Fn: createAMDGPUAsmTargetStreamer);
226 TargetRegistry::RegisterObjectTargetStreamer(
227 T&: *T, Fn: createAMDGPUObjectTargetStreamer);
228 TargetRegistry::RegisterNullTargetStreamer(T&: *T,
229 Fn: createAMDGPUNullTargetStreamer);
230 }
231}
232