< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64MatchRuleTest.java

Print this page

        

@@ -24,18 +24,23 @@
 
 package org.graalvm.compiler.core.amd64.test;
 
 import static org.junit.Assume.assumeTrue;
 
+import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.core.test.MatchRuleTest;
 import org.graalvm.compiler.lir.LIR;
 import org.graalvm.compiler.lir.LIRInstruction;
+import org.graalvm.compiler.lir.amd64.AMD64Binary;
 import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer.MemoryConstOp;
+import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer.ConstOp;
+import org.graalvm.compiler.lir.amd64.AMD64Unary;
 import org.junit.Before;
 import org.junit.Test;
 
 import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.amd64.AMD64Kind;
 
 public class AMD64MatchRuleTest extends MatchRuleTest {
     @Before
     public void checkAMD64() {
         assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64);

@@ -75,6 +80,184 @@
         public TestClass(int x) {
             super();
             this.x = x;
         }
     }
+
+    static volatile short shortValue;
+
+    public static long testVolatileExtensionSnippet() {
+        return shortValue;
+    }
+
+    @Test
+    public void testVolatileExtension() {
+        compile(getResolvedJavaMethod("testVolatileExtensionSnippet"), null);
+        LIR lir = getLIR();
+        boolean found = false;
+        for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) {
+            if (ins instanceof AMD64Unary.MemoryOp) {
+                ins.visitEachOutput((value, mode, flags) -> assertTrue(value.getPlatformKind().toString(), value.getPlatformKind().equals(AMD64Kind.QWORD)));
+                assertFalse("MemoryOp expected only once in first block", found);
+                found = true;
+            }
+        }
+        assertTrue("sign extending load must be in the LIR", found);
+    }
+
+    static int intValue;
+    static volatile int volatileIntValue;
+
+    /**
+     * Can't match test and load of input because of volatile store in between.
+     */
+    public static short testLoadTestNoMatchSnippet() {
+        int v = intValue;
+        volatileIntValue = 42;
+        if (v == 42) {
+            return shortValue;
+        }
+        return 0;
+    }
+
+    @Test
+    public void testLoadTestNoMatch() {
+        compile(getResolvedJavaMethod("testLoadTestNoMatchSnippet"), null);
+        LIR lir = getLIR();
+        boolean found = false;
+        for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) {
+            if (ins instanceof ConstOp && ((ConstOp) ins).getOpcode().toString().equals("CMP")) {
+                assertFalse("CMP expected only once in first block", found);
+                found = true;
+            }
+        }
+        assertTrue("CMP must be in the LIR", found);
+    }
+
+    /**
+     * Should match as an add with a memory operand.
+     */
+    public static int testAddLoadSnippet() {
+        int v1 = volatileIntValue;
+        int v2 = intValue;
+        return v2 + (2 * v1);
+    }
+
+    @Test
+    public void testAddLoad() {
+        compile(getResolvedJavaMethod("testAddLoadSnippet"), null);
+        LIR lir = getLIR();
+        boolean found = false;
+        for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) {
+            if (ins instanceof AMD64Binary.MemoryTwoOp && ((AMD64Binary.MemoryTwoOp) ins).getOpcode().toString().equals("ADD")) {
+                assertFalse("MemoryTwoOp expected only once in first block", found);
+                found = true;
+            }
+        }
+        assertTrue("ADD with memory argument must be in the LIR", found);
+    }
+
+    /**
+     * Can't match as an add with a memory operand because the other add input is too late.
+     */
+    public static int testAddLoadNoMatchSnippet() {
+        int v1 = volatileIntValue;
+        int v2 = intValue;
+        return v1 + (2 * v2);
+    }
+
+    @Test
+    public void testAddLoadNoMatch() {
+        compile(getResolvedJavaMethod("testAddLoadNoMatchSnippet"), null);
+        LIR lir = getLIR();
+        boolean found = false;
+        for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) {
+            if (ins instanceof AMD64Binary.CommutativeTwoOp && ((AMD64Binary.CommutativeTwoOp) ins).getOpcode().toString().equals("ADD")) {
+                assertFalse("CommutativeTwoOp expected only once in first block", found);
+                found = true;
+            }
+        }
+        assertTrue("ADD with memory argument must not be in the LIR", found);
+    }
+
+    /**
+     * sign extension and load are in different blocks but can still be matched as a single
+     * instruction.
+     */
+    public static long testVolatileExtensionDifferentBlocksSnippet(boolean flag) {
+        short v = shortValue;
+        if (flag) {
+            return v;
+        }
+        return 0;
+    }
+
+    @Test
+    public void testVolatileExtensionDifferentBlocks() {
+        compile(getResolvedJavaMethod("testVolatileExtensionDifferentBlocksSnippet"), null);
+        LIR lir = getLIR();
+        boolean found = false;
+        for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) {
+            if (ins instanceof AMD64Unary.MemoryOp) {
+                ins.visitEachOutput((value, mode, flags) -> assertTrue(value.getPlatformKind().toString(), value.getPlatformKind().equals(AMD64Kind.QWORD)));
+                assertFalse("MemoryOp expected only once in first block", found);
+                found = true;
+            }
+        }
+        assertTrue("sign extending load must be in the LIR", found);
+    }
+
+    /**
+     * Add and load are not in the same block and one input is too late: can't match.
+     */
+    public static int testAddLoadDifferentBlocksNoMatchSnippet(boolean flag) {
+        int v1 = volatileIntValue;
+        if (flag) {
+            int v2 = intValue;
+            return v1 + (2 * v2);
+        }
+        return 0;
+    }
+
+    @Test
+    public void testAddLoadDifferentBlocksNoMatch() {
+        compile(getResolvedJavaMethod("testAddLoadDifferentBlocksNoMatchSnippet"), null);
+        LIR lir = getLIR();
+        boolean found = false;
+        for (AbstractBlockBase<?> b : lir.codeEmittingOrder()) {
+            for (LIRInstruction ins : lir.getLIRforBlock(b)) {
+                if (ins instanceof AMD64Binary.CommutativeTwoOp && ((AMD64Binary.CommutativeTwoOp) ins).getOpcode().toString().equals("ADD")) {
+                    assertFalse("CommutativeTwoOp expected only once in first block", found);
+                    found = true;
+                }
+            }
+        }
+        assertTrue("ADD with memory argument must not be in the LIR", found);
+    }
+
+    /**
+     * Add and load are in different blocks but can still match.
+     */
+    public static int testAddLoadDifferentBlocksSnippet(boolean flag) {
+        int v2 = intValue;
+        int v1 = volatileIntValue;
+        if (flag) {
+            return v1 + v2;
+        }
+        return 0;
+    }
+
+    @Test
+    public void testAddLoadDifferentBlocks() {
+        compile(getResolvedJavaMethod("testAddLoadDifferentBlocksSnippet"), null);
+        LIR lir = getLIR();
+        boolean found = false;
+        for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) {
+            if (ins instanceof AMD64Binary.MemoryTwoOp && ((AMD64Binary.MemoryTwoOp) ins).getOpcode().toString().equals("ADD")) {
+                assertFalse("MemoryTwoOp expected only once in first block", found);
+                found = true;
+            }
+        }
+        assertTrue("ADD with memory argument must be in the LIR", found);
+    }
+
 }
< prev index next >