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.LIRInstruction;
  30 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
  31 import org.junit.Test;
  32 
  33 import java.util.function.Predicate;
  34 
  35 public class AArch64AddSubShiftTest extends AArch64MatchRuleTest {
  36     private static final Predicate<LIRInstruction> predicate = op -> (op instanceof AArch64ArithmeticOp.BinaryShiftOp);
  37 
  38     /**
  39      * addSubShift match rule test for add operation with int type.
  40      */
  41     private static int addLeftShiftInt(int input) {
  42         int output = (input << 5) + input;
  43         output += output << -5;
  44         output += output << 32;
  45         return output;
  46     }
  47 
  48     private static int addRightShiftInt(int input) {
  49         int output = (input >> 5) + input;
  50         output += output >> -5;
  51         output += output >> 32;
  52         return output;
  53     }
  54 
  55     private static int addUnsignedRightShiftInt(int input) {
  56         int output = (input >>> 5) + input;
  57         output += output >>> -5;
  58         output += output >>> 32;
  59         return output;
  60     }
  61 
  62     public static int addShiftInt(int input) {
  63         return addLeftShiftInt(input) + addRightShiftInt(input) + addUnsignedRightShiftInt(input);
  64     }
  65 
  66     /**
  67      * Check whether the addSubShift match rule in AArch64NodeMatchRules does work for add operation
  68      * with int type and check if the expected LIR instructions show up.
  69      */
  70     @Test
  71     public void testAddShiftInt() {
  72         test("addShiftInt", 123);
  73         checkLIR("addShiftInt", predicate, 6);
  74     }
  75 
  76     /**
  77      * addSubShift match rule test for add operation with long type.
  78      */
  79     private static long addLeftShiftLong(long input) {
  80         long output = (input << 5) + input;
  81         output += output << -5;
  82         output += output << 64;
  83         return output;
  84     }
  85 
  86     private static long addRightShiftLong(long input) {
  87         long output = (input >> 5) + input;
  88         output += output >> -5;
  89         output += output >> 64;
  90         return output;
  91     }
  92 
  93     private static long addUnsignedRightShiftLong(long input) {
  94         long output = (input >>> 5) + input;
  95         output += output >>> -5;
  96         output += output >>> 64;
  97         return output;
  98     }
  99 
 100     public static long addShiftLong(long input) {
 101         return addLeftShiftLong(input) + addRightShiftLong(input) + addUnsignedRightShiftLong(input);
 102     }
 103 
 104     /**
 105      * Check whether the addSubShift match rule in AArch64NodeMatchRules does work for add operation
 106      * with long type and check if the expected LIR instructions show up.
 107      */
 108     @Test
 109     public void testAddShiftLong() {
 110         test("addShiftLong", 1234567L);
 111         checkLIR("addShiftLong", predicate, 6);
 112     }
 113 
 114     /**
 115      * addSubShift match rule test for sub operation with int type.
 116      */
 117     private static int subLeftShiftInt(int input0, int input1) {
 118         return input0 - (input1 << 5);
 119     }
 120 
 121     private static int subRightShiftInt(int input0, int input1) {
 122         return input0 - (input1 >> 5);
 123     }
 124 
 125     private static int subUnsignedRightShiftInt(int input0, int input1) {
 126         return input0 - (input1 >>> 5);
 127     }
 128 
 129     public static int subShiftInt(int input0, int input1) {
 130         return subLeftShiftInt(input0, input1) + subRightShiftInt(input0, input1) + subUnsignedRightShiftInt(input0, input1);
 131     }
 132 
 133     /**
 134      * Check whether the addSubShift match rule in AArch64NodeMatchRules does work for sub operation
 135      * with int type and check if the expected LIR instructions show up.
 136      */
 137     @Test
 138     public void testSubShiftInt() {
 139         test("subShiftInt", 123, 456);
 140         checkLIR("subShiftInt", predicate, 3);
 141     }
 142 
 143     /**
 144      * addSubShift match rule test for sub operation with long type.
 145      */
 146     private static long subLeftShiftLong(long input0, long input1) {
 147         return input0 - (input1 << 5);
 148     }
 149 
 150     private static long subRightShiftLong(long input0, long input1) {
 151         return input0 - (input1 >> 5);
 152     }
 153 
 154     private static long subUnsignedRightShiftLong(long input0, long input1) {
 155         return input0 - (input1 >>> 5);
 156     }
 157 
 158     public static long subShiftLong(long input0, long input1) {
 159         return subLeftShiftLong(input0, input1) + subRightShiftLong(input0, input1) + subUnsignedRightShiftLong(input0, input1);
 160     }
 161 
 162     /**
 163      * Check whether the addSubShift match rule in AArch64NodeMatchRules does work for sub operation
 164      * with long type and check if the expected LIR instructions show up.
 165      */
 166     @Test
 167     public void testSubShiftLong() {
 168         test("subShiftLong", 1234567L, 123L);
 169         checkLIR("subShiftLong", predicate, 3);
 170     }
 171 }