17ec681f3Smrg/*
27ec681f3Smrg * Copyright © 2021 Google LLC
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
217ec681f3Smrg * IN THE SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include <gtest/gtest.h>
257ec681f3Smrg#include "ralloc.h"
267ec681f3Smrg#include "register_allocate.h"
277ec681f3Smrg#include "register_allocate_internal.h"
287ec681f3Smrg
297ec681f3Smrgclass ra_test : public ::testing::Test {
307ec681f3Smrgpublic:
317ec681f3Smrg   void *mem_ctx;
327ec681f3Smrg
337ec681f3Smrgprotected:
347ec681f3Smrg   ra_test();
357ec681f3Smrg   ~ra_test();
367ec681f3Smrg};
377ec681f3Smrg
387ec681f3Smrgra_test::ra_test()
397ec681f3Smrg{
407ec681f3Smrg   mem_ctx = ralloc_context(NULL);
417ec681f3Smrg}
427ec681f3Smrg
437ec681f3Smrgra_test::~ra_test()
447ec681f3Smrg{
457ec681f3Smrg   ralloc_free(mem_ctx);
467ec681f3Smrg}
477ec681f3Smrg
487ec681f3Smrgvoid
497ec681f3Smrgthumb_checks(struct ra_regs *regs, unsigned reg32_base, unsigned reg64_base)
507ec681f3Smrg{
517ec681f3Smrg   struct ra_class *reg32low = ra_get_class_from_index(regs, 0);
527ec681f3Smrg   struct ra_class *reg64low = ra_get_class_from_index(regs, 1);
537ec681f3Smrg   struct ra_class *reg96 = ra_get_class_from_index(regs, 2);
547ec681f3Smrg
557ec681f3Smrg   /* Table 4.1 */
567ec681f3Smrg   ASSERT_EQ(reg32low->p, 8);
577ec681f3Smrg   ASSERT_EQ(reg32low->q[reg32low->index], 1);
587ec681f3Smrg   ASSERT_EQ(reg32low->q[reg64low->index], 2);
597ec681f3Smrg   ASSERT_EQ(reg32low->q[reg96->index], 3);
607ec681f3Smrg   ASSERT_EQ(reg64low->p, 8);
617ec681f3Smrg   ASSERT_EQ(reg64low->q[reg32low->index], 2);
627ec681f3Smrg   ASSERT_EQ(reg64low->q[reg64low->index], 3);
637ec681f3Smrg   ASSERT_EQ(reg64low->q[reg96->index], 4);
647ec681f3Smrg   ASSERT_EQ(reg96->p, 2);
657ec681f3Smrg   ASSERT_EQ(reg96->q[reg96->index], 2);
667ec681f3Smrg   ASSERT_EQ(reg96->q[reg64low->index], 2);
677ec681f3Smrg   ASSERT_EQ(reg96->q[reg96->index], 2);
687ec681f3Smrg
697ec681f3Smrg   /* These individual regs should conflict with themselves, but nothing else from their class */
707ec681f3Smrg   for (int i = 0; i < 7; i++) {
717ec681f3Smrg      ASSERT_FALSE(ra_class_allocations_conflict(reg32low, reg32_base + i, reg32low, reg32_base + i + 1));
727ec681f3Smrg      ASSERT_TRUE(ra_class_allocations_conflict(reg32low, reg32_base + i, reg32low, reg32_base + i));
737ec681f3Smrg   }
747ec681f3Smrg
757ec681f3Smrg   /* Check that reg64low conflicts with the pairs of reg32low but not neighbors */
767ec681f3Smrg   ASSERT_TRUE(ra_class_allocations_conflict(reg64low, reg64_base + 0, reg32low, reg32_base + 0));
777ec681f3Smrg   ASSERT_TRUE(ra_class_allocations_conflict(reg64low, reg64_base + 0, reg32low, reg32_base + 1));
787ec681f3Smrg   ASSERT_FALSE(ra_class_allocations_conflict(reg64low, reg64_base + 0, reg32low, reg32_base + 2));
797ec681f3Smrg
807ec681f3Smrg   ASSERT_FALSE(ra_class_allocations_conflict(reg64low, reg64_base + 1, reg32low, reg32_base + 0));
817ec681f3Smrg   ASSERT_TRUE(ra_class_allocations_conflict(reg64low, reg64_base + 1, reg32low, reg32_base + 1));
827ec681f3Smrg   ASSERT_TRUE(ra_class_allocations_conflict(reg64low, reg64_base + 1, reg32low, reg32_base + 2));
837ec681f3Smrg   ASSERT_FALSE(ra_class_allocations_conflict(reg64low, reg64_base + 1, reg32low, reg32_base + 3));
847ec681f3Smrg}
857ec681f3Smrg
867ec681f3SmrgTEST_F(ra_test, thumb)
877ec681f3Smrg{
887ec681f3Smrg   struct ra_regs *regs = ra_alloc_reg_set(mem_ctx, 100, true);
897ec681f3Smrg
907ec681f3Smrg   /* r0..15 are the real HW registers. */
917ec681f3Smrg   int next_vreg = 16;
927ec681f3Smrg
937ec681f3Smrg   /* reg32low is any of the low 8 registers. */
947ec681f3Smrg   unsigned int reg32_base = next_vreg;
957ec681f3Smrg   struct ra_class *reg32low = ra_alloc_reg_class(regs);
967ec681f3Smrg   for (int i = 0; i < 8; i++) {
977ec681f3Smrg      int vreg = next_vreg++;
987ec681f3Smrg      ra_class_add_reg(reg32low, vreg);
997ec681f3Smrg      ra_add_transitive_reg_conflict(regs, i, vreg);
1007ec681f3Smrg   }
1017ec681f3Smrg
1027ec681f3Smrg   /* reg64low is pairs of the low 8 registers (with wraparound!) */
1037ec681f3Smrg   unsigned int reg64_base = next_vreg;
1047ec681f3Smrg   struct ra_class *reg64low = ra_alloc_reg_class(regs);
1057ec681f3Smrg   for (int i = 0; i < 8; i++) {
1067ec681f3Smrg      int vreg = next_vreg++;
1077ec681f3Smrg      ra_class_add_reg(reg64low, vreg);
1087ec681f3Smrg      ra_add_transitive_reg_conflict(regs, i, vreg);
1097ec681f3Smrg      ra_add_transitive_reg_conflict(regs, (i + 1) % 8, vreg);
1107ec681f3Smrg   }
1117ec681f3Smrg
1127ec681f3Smrg   /* reg96 is one of either r[0..2] or r[1..3] */
1137ec681f3Smrg   struct ra_class *reg96 = ra_alloc_reg_class(regs);
1147ec681f3Smrg   for (int i = 0; i < 2; i++) {
1157ec681f3Smrg      int vreg = next_vreg++;
1167ec681f3Smrg      ra_class_add_reg(reg96, vreg);
1177ec681f3Smrg      for (int j = 0; j < 3; j++)
1187ec681f3Smrg         ra_add_transitive_reg_conflict(regs, i + j, vreg);
1197ec681f3Smrg   }
1207ec681f3Smrg
1217ec681f3Smrg   ra_set_finalize(regs, NULL);
1227ec681f3Smrg
1237ec681f3Smrg   thumb_checks(regs, reg32_base, reg64_base);
1247ec681f3Smrg}
1257ec681f3Smrg
1267ec681f3SmrgTEST_F(ra_test, thumb_contigregs)
1277ec681f3Smrg{
1287ec681f3Smrg   struct ra_regs *regs = ra_alloc_reg_set(mem_ctx, 16, true);
1297ec681f3Smrg
1307ec681f3Smrg   /* reg32low is any of the low 8 registers. */
1317ec681f3Smrg   struct ra_class *reg32low = ra_alloc_contig_reg_class(regs, 1);
1327ec681f3Smrg   for (int i = 0; i < 8; i++)
1337ec681f3Smrg      ra_class_add_reg(reg32low, i);
1347ec681f3Smrg
1357ec681f3Smrg   /* reg64low is pairs of the low 8 registers (we're ignoring the wraparound thing here) */
1367ec681f3Smrg   struct ra_class *reg64low = ra_alloc_contig_reg_class(regs, 2);
1377ec681f3Smrg   for (int i = 0; i < 8; i++)
1387ec681f3Smrg      ra_class_add_reg(reg64low, i);
1397ec681f3Smrg
1407ec681f3Smrg   /* reg96 is one of either r[0..2] or r[1..3] */
1417ec681f3Smrg   struct ra_class *reg96 = ra_alloc_contig_reg_class(regs, 3);
1427ec681f3Smrg   for (int i = 0; i < 2; i++)
1437ec681f3Smrg      ra_class_add_reg(reg96, i);
1447ec681f3Smrg
1457ec681f3Smrg   ra_set_finalize(regs, NULL);
1467ec681f3Smrg
1477ec681f3Smrg   thumb_checks(regs, 0, 0);
1487ec681f3Smrg}
1497ec681f3Smrg
1507ec681f3SmrgTEST_F(ra_test, nonintersect_contigregs)
1517ec681f3Smrg{
1527ec681f3Smrg   struct ra_regs *regs = ra_alloc_reg_set(mem_ctx, 16, true);
1537ec681f3Smrg
1547ec681f3Smrg   struct ra_class *low = ra_alloc_contig_reg_class(regs, 1);
1557ec681f3Smrg   for (int i = 0; i < 8; i++)
1567ec681f3Smrg      ra_class_add_reg(low, i);
1577ec681f3Smrg
1587ec681f3Smrg   struct ra_class *high = ra_alloc_contig_reg_class(regs, 1);
1597ec681f3Smrg   for (int i = 8; i < 16; i++)
1607ec681f3Smrg      ra_class_add_reg(high, i);
1617ec681f3Smrg
1627ec681f3Smrg   ra_set_finalize(regs, NULL);
1637ec681f3Smrg
1647ec681f3Smrg   ASSERT_EQ(low->q[low->index], 1);
1657ec681f3Smrg   ASSERT_EQ(low->q[high->index], 0);
1667ec681f3Smrg   ASSERT_EQ(high->q[low->index], 0);
1677ec681f3Smrg   ASSERT_EQ(high->q[high->index], 1);
1687ec681f3Smrg}
1697ec681f3Smrg
1707ec681f3SmrgTEST_F(ra_test, aligned_contigregs)
1717ec681f3Smrg{
1727ec681f3Smrg   int base_regs = 32;
1737ec681f3Smrg   struct ra_regs *regs = ra_alloc_reg_set(mem_ctx, base_regs, true);
1747ec681f3Smrg
1757ec681f3Smrg   struct ra_class *c1 = ra_alloc_contig_reg_class(regs, 1);
1767ec681f3Smrg   for (int i = 0; i < base_regs; i++)
1777ec681f3Smrg      ra_class_add_reg(c1, i);
1787ec681f3Smrg
1797ec681f3Smrg   struct ra_class *c2 = ra_alloc_contig_reg_class(regs, 2);
1807ec681f3Smrg   for (int i = 8; i < base_regs; i += 2)
1817ec681f3Smrg      ra_class_add_reg(c2, i);
1827ec681f3Smrg
1837ec681f3Smrg   struct ra_class *c4 = ra_alloc_contig_reg_class(regs, 4);
1847ec681f3Smrg   for (int i = 8; i < base_regs; i += 4)
1857ec681f3Smrg      ra_class_add_reg(c4, i);
1867ec681f3Smrg
1877ec681f3Smrg   ra_set_finalize(regs, NULL);
1887ec681f3Smrg
1897ec681f3Smrg   ASSERT_EQ(c1->q[c1->index], 1);
1907ec681f3Smrg   ASSERT_EQ(c1->q[c2->index], 2);
1917ec681f3Smrg   ASSERT_EQ(c1->q[c4->index], 4);
1927ec681f3Smrg   ASSERT_EQ(c2->q[c1->index], 1);
1937ec681f3Smrg   ASSERT_EQ(c2->q[c2->index], 1);
1947ec681f3Smrg   ASSERT_EQ(c2->q[c4->index], 2);
1957ec681f3Smrg   ASSERT_EQ(c4->q[c1->index], 1);
1967ec681f3Smrg   ASSERT_EQ(c4->q[c2->index], 1);
1977ec681f3Smrg   ASSERT_EQ(c4->q[c4->index], 1);
1987ec681f3Smrg
1997ec681f3Smrg   /* Check conflicts for a c4 allocation at i against other classes. */
2007ec681f3Smrg   for (int i = 0; i < base_regs / 4; i += 4) {
2017ec681f3Smrg      for (int j = 0; j < base_regs; j++) {
2027ec681f3Smrg         ASSERT_EQ(ra_class_allocations_conflict(c4, i, c1, j),
2037ec681f3Smrg                   j >= i && j < i + 4);
2047ec681f3Smrg      }
2057ec681f3Smrg
2067ec681f3Smrg      for (int j = 0; j < base_regs; j += 2) {
2077ec681f3Smrg         ASSERT_EQ(ra_class_allocations_conflict(c4, i, c2, j),
2087ec681f3Smrg                   j >= i && j < i + 4);
2097ec681f3Smrg      }
2107ec681f3Smrg   }
2117ec681f3Smrg}
212