1 /*
   2  * Copyright (c) 2015, 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.nodes.test;
  26 
  27 import org.graalvm.compiler.api.directives.GraalDirectives;
  28 import org.graalvm.compiler.core.test.GraalCompilerTest;
  29 import org.graalvm.compiler.graph.Node;
  30 import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
  31 import org.graalvm.compiler.nodes.IfNode;
  32 import org.graalvm.compiler.nodes.LogicNode;
  33 import org.graalvm.compiler.nodes.StructuredGraph;
  34 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
  35 import org.graalvm.compiler.nodes.calc.SubNode;
  36 import org.graalvm.compiler.nodes.spi.CoreProviders;
  37 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
  38 import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
  39 import org.junit.Assert;
  40 import org.junit.Ignore;
  41 import org.junit.Test;
  42 
  43 /**
  44  * A few tests of expected simplifications by
  45  * {@link IfNode#simplify(org.graalvm.compiler.graph.spi.SimplifierTool)}.
  46  */
  47 public class IfNodeCanonicalizationTest extends GraalCompilerTest {
  48 
  49     static int value;
  50 
  51     static final byte[] testValues = {-128, -1, 0, 1, 127};
  52 
  53     @Test
  54     public void test1() {
  55         /*
  56          * exercise conversion of x - y < 0 into x < y, both by checking expected graph shape and
  57          * that the transformed code produces the right answer.
  58          */
  59         test("testSnippet1", SubNode.class, 0);
  60         byte[] values = new byte[4];
  61         for (byte a : testValues) {
  62             values[0] = a;
  63             for (byte b : testValues) {
  64                 values[1] = b;
  65                 for (byte c : testValues) {
  66                     values[2] = c;
  67                     for (byte d : testValues) {
  68                         values[3] = d;
  69                         value = 2;
  70                         super.test("testSnippet1", values, true);
  71                         super.test("testSnippet1", values, false);
  72                     }
  73                 }
  74             }
  75         }
  76     }
  77 
  78     public int testSnippet1(byte[] values, boolean test) {
  79         int v = values[0] - values[1];
  80         if (test) {
  81             v = values[2] - values[3];
  82         }
  83         if (v < 0) {
  84             value = 1;
  85         }
  86         return value;
  87     }
  88 
  89     @Test
  90     public void test2() {
  91         test("testSnippet2", 1);
  92     }
  93 
  94     public boolean testSnippet2(int a, int[] limit) {
  95         int l = limit.length;
  96         if (!(a >= 0 && a < l)) {
  97             value = a;
  98             return true;
  99         }
 100         return false;
 101     }
 102 
 103     @Ignore("currently not working because swapped case isn't handled")
 104     @Test
 105     public void test3() {
 106         test("testSnippet3", 1);
 107     }
 108 
 109     public boolean testSnippet3(int a, int[] limit) {
 110         int l = limit.length;
 111         if (a < l && a >= 0) {
 112             value = 9;
 113             return true;
 114         }
 115         return false;
 116     }
 117 
 118     @Test
 119     public void test4() {
 120         test("testSnippet4", 1);
 121     }
 122 
 123     public boolean testSnippet4(int a, int[] limit) {
 124         int l = limit.length;
 125         if (a < 0) {
 126             GraalDirectives.deoptimize();
 127         }
 128         if (a >= l) {
 129             GraalDirectives.deoptimize();
 130         }
 131         return true;
 132     }
 133 
 134     @Ignore("Reversed conditions aren't working with guards")
 135     @Test
 136     public void test5() {
 137         test("testSnippet5", 1);
 138     }
 139 
 140     public boolean testSnippet5(int a, int[] limit) {
 141         int l = limit.length;
 142         if (a >= l) {
 143             GraalDirectives.deoptimize();
 144         }
 145         if (a < 0) {
 146             GraalDirectives.deoptimize();
 147         }
 148         return true;
 149     }
 150 
 151     public void test(String name, int logicCount) {
 152         test(name, LogicNode.class, logicCount);
 153     }
 154 
 155     public void test(String name, Class<? extends Node> expectedClass, int expectedCount) {
 156         StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
 157 
 158         CoreProviders context = getProviders();
 159         CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
 160         new ConvertDeoptimizeToGuardPhase().apply(graph, context);
 161         graph.clearAllStateAfter();
 162         graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA);
 163         canonicalizer.apply(graph, context);
 164 
 165         // new DominatorConditionalEliminationPhase(true).apply(graph, context);
 166         new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context);
 167         canonicalizer.apply(graph, context);
 168         canonicalizer.apply(graph, context);
 169 
 170         Assert.assertEquals(expectedCount, graph.getNodes().filter(expectedClass).count());
 171     }
 172 }