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