1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2018, Arm Limited and affiliates. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 
  26 
  27 package org.graalvm.compiler.core.aarch64.test;
  28 
  29 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
  30 import org.junit.Assert;
  31 import org.junit.Test;
  32 
  33 public class AArch64AddSubShiftTest extends AArch64MatchRuleTest {
  34     /**
  35      * addSubShift match rule test for add operation with int type.
  36      */
  37     private static int addLeftShiftInt(int input) {
  38         int output = (input << 5) + input;
  39         output += output << -5;
  40         output += output << 32;
  41         return output;
  42     }
  43 
  44     private static int addRightShiftInt(int input) {
  45         int output = (input >> 5) + input;
  46         output += output >> -5;
  47         output += output >> 32;
  48         return output;
  49     }
  50 
  51     private static int addUnsignedRightShiftInt(int input) {
  52         int output = (input >>> 5) + input;
  53         output += output >>> -5;
  54         output += output >>> 32;
  55         return output;
  56     }
  57 
  58     private static int addShiftInt(int input) {
  59         return addLeftShiftInt(input) + addRightShiftInt(input) + addUnsignedRightShiftInt(input);
  60     }
  61 
  62     /**
  63      * Check whether the addSubShift match rule in AArch64NodeMatchRules does work for add operation
  64      * with int type and check if the expected LIR instructions show up.
  65      */
  66     @Test
  67     public void testAddShiftInt() {
  68         int expected = addShiftInt(123);
  69 
  70         Result result = executeActual(getResolvedJavaMethod("addShiftInt"), null, 123);
  71         int actual = (int) result.returnValue;
  72         Assert.assertEquals(expected, actual);
  73 
  74         checkLIR(AArch64ArithmeticOp.AddSubShiftOp.class, 6);
  75     }
  76 
  77     /**
  78      * addSubShift match rule test for add operation with long type.
  79      */
  80     private static long addLeftShiftLong(long input) {
  81         long output = (input << 5) + input;
  82         output += output << -5;
  83         output += output << 64;
  84         return output;
  85     }
  86 
  87     private static long addRightShiftLong(long input) {
  88         long output = (input >> 5) + input;
  89         output += output >> -5;
  90         output += output >> 64;
  91         return output;
  92     }
  93 
  94     private static long addUnsignedRightShiftLong(long input) {
  95         long output = (input >>> 5) + input;
  96         output += output >>> -5;
  97         output += output >>> 64;
  98         return output;
  99     }
 100 
 101     private static long addShiftLong(long input) {
 102         return addLeftShiftLong(input) + addRightShiftLong(input) + addUnsignedRightShiftLong(input);
 103     }
 104 
 105     /**
 106      * Check whether the addSubShift match rule in AArch64NodeMatchRules does work for add operation
 107      * with long type and check if the expected LIR instructions show up.
 108      */
 109     @Test
 110     public void testAddShiftLong() {
 111         long expected = addShiftLong(1234567);
 112 
 113         Result result = executeActual(getResolvedJavaMethod("addShiftLong"), null, (long) 1234567);
 114         long actual = (long) result.returnValue;
 115         Assert.assertEquals(expected, actual);
 116 
 117         checkLIR(AArch64ArithmeticOp.AddSubShiftOp.class, 6);
 118     }
 119 
 120     /**
 121      * addSubShift match rule test for sub operation with int type.
 122      */
 123     private static int subLeftShiftInt(int input0, int input1) {
 124         return input0 - (input1 << 5);
 125     }
 126 
 127     private static int subRightShiftInt(int input0, int input1) {
 128         return input0 - (input1 >> 5);
 129     }
 130 
 131     private static int subUnsignedRightShiftInt(int input0, int input1) {
 132         return input0 - (input1 >>> 5);
 133     }
 134 
 135     private static int subShiftInt(int input0, int input1) {
 136         return subLeftShiftInt(input0, input1) + subRightShiftInt(input0, input1) + subUnsignedRightShiftInt(input0, input1);
 137     }
 138 
 139     /**
 140      * Check whether the addSubShift match rule in AArch64NodeMatchRules does work for sub operation
 141      * with int type and check if the expected LIR instructions show up.
 142      */
 143     @Test
 144     public void testSubShiftInt() {
 145         int expected = subShiftInt(123, 456);
 146 
 147         Result result = executeActual(getResolvedJavaMethod("subShiftInt"), null, 123, 456);
 148         int actual = (int) result.returnValue;
 149         Assert.assertEquals(expected, actual);
 150 
 151         checkLIR(AArch64ArithmeticOp.AddSubShiftOp.class, 3);
 152     }
 153 
 154     /**
 155      * addSubShift match rule test for sub operation with long type.
 156      */
 157     private static long subLeftShiftLong(long input0, long input1) {
 158         return input0 - (input1 << 5);
 159     }
 160 
 161     private static long subRightShiftLong(long input0, long input1) {
 162         return input0 - (input1 >> 5);
 163     }
 164 
 165     private static long subUnsignedRightShiftLong(long input0, long input1) {
 166         return input0 - (input1 >>> 5);
 167     }
 168 
 169     private static long subShiftLong(long input0, long input1) {
 170         return subLeftShiftLong(input0, input1) + subRightShiftLong(input0, input1) + subUnsignedRightShiftLong(input0, input1);
 171     }
 172 
 173     /**
 174      * Check whether the addSubShift match rule in AArch64NodeMatchRules does work for sub operation
 175      * with long type and check if the expected LIR instructions show up.
 176      */
 177     @Test
 178     public void testSubShiftLong() {
 179         long expected = subShiftLong(1234567, 123);
 180 
 181         Result result = executeActual(getResolvedJavaMethod("subShiftLong"), null, (long) 1234567, (long) 123);
 182         long actual = (long) result.returnValue;
 183         Assert.assertEquals(expected, actual);
 184 
 185         checkLIR(AArch64ArithmeticOp.AddSubShiftOp.class, 3);
 186     }
 187 }