xref: /llvm-project/llvm/lib/Target/AMDGPU/AMDGPUMIRFormatter.cpp (revision be187369a03bf2df8bdbc76ecd381377b3bb6074)
1 //===- AMDGPUMIRFormatter.cpp ---------------------------------------------===//
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 /// Implementation of AMDGPU overrides of MIRFormatter.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "AMDGPUMIRFormatter.h"
15 #include "SIMachineFunctionInfo.h"
16 
17 using namespace llvm;
18 
19 void AMDGPUMIRFormatter::printImm(raw_ostream &OS, const MachineInstr &MI,
20                       std::optional<unsigned int> OpIdx, int64_t Imm) const {
21 
22   switch (MI.getOpcode()) {
23   case AMDGPU::S_DELAY_ALU:
24     assert(OpIdx == 0);
25     printSDelayAluImm(Imm, OS);
26     break;
27   default:
28     MIRFormatter::printImm(OS, MI, OpIdx, Imm);
29     break;
30   }
31 }
32 
33 /// Implement target specific parsing of immediate mnemonics. The mnemonic is
34 /// a string with a leading dot.
35 bool AMDGPUMIRFormatter::parseImmMnemonic(const unsigned OpCode,
36                               const unsigned OpIdx,
37                               StringRef Src, int64_t &Imm,
38                               ErrorCallbackType ErrorCallback) const
39 {
40 
41   switch (OpCode) {
42   case AMDGPU::S_DELAY_ALU:
43     return parseSDelayAluImmMnemonic(OpIdx, Imm, Src, ErrorCallback);
44   default:
45     break;
46   }
47   return true; // Don't know what this is
48 }
49 
50 void AMDGPUMIRFormatter::printSDelayAluImm(int64_t Imm,
51                                            llvm::raw_ostream &OS) const {
52   // Construct an immediate string to represent the information encoded in the
53   // s_delay_alu immediate.
54   // .id0_<dep>[_skip_<count>_id1<dep>]
55   constexpr int64_t None = 0;
56   constexpr int64_t Same = 0;
57 
58   uint64_t Id0 = (Imm & 0xF);
59   uint64_t Skip = ((Imm >> 4) & 0x7);
60   uint64_t Id1 = ((Imm >> 7) & 0xF);
61   auto Outdep = [&](uint64_t Id) {
62     if (Id == None)
63       OS << "NONE";
64     else if (Id < 5)
65       OS << "VALU_DEP_" << Id;
66     else if (Id < 8)
67       OS << "TRANS32_DEP_" << Id - 4;
68     else
69       OS << "SALU_CYCLE_" << Id - 8;
70   };
71 
72   OS << ".id0_";
73   Outdep(Id0);
74 
75   // If the second inst is "same" and "none", no need to print the rest of the
76   // string.
77   if (Skip == Same && Id1 == None)
78     return;
79 
80   // Encode the second delay specification.
81   OS << "_skip_";
82   if (Skip == 0)
83     OS << "SAME";
84   else if (Skip == 1)
85     OS << "NEXT";
86   else
87     OS << "SKIP_" << Skip - 1;
88 
89   OS << "_id1_";
90   Outdep(Id1);
91 }
92 
93 bool AMDGPUMIRFormatter::parseSDelayAluImmMnemonic(
94     const unsigned int OpIdx, int64_t &Imm, llvm::StringRef &Src,
95     llvm::MIRFormatter::ErrorCallbackType &ErrorCallback) const
96 {
97   assert(OpIdx == 0);
98 
99   Imm = 0;
100   bool Expected = Src.consume_front(".id0_");
101   if (!Expected)
102     return ErrorCallback(Src.begin(), "Expected .id0_");
103 
104   auto ExpectInt = [&](StringRef &Src, int64_t Offset) -> int64_t {
105     int64_t Dep;
106     if (!Src.consumeInteger(10, Dep))
107       return Dep + Offset;
108 
109     return -1;
110   };
111 
112   auto DecodeDelay = [&](StringRef &Src) -> int64_t {
113     if (Src.consume_front("NONE"))
114       return 0;
115     if (Src.consume_front("VALU_DEP_"))
116       return ExpectInt(Src, 0);
117     if (Src.consume_front("TRANS32_DEP_"))
118       return ExpectInt(Src, 4);
119     if (Src.consume_front("SALU_CYCLE_"))
120       return ExpectInt(Src, 8);
121 
122     return -1;
123   };
124 
125   int64_t Delay0 = DecodeDelay(Src);
126   int64_t Skip = 0;
127   int64_t Delay1 = 0;
128   if (Delay0 == -1)
129     return ErrorCallback(Src.begin(), "Could not decode delay0");
130 
131 
132   // Set the Imm so far, to that early return has the correct value.
133   Imm = Delay0;
134 
135   // If that was the end of the string, the second instruction is "same" and
136   // "none"
137   if (Src.begin() == Src.end())
138     return false;
139 
140   Expected = Src.consume_front("_skip_");
141   if (!Expected)
142     return ErrorCallback(Src.begin(), "Expected _skip_");
143 
144 
145   if (Src.consume_front("SAME")) {
146     Skip = 0;
147   } else if (Src.consume_front("NEXT")) {
148     Skip = 1;
149   } else if (Src.consume_front("SKIP_")) {
150     if (Src.consumeInteger(10, Skip)) {
151       return ErrorCallback(Src.begin(), "Expected integer Skip value");
152     }
153     Skip += 1;
154   } else {
155     ErrorCallback(Src.begin(), "Unexpected Skip Value");
156   }
157 
158   Expected = Src.consume_front("_id1_");
159   if (!Expected)
160     return ErrorCallback(Src.begin(), "Expected _id1_");
161 
162   Delay1 = DecodeDelay(Src);
163   if (Delay1 == -1)
164     return ErrorCallback(Src.begin(), "Could not decode delay1");
165 
166   Imm = Imm | (Skip << 4) | (Delay1 << 7);
167   return false;
168 }
169 
170 bool AMDGPUMIRFormatter::parseCustomPseudoSourceValue(
171     StringRef Src, MachineFunction &MF, PerFunctionMIParsingState &PFS,
172     const PseudoSourceValue *&PSV, ErrorCallbackType ErrorCallback) const {
173   SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
174   const AMDGPUTargetMachine &TM =
175       static_cast<const AMDGPUTargetMachine &>(MF.getTarget());
176   if (Src == "GWSResource") {
177     PSV = MFI->getGWSPSV(TM);
178     return false;
179   }
180   llvm_unreachable("unknown MIR custom pseudo source value");
181 }
182