1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.lir.test.alloc.trace; 24 25 import static org.junit.Assert.assertEquals; 26 import static org.junit.Assert.assertTrue; 27 28 import java.util.HashSet; 29 30 import org.junit.Before; 31 import org.junit.Ignore; 32 import org.junit.Test; 33 34 import org.graalvm.compiler.core.common.LIRKind; 35 import org.graalvm.compiler.lir.alloc.trace.ShadowedRegisterValue; 36 import org.graalvm.compiler.lir.alloc.trace.TraceGlobalMoveResolutionPhase; 37 38 import jdk.vm.ci.code.Register; 39 import jdk.vm.ci.code.Register.RegisterCategory; 40 import jdk.vm.ci.code.RegisterValue; 41 import jdk.vm.ci.code.StackSlot; 42 import jdk.vm.ci.meta.AllocatableValue; 43 import jdk.vm.ci.meta.PlatformKind; 44 import jdk.vm.ci.meta.Value; 45 46 /** 47 * Test global move resolver of the trace register allocator. 48 * 49 * Especially the mapping of LabelOp.incoming and BlockEndOp.outgoing. 50 */ 51 public class TraceGlobalMoveResolutionMappingTest { 52 53 private static final class MoveResolverMock extends TraceGlobalMoveResolutionPhase.MoveResolver { 54 55 private static final class Pair { 56 57 @Override 58 public int hashCode() { 59 final int prime = 31; 60 int result = 1; 61 result = prime * result + ((dst == null) ? 0 : dst.hashCode()); 62 result = prime * result + ((src == null) ? 0 : src.hashCode()); 63 return result; 64 } 65 66 @Override 67 public boolean equals(Object obj) { 68 if (this == obj) { 69 return true; 70 } 71 if (obj == null) { 72 return false; 73 } 74 if (getClass() != obj.getClass()) { 75 return false; 76 } 77 Pair other = (Pair) obj; 78 if (dst == null) { 79 if (other.dst != null) { 80 return false; 81 } 82 } else if (!dst.equals(other.dst)) { 83 return false; 84 } 85 if (src == null) { 86 if (other.src != null) { 87 return false; 88 } 89 } else if (!src.equals(other.src)) { 90 return false; 91 } 92 return true; 93 } 94 95 private final Value src; 96 private final AllocatableValue dst; 97 98 Pair(Value src, AllocatableValue dst) { 99 this.src = src; 100 this.dst = dst; 101 } 102 103 @Override 104 public String toString() { 105 return dst.toString() + " <- " + src; 106 } 107 } 108 109 private final HashSet<Pair> mapping = new HashSet<>(); 110 111 @Override 112 public void addMapping(Value src, AllocatableValue dst, Value srcStack) { 113 mapping.add(new Pair(src, dst)); 114 } 115 116 public int size() { 117 return mapping.size(); 118 } 119 120 public boolean contains(Value src, AllocatableValue dst) { 121 return mapping.contains(new Pair(src, dst)); 122 } 123 124 @Override 125 public String toString() { 126 return mapping.toString(); 127 } 128 129 } 130 131 private static final RegisterCategory CPU = new RegisterCategory("CPU"); 132 133 private static final Register r0 = new Register(0, 0, "r0", CPU); 134 private static final Register r1 = new Register(1, 1, "r1", CPU); 135 136 private enum DummyPlatformKind implements PlatformKind { 137 Long; 138 139 private EnumKey<DummyPlatformKind> key = new EnumKey<>(this); 140 141 @Override 142 public Key getKey() { 143 return key; 144 } 145 146 @Override 147 public int getSizeInBytes() { 148 return 8; 149 } 150 151 @Override 152 public int getVectorLength() { 153 return 1; 154 } 155 156 @Override 157 public char getTypeChar() { 158 return 'l'; 159 } 160 } 161 162 private static final LIRKind kind = LIRKind.value(DummyPlatformKind.Long); 163 164 private MoveResolverMock resolver; 165 166 @Before 167 public void setUp() { 168 resolver = new MoveResolverMock(); 169 } 170 171 private void addMapping(Value src, Value dst) { 172 TraceGlobalMoveResolutionPhase.addMapping(resolver, src, dst); 173 } 174 175 /** Create RegisterValue. */ 176 private static RegisterValue v(Register r) { 177 return r.asValue(kind); 178 } 179 180 /** Create StackSlot. */ 181 private static StackSlot s(int offset) { 182 return StackSlot.get(kind, -offset, true); 183 } 184 185 /** Create ShadowedRegisterValue. */ 186 private static ShadowedRegisterValue sd(Register reg, int offset) { 187 return new ShadowedRegisterValue(v(reg), s(offset)); 188 } 189 190 private void assertContains(Value src, AllocatableValue dst) { 191 assertTrue(String.format("Expected move from %s to %s. %s", src, dst, resolver), resolver.contains(src, dst)); 192 } 193 194 private void assertSize(int expected) { 195 assertEquals(resolver.toString(), expected, resolver.size()); 196 } 197 198 @Test 199 public void testReg2Reg0() { 200 addMapping(v(r0), v(r1)); 201 assertContains(v(r0), v(r1)); 202 } 203 204 @Test 205 public void testReg2Reg1() { 206 addMapping(v(r0), v(r0)); 207 assertSize(0); 208 } 209 210 @Test 211 public void testStack2Stack0() { 212 addMapping(s(1), s(2)); 213 assertContains(s(1), s(2)); 214 } 215 216 @Test 217 public void testStack2Stack1() { 218 addMapping(s(1), s(1)); 219 assertSize(0); 220 } 221 222 @Test 223 public void testStack2Reg() { 224 addMapping(s(1), v(r1)); 225 assertContains(s(1), v(r1)); 226 } 227 228 @Test 229 public void testReg2Stack() { 230 addMapping(v(r0), s(1)); 231 assertContains(v(r0), s(1)); 232 } 233 234 @Test 235 public void testShadowed2Reg() { 236 addMapping(sd(r0, 1), v(r1)); 237 assertContains(v(r0), v(r1)); 238 } 239 240 @Test 241 public void testReg2Shadowed0() { 242 addMapping(v(r0), sd(r1, 1)); 243 assertSize(2); 244 assertContains(v(r0), v(r1)); 245 assertContains(v(r0), s(1)); 246 } 247 248 @Test 249 public void testReg2Shadowed1() { 250 addMapping(v(r0), sd(r0, 1)); 251 assertSize(1); 252 assertContains(v(r0), s(1)); 253 } 254 255 @Test 256 @Ignore("Cannot express mapping dependencies (yet)") 257 public void testStack2Shadowed0() { 258 addMapping(s(2), sd(r1, 1)); 259 assertSize(2); 260 assertContains(s(2), v(r1)); 261 assertContains(v(r1), s(1)); 262 } 263 264 @Test 265 public void testStack2Shadowed0WorkArount() { 266 addMapping(s(2), sd(r1, 1)); 267 assertSize(2); 268 assertContains(s(2), v(r1)); 269 assertContains(s(2), s(1)); 270 } 271 272 @Test 273 public void testStack2Shadowed1() { 274 addMapping(s(1), sd(r1, 1)); 275 assertSize(1); 276 assertContains(s(1), v(r1)); 277 } 278 279 @Test 280 public void testShadowed2Shadowed0() { 281 addMapping(sd(r0, 1), sd(r1, 2)); 282 assertSize(2); 283 assertContains(v(r0), v(r1)); 284 assertContains(v(r0), s(2)); 285 } 286 287 @Test 288 public void testShadowed2Shadowed1() { 289 addMapping(sd(r0, 1), sd(r1, 1)); 290 assertSize(1); 291 assertContains(v(r0), v(r1)); 292 } 293 294 @Test 295 public void testShadowed2Shadowed2() { 296 addMapping(sd(r0, 1), sd(r0, 1)); 297 assertSize(0); 298 } 299 }