changeset 22978:64eb72b6165d

TraceRA: add TraceGlobalMoveResolutionMappingTest.
author Josef Eisl <josef.eisl@jku.at>
date Thu, 12 Nov 2015 18:04:38 +0100
parents 913b2001af72
children 9ef376e2e6b6
files graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/ShadowedRegisterValue.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolutionPhase.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolver.java
diffstat 4 files changed, 336 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java	Thu Nov 12 18:04:38 2015 +0100
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.test.alloc.trace;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashSet;
+
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.code.RegisterValue;
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.LIRKind;
+import jdk.vm.ci.meta.PlatformKind;
+import jdk.vm.ci.meta.Value;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.oracle.graal.lir.alloc.trace.ShadowedRegisterValue;
+import com.oracle.graal.lir.alloc.trace.TraceGlobalMoveResolutionPhase;
+
+/**
+ * Test global move resolver of the trace register allocator.
+ *
+ * Especially the mapping of LabelOp.incoming and BlockEndOp.outgoing.
+ */
+public class TraceGlobalMoveResolutionMappingTest {
+
+    private static final class MoveResolverMock extends TraceGlobalMoveResolutionPhase.MoveResolver {
+
+        private static final class Pair {
+
+            @Override
+            public int hashCode() {
+                final int prime = 31;
+                int result = 1;
+                result = prime * result + ((dst == null) ? 0 : dst.hashCode());
+                result = prime * result + ((src == null) ? 0 : src.hashCode());
+                return result;
+            }
+
+            @Override
+            public boolean equals(Object obj) {
+                if (this == obj) {
+                    return true;
+                }
+                if (obj == null) {
+                    return false;
+                }
+                if (getClass() != obj.getClass()) {
+                    return false;
+                }
+                Pair other = (Pair) obj;
+                if (dst == null) {
+                    if (other.dst != null) {
+                        return false;
+                    }
+                } else if (!dst.equals(other.dst)) {
+                    return false;
+                }
+                if (src == null) {
+                    if (other.src != null) {
+                        return false;
+                    }
+                } else if (!src.equals(other.src)) {
+                    return false;
+                }
+                return true;
+            }
+
+            private final Value src;
+            private final AllocatableValue dst;
+
+            Pair(Value src, AllocatableValue dst) {
+                this.src = src;
+                this.dst = dst;
+            }
+
+            @Override
+            public String toString() {
+                return dst.toString() + " <- " + src;
+            }
+        }
+
+        private final HashSet<Pair> mapping = new HashSet<>();
+
+        @Override
+        public void addMapping(Value src, AllocatableValue dst) {
+            mapping.add(new Pair(src, dst));
+        }
+
+        public int size() {
+            return mapping.size();
+        }
+
+        public boolean contains(Value src, AllocatableValue dst) {
+            return mapping.contains(new Pair(src, dst));
+        }
+
+        @Override
+        public String toString() {
+            return mapping.toString();
+        }
+
+    }
+
+    private static final RegisterCategory CPU = new RegisterCategory("CPU");
+
+    private static final Register r0 = new Register(0, 0, "r0", CPU);
+    private static final Register r1 = new Register(1, 1, "r1", CPU);
+
+    private static enum DummyPlatformKind implements PlatformKind {
+        Long;
+
+        private EnumKey<DummyPlatformKind> key = new EnumKey<>(this);
+
+        public Key getKey() {
+            return key;
+        }
+
+        public int getSizeInBytes() {
+            return 8;
+        }
+
+        public int getVectorLength() {
+            return 1;
+        }
+
+        public char getTypeChar() {
+            return 'l';
+        }
+    }
+
+    private static final LIRKind kind = LIRKind.value(DummyPlatformKind.Long);
+
+    private MoveResolverMock resolver;
+
+    @Before
+    public void setUp() {
+        resolver = new MoveResolverMock();
+    }
+
+    private void addMapping(Value src, Value dst) {
+        TraceGlobalMoveResolutionPhase.addMapping(resolver, src, dst);
+    }
+
+    /** Create RegisterValue. */
+    private static RegisterValue v(Register r) {
+        return r.asValue(kind);
+    }
+
+    /** Create StackSlot. */
+    private static StackSlot s(int offset) {
+        return StackSlot.get(kind, -offset, true);
+    }
+
+    /** Create ShadowedRegisterValue. */
+    private static ShadowedRegisterValue sd(Register reg, int offset) {
+        return new ShadowedRegisterValue(v(reg), s(offset));
+    }
+
+    private void assertContains(Value src, AllocatableValue dst) {
+        assertTrue(String.format("Expected move from %s to %s. %s", src, dst, resolver), resolver.contains(src, dst));
+    }
+
+    private void assertSize(int expected) {
+        assertEquals(resolver.toString(), expected, resolver.size());
+    }
+
+    @Test
+    public void testReg2Reg0() {
+        addMapping(v(r0), v(r1));
+        assertContains(v(r0), v(r1));
+    }
+
+    @Test
+    public void testReg2Reg1() {
+        addMapping(v(r0), v(r0));
+        assertSize(0);
+    }
+
+    @Test
+    public void testStack2Stack0() {
+        addMapping(s(1), s(2));
+        assertContains(s(1), s(2));
+    }
+
+    @Test
+    public void testStack2Stack1() {
+        addMapping(s(1), s(1));
+        assertSize(0);
+    }
+
+    @Test
+    public void testStack2Reg() {
+        addMapping(s(1), v(r1));
+        assertContains(s(1), v(r1));
+    }
+
+    @Test
+    public void testReg2Stack() {
+        addMapping(v(r0), s(1));
+        assertContains(v(r0), s(1));
+    }
+
+    @Test
+    public void testShadowed2Reg() {
+        addMapping(sd(r0, 1), v(r1));
+        assertContains(v(r0), v(r1));
+    }
+
+    @Test
+    public void testReg2Shadowed0() {
+        addMapping(v(r0), sd(r1, 1));
+        assertSize(2);
+        assertContains(v(r0), v(r1));
+        assertContains(v(r0), s(1));
+    }
+
+    @Test
+    public void testReg2Shadowed1() {
+        addMapping(v(r0), sd(r0, 1));
+        assertSize(1);
+        assertContains(v(r0), s(1));
+    }
+
+    @Test
+    public void testStack2Shadowed0() {
+        addMapping(s(2), sd(r1, 1));
+        assertSize(2);
+        assertContains(s(2), v(r1));
+        assertContains(v(r1), s(1));
+    }
+
+    @Test
+    public void testStack2Shadowed1() {
+        addMapping(s(1), sd(r1, 1));
+        assertSize(1);
+        assertContains(s(1), v(r1));
+    }
+
+    @Test
+    public void testShadowed2Shadowed0() {
+        addMapping(sd(r0, 1), sd(r1, 2));
+        assertSize(2);
+        assertContains(v(r0), v(r1));
+        assertContains(v(r0), s(2));
+    }
+
+    @Test
+    public void testShadowed2Shadowed1() {
+        addMapping(sd(r0, 1), sd(r1, 1));
+        assertSize(1);
+        assertContains(v(r0), v(r1));
+    }
+
+    @Test
+    public void testShadowed2Shadowed2() {
+        addMapping(sd(r0, 1), sd(r0, 1));
+        assertSize(0);
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/ShadowedRegisterValue.java	Wed Nov 11 17:09:42 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/ShadowedRegisterValue.java	Thu Nov 12 18:04:38 2015 +0100
@@ -40,7 +40,7 @@
 /**
  * Represents a {@link #register} which has a shadow copy on the {@link #stackslot stack}.
  */
-final class ShadowedRegisterValue extends CompositeValue {
+public final class ShadowedRegisterValue extends CompositeValue {
     private static final EnumSet<OperandFlag> registerFlags = EnumSet.of(REG);
     private static final EnumSet<OperandFlag> stackslotFlags = EnumSet.of(STACK);
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolutionPhase.java	Wed Nov 11 17:09:42 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolutionPhase.java	Thu Nov 12 18:04:38 2015 +0100
@@ -47,7 +47,14 @@
 import com.oracle.graal.lir.ssa.SSAUtil.PhiValueVisitor;
 import com.oracle.graal.lir.ssi.SSIUtil;
 
-final class TraceGlobalMoveResolutionPhase extends TraceAllocationPhase {
+public final class TraceGlobalMoveResolutionPhase extends TraceAllocationPhase {
+
+    /**
+     * Abstract move resolver interface for testing.
+     */
+    public abstract static class MoveResolver {
+        public abstract void addMapping(Value src, AllocatableValue dst);
+    }
 
     private final TraceBuilderResult<?> resultTraces;
 
@@ -68,41 +75,7 @@
         TraceGlobalMoveResolver moveResolver = new TraceGlobalMoveResolver(lirGenRes, spillMoveFactory, arch);
         PhiValueVisitor visitor = (Value phiIn, Value phiOut) -> {
             if (!isIllegal(phiIn) && !TraceGlobalMoveResolver.isMoveToSelf(phiOut, phiIn)) {
-                // prepare input/output values.
-                final Value src;
-                final Value srcShadow;
-                if (isShadowedRegisterValue(phiOut)) {
-                    ShadowedRegisterValue phiOutSh = asShadowedRegisterValue(phiOut);
-                    src = phiOutSh.getRegister();
-                    srcShadow = phiOutSh.getStackSlot();
-                } else {
-                    src = phiOut;
-                    srcShadow = null;
-                }
-                assert src != null;
-                assert srcShadow == null || isRegister(src) && isStackSlotValue(srcShadow) : "Unexpected shadowed value: " + phiOut;
-
-                final Value dst;
-                final Value dstShadow;
-                if (isShadowedRegisterValue(phiIn)) {
-                    ShadowedRegisterValue phiInSh = asShadowedRegisterValue(phiIn);
-                    dst = phiInSh.getRegister();
-                    dstShadow = phiInSh.getStackSlot();
-                } else {
-                    dst = phiIn;
-                    dstShadow = null;
-                }
-                assert dst != null;
-                assert dstShadow == null || isRegister(dst) && isStackSlotValue(dstShadow) : "Unexpected shadowed value: " + phiIn;
-
-                // set dst
-                if (!dst.equals(src)) {
-                    moveResolver.addMapping(src, (AllocatableValue) dst);
-                }
-                // set dst_shadow
-                if (dstShadow != null && !dstShadow.equals(src)) {
-                    moveResolver.addMapping(src, (AllocatableValue) dstShadow);
-                }
+                addMapping(moveResolver, phiOut, phiIn);
             }
         };
 
@@ -135,4 +108,43 @@
             }
         }
     }
+
+    public static void addMapping(MoveResolver moveResolver, Value from, Value to) {
+        assert !isIllegal(to);
+        // prepare input/output values.
+        final Value src;
+        final Value srcShadow;
+        if (isShadowedRegisterValue(from)) {
+            ShadowedRegisterValue phiOutSh = asShadowedRegisterValue(from);
+            src = phiOutSh.getRegister();
+            srcShadow = phiOutSh.getStackSlot();
+        } else {
+            src = from;
+            srcShadow = null;
+        }
+        assert src != null;
+        assert srcShadow == null || isRegister(src) && isStackSlotValue(srcShadow) : "Unexpected shadowed value: " + from;
+
+        final Value dst;
+        final Value dstShadow;
+        if (isShadowedRegisterValue(to)) {
+            ShadowedRegisterValue phiInSh = asShadowedRegisterValue(to);
+            dst = phiInSh.getRegister();
+            dstShadow = phiInSh.getStackSlot();
+        } else {
+            dst = to;
+            dstShadow = null;
+        }
+        assert dst != null;
+        assert dstShadow == null || isRegister(dst) && isStackSlotValue(dstShadow) : "Unexpected shadowed value: " + to;
+
+        // set dst
+        if (!dst.equals(src)) {
+            moveResolver.addMapping(src, (AllocatableValue) dst);
+        }
+        // set dst_shadow
+        if (dstShadow != null && !dstShadow.equals(src)) {
+            moveResolver.addMapping(src, (AllocatableValue) dstShadow);
+        }
+    }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolver.java	Wed Nov 11 17:09:42 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolver.java	Thu Nov 12 18:04:38 2015 +0100
@@ -60,7 +60,7 @@
 
 /**
  */
-final class TraceGlobalMoveResolver {
+final class TraceGlobalMoveResolver extends TraceGlobalMoveResolutionPhase.MoveResolver {
 
     private int insertIdx;
     private LIRInsertionBuffer insertionBuffer; // buffer where moves are inserted
@@ -416,6 +416,7 @@
         this.insertIdx = insertIdx;
     }
 
+    @Override
     public void addMapping(Value from, AllocatableValue to) {
         if (Debug.isLogEnabled()) {
             Debug.log("add move mapping from %s to %s", from, to);