1 //===- MLRegAllocDevelopmentFeatures.cpp - test dev MLRegAlloc features ---===//
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 "../../lib/CodeGen/MLRegAllocEvictAdvisor.h"
10 #include "llvm/Analysis/NoInferenceModelRunner.h"
11 #include "llvm/CodeGen/CodeGenTargetMachineImpl.h"
12 #include "llvm/CodeGen/MachineBasicBlock.h"
13 #include "llvm/CodeGen/MachineFunction.h"
14 #include "llvm/CodeGen/MachineModuleInfo.h"
15 #include "llvm/CodeGen/SlotIndexes.h"
16 #include "llvm/CodeGen/TargetFrameLowering.h"
17 #include "llvm/CodeGen/TargetInstrInfo.h"
18 #include "llvm/CodeGen/TargetLowering.h"
19 #include "llvm/IR/LLVMContext.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/MC/TargetRegistry.h"
22 #include "llvm/Support/Allocator.h"
23 #include "llvm/Support/CodeGen.h"
24 #include "llvm/Support/TargetSelect.h"
25 #include "llvm/Target/TargetOptions.h"
26 #include "llvm/TargetParser/Triple.h"
27 #include "gmock/gmock.h"
28 #include "gtest/gtest.h"
34 using testing::ContainerEq
;
39 #include "MFCommon.inc"
41 struct LRPosInfoIndexes
{
47 class RegAllocDevelopmentFeaturesTest
: public ::Test
{
49 SmallVector
<LRStartEndInfo
>
50 setupOverlapProblem(const SmallVectorImpl
<LRPosInfoIndexes
> &Segments
,
51 simple_ilist
<IndexListEntry
> &IndexList
) {
52 SmallVector
<LRStartEndInfo
> PositionsToReturn
;
53 PositionsToReturn
.reserve(Segments
.size());
54 for (auto CurrentPosIndexInfo
: Segments
) {
55 LRStartEndInfo CurrentPosInfo
= {};
56 CurrentPosInfo
.Pos
= CurrentPosIndexInfo
.PhysReg
;
57 PositionsToReturn
.push_back(CurrentPosInfo
);
59 size_t CurrentSegmentIndex
= 0;
60 size_t CurrentIndex
= 0;
61 while (CurrentSegmentIndex
< Segments
.size()) {
62 auto *CurrentLEMem
= static_cast<IndexListEntry
*>(
63 Allocator
.Allocate(sizeof(IndexListEntry
), alignof(IndexListEntry
)));
64 auto *CurrentListEntry
=
65 new (CurrentLEMem
) IndexListEntry(nullptr, CurrentIndex
);
66 IndexList
.push_back(*CurrentListEntry
);
67 for (size_t CurrentPosInfoIndex
= 0;
68 CurrentPosInfoIndex
< Segments
.size(); ++CurrentPosInfoIndex
) {
69 if ((CurrentIndex
/ SlotIndex::InstrDist
) ==
70 Segments
[CurrentPosInfoIndex
].StartIndex
) {
71 PositionsToReturn
[CurrentPosInfoIndex
].Begin
=
72 SlotIndex(CurrentListEntry
, 0);
73 } else if ((CurrentIndex
/ SlotIndex::InstrDist
) ==
74 Segments
[CurrentPosInfoIndex
].EndIndex
) {
75 PositionsToReturn
[CurrentPosInfoIndex
].End
=
76 SlotIndex(CurrentListEntry
, 0);
77 ++CurrentSegmentIndex
;
80 CurrentIndex
+= SlotIndex::InstrDist
;
82 return PositionsToReturn
;
85 NoInferenceModelRunner
setupModelRunner() {
86 const std::vector
<TensorSpec
> Inputs
{
87 TensorSpec::createSpec
<int64_t>("instructions", InstructionsShape
),
88 TensorSpec::createSpec
<int64_t>("instructions_mapping",
89 InstructionsMappingShape
),
90 TensorSpec::createSpec
<float>("mbb_frequencies", MBBFrequencyShape
),
91 TensorSpec::createSpec
<int64_t>("mbb_mapping", InstructionsShape
)};
93 return NoInferenceModelRunner(Ctx
, Inputs
);
97 getExpectedMappingMatrix(SmallVectorImpl
<LRPosInfoIndexes
> &OverlapSetup
) {
98 std::vector
<int64_t> ExpectedMappingMatrix(
99 NumberOfInterferences
* ModelMaxSupportedInstructionCount
, 0);
100 for (auto NewSegment
: OverlapSetup
) {
101 for (size_t CurrentIndex
= NewSegment
.StartIndex
;
102 CurrentIndex
<= NewSegment
.EndIndex
; ++CurrentIndex
) {
103 ExpectedMappingMatrix
[NewSegment
.PhysReg
*
104 ModelMaxSupportedInstructionCount
+
108 return ExpectedMappingMatrix
;
111 void runOverlapTest(SmallVectorImpl
<LRPosInfoIndexes
> &OverlapSetup
) {
112 simple_ilist
<IndexListEntry
> IndexList
;
113 auto OverlapProblem
= setupOverlapProblem(OverlapSetup
, IndexList
);
114 NoInferenceModelRunner ModelRunner
= setupModelRunner();
116 for (size_t CurrentOverlap
= 0; CurrentOverlap
< OverlapSetup
.size();
118 if (OverlapSetup
[CurrentOverlap
].EndIndex
>
119 OverlapSetup
[MaxIndex
].EndIndex
) {
120 MaxIndex
= CurrentOverlap
;
123 SlotIndex LastIndex
= OverlapProblem
[MaxIndex
].End
;
124 extractInstructionFeatures(
125 OverlapProblem
, &ModelRunner
,
126 [](SlotIndex InputSlot
) -> int { return 0; },
127 [](SlotIndex InputSlot
) -> float { return 0.0f
; },
128 [](SlotIndex InputSlot
) -> MachineBasicBlock
* { return nullptr; }, 0,
130 std::vector
<int64_t> MappingMatrix(
131 ModelRunner
.getTensor
<int64_t>(1),
132 ModelRunner
.getTensor
<int64_t>(1) +
133 NumberOfInterferences
* ModelMaxSupportedInstructionCount
);
134 ASSERT_THAT(MappingMatrix
,
135 ContainerEq(getExpectedMappingMatrix(OverlapSetup
)));
139 BumpPtrAllocator Allocator
;
142 // meta tests to ensure that test setup works correctly
144 TEST_F(RegAllocDevelopmentFeaturesTest
,
145 MetaOverlapInstructionDistancesAreCorrect
) {
146 SmallVector
<LRPosInfoIndexes
, 2> OverlapSetup
;
147 OverlapSetup
.push_back({0, 5, 0});
148 OverlapSetup
.push_back({5, 10, 0});
149 simple_ilist
<IndexListEntry
> IndexList
;
150 auto OverlapProblem
= setupOverlapProblem(OverlapSetup
, IndexList
);
151 ASSERT_EQ(OverlapProblem
[0].End
.distance(OverlapProblem
[1].End
),
152 5 * SlotIndex::InstrDist
);
153 ASSERT_EQ(OverlapProblem
[0].End
.distance(OverlapProblem
[1].Begin
), 0);
156 TEST_F(RegAllocDevelopmentFeaturesTest
, MetaSlotIndicesAreValid
) {
157 SmallVector
<LRPosInfoIndexes
, 1> OverlapSetup
;
158 OverlapSetup
.push_back({0, 10, 0});
159 simple_ilist
<IndexListEntry
> IndexList
;
160 auto OverlapProblem
= setupOverlapProblem(OverlapSetup
, IndexList
);
161 ASSERT_TRUE(OverlapProblem
[0].Begin
.isValid());
162 ASSERT_TRUE(OverlapProblem
[0].End
.isValid());
165 // Testing of feature extraction for per-instruction features
167 TEST_F(RegAllocDevelopmentFeaturesTest
, InstructionOpcodesAreCorrect
) {
168 SmallVector
<LRPosInfoIndexes
, 1> OverlapSetup
;
169 OverlapSetup
.push_back({0, ModelMaxSupportedInstructionCount
- 1, 0});
170 simple_ilist
<IndexListEntry
> IndexList
;
171 auto OverlapProblem
= setupOverlapProblem(OverlapSetup
, IndexList
);
172 NoInferenceModelRunner ModelRunner
= setupModelRunner();
173 SlotIndex LastIndex
= OverlapProblem
[0].End
;
174 SlotIndex FirstIndex
= OverlapProblem
[0].Begin
;
175 extractInstructionFeatures(
176 OverlapProblem
, &ModelRunner
,
177 [FirstIndex
](SlotIndex InputSlot
) -> int {
178 return FirstIndex
.distance(InputSlot
) / SlotIndex::InstrDist
;
180 [](SlotIndex InputSlot
) -> float { return 0.0f
; },
181 [](SlotIndex InputSlot
) -> MachineBasicBlock
* { return nullptr; }, 0, 1,
183 for (size_t CurrentInstructionIndex
= 0;
184 CurrentInstructionIndex
< ModelMaxSupportedInstructionCount
;
185 ++CurrentInstructionIndex
) {
187 (size_t)ModelRunner
.getTensor
<int64_t>(0)[CurrentInstructionIndex
],
188 CurrentInstructionIndex
);
192 TEST_F(RegAllocDevelopmentFeaturesTest
, FullOverlap
) {
193 SmallVector
<LRPosInfoIndexes
, 2> OverlapSetup
;
194 OverlapSetup
.push_back({0, ModelMaxSupportedInstructionCount
- 1, 0});
195 OverlapSetup
.push_back({0, ModelMaxSupportedInstructionCount
- 1, 1});
196 runOverlapTest(OverlapSetup
);
199 TEST_F(RegAllocDevelopmentFeaturesTest
, PartialOverlap
) {
200 SmallVector
<LRPosInfoIndexes
, 2> OverlapSetup
;
201 OverlapSetup
.push_back({0, 20, 0});
202 OverlapSetup
.push_back({15, 30, 1});
203 runOverlapTest(OverlapSetup
);
206 TEST_F(RegAllocDevelopmentFeaturesTest
, PartialOverlapOpposite
) {
207 SmallVector
<LRPosInfoIndexes
, 2> OverlapSetup
;
208 OverlapSetup
.push_back({15, 30, 1});
209 OverlapSetup
.push_back({0, 20, 0});
210 runOverlapTest(OverlapSetup
);
213 TEST_F(RegAllocDevelopmentFeaturesTest
, InternalOverlap
) {
214 SmallVector
<LRPosInfoIndexes
, 2> OverlapSetup
;
215 OverlapSetup
.push_back({0, 30, 0});
216 OverlapSetup
.push_back({10, 20, 1});
217 runOverlapTest(OverlapSetup
);
220 TEST_F(RegAllocDevelopmentFeaturesTest
, TripleInternalOverlap
) {
221 SmallVector
<LRPosInfoIndexes
, 3> OverlapSetup
;
222 OverlapSetup
.push_back({0, 30, 0});
223 OverlapSetup
.push_back({10, 25, 1});
224 OverlapSetup
.push_back({15, 20, 2});
225 runOverlapTest(OverlapSetup
);
228 TEST_F(RegAllocDevelopmentFeaturesTest
, InternalMultiOverlap
) {
229 SmallVector
<LRPosInfoIndexes
, 3> OverlapSetup
;
230 OverlapSetup
.push_back({0, 45, 0});
231 OverlapSetup
.push_back({30, 40, 1});
232 OverlapSetup
.push_back({35, 60, 2});
233 runOverlapTest(OverlapSetup
);
236 TEST_F(RegAllocDevelopmentFeaturesTest
, SingleMBBTest
) {
237 NoInferenceModelRunner ModelRunner
= setupModelRunner();
238 SlotIndex CurrentIndex
;
239 // set index to 1 so we can ensure that the mapping actually get set
240 std::map
<MachineBasicBlock
*, size_t> VisitedMBBs
= {{nullptr, 1}};
242 CurrentIndex
, 0, VisitedMBBs
,
243 [](SlotIndex InputSlot
) -> float { return 1.0f
; }, nullptr, &ModelRunner
,
245 ASSERT_FLOAT_EQ(ModelRunner
.getTensor
<float>(2)[1], 1.0f
);
246 ASSERT_EQ(ModelRunner
.getTensor
<int64_t>(3)[0], 1);
249 TEST_F(RegAllocDevelopmentFeaturesTest
, MBBFullTruncated
) {
250 SmallVector
<LRPosInfoIndexes
, 1> OverlapSetup
;
251 OverlapSetup
.push_back({0, ModelMaxSupportedInstructionCount
- 1, 0});
252 simple_ilist
<IndexListEntry
> IndexList
;
253 auto OverlapProblem
= setupOverlapProblem(OverlapSetup
, IndexList
);
254 NoInferenceModelRunner ModelRunner
= setupModelRunner();
255 SlotIndex LastIndex
= OverlapProblem
[0].End
;
256 SlotIndex FirstIndex
= OverlapProblem
[0].Begin
;
259 Module
Mod("Module", Ctx
);
260 auto MF
= createMachineFunction(Ctx
, Mod
);
261 std::array
<MachineBasicBlock
*, ModelMaxSupportedInstructionCount
>
263 for (size_t I
= 0; I
< ModelMaxSupportedInstructionCount
; ++I
) {
264 MBBsForTest
[I
] = MF
->CreateMachineBasicBlock();
267 extractInstructionFeatures(
268 OverlapProblem
, &ModelRunner
,
269 [](SlotIndex InputSlot
) -> int { return 0; },
270 [FirstIndex
](SlotIndex InputSlot
) -> float {
271 return static_cast<float>(FirstIndex
.distance(InputSlot
) /
272 SlotIndex::InstrDist
);
274 [FirstIndex
, MBBsForTest
](SlotIndex InputSlot
) -> MachineBasicBlock
* {
275 return MBBsForTest
[FirstIndex
.distance(InputSlot
) /
276 SlotIndex::InstrDist
];
278 0, 1, 2, 3, LastIndex
);
279 for (size_t MBBIndex
= 0; MBBIndex
< ModelMaxSupportedMBBCount
; ++MBBIndex
) {
280 ASSERT_FLOAT_EQ(ModelRunner
.getTensor
<float>(2)[MBBIndex
],
281 static_cast<float>(MBBIndex
));
282 ASSERT_EQ(ModelRunner
.getTensor
<int64_t>(3)[MBBIndex
],
283 static_cast<int64_t>(MBBIndex
));
285 // the rest of the mapping values should be zero (truncated to 100 MBBs)
286 for (size_t MBBIndex
= ModelMaxSupportedMBBCount
;
287 MBBIndex
< ModelMaxSupportedInstructionCount
; ++MBBIndex
) {
288 ASSERT_EQ(ModelRunner
.getTensor
<int64_t>(3)[MBBIndex
],
289 static_cast<int64_t>(0));