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