1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[NFC][regalloc] Unit test for AllocationOrder iteration.

Added unittests. In the process, separated core construction - which just
needs the hits, order, and 'HardHints' values - from construction from
current register allocation state, to simplify testing.

Differential Revision: https://reviews.llvm.org/D88455
This commit is contained in:
Mircea Trofin 2020-09-28 16:41:28 -07:00
parent 8fcad9cff9
commit a84003ad67
6 changed files with 143 additions and 20 deletions

View File

@ -26,17 +26,15 @@ using namespace llvm;
#define DEBUG_TYPE "regalloc"
// Compare VirtRegMap::getRegAllocPref().
AllocationOrder::AllocationOrder(unsigned VirtReg,
const VirtRegMap &VRM,
const RegisterClassInfo &RegClassInfo,
const LiveRegMatrix *Matrix)
: Pos(0), HardHints(false) {
AllocationOrder AllocationOrder::create(unsigned VirtReg, const VirtRegMap &VRM,
const RegisterClassInfo &RegClassInfo,
const LiveRegMatrix *Matrix) {
const MachineFunction &MF = VRM.getMachineFunction();
const TargetRegisterInfo *TRI = &VRM.getTargetRegInfo();
Order = RegClassInfo.getOrder(MF.getRegInfo().getRegClass(VirtReg));
if (TRI->getRegAllocationHints(VirtReg, Order, Hints, MF, &VRM, Matrix))
HardHints = true;
rewind();
auto Order = RegClassInfo.getOrder(MF.getRegInfo().getRegClass(VirtReg));
SmallVector<MCPhysReg, 16> Hints;
bool HardHints =
TRI->getRegAllocationHints(VirtReg, Order, Hints, MF, &VRM, Matrix);
LLVM_DEBUG({
if (!Hints.empty()) {
@ -51,4 +49,5 @@ AllocationOrder::AllocationOrder(unsigned VirtReg,
assert(is_contained(Order, Hints[I]) &&
"Target hint is outside allocation order.");
#endif
return AllocationOrder(std::move(Hints), Order, HardHints);
}

View File

@ -28,12 +28,12 @@ class VirtRegMap;
class LiveRegMatrix;
class LLVM_LIBRARY_VISIBILITY AllocationOrder {
SmallVector<MCPhysReg, 16> Hints;
const SmallVector<MCPhysReg, 16> Hints;
ArrayRef<MCPhysReg> Order;
int Pos;
int Pos = 0;
// If HardHints is true, *only* Hints will be returned.
bool HardHints;
const bool HardHints;
public:
@ -41,10 +41,16 @@ public:
/// @param VirtReg Virtual register to allocate for.
/// @param VRM Virtual register map for function.
/// @param RegClassInfo Information about reserved and allocatable registers.
AllocationOrder(unsigned VirtReg,
const VirtRegMap &VRM,
const RegisterClassInfo &RegClassInfo,
const LiveRegMatrix *Matrix);
static AllocationOrder create(unsigned VirtReg, const VirtRegMap &VRM,
const RegisterClassInfo &RegClassInfo,
const LiveRegMatrix *Matrix);
/// Create an AllocationOrder given the Hits, Order, and HardHits values.
/// Use the create method above - the ctor is for unittests.
AllocationOrder(SmallVector<MCPhysReg, 16> &&Hints, ArrayRef<MCPhysReg> Order,
bool HardHints)
: Hints(std::move(Hints)), Order(Order),
Pos(-static_cast<int>(this->Hints.size())), HardHints(HardHints) {}
/// Get the allocation order without reordered hints.
ArrayRef<MCPhysReg> getOrder() const { return Order; }
@ -52,7 +58,7 @@ public:
/// Return the next physical register in the allocation order, or 0.
/// It is safe to call next() again after it returned 0, it will keep
/// returning 0 until rewind() is called.
unsigned next(unsigned Limit = 0) {
MCPhysReg next(unsigned Limit = 0) {
if (Pos < 0)
return Hints.end()[Pos++];
if (HardHints)

View File

@ -259,7 +259,8 @@ Register RABasic::selectOrSplit(LiveInterval &VirtReg,
SmallVector<Register, 8> PhysRegSpillCands;
// Check for an available register in this class.
AllocationOrder Order(VirtReg.reg(), *VRM, RegClassInfo, Matrix);
auto Order =
AllocationOrder::create(VirtReg.reg(), *VRM, RegClassInfo, Matrix);
while (Register PhysReg = Order.next()) {
// Check for interference in PhysReg
switch (Matrix->checkInterference(VirtReg, PhysReg)) {

View File

@ -800,7 +800,8 @@ Register RAGreedy::tryAssign(LiveInterval &VirtReg,
//===----------------------------------------------------------------------===//
Register RAGreedy::canReassign(LiveInterval &VirtReg, Register PrevReg) {
AllocationOrder Order(VirtReg.reg(), *VRM, RegClassInfo, Matrix);
auto Order =
AllocationOrder::create(VirtReg.reg(), *VRM, RegClassInfo, Matrix);
Register PhysReg;
while ((PhysReg = Order.next())) {
if (PhysReg == PrevReg)
@ -3013,7 +3014,8 @@ Register RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
unsigned Depth) {
unsigned CostPerUseLimit = ~0u;
// First try assigning a free register.
AllocationOrder Order(VirtReg.reg(), *VRM, RegClassInfo, Matrix);
auto Order =
AllocationOrder::create(VirtReg.reg(), *VRM, RegClassInfo, Matrix);
if (unsigned PhysReg = tryAssign(VirtReg, Order, NewVRegs, FixedRegisters)) {
// If VirtReg got an assignment, the eviction info is no longre relevant.
LastEvicted.clearEvicteeInfo(VirtReg.reg());

View File

@ -0,0 +1,114 @@
//===- llvm/unittest/CodeGen/AllocationOrderTest.cpp - AllocationOrder tests =//
//
// 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/AllocationOrder.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
std::vector<MCPhysReg> loadOrder(AllocationOrder &O, unsigned Limit = 0) {
std::vector<MCPhysReg> Ret;
O.rewind();
while (auto R = O.next(Limit))
Ret.push_back(R);
return Ret;
}
} // namespace
TEST(AllocationOrderTest, Basic) {
SmallVector<MCPhysReg, 16> Hints = {1, 2, 3};
SmallVector<MCPhysReg, 16> Order = {4, 5, 6, 7};
AllocationOrder O(std::move(Hints), Order, false);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4, 5, 6, 7}), loadOrder(O));
}
TEST(AllocationOrderTest, Duplicates) {
SmallVector<MCPhysReg, 16> Hints = {1, 2, 3};
SmallVector<MCPhysReg, 16> Order = {4, 1, 5, 6};
AllocationOrder O(std::move(Hints), Order, false);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4, 5, 6}), loadOrder(O));
}
TEST(AllocationOrderTest, HardHints) {
SmallVector<MCPhysReg, 16> Hints = {1, 2, 3};
SmallVector<MCPhysReg, 16> Order = {4, 5, 6, 7};
AllocationOrder O(std::move(Hints), Order, true);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3}), loadOrder(O));
}
TEST(AllocationOrderTest, LimitsBasic) {
SmallVector<MCPhysReg, 16> Hints = {1, 2, 3};
SmallVector<MCPhysReg, 16> Order = {4, 5, 6, 7};
AllocationOrder O(std::move(Hints), Order, false);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4, 5, 6, 7}), loadOrder(O, 0));
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4}), loadOrder(O, 1));
}
TEST(AllocationOrderTest, LimitsDuplicates) {
SmallVector<MCPhysReg, 16> Hints = {1, 2, 3};
SmallVector<MCPhysReg, 16> Order = {4, 1, 5, 6};
AllocationOrder O(std::move(Hints), Order, false);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4}), loadOrder(O, 1));
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4}), loadOrder(O, 2));
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4, 5}), loadOrder(O, 3));
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4, 5, 6}), loadOrder(O, 4));
}
TEST(AllocationOrderTest, LimitsHardHints) {
SmallVector<MCPhysReg, 16> Hints = {1, 2, 3};
SmallVector<MCPhysReg, 16> Order = {4, 1, 5, 6};
AllocationOrder O(std::move(Hints), Order, true);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3}), loadOrder(O, 1));
}
TEST(AllocationOrderTest, DuplicateIsFirst) {
SmallVector<MCPhysReg, 16> Hints = {1, 2, 3};
SmallVector<MCPhysReg, 16> Order = {1, 4, 5, 6};
AllocationOrder O(std::move(Hints), Order, false);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4, 5, 6}), loadOrder(O));
}
TEST(AllocationOrderTest, DuplicateIsFirstWithLimits) {
SmallVector<MCPhysReg, 16> Hints = {1, 2, 3};
SmallVector<MCPhysReg, 16> Order = {1, 4, 5, 6};
AllocationOrder O(std::move(Hints), Order, false);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3}), loadOrder(O, 1));
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4}), loadOrder(O, 2));
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4, 5}), loadOrder(O, 3));
}
TEST(AllocationOrderTest, NoHints) {
SmallVector<MCPhysReg, 16> Hints;
SmallVector<MCPhysReg, 16> Order = {1, 2, 3, 4};
AllocationOrder O(std::move(Hints), Order, false);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4}), loadOrder(O));
EXPECT_EQ((std::vector<MCPhysReg>{1, 2}), loadOrder(O, 2));
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3}), loadOrder(O, 3));
}
TEST(AllocationOrderTest, IsHintTest) {
SmallVector<MCPhysReg, 16> Hints = {1, 2, 3};
SmallVector<MCPhysReg, 16> Order = {4, 1, 5, 6};
AllocationOrder O(std::move(Hints), Order, false);
O.rewind();
auto V = O.next();
EXPECT_TRUE(O.isHint());
EXPECT_EQ(V, 1U);
O.next();
EXPECT_TRUE(O.isHint());
O.next();
EXPECT_TRUE(O.isHint());
V = O.next();
EXPECT_FALSE(O.isHint());
EXPECT_EQ(V, 4U);
V = O.next();
EXPECT_TRUE(O.isHint(1));
EXPECT_FALSE(O.isHint());
EXPECT_EQ(V, 5U);
}

View File

@ -15,6 +15,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(CodeGenTests
AArch64SelectionDAGTest.cpp
AllocationOrderTest.cpp
AsmPrinterDwarfTest.cpp
DIEHashTest.cpp
DIETest.cpp