[Clang][MIPS] Send correct architecture for MinGW toolchains (#121042)
[llvm-project.git] / llvm / unittests / Target / AMDGPU / AMDGPUUnitTests.cpp
blobd0a3cfa84ee0187d160d2ab8b0c1f409b1860584
1 //===--------- llvm/unittests/Target/AMDGPU/AMDGPUUnitTests.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 //===----------------------------------------------------------------------===//
9 #include "AMDGPUUnitTests.h"
10 #include "AMDGPUTargetMachine.h"
11 #include "GCNSubtarget.h"
12 #include "llvm/MC/TargetRegistry.h"
13 #include "llvm/Support/TargetSelect.h"
14 #include "llvm/TargetParser/TargetParser.h"
15 #include "gtest/gtest.h"
17 #include "AMDGPUGenSubtargetInfo.inc"
19 using namespace llvm;
21 std::once_flag flag;
23 void InitializeAMDGPUTarget() {
24 std::call_once(flag, []() {
25 LLVMInitializeAMDGPUTargetInfo();
26 LLVMInitializeAMDGPUTarget();
27 LLVMInitializeAMDGPUTargetMC();
28 });
31 std::unique_ptr<const GCNTargetMachine>
32 llvm::createAMDGPUTargetMachine(std::string TStr, StringRef CPU, StringRef FS) {
33 InitializeAMDGPUTarget();
35 std::string Error;
36 const Target *T = TargetRegistry::lookupTarget(TStr, Error);
37 if (!T)
38 return nullptr;
40 TargetOptions Options;
41 return std::unique_ptr<GCNTargetMachine>(
42 static_cast<GCNTargetMachine *>(T->createTargetMachine(
43 TStr, CPU, FS, Options, std::nullopt, std::nullopt)));
46 static cl::opt<bool> PrintCpuRegLimits(
47 "print-cpu-reg-limits", cl::NotHidden, cl::init(false),
48 cl::desc("force printing per AMDGPU CPU register limits"));
50 static bool checkMinMax(std::stringstream &OS, unsigned Occ, unsigned MinOcc,
51 unsigned MaxOcc,
52 std::function<unsigned(unsigned)> GetOcc,
53 std::function<unsigned(unsigned)> GetMinGPRs,
54 std::function<unsigned(unsigned)> GetMaxGPRs) {
55 bool MinValid = true, MaxValid = true, RangeValid = true;
56 unsigned MinGPRs = GetMinGPRs(Occ);
57 unsigned MaxGPRs = GetMaxGPRs(Occ);
58 unsigned RealOcc;
60 if (MinGPRs >= MaxGPRs)
61 RangeValid = false;
62 else {
63 RealOcc = GetOcc(MinGPRs);
64 for (unsigned NumRegs = MinGPRs + 1; NumRegs <= MaxGPRs; ++NumRegs) {
65 if (RealOcc != GetOcc(NumRegs)) {
66 RangeValid = false;
67 break;
72 if (RangeValid && RealOcc > MinOcc && RealOcc <= MaxOcc) {
73 if (MinGPRs > 0 && GetOcc(MinGPRs - 1) <= RealOcc)
74 MinValid = false;
76 if (GetOcc(MaxGPRs + 1) >= RealOcc)
77 MaxValid = false;
80 std::stringstream MinStr;
81 MinStr << (MinValid ? ' ' : '<') << ' ' << std::setw(3) << MinGPRs << " (O"
82 << GetOcc(MinGPRs) << ") " << (RangeValid ? ' ' : 'R');
84 OS << std::left << std::setw(15) << MinStr.str() << std::setw(3) << MaxGPRs
85 << " (O" << GetOcc(MaxGPRs) << ')' << (MaxValid ? "" : " >");
87 return MinValid && MaxValid && RangeValid;
90 static const std::pair<StringRef, StringRef>
91 EmptyFS = {"", ""},
92 W32FS = {"+wavefrontsize32", "w32"},
93 W64FS = {"+wavefrontsize64", "w64"};
95 using TestFuncTy =
96 function_ref<bool(std::stringstream &, unsigned, const GCNSubtarget &)>;
98 static bool testAndRecord(std::stringstream &Table, const GCNSubtarget &ST,
99 TestFuncTy test) {
100 bool Success = true;
101 unsigned MaxOcc = ST.getMaxWavesPerEU();
102 for (unsigned Occ = MaxOcc; Occ > 0; --Occ) {
103 Table << std::right << std::setw(3) << Occ << " ";
104 Success = test(Table, Occ, ST) && Success;
105 Table << '\n';
107 return Success;
110 static void testGPRLimits(const char *RegName, bool TestW32W64,
111 TestFuncTy test) {
112 SmallVector<StringRef> CPUs;
113 AMDGPU::fillValidArchListAMDGCN(CPUs);
115 std::map<std::string, SmallVector<std::string>> TablePerCPUs;
116 for (auto CPUName : CPUs) {
117 auto CanonCPUName =
118 AMDGPU::getArchNameAMDGCN(AMDGPU::parseArchAMDGCN(CPUName));
120 auto *FS = &EmptyFS;
121 while (true) {
122 auto TM = createAMDGPUTargetMachine("amdgcn-amd-", CPUName, FS->first);
123 if (!TM)
124 break;
126 GCNSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
127 std::string(TM->getTargetFeatureString()), *TM);
129 if (TestW32W64 &&
130 ST.getFeatureBits().test(AMDGPU::FeatureWavefrontSize32))
131 FS = &W32FS;
133 std::stringstream Table;
134 bool Success = testAndRecord(Table, ST, test);
135 if (!Success || PrintCpuRegLimits)
136 TablePerCPUs[Table.str()].push_back((CanonCPUName + FS->second).str());
138 if (FS != &W32FS)
139 break;
141 FS = &W64FS;
144 std::stringstream OS;
145 for (auto &P : TablePerCPUs) {
146 for (auto &CPUName : P.second)
147 OS << ' ' << CPUName;
148 OS << ":\nOcc Min" << RegName << " Max" << RegName << '\n'
149 << P.first << '\n';
151 auto ErrStr = OS.str();
152 EXPECT_TRUE(ErrStr.empty()) << ErrStr;
155 TEST(AMDGPU, TestVGPRLimitsPerOccupancy) {
156 auto test = [](std::stringstream &OS, unsigned Occ, const GCNSubtarget &ST) {
157 unsigned MaxVGPRNum = ST.getAddressableNumVGPRs();
158 return checkMinMax(
159 OS, Occ, ST.getOccupancyWithNumVGPRs(MaxVGPRNum), ST.getMaxWavesPerEU(),
160 [&](unsigned NumGPRs) { return ST.getOccupancyWithNumVGPRs(NumGPRs); },
161 [&](unsigned Occ) { return ST.getMinNumVGPRs(Occ); },
162 [&](unsigned Occ) { return ST.getMaxNumVGPRs(Occ); });
165 testGPRLimits("VGPR", true, test);