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