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 }