1/* 2 * Copyright © 2021 Google LLC 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include <gtest/gtest.h> 25#include "ralloc.h" 26#include "register_allocate.h" 27#include "register_allocate_internal.h" 28 29class ra_test : public ::testing::Test { 30public: 31 void *mem_ctx; 32 33protected: 34 ra_test(); 35 ~ra_test(); 36}; 37 38ra_test::ra_test() 39{ 40 mem_ctx = ralloc_context(NULL); 41} 42 43ra_test::~ra_test() 44{ 45 ralloc_free(mem_ctx); 46} 47 48void 49thumb_checks(struct ra_regs *regs, unsigned reg32_base, unsigned reg64_base) 50{ 51 struct ra_class *reg32low = ra_get_class_from_index(regs, 0); 52 struct ra_class *reg64low = ra_get_class_from_index(regs, 1); 53 struct ra_class *reg96 = ra_get_class_from_index(regs, 2); 54 55 /* Table 4.1 */ 56 ASSERT_EQ(reg32low->p, 8); 57 ASSERT_EQ(reg32low->q[reg32low->index], 1); 58 ASSERT_EQ(reg32low->q[reg64low->index], 2); 59 ASSERT_EQ(reg32low->q[reg96->index], 3); 60 ASSERT_EQ(reg64low->p, 8); 61 ASSERT_EQ(reg64low->q[reg32low->index], 2); 62 ASSERT_EQ(reg64low->q[reg64low->index], 3); 63 ASSERT_EQ(reg64low->q[reg96->index], 4); 64 ASSERT_EQ(reg96->p, 2); 65 ASSERT_EQ(reg96->q[reg96->index], 2); 66 ASSERT_EQ(reg96->q[reg64low->index], 2); 67 ASSERT_EQ(reg96->q[reg96->index], 2); 68 69 /* These individual regs should conflict with themselves, but nothing else from their class */ 70 for (int i = 0; i < 7; i++) { 71 ASSERT_FALSE(ra_class_allocations_conflict(reg32low, reg32_base + i, reg32low, reg32_base + i + 1)); 72 ASSERT_TRUE(ra_class_allocations_conflict(reg32low, reg32_base + i, reg32low, reg32_base + i)); 73 } 74 75 /* Check that reg64low conflicts with the pairs of reg32low but not neighbors */ 76 ASSERT_TRUE(ra_class_allocations_conflict(reg64low, reg64_base + 0, reg32low, reg32_base + 0)); 77 ASSERT_TRUE(ra_class_allocations_conflict(reg64low, reg64_base + 0, reg32low, reg32_base + 1)); 78 ASSERT_FALSE(ra_class_allocations_conflict(reg64low, reg64_base + 0, reg32low, reg32_base + 2)); 79 80 ASSERT_FALSE(ra_class_allocations_conflict(reg64low, reg64_base + 1, reg32low, reg32_base + 0)); 81 ASSERT_TRUE(ra_class_allocations_conflict(reg64low, reg64_base + 1, reg32low, reg32_base + 1)); 82 ASSERT_TRUE(ra_class_allocations_conflict(reg64low, reg64_base + 1, reg32low, reg32_base + 2)); 83 ASSERT_FALSE(ra_class_allocations_conflict(reg64low, reg64_base + 1, reg32low, reg32_base + 3)); 84} 85 86TEST_F(ra_test, thumb) 87{ 88 struct ra_regs *regs = ra_alloc_reg_set(mem_ctx, 100, true); 89 90 /* r0..15 are the real HW registers. */ 91 int next_vreg = 16; 92 93 /* reg32low is any of the low 8 registers. */ 94 unsigned int reg32_base = next_vreg; 95 struct ra_class *reg32low = ra_alloc_reg_class(regs); 96 for (int i = 0; i < 8; i++) { 97 int vreg = next_vreg++; 98 ra_class_add_reg(reg32low, vreg); 99 ra_add_transitive_reg_conflict(regs, i, vreg); 100 } 101 102 /* reg64low is pairs of the low 8 registers (with wraparound!) */ 103 unsigned int reg64_base = next_vreg; 104 struct ra_class *reg64low = ra_alloc_reg_class(regs); 105 for (int i = 0; i < 8; i++) { 106 int vreg = next_vreg++; 107 ra_class_add_reg(reg64low, vreg); 108 ra_add_transitive_reg_conflict(regs, i, vreg); 109 ra_add_transitive_reg_conflict(regs, (i + 1) % 8, vreg); 110 } 111 112 /* reg96 is one of either r[0..2] or r[1..3] */ 113 struct ra_class *reg96 = ra_alloc_reg_class(regs); 114 for (int i = 0; i < 2; i++) { 115 int vreg = next_vreg++; 116 ra_class_add_reg(reg96, vreg); 117 for (int j = 0; j < 3; j++) 118 ra_add_transitive_reg_conflict(regs, i + j, vreg); 119 } 120 121 ra_set_finalize(regs, NULL); 122 123 thumb_checks(regs, reg32_base, reg64_base); 124} 125 126TEST_F(ra_test, thumb_contigregs) 127{ 128 struct ra_regs *regs = ra_alloc_reg_set(mem_ctx, 16, true); 129 130 /* reg32low is any of the low 8 registers. */ 131 struct ra_class *reg32low = ra_alloc_contig_reg_class(regs, 1); 132 for (int i = 0; i < 8; i++) 133 ra_class_add_reg(reg32low, i); 134 135 /* reg64low is pairs of the low 8 registers (we're ignoring the wraparound thing here) */ 136 struct ra_class *reg64low = ra_alloc_contig_reg_class(regs, 2); 137 for (int i = 0; i < 8; i++) 138 ra_class_add_reg(reg64low, i); 139 140 /* reg96 is one of either r[0..2] or r[1..3] */ 141 struct ra_class *reg96 = ra_alloc_contig_reg_class(regs, 3); 142 for (int i = 0; i < 2; i++) 143 ra_class_add_reg(reg96, i); 144 145 ra_set_finalize(regs, NULL); 146 147 thumb_checks(regs, 0, 0); 148} 149 150TEST_F(ra_test, nonintersect_contigregs) 151{ 152 struct ra_regs *regs = ra_alloc_reg_set(mem_ctx, 16, true); 153 154 struct ra_class *low = ra_alloc_contig_reg_class(regs, 1); 155 for (int i = 0; i < 8; i++) 156 ra_class_add_reg(low, i); 157 158 struct ra_class *high = ra_alloc_contig_reg_class(regs, 1); 159 for (int i = 8; i < 16; i++) 160 ra_class_add_reg(high, i); 161 162 ra_set_finalize(regs, NULL); 163 164 ASSERT_EQ(low->q[low->index], 1); 165 ASSERT_EQ(low->q[high->index], 0); 166 ASSERT_EQ(high->q[low->index], 0); 167 ASSERT_EQ(high->q[high->index], 1); 168} 169 170TEST_F(ra_test, aligned_contigregs) 171{ 172 int base_regs = 32; 173 struct ra_regs *regs = ra_alloc_reg_set(mem_ctx, base_regs, true); 174 175 struct ra_class *c1 = ra_alloc_contig_reg_class(regs, 1); 176 for (int i = 0; i < base_regs; i++) 177 ra_class_add_reg(c1, i); 178 179 struct ra_class *c2 = ra_alloc_contig_reg_class(regs, 2); 180 for (int i = 8; i < base_regs; i += 2) 181 ra_class_add_reg(c2, i); 182 183 struct ra_class *c4 = ra_alloc_contig_reg_class(regs, 4); 184 for (int i = 8; i < base_regs; i += 4) 185 ra_class_add_reg(c4, i); 186 187 ra_set_finalize(regs, NULL); 188 189 ASSERT_EQ(c1->q[c1->index], 1); 190 ASSERT_EQ(c1->q[c2->index], 2); 191 ASSERT_EQ(c1->q[c4->index], 4); 192 ASSERT_EQ(c2->q[c1->index], 1); 193 ASSERT_EQ(c2->q[c2->index], 1); 194 ASSERT_EQ(c2->q[c4->index], 2); 195 ASSERT_EQ(c4->q[c1->index], 1); 196 ASSERT_EQ(c4->q[c2->index], 1); 197 ASSERT_EQ(c4->q[c4->index], 1); 198 199 /* Check conflicts for a c4 allocation at i against other classes. */ 200 for (int i = 0; i < base_regs / 4; i += 4) { 201 for (int j = 0; j < base_regs; j++) { 202 ASSERT_EQ(ra_class_allocations_conflict(c4, i, c1, j), 203 j >= i && j < i + 4); 204 } 205 206 for (int j = 0; j < base_regs; j += 2) { 207 ASSERT_EQ(ra_class_allocations_conflict(c4, i, c2, j), 208 j >= i && j < i + 4); 209 } 210 } 211} 212