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 */
23package org.graalvm.compiler.lir.test.alloc.trace;
24
25import static org.junit.Assert.assertEquals;
26import static org.junit.Assert.assertTrue;
27
28import java.util.HashSet;
29
30import org.junit.Before;
31import org.junit.Ignore;
32import org.junit.Test;
33
34import org.graalvm.compiler.core.common.LIRKind;
35import org.graalvm.compiler.lir.alloc.trace.ShadowedRegisterValue;
36import org.graalvm.compiler.lir.alloc.trace.TraceGlobalMoveResolutionPhase;
37import org.graalvm.util.Pair;
38
39import jdk.vm.ci.code.Register;
40import jdk.vm.ci.code.Register.RegisterCategory;
41import jdk.vm.ci.code.RegisterValue;
42import jdk.vm.ci.code.StackSlot;
43import jdk.vm.ci.meta.AllocatableValue;
44import jdk.vm.ci.meta.PlatformKind;
45import jdk.vm.ci.meta.Value;
46
47/**
48 * Test global move resolver of the trace register allocator.
49 *
50 * Especially the mapping of LabelOp.incoming and BlockEndOp.outgoing.
51 */
52public class TraceGlobalMoveResolutionMappingTest {
53
54    private static final class MoveResolverMock extends TraceGlobalMoveResolutionPhase.MoveResolver {
55
56        private final HashSet<Pair<Value, AllocatableValue>> mapping = new HashSet<>();
57
58        @Override
59        public void addMapping(Value src, AllocatableValue dst, Value srcStack) {
60            mapping.add(Pair.create(src, dst));
61        }
62
63        public int size() {
64            return mapping.size();
65        }
66
67        public boolean contains(Value src, AllocatableValue dst) {
68            return mapping.contains(Pair.create(src, dst));
69        }
70
71        @Override
72        public String toString() {
73            return mapping.toString();
74        }
75
76    }
77
78    private static final RegisterCategory CPU = new RegisterCategory("CPU");
79
80    private static final Register r0 = new Register(0, 0, "r0", CPU);
81    private static final Register r1 = new Register(1, 1, "r1", CPU);
82
83    private enum DummyPlatformKind implements PlatformKind {
84        Long;
85
86        private EnumKey<DummyPlatformKind> key = new EnumKey<>(this);
87
88        @Override
89        public Key getKey() {
90            return key;
91        }
92
93        @Override
94        public int getSizeInBytes() {
95            return 8;
96        }
97
98        @Override
99        public int getVectorLength() {
100            return 1;
101        }
102
103        @Override
104        public char getTypeChar() {
105            return 'l';
106        }
107    }
108
109    private static final LIRKind kind = LIRKind.value(DummyPlatformKind.Long);
110
111    private MoveResolverMock resolver;
112
113    @Before
114    public void setUp() {
115        resolver = new MoveResolverMock();
116    }
117
118    private void addMapping(Value src, Value dst) {
119        TraceGlobalMoveResolutionPhase.addMapping(resolver, src, dst);
120    }
121
122    /** Create RegisterValue. */
123    private static RegisterValue v(Register r) {
124        return r.asValue(kind);
125    }
126
127    /** Create StackSlot. */
128    private static StackSlot s(int offset) {
129        return StackSlot.get(kind, -offset, true);
130    }
131
132    /** Create ShadowedRegisterValue. */
133    private static ShadowedRegisterValue sd(Register reg, int offset) {
134        return new ShadowedRegisterValue(v(reg), s(offset));
135    }
136
137    private void assertContains(Value src, AllocatableValue dst) {
138        assertTrue(String.format("Expected move from %s to %s. %s", src, dst, resolver), resolver.contains(src, dst));
139    }
140
141    private void assertSize(int expected) {
142        assertEquals(resolver.toString(), expected, resolver.size());
143    }
144
145    @Test
146    public void testReg2Reg0() {
147        addMapping(v(r0), v(r1));
148        assertContains(v(r0), v(r1));
149    }
150
151    @Test
152    public void testReg2Reg1() {
153        addMapping(v(r0), v(r0));
154        assertSize(0);
155    }
156
157    @Test
158    public void testStack2Stack0() {
159        addMapping(s(1), s(2));
160        assertContains(s(1), s(2));
161    }
162
163    @Test
164    public void testStack2Stack1() {
165        addMapping(s(1), s(1));
166        assertSize(0);
167    }
168
169    @Test
170    public void testStack2Reg() {
171        addMapping(s(1), v(r1));
172        assertContains(s(1), v(r1));
173    }
174
175    @Test
176    public void testReg2Stack() {
177        addMapping(v(r0), s(1));
178        assertContains(v(r0), s(1));
179    }
180
181    @Test
182    public void testShadowed2Reg() {
183        addMapping(sd(r0, 1), v(r1));
184        assertContains(v(r0), v(r1));
185    }
186
187    @Test
188    public void testReg2Shadowed0() {
189        addMapping(v(r0), sd(r1, 1));
190        assertSize(2);
191        assertContains(v(r0), v(r1));
192        assertContains(v(r0), s(1));
193    }
194
195    @Test
196    public void testReg2Shadowed1() {
197        addMapping(v(r0), sd(r0, 1));
198        assertSize(1);
199        assertContains(v(r0), s(1));
200    }
201
202    @Test
203    @Ignore("Cannot express mapping dependencies (yet)")
204    public void testStack2Shadowed0() {
205        addMapping(s(2), sd(r1, 1));
206        assertSize(2);
207        assertContains(s(2), v(r1));
208        assertContains(v(r1), s(1));
209    }
210
211    @Test
212    public void testStack2Shadowed0WorkArount() {
213        addMapping(s(2), sd(r1, 1));
214        assertSize(2);
215        assertContains(s(2), v(r1));
216        assertContains(s(2), s(1));
217    }
218
219    @Test
220    public void testStack2Shadowed1() {
221        addMapping(s(1), sd(r1, 1));
222        assertSize(1);
223        assertContains(s(1), v(r1));
224    }
225
226    @Test
227    public void testShadowed2Shadowed0() {
228        addMapping(sd(r0, 1), sd(r1, 2));
229        assertSize(2);
230        assertContains(v(r0), v(r1));
231        assertContains(v(r0), s(2));
232    }
233
234    @Test
235    public void testShadowed2Shadowed1() {
236        addMapping(sd(r0, 1), sd(r1, 1));
237        assertSize(1);
238        assertContains(v(r0), v(r1));
239    }
240
241    @Test
242    public void testShadowed2Shadowed2() {
243        addMapping(sd(r0, 1), sd(r0, 1));
244        assertSize(0);
245    }
246}
247