blob: e1a95595aa6b4c2cacd39783f294d4f8b3551339 [file] [log] [blame]
Matt Arsenaultd82c1832013-11-10 01:03:59 +00001//===-- AMDGPUAsmPrinter.h - Print AMDGPU assembly code ---------*- C++ -*-===//
Tom Stellard75aadc22012-12-11 21:25:42 +00002//
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
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000011/// AMDGPU Assembly printer class.
Tom Stellard75aadc22012-12-11 21:25:42 +000012//
13//===----------------------------------------------------------------------===//
14
Matt Arsenault6b6a2c32016-03-11 08:00:27 +000015#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUASMPRINTER_H
16#define LLVM_LIB_TARGET_AMDGPU_AMDGPUASMPRINTER_H
Tom Stellard75aadc22012-12-11 21:25:42 +000017
Yaxun Liu1a14bfa2017-03-27 14:04:01 +000018#include "AMDGPU.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "AMDKernelCodeT.h"
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +000020#include "MCTargetDesc/AMDGPUHSAMetadataStreamer.h"
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000021#include "llvm/ADT/StringRef.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000022#include "llvm/CodeGen/AsmPrinter.h"
Konstantin Zhuravlyov00f2cb12018-06-12 18:02:46 +000023#include "llvm/Support/AMDHSAKernelDescriptor.h"
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000024#include <cstddef>
25#include <cstdint>
26#include <limits>
27#include <memory>
28#include <string>
Tom Stellarded699252013-10-12 05:02:51 +000029#include <vector>
Tom Stellard75aadc22012-12-11 21:25:42 +000030
31namespace llvm {
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000032
Stanislav Mekhanoshin1c538422018-05-25 17:25:12 +000033class AMDGPUMachineFunction;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +000034class AMDGPUTargetStreamer;
Matt Arsenault11f74022016-10-06 17:19:11 +000035class MCOperand;
Matt Arsenaultb03dd8d2017-05-02 17:14:00 +000036class SISubtarget;
Tom Stellard75aadc22012-12-11 21:25:42 +000037
Matt Arsenault6b6a2c32016-03-11 08:00:27 +000038class AMDGPUAsmPrinter final : public AsmPrinter {
Matt Arsenault89cc49f2013-12-05 05:15:35 +000039private:
Matt Arsenaultb03dd8d2017-05-02 17:14:00 +000040 // Track resource usage for callee functions.
41 struct SIFunctionResourceInfo {
42 // Track the number of explicitly used VGPRs. Special registers reserved at
43 // the end are tracked separately.
44 int32_t NumVGPR = 0;
45 int32_t NumExplicitSGPR = 0;
Matt Arsenault9ba465a2017-11-14 20:33:14 +000046 uint64_t PrivateSegmentSize = 0;
Matt Arsenaultb03dd8d2017-05-02 17:14:00 +000047 bool UsesVCC = false;
48 bool UsesFlatScratch = false;
49 bool HasDynamicallySizedStack = false;
50 bool HasRecursion = false;
51
52 int32_t getTotalNumSGPRs(const SISubtarget &ST) const;
53 };
54
55 // Track resource usage for kernels / entry functions.
Matt Arsenault89cc49f2013-12-05 05:15:35 +000056 struct SIProgramInfo {
Matt Arsenault0989d512014-06-26 17:22:30 +000057 // Fields set in PGM_RSRC1 pm4 packet.
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000058 uint32_t VGPRBlocks = 0;
59 uint32_t SGPRBlocks = 0;
60 uint32_t Priority = 0;
61 uint32_t FloatMode = 0;
62 uint32_t Priv = 0;
63 uint32_t DX10Clamp = 0;
64 uint32_t DebugMode = 0;
65 uint32_t IEEEMode = 0;
Matt Arsenault9ba465a2017-11-14 20:33:14 +000066 uint64_t ScratchSize = 0;
Matt Arsenault0989d512014-06-26 17:22:30 +000067
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000068 uint64_t ComputePGMRSrc1 = 0;
Tom Stellard4df465b2014-12-02 21:28:53 +000069
70 // Fields set in PGM_RSRC2 pm4 packet.
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000071 uint32_t LDSBlocks = 0;
72 uint32_t ScratchBlocks = 0;
Tom Stellard4df465b2014-12-02 21:28:53 +000073
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000074 uint64_t ComputePGMRSrc2 = 0;
Tom Stellard4df465b2014-12-02 21:28:53 +000075
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000076 uint32_t NumVGPR = 0;
77 uint32_t NumSGPR = 0;
Matt Arsenaulta3566f22017-04-17 19:48:30 +000078 uint32_t LDSSize = 0;
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000079 bool FlatUsed = false;
Matt Arsenault3f981402014-09-15 15:41:53 +000080
Konstantin Zhuravlyov1d650262016-09-06 20:22:28 +000081 // Number of SGPRs that meets number of waves per execution unit request.
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000082 uint32_t NumSGPRsForWavesPerEU = 0;
Konstantin Zhuravlyov1d650262016-09-06 20:22:28 +000083
84 // Number of VGPRs that meets number of waves per execution unit request.
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000085 uint32_t NumVGPRsForWavesPerEU = 0;
Konstantin Zhuravlyov1d650262016-09-06 20:22:28 +000086
Konstantin Zhuravlyov71515e52016-04-26 17:24:40 +000087 // If ReservedVGPRCount is 0 then must be 0. Otherwise, this is the first
88 // fixed VGPR number reserved.
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000089 uint16_t ReservedVGPRFirst = 0;
Konstantin Zhuravlyov1d650262016-09-06 20:22:28 +000090
Konstantin Zhuravlyov71515e52016-04-26 17:24:40 +000091 // The number of consecutive VGPRs reserved.
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000092 uint16_t ReservedVGPRCount = 0;
Konstantin Zhuravlyov1d99c4d2016-04-26 15:43:14 +000093
Konstantin Zhuravlyovf2f3d142016-06-25 03:11:28 +000094 // Fixed SGPR number used to hold wave scratch offset for entire kernel
Eugene Zelenkoa63528c2017-01-23 23:41:16 +000095 // execution, or std::numeric_limits<uint16_t>::max() if the register is not
96 // used or not known.
Eugene Zelenko734bb7b2017-01-20 17:52:16 +000097 uint16_t DebuggerWavefrontPrivateSegmentOffsetSGPR =
98 std::numeric_limits<uint16_t>::max();
Konstantin Zhuravlyov1d650262016-09-06 20:22:28 +000099
Konstantin Zhuravlyovf2f3d142016-06-25 03:11:28 +0000100 // Fixed SGPR number of the first 4 SGPRs used to hold scratch V# for entire
Eugene Zelenkoa63528c2017-01-23 23:41:16 +0000101 // kernel execution, or std::numeric_limits<uint16_t>::max() if the register
102 // is not used or not known.
Eugene Zelenko734bb7b2017-01-20 17:52:16 +0000103 uint16_t DebuggerPrivateSegmentBufferSGPR =
104 std::numeric_limits<uint16_t>::max();
Konstantin Zhuravlyovf2f3d142016-06-25 03:11:28 +0000105
Matt Arsenaultb03dd8d2017-05-02 17:14:00 +0000106 // Whether there is recursion, dynamic allocas, indirect calls or some other
107 // reason there may be statically unknown stack usage.
108 bool DynamicCallStack = false;
109
Matt Arsenault0989d512014-06-26 17:22:30 +0000110 // Bonus information for debugging.
Eugene Zelenko734bb7b2017-01-20 17:52:16 +0000111 bool VCCUsed = false;
Eugene Zelenko734bb7b2017-01-20 17:52:16 +0000112
113 SIProgramInfo() = default;
Matt Arsenault89cc49f2013-12-05 05:15:35 +0000114 };
115
Matt Arsenaultb03dd8d2017-05-02 17:14:00 +0000116 SIProgramInfo CurrentProgramInfo;
117 DenseMap<const Function *, SIFunctionResourceInfo> CallGraphResourceInfo;
Konstantin Zhuravlyov516651b2017-10-11 22:59:35 +0000118
119 AMDGPU::HSAMD::MetadataStreamer HSAMetadataStream;
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +0000120 std::map<uint32_t, uint32_t> PALMetadataMap;
Matt Arsenaultb03dd8d2017-05-02 17:14:00 +0000121
Matt Arsenaulta3566f22017-04-17 19:48:30 +0000122 uint64_t getFunctionCodeSize(const MachineFunction &MF) const;
Matt Arsenaultb03dd8d2017-05-02 17:14:00 +0000123 SIFunctionResourceInfo analyzeResourceUsage(const MachineFunction &MF) const;
124
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +0000125 void readPALMetadata(Module &M);
Matt Arsenaultb03dd8d2017-05-02 17:14:00 +0000126 void getSIProgramInfo(SIProgramInfo &Out, const MachineFunction &MF);
Konstantin Zhuravlyovca0e7f62017-03-22 22:54:39 +0000127 void getAmdKernelCode(amd_kernel_code_t &Out, const SIProgramInfo &KernelInfo,
128 const MachineFunction &MF) const;
Matt Arsenaultd32dbb62014-07-13 03:06:43 +0000129 void findNumUsedRegistersSI(const MachineFunction &MF,
Matt Arsenault89cc49f2013-12-05 05:15:35 +0000130 unsigned &NumSGPR,
131 unsigned &NumVGPR) const;
132
Konstantin Zhuravlyova01d8b02017-10-14 19:03:51 +0000133 AMDGPU::HSAMD::Kernel::CodeProps::Metadata getHSACodeProps(
134 const MachineFunction &MF,
135 const SIProgramInfo &ProgramInfo) const;
136 AMDGPU::HSAMD::Kernel::DebugProps::Metadata getHSADebugProps(
137 const MachineFunction &MF,
138 const SIProgramInfo &ProgramInfo) const;
139
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000140 /// Emit register usage information so that the GPU driver
Matt Arsenault89cc49f2013-12-05 05:15:35 +0000141 /// can correctly setup the GPU state.
Konstantin Zhuravlyovc3beb6a2017-10-11 22:41:09 +0000142 void EmitProgramInfoSI(const MachineFunction &MF,
143 const SIProgramInfo &KernelInfo);
144 void EmitPALMetadata(const MachineFunction &MF,
145 const SIProgramInfo &KernelInfo);
Matt Arsenaultb03dd8d2017-05-02 17:14:00 +0000146 void emitCommonFunctionComments(uint32_t NumVGPR,
147 uint32_t NumSGPR,
Matt Arsenault9ba465a2017-11-14 20:33:14 +0000148 uint64_t ScratchSize,
Stanislav Mekhanoshin1c538422018-05-25 17:25:12 +0000149 uint64_t CodeSize,
150 const AMDGPUMachineFunction* MFI);
Tom Stellard75aadc22012-12-11 21:25:42 +0000151
Konstantin Zhuravlyov00f2cb12018-06-12 18:02:46 +0000152 uint16_t getAmdhsaKernelCodeProperties(
153 const MachineFunction &MF) const;
154
155 amdhsa::kernel_descriptor_t getAmdhsaKernelDescriptor(
156 const MachineFunction &MF,
157 const SIProgramInfo &PI) const;
158
Tom Stellard75aadc22012-12-11 21:25:42 +0000159public:
David Blaikie94598322015-01-18 20:29:04 +0000160 explicit AMDGPUAsmPrinter(TargetMachine &TM,
161 std::unique_ptr<MCStreamer> Streamer);
Tom Stellard75aadc22012-12-11 21:25:42 +0000162
Mehdi Amini117296c2016-10-01 02:56:57 +0000163 StringRef getPassName() const override;
Tom Stellard75aadc22012-12-11 21:25:42 +0000164
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000165 const MCSubtargetInfo* getSTI() const;
166
Konstantin Zhuravlyov8c18f5b2017-10-14 22:16:26 +0000167 AMDGPUTargetStreamer* getTargetStreamer() const;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000168
Matt Arsenaultb03dd8d2017-05-02 17:14:00 +0000169 bool doFinalization(Module &M) override;
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000170 bool runOnMachineFunction(MachineFunction &MF) override;
171
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000172 /// Wrapper for MCInstLowering.lowerOperand() for the tblgen'erated
Matt Arsenault11f74022016-10-06 17:19:11 +0000173 /// pseudo lowering.
174 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const;
175
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000176 /// Lower the specified LLVM Constant to an MCExpr.
Yaxun Liu8f844f32017-02-07 00:43:21 +0000177 /// The AsmPrinter::lowerConstantof does not know how to lower
178 /// addrspacecast, therefore they should be lowered by this function.
179 const MCExpr *lowerConstant(const Constant *CV) override;
180
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000181 /// tblgen'erated driver function for lowering simple MI->MC pseudo
Matt Arsenault11f74022016-10-06 17:19:11 +0000182 /// instructions.
183 bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
184 const MachineInstr *MI);
185
Tom Stellard75aadc22012-12-11 21:25:42 +0000186 /// Implemented in AMDGPUMCInstLower.cpp
Craig Topper5656db42014-04-29 07:57:24 +0000187 void EmitInstruction(const MachineInstr *MI) override;
Tom Stellarded699252013-10-12 05:02:51 +0000188
Tom Stellardf151a452015-06-26 21:14:58 +0000189 void EmitFunctionBodyStart() override;
190
Konstantin Zhuravlyov00f2cb12018-06-12 18:02:46 +0000191 void EmitFunctionBodyEnd() override;
192
Tom Stellard1e1b05d2015-11-06 11:45:14 +0000193 void EmitFunctionEntryLabel() override;
194
Tim Renoufcead41d2017-12-08 14:09:34 +0000195 void EmitBasicBlockStart(const MachineBasicBlock &MBB) const override;
196
Tom Stellarde3b5aea2015-12-02 17:00:42 +0000197 void EmitGlobalVariable(const GlobalVariable *GV) override;
198
Tom Stellardf4218372016-01-12 17:18:17 +0000199 void EmitStartOfAsmFile(Module &M) override;
200
Konstantin Zhuravlyov7498cd62017-03-22 22:32:22 +0000201 void EmitEndOfAsmFile(Module &M) override;
202
Matt Arsenault6bc43d82016-10-06 16:20:41 +0000203 bool isBlockOnlyReachableByFallthrough(
204 const MachineBasicBlock *MBB) const override;
205
Tom Stellardd7e6f132015-04-08 01:09:26 +0000206 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
207 unsigned AsmVariant, const char *ExtraCode,
Tom Stellard80e169a2015-04-08 02:07:05 +0000208 raw_ostream &O) override;
Tom Stellardd7e6f132015-04-08 01:09:26 +0000209
Tom Stellarded699252013-10-12 05:02:51 +0000210protected:
Tim Renoufcead41d2017-12-08 14:09:34 +0000211 mutable std::vector<std::string> DisasmLines, HexLines;
212 mutable size_t DisasmLineMaxLen;
Yaxun Liu1a14bfa2017-03-27 14:04:01 +0000213 AMDGPUAS AMDGPUASI;
Tom Stellard75aadc22012-12-11 21:25:42 +0000214};
215
Eugene Zelenko734bb7b2017-01-20 17:52:16 +0000216} // end namespace llvm
Tom Stellard75aadc22012-12-11 21:25:42 +0000217
Eugene Zelenko734bb7b2017-01-20 17:52:16 +0000218#endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUASMPRINTER_H