1 /* 2 * Copyright (c) 2011, 2018, 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 24 25 package org.graalvm.compiler.core.test; 26 27 import org.junit.Test; 28 29 import org.graalvm.compiler.nodes.FrameState; 30 import org.graalvm.compiler.nodes.StructuredGraph; 31 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 32 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 33 import org.graalvm.compiler.phases.tiers.PhaseContext; 34 35 public class IntegerEqualsCanonicalizerTest extends GraalCompilerTest { 36 37 @Test 38 public void testSubtractEqualsZero() { 39 test("testSubtractEqualsZeroSnippet", "testSubtractEqualsZeroReference"); 40 } 41 42 public static int testSubtractEqualsZeroReference(int a, int b) { 43 if (a == b) { 44 return 1; 45 } 46 return 0; 47 } 48 49 public static int testSubtractEqualsZeroSnippet(int a, int b) { 50 if (a - b == 0) { 51 return 1; 52 } 53 return 0; 54 } 55 56 @Test 57 public void testSubtractEqualsZeroLong() { 58 test("testSubtractEqualsZeroLongSnippet", "testSubtractEqualsZeroLongReference"); 59 } 60 61 public static int testSubtractEqualsZeroLongReference(long a, long b) { 62 if (a == b) { 63 return 1; 64 } 65 return 0; 66 } 67 68 public static int testSubtractEqualsZeroLongSnippet(long a, long b) { 69 if (a - b == 0) { 70 return 1; 71 } 72 return 0; 73 } 74 75 /** 76 * Tests the canonicalization of (x >>> const) == 0 to x |test| (-1 << const). 77 */ 78 @Test 79 public void testShiftEquals() { 80 test("testShiftEqualsSnippet", "testShiftEqualsReference"); 81 } 82 83 @SuppressWarnings("unused") private static int field; 84 85 public static void testShiftEqualsSnippet(int x, int[] array, int y) { 86 // optimize 87 field = (x >>> 10) == 0 ? 1 : 0; 88 field = (array.length >> 10) == 0 ? 1 : 0; 89 field = (x << 10) == 0 ? 1 : 0; 90 // don't optimize 91 field = (x >> 10) == 0 ? 1 : 0; 92 field = (x >>> y) == 0 ? 1 : 0; 93 field = (x >> y) == 0 ? 1 : 0; 94 field = (x << y) == 0 ? 1 : 0; 95 field = (x >>> y) == 1 ? 1 : 0; 96 field = (x >> y) == 1 ? 1 : 0; 97 field = (x << y) == 1 ? 1 : 0; 98 } 99 100 public static void testShiftEqualsReference(int x, int[] array, int y) { 101 field = (x & 0xfffffc00) == 0 ? 1 : 0; 102 field = (array.length & 0xfffffc00) == 0 ? 1 : 0; 103 field = (x & 0x3fffff) == 0 ? 1 : 0; 104 // don't optimize signed right shifts 105 field = (x >> 10) == 0 ? 1 : 0; 106 // don't optimize no-constant shift amounts 107 field = (x >>> y) == 0 ? 1 : 0; 108 field = (x >> y) == 0 ? 1 : 0; 109 field = (x << y) == 0 ? 1 : 0; 110 // don't optimize non-zero comparisons 111 field = (x >>> y) == 1 ? 1 : 0; 112 field = (x >> y) == 1 ? 1 : 0; 113 field = (x << y) == 1 ? 1 : 0; 114 } 115 116 @Test 117 public void testCompare() { 118 test("testCompareSnippet", "testCompareReference"); 119 } 120 121 public static void testCompareSnippet(int x, int y, int[] array1, int[] array2) { 122 int tempX = x; 123 int array1Length = array1.length; 124 int array2Length = array2.length; 125 // optimize 126 field = x == tempX ? 1 : 0; 127 field = x != tempX ? 1 : 0; 128 field = array1Length != (-1 - array2Length) ? 1 : 0; 129 field = array1Length == (-1 - array2Length) ? 1 : 0; 130 // don't optimize 131 field = x == y ? 1 : 0; 132 field = array1Length == array2Length ? 1 : 0; 133 field = array1Length == (-array2Length) ? 1 : 0; 134 } 135 136 public static void testCompareReference(int x, int y, int[] array1, int[] array2) { 137 int array1Length = array1.length; 138 int array2Length = array2.length; 139 // optimize 140 field = 1; 141 field = 0; 142 field = 1; 143 field = 0; 144 // don't optimize (overlapping value ranges) 145 field = x == y ? 1 : 0; 146 field = array1Length == array2Length ? 1 : 0; 147 field = array1Length == (-array2Length) ? 1 : 0; 148 } 149 150 public static boolean testNormalIntegerTest(int a) { 151 return (a & 8) != 0; 152 } 153 154 public static boolean testAlternateIntegerTest(int a) { 155 return (a & 8) == 8; 156 } 157 158 @Test 159 public void testIntegerTest() { 160 test("testNormalIntegerTest", "testAlternateIntegerTest"); 161 } 162 163 private void test(String snippet, String referenceSnippet) { 164 StructuredGraph graph = getCanonicalizedGraph(snippet); 165 StructuredGraph referenceGraph = getCanonicalizedGraph(referenceSnippet); 166 assertEquals(referenceGraph, graph); 167 } 168 169 private StructuredGraph getCanonicalizedGraph(String snippet) { 170 StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); 171 new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); 172 for (FrameState state : graph.getNodes(FrameState.TYPE).snapshot()) { 173 state.replaceAtUsages(null); 174 state.safeDelete(); 175 } 176 return graph; 177 } 178 }