[NFC][regalloc] Unit test for AllocationOrder iteration.
authorMircea Trofin <mtrofin@google.com>
Mon, 28 Sep 2020 23:41:28 +0000 (16:41 -0700)
committerMircea Trofin <mtrofin@google.com>
Tue, 29 Sep 2020 17:48:07 +0000 (10:48 -0700)
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

llvm/lib/CodeGen/AllocationOrder.cpp
llvm/lib/CodeGen/AllocationOrder.h
llvm/lib/CodeGen/RegAllocBasic.cpp
llvm/lib/CodeGen/RegAllocGreedy.cpp
llvm/unittests/CodeGen/AllocationOrderTest.cpp [new file with mode: 0644]
llvm/unittests/CodeGen/CMakeLists.txt

index c998006..2aef123 100644 (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);
 }
index 75f87dd..368a3cd 100644 (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)
index a4ce9d7..0fa50d9 100644 (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)) {
index f2bd458..eb0a096 100644 (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());
diff --git a/llvm/unittests/CodeGen/AllocationOrderTest.cpp b/llvm/unittests/CodeGen/AllocationOrderTest.cpp
new file mode 100644 (file)
index 0000000..ba1a1e4
--- /dev/null
@@ -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);
+}
index 817ddb1..0e02144 100644 (file)
@@ -15,6 +15,7 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_unittest(CodeGenTests
   AArch64SelectionDAGTest.cpp
+  AllocationOrderTest.cpp
   AsmPrinterDwarfTest.cpp
   DIEHashTest.cpp
   DIETest.cpp