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/SlotIndexes.h"
12 #include "llvm/IR/LLVMContext.h"
13 #include "llvm/Support/Allocator.h"
14 #include "llvm/Support/CodeGen.h"
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
20 using testing::ContainerEq
;
23 struct LRPosInfoIndexes
{
29 class RegallocDevelopmentFeaturesTest
: public ::Test
{
31 SmallVector
<LRStartEndInfo
>
32 setupOverlapProblem(const SmallVectorImpl
<LRPosInfoIndexes
> &Segments
,
33 ilist
<IndexListEntry
> &IndexList
) {
34 SmallVector
<LRStartEndInfo
> PositionsToReturn
;
35 PositionsToReturn
.reserve(Segments
.size());
36 for (auto CurrentPosIndexInfo
: Segments
) {
37 LRStartEndInfo CurrentPosInfo
= {};
38 CurrentPosInfo
.Pos
= CurrentPosIndexInfo
.PhysReg
;
39 PositionsToReturn
.push_back(CurrentPosInfo
);
41 size_t CurrentSegmentIndex
= 0;
42 size_t CurrentIndex
= 0;
43 while (CurrentSegmentIndex
< Segments
.size()) {
44 auto *CurrentLEMem
= static_cast<IndexListEntry
*>(
45 Allocator
.Allocate(sizeof(IndexListEntry
), alignof(IndexListEntry
)));
46 auto *CurrentListEntry
=
47 new (CurrentLEMem
) IndexListEntry(nullptr, CurrentIndex
);
48 IndexList
.push_back(CurrentListEntry
);
49 for (size_t CurrentPosInfoIndex
= 0;
50 CurrentPosInfoIndex
< Segments
.size(); ++CurrentPosInfoIndex
) {
51 if ((CurrentIndex
/ SlotIndex::InstrDist
) ==
52 Segments
[CurrentPosInfoIndex
].StartIndex
) {
53 PositionsToReturn
[CurrentPosInfoIndex
].Begin
=
54 SlotIndex(CurrentListEntry
, 0);
55 } else if ((CurrentIndex
/ SlotIndex::InstrDist
) ==
56 Segments
[CurrentPosInfoIndex
].EndIndex
) {
57 PositionsToReturn
[CurrentPosInfoIndex
].End
=
58 SlotIndex(CurrentListEntry
, 0);
59 ++CurrentSegmentIndex
;
62 CurrentIndex
+= SlotIndex::InstrDist
;
64 return PositionsToReturn
;
67 NoInferenceModelRunner
setupModelRunner() {
68 const std::vector
<TensorSpec
> Inputs
{
69 TensorSpec::createSpec
<int64_t>("instructions", InstructionsShape
),
70 TensorSpec::createSpec
<int64_t>("instructions_mapping",
71 InstructionsMappingShape
)};
73 return NoInferenceModelRunner(Ctx
, Inputs
);
77 getExpectedMappingMatrix(SmallVectorImpl
<LRPosInfoIndexes
> &OverlapSetup
) {
78 std::vector
<int64_t> ExpectedMappingMatrix(
79 NumberOfInterferences
* ModelMaxSupportedInstructionCount
, 0);
80 for (auto NewSegment
: OverlapSetup
) {
81 for (size_t CurrentIndex
= NewSegment
.StartIndex
;
82 CurrentIndex
<= NewSegment
.EndIndex
; ++CurrentIndex
) {
83 ExpectedMappingMatrix
[NewSegment
.PhysReg
*
84 ModelMaxSupportedInstructionCount
+
88 return ExpectedMappingMatrix
;
91 void runOverlapTest(SmallVectorImpl
<LRPosInfoIndexes
> &OverlapSetup
) {
92 ilist
<IndexListEntry
> IndexList
;
93 auto OverlapProblem
= setupOverlapProblem(OverlapSetup
, IndexList
);
94 NoInferenceModelRunner ModelRunner
= setupModelRunner();
96 for (size_t CurrentOverlap
= 0; CurrentOverlap
< OverlapSetup
.size();
98 if (OverlapSetup
[CurrentOverlap
].EndIndex
>
99 OverlapSetup
[MaxIndex
].EndIndex
) {
100 MaxIndex
= CurrentOverlap
;
103 SlotIndex LastIndex
= OverlapProblem
[MaxIndex
].End
;
104 extractInstructionFeatures(
105 OverlapProblem
, &ModelRunner
,
106 [](SlotIndex InputSlot
) -> int { return 0; }, 0, 1, LastIndex
);
107 std::vector
<int64_t> MappingMatrix(
108 ModelRunner
.getTensor
<int64_t>(1),
109 ModelRunner
.getTensor
<int64_t>(1) +
110 NumberOfInterferences
* ModelMaxSupportedInstructionCount
);
111 ASSERT_THAT(MappingMatrix
,
112 ContainerEq(getExpectedMappingMatrix(OverlapSetup
)));
113 IndexList
.clearAndLeakNodesUnsafely();
116 BumpPtrAllocator Allocator
;
119 // meta tests to ensure that test setup works correctly
121 TEST_F(RegallocDevelopmentFeaturesTest
,
122 MetaOverlapInstructionDistancesAreCorrect
) {
123 SmallVector
<LRPosInfoIndexes
, 2> OverlapSetup
;
124 OverlapSetup
.push_back({0, 5, 0});
125 OverlapSetup
.push_back({5, 10, 0});
126 ilist
<IndexListEntry
> IndexList
;
127 auto OverlapProblem
= setupOverlapProblem(OverlapSetup
, IndexList
);
128 ASSERT_EQ(OverlapProblem
[0].End
.distance(OverlapProblem
[1].End
),
129 5 * SlotIndex::InstrDist
);
130 ASSERT_EQ(OverlapProblem
[0].End
.distance(OverlapProblem
[1].Begin
), 0);
133 TEST_F(RegallocDevelopmentFeaturesTest
, MetaSlotIndicesAreValid
) {
134 SmallVector
<LRPosInfoIndexes
, 1> OverlapSetup
;
135 OverlapSetup
.push_back({0, 10, 0});
136 ilist
<IndexListEntry
> IndexList
;
137 auto OverlapProblem
= setupOverlapProblem(OverlapSetup
, IndexList
);
138 ASSERT_TRUE(OverlapProblem
[0].Begin
.isValid());
139 ASSERT_TRUE(OverlapProblem
[0].End
.isValid());
142 // Testing of feature extraction for per-instruction features
144 TEST_F(RegallocDevelopmentFeaturesTest
, InstructionOpcodesAreCorrect
) {
145 SmallVector
<LRPosInfoIndexes
, 1> OverlapSetup
;
146 OverlapSetup
.push_back({0, ModelMaxSupportedInstructionCount
- 1, 0});
147 ilist
<IndexListEntry
> IndexList
;
148 auto OverlapProblem
= setupOverlapProblem(OverlapSetup
, IndexList
);
149 NoInferenceModelRunner ModelRunner
= setupModelRunner();
150 SlotIndex LastIndex
= OverlapProblem
[0].End
;
151 SlotIndex FirstIndex
= OverlapProblem
[0].Begin
;
152 extractInstructionFeatures(
153 OverlapProblem
, &ModelRunner
,
154 [FirstIndex
](SlotIndex InputSlot
) -> int {
155 return FirstIndex
.distance(InputSlot
) / SlotIndex::InstrDist
;
158 for (size_t CurrentInstructionIndex
= 0;
159 CurrentInstructionIndex
< ModelMaxSupportedInstructionCount
;
160 ++CurrentInstructionIndex
) {
162 (size_t)ModelRunner
.getTensor
<int64_t>(0)[CurrentInstructionIndex
],
163 CurrentInstructionIndex
);
167 TEST_F(RegallocDevelopmentFeaturesTest
, FullOverlap
) {
168 SmallVector
<LRPosInfoIndexes
, 2> OverlapSetup
;
169 OverlapSetup
.push_back({0, ModelMaxSupportedInstructionCount
- 1, 0});
170 OverlapSetup
.push_back({0, ModelMaxSupportedInstructionCount
- 1, 1});
171 runOverlapTest(OverlapSetup
);
174 TEST_F(RegallocDevelopmentFeaturesTest
, PartialOverlap
) {
175 SmallVector
<LRPosInfoIndexes
, 2> OverlapSetup
;
176 OverlapSetup
.push_back({0, 20, 0});
177 OverlapSetup
.push_back({15, 30, 1});
178 runOverlapTest(OverlapSetup
);
181 TEST_F(RegallocDevelopmentFeaturesTest
, PartialOverlapOpposite
) {
182 SmallVector
<LRPosInfoIndexes
, 2> OverlapSetup
;
183 OverlapSetup
.push_back({15, 30, 1});
184 OverlapSetup
.push_back({0, 20, 0});
185 runOverlapTest(OverlapSetup
);
188 TEST_F(RegallocDevelopmentFeaturesTest
, InternalOverlap
) {
189 SmallVector
<LRPosInfoIndexes
, 2> OverlapSetup
;
190 OverlapSetup
.push_back({0, 30, 0});
191 OverlapSetup
.push_back({10, 20, 1});
192 runOverlapTest(OverlapSetup
);
195 TEST_F(RegallocDevelopmentFeaturesTest
, TripleInternalOverlap
) {
196 SmallVector
<LRPosInfoIndexes
, 3> OverlapSetup
;
197 OverlapSetup
.push_back({0, 30, 0});
198 OverlapSetup
.push_back({10, 25, 1});
199 OverlapSetup
.push_back({15, 20, 2});
200 runOverlapTest(OverlapSetup
);
203 TEST_F(RegallocDevelopmentFeaturesTest
, InternalMultiOverlap
) {
204 SmallVector
<LRPosInfoIndexes
, 3> OverlapSetup
;
205 OverlapSetup
.push_back({0, 45, 0});
206 OverlapSetup
.push_back({30, 40, 1});
207 OverlapSetup
.push_back({35, 60, 2});
208 runOverlapTest(OverlapSetup
);