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