llvm-project/llvm/unittests/CodeGen/MLRegallocDevelopmentFeatur...

210 lines
7.7 KiB
C++

//===- MLRegAllocDevelopmentFeatures.cpp - test dev MLRegalloc features ---===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "../../lib/CodeGen/MLRegallocEvictAdvisor.h"
#include "llvm/Analysis/NoInferenceModelRunner.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/CodeGen.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <vector>
using testing::ContainerEq;
using testing::Test;
struct LRPosInfoIndexes {
size_t StartIndex;
size_t EndIndex;
size_t PhysReg;
};
class RegallocDevelopmentFeaturesTest : public ::Test {
protected:
SmallVector<LRStartEndInfo>
setupOverlapProblem(const SmallVectorImpl<LRPosInfoIndexes> &Segments,
ilist<IndexListEntry> &IndexList) {
SmallVector<LRStartEndInfo> PositionsToReturn;
PositionsToReturn.reserve(Segments.size());
for (auto CurrentPosIndexInfo : Segments) {
LRStartEndInfo CurrentPosInfo = {};
CurrentPosInfo.Pos = CurrentPosIndexInfo.PhysReg;
PositionsToReturn.push_back(CurrentPosInfo);
}
size_t CurrentSegmentIndex = 0;
size_t CurrentIndex = 0;
while (CurrentSegmentIndex < Segments.size()) {
auto *CurrentLEMem = static_cast<IndexListEntry *>(
Allocator.Allocate(sizeof(IndexListEntry), alignof(IndexListEntry)));
auto *CurrentListEntry =
new (CurrentLEMem) IndexListEntry(nullptr, CurrentIndex);
IndexList.push_back(CurrentListEntry);
for (size_t CurrentPosInfoIndex = 0;
CurrentPosInfoIndex < Segments.size(); ++CurrentPosInfoIndex) {
if ((CurrentIndex / SlotIndex::InstrDist) ==
Segments[CurrentPosInfoIndex].StartIndex) {
PositionsToReturn[CurrentPosInfoIndex].Begin =
SlotIndex(CurrentListEntry, 0);
} else if ((CurrentIndex / SlotIndex::InstrDist) ==
Segments[CurrentPosInfoIndex].EndIndex) {
PositionsToReturn[CurrentPosInfoIndex].End =
SlotIndex(CurrentListEntry, 0);
++CurrentSegmentIndex;
}
}
CurrentIndex += SlotIndex::InstrDist;
}
return PositionsToReturn;
}
NoInferenceModelRunner setupModelRunner() {
const std::vector<TensorSpec> Inputs{
TensorSpec::createSpec<int64_t>("instructions", InstructionsShape),
TensorSpec::createSpec<int64_t>("instructions_mapping",
InstructionsMappingShape)};
LLVMContext Ctx;
return NoInferenceModelRunner(Ctx, Inputs);
}
std::vector<int64_t>
getExpectedMappingMatrix(SmallVectorImpl<LRPosInfoIndexes> &OverlapSetup) {
std::vector<int64_t> ExpectedMappingMatrix(
NumberOfInterferences * ModelMaxSupportedInstructionCount, 0);
for (auto NewSegment : OverlapSetup) {
for (size_t CurrentIndex = NewSegment.StartIndex;
CurrentIndex <= NewSegment.EndIndex; ++CurrentIndex) {
ExpectedMappingMatrix[NewSegment.PhysReg *
ModelMaxSupportedInstructionCount +
CurrentIndex] = 1;
}
}
return ExpectedMappingMatrix;
}
void runOverlapTest(SmallVectorImpl<LRPosInfoIndexes> &OverlapSetup) {
ilist<IndexListEntry> IndexList;
auto OverlapProblem = setupOverlapProblem(OverlapSetup, IndexList);
NoInferenceModelRunner ModelRunner = setupModelRunner();
size_t MaxIndex = 0;
for (size_t CurrentOverlap = 0; CurrentOverlap < OverlapSetup.size();
++CurrentOverlap) {
if (OverlapSetup[CurrentOverlap].EndIndex >
OverlapSetup[MaxIndex].EndIndex) {
MaxIndex = CurrentOverlap;
}
}
SlotIndex LastIndex = OverlapProblem[MaxIndex].End;
extractInstructionFeatures(
OverlapProblem, &ModelRunner,
[](SlotIndex InputSlot) -> int { return 0; }, 0, 1, LastIndex);
std::vector<int64_t> MappingMatrix(
ModelRunner.getTensor<int64_t>(1),
ModelRunner.getTensor<int64_t>(1) +
NumberOfInterferences * ModelMaxSupportedInstructionCount);
ASSERT_THAT(MappingMatrix,
ContainerEq(getExpectedMappingMatrix(OverlapSetup)));
IndexList.clearAndLeakNodesUnsafely();
}
BumpPtrAllocator Allocator;
};
// meta tests to ensure that test setup works correctly
TEST_F(RegallocDevelopmentFeaturesTest,
MetaOverlapInstructionDistancesAreCorrect) {
SmallVector<LRPosInfoIndexes, 2> OverlapSetup;
OverlapSetup.push_back({0, 5, 0});
OverlapSetup.push_back({5, 10, 0});
ilist<IndexListEntry> IndexList;
auto OverlapProblem = setupOverlapProblem(OverlapSetup, IndexList);
ASSERT_EQ(OverlapProblem[0].End.distance(OverlapProblem[1].End),
5 * SlotIndex::InstrDist);
ASSERT_EQ(OverlapProblem[0].End.distance(OverlapProblem[1].Begin), 0);
}
TEST_F(RegallocDevelopmentFeaturesTest, MetaSlotIndicesAreValid) {
SmallVector<LRPosInfoIndexes, 1> OverlapSetup;
OverlapSetup.push_back({0, 10, 0});
ilist<IndexListEntry> IndexList;
auto OverlapProblem = setupOverlapProblem(OverlapSetup, IndexList);
ASSERT_TRUE(OverlapProblem[0].Begin.isValid());
ASSERT_TRUE(OverlapProblem[0].End.isValid());
}
// Testing of feature extraction for per-instruction features
TEST_F(RegallocDevelopmentFeaturesTest, InstructionOpcodesAreCorrect) {
SmallVector<LRPosInfoIndexes, 1> OverlapSetup;
OverlapSetup.push_back({0, ModelMaxSupportedInstructionCount - 1, 0});
ilist<IndexListEntry> IndexList;
auto OverlapProblem = setupOverlapProblem(OverlapSetup, IndexList);
NoInferenceModelRunner ModelRunner = setupModelRunner();
SlotIndex LastIndex = OverlapProblem[0].End;
SlotIndex FirstIndex = OverlapProblem[0].Begin;
extractInstructionFeatures(
OverlapProblem, &ModelRunner,
[FirstIndex](SlotIndex InputSlot) -> int {
return FirstIndex.distance(InputSlot) / SlotIndex::InstrDist;
},
0, 1, LastIndex);
for (size_t CurrentInstructionIndex = 0;
CurrentInstructionIndex < ModelMaxSupportedInstructionCount;
++CurrentInstructionIndex) {
ASSERT_EQ(
(size_t)ModelRunner.getTensor<int64_t>(0)[CurrentInstructionIndex],
CurrentInstructionIndex);
}
}
TEST_F(RegallocDevelopmentFeaturesTest, FullOverlap) {
SmallVector<LRPosInfoIndexes, 2> OverlapSetup;
OverlapSetup.push_back({0, ModelMaxSupportedInstructionCount - 1, 0});
OverlapSetup.push_back({0, ModelMaxSupportedInstructionCount - 1, 1});
runOverlapTest(OverlapSetup);
}
TEST_F(RegallocDevelopmentFeaturesTest, PartialOverlap) {
SmallVector<LRPosInfoIndexes, 2> OverlapSetup;
OverlapSetup.push_back({0, 20, 0});
OverlapSetup.push_back({15, 30, 1});
runOverlapTest(OverlapSetup);
}
TEST_F(RegallocDevelopmentFeaturesTest, PartialOverlapOpposite) {
SmallVector<LRPosInfoIndexes, 2> OverlapSetup;
OverlapSetup.push_back({15, 30, 1});
OverlapSetup.push_back({0, 20, 0});
runOverlapTest(OverlapSetup);
}
TEST_F(RegallocDevelopmentFeaturesTest, InternalOverlap) {
SmallVector<LRPosInfoIndexes, 2> OverlapSetup;
OverlapSetup.push_back({0, 30, 0});
OverlapSetup.push_back({10, 20, 1});
runOverlapTest(OverlapSetup);
}
TEST_F(RegallocDevelopmentFeaturesTest, TripleInternalOverlap) {
SmallVector<LRPosInfoIndexes, 3> OverlapSetup;
OverlapSetup.push_back({0, 30, 0});
OverlapSetup.push_back({10, 25, 1});
OverlapSetup.push_back({15, 20, 2});
runOverlapTest(OverlapSetup);
}
TEST_F(RegallocDevelopmentFeaturesTest, InternalMultiOverlap) {
SmallVector<LRPosInfoIndexes, 3> OverlapSetup;
OverlapSetup.push_back({0, 45, 0});
OverlapSetup.push_back({30, 40, 1});
OverlapSetup.push_back({35, 60, 2});
runOverlapTest(OverlapSetup);
}