1 //===--------- llvm/unittests/Target/AMDGPU/AMDGPUUnitTests.cpp -----------===//
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
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"
23 void InitializeAMDGPUTarget() {
24 std::call_once(flag
, []() {
25 LLVMInitializeAMDGPUTargetInfo();
26 LLVMInitializeAMDGPUTarget();
27 LLVMInitializeAMDGPUTargetMC();
31 std::unique_ptr
<const GCNTargetMachine
>
32 llvm::createAMDGPUTargetMachine(std::string TStr
, StringRef CPU
, StringRef FS
) {
33 InitializeAMDGPUTarget();
36 const Target
*T
= TargetRegistry::lookupTarget(TStr
, Error
);
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
,
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
);
60 if (MinGPRs
>= MaxGPRs
)
63 RealOcc
= GetOcc(MinGPRs
);
64 for (unsigned NumRegs
= MinGPRs
+ 1; NumRegs
<= MaxGPRs
; ++NumRegs
) {
65 if (RealOcc
!= GetOcc(NumRegs
)) {
72 if (RangeValid
&& RealOcc
> MinOcc
&& RealOcc
<= MaxOcc
) {
73 if (MinGPRs
> 0 && GetOcc(MinGPRs
- 1) <= RealOcc
)
76 if (GetOcc(MaxGPRs
+ 1) >= RealOcc
)
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
>
92 W32FS
= {"+wavefrontsize32", "w32"},
93 W64FS
= {"+wavefrontsize64", "w64"};
96 function_ref
<bool(std::stringstream
&, unsigned, const GCNSubtarget
&)>;
98 static bool testAndRecord(std::stringstream
&Table
, const GCNSubtarget
&ST
,
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
;
110 static void testGPRLimits(const char *RegName
, bool TestW32W64
,
112 SmallVector
<StringRef
> CPUs
;
113 AMDGPU::fillValidArchListAMDGCN(CPUs
);
115 std::map
<std::string
, SmallVector
<std::string
>> TablePerCPUs
;
116 for (auto CPUName
: CPUs
) {
118 AMDGPU::getArchNameAMDGCN(AMDGPU::parseArchAMDGCN(CPUName
));
122 auto TM
= createAMDGPUTargetMachine("amdgcn-amd-", CPUName
, FS
->first
);
126 GCNSubtarget
ST(TM
->getTargetTriple(), std::string(TM
->getTargetCPU()),
127 std::string(TM
->getTargetFeatureString()), *TM
);
130 ST
.getFeatureBits().test(AMDGPU::FeatureWavefrontSize32
))
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());
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'
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();
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
);