1 /*
2  * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
3  * Copyright (c) 2019, 2020, Arm Limited. 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 package org.graalvm.compiler.core.aarch64.test;
27 
28 import org.graalvm.compiler.api.directives.GraalDirectives;
29 import org.graalvm.compiler.lir.LIRInstruction;
30 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp.ExtendedAddSubShiftOp;
31 import org.junit.Test;
32 
33 import java.util.ArrayDeque;
34 import java.util.HashSet;
35 import java.util.Set;
36 import java.util.function.Predicate;
37 
38 public class AArch64ArrayAddressTest extends AArch64MatchRuleTest {
39     private static final Predicate<LIRInstruction> predicate = op -> (op instanceof ExtendedAddSubShiftOp);
40 
loadByte(byte[] arr, int n)41     public static byte loadByte(byte[] arr, int n) {
42         return arr[n];
43     }
44 
45     @Test
testLoadByte()46     public void testLoadByte() {
47         byte[] arr = {3, 4, 5, 6, 7, 8};
48         test("loadByte", arr, 5);
49         checkLIR("loadByte", predicate, 1, 1);
50     }
51 
loadChar(char[] arr, int n)52     public static char loadChar(char[] arr, int n) {
53         return arr[n];
54     }
55 
56     @Test
testLoadChar()57     public void testLoadChar() {
58         char[] arr = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
59         test("loadChar", arr, 5);
60         checkLIR("loadChar", predicate, 1, 1);
61     }
62 
loadShort(short[] arr, int n)63     public static short loadShort(short[] arr, int n) {
64         return arr[n];
65     }
66 
67     @Test
testLoadShort()68     public void testLoadShort() {
69         short[] arr = {3, 4, 5, 6, 7, 8};
70         test("loadShort", arr, 5);
71         checkLIR("loadShort", predicate, 1, 1);
72     }
73 
loadInt(int[] arr, int n)74     public static int loadInt(int[] arr, int n) {
75         return arr[n];
76     }
77 
78     @Test
testLoadInt()79     public void testLoadInt() {
80         int[] arr = {3, 4, 5, 6, 7, 8};
81         test("loadInt", arr, 5);
82         checkLIR("loadInt", predicate, 1, 1);
83     }
84 
loadLong(long[] arr, int n)85     public static long loadLong(long[] arr, int n) {
86         return arr[n];
87     }
88 
89     @Test
testLoadLong()90     public void testLoadLong() {
91         long[] arr = {3L, 4L, 5L, 6L, 7L, 8L};
92         test("loadLong", arr, 5);
93         checkLIR("loadLong", predicate, 1, 1);
94     }
95 
loadFloat(float[] arr, int n)96     public static float loadFloat(float[] arr, int n) {
97         return arr[n];
98     }
99 
100     @Test
testLoadFloat()101     public void testLoadFloat() {
102         float[] arr = {3.0F, 4.0F, 5.0F, 6.0F, 7.0F, 8.0F};
103         test("loadFloat", arr, 5);
104         checkLIR("loadFloat", predicate, 1, 1);
105     }
106 
loadDouble(double[] arr, int n)107     public static double loadDouble(double[] arr, int n) {
108         return arr[n];
109     }
110 
111     @Test
testLoadDouble()112     public void testLoadDouble() {
113         double[] arr = {3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
114         test("loadDouble", arr, 5);
115         checkLIR("loadDouble", predicate, 1, 1);
116     }
117 
loadObject(String[] arr, int n)118     public static String loadObject(String[] arr, int n) {
119         return arr[n];
120     }
121 
122     @Test
testLoadObject()123     public void testLoadObject() {
124         String[] arr = {"ac", "ad", "ew", "asf", "sdad", "aff"};
125         test("loadObject", arr, 5);
126         checkLIRforAll("loadObject", predicate, 1);
127     }
128 
storeInt(int[] arr, int n)129     public static int storeInt(int[] arr, int n) {
130         arr[n] = n * n;
131         return arr[n];
132     }
133 
134     @Test
testStoreInt()135     public void testStoreInt() {
136         int[] arr = {3, 4, 5, 6, 7, 8};
137         test("storeInt", arr, 5);
138         checkLIRforAll("storeInt", predicate, 1);
139     }
140 
loadAndStoreObject(Integer[] arr, int i)141     public static Integer loadAndStoreObject(Integer[] arr, int i) {
142         if (arr[i] > 0) {
143             return 0;
144         }
145         arr[i] += 3;
146         return arr[i];
147     }
148 
149     @Test
testLoadAndStoreObject()150     public void testLoadAndStoreObject() {
151         Integer[] arr = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
152         test("loadAndStoreObject", arr, 2);
153         checkLIRforAll("loadAndStoreObject", predicate, 2);
154     }
155 
useArrayInLoop(int[] arr)156     public static int useArrayInLoop(int[] arr) {
157         int ret = 0;
158         for (int i = 0; i < arr.length; i++) {
159             ret += GraalDirectives.opaque(arr[i]);
160         }
161         return ret;
162     }
163 
164     @Test
testUseArrayInLoop()165     public void testUseArrayInLoop() {
166         int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
167         test("useArrayInLoop", arr);
168         checkLIRforAll("useArrayInLoop", predicate, 1);
169     }
170 
useArrayDeque(ArrayDeque<Integer> ad)171     public static int useArrayDeque(ArrayDeque<Integer> ad) {
172         ad.addFirst(4);
173         return ad.removeFirst();
174     }
175 
176     @Test
testUseArrayDeque()177     public void testUseArrayDeque() {
178         ArrayDeque<Integer> ad = new ArrayDeque<>();
179         test("useArrayDeque", ad);
180     }
181 
182     // Array load test when the index is narrowed firstly.
183     private static class Frame {
184         int index;
185 
Frame(int index)186         Frame(int index) {
187             this.index = index;
188         }
189     }
190 
191     private static final Frame[] frameCache = new Frame[256];
192 
newFrame(byte data)193     private static Frame newFrame(byte data) {
194         return frameCache[data & 255];
195     }
196 
getFrameIndex(int n)197     public static int getFrameIndex(int n) {
198         return newFrame((byte) n).index;
199     }
200 
201     @Test
testGetFrameIndex()202     public void testGetFrameIndex() {
203         for (int i = 0; i < 256; i++) {
204             frameCache[i] = new Frame(i * i);
205         }
206         test("getFrameIndex", 258);
207         checkLIRforAll("getFrameIndex", predicate, 1);
208     }
209 
210     static Set<Long> allBarcodes = new HashSet<>();
211     static Set<Long> localBarcodes = new HashSet<>();
212 
useConstReferenceAsBase(long l)213     public static long useConstReferenceAsBase(long l) {
214         localBarcodes.add(l);
215         allBarcodes.add(l);
216         return l;
217     }
218 
219     @Test
testUseConstReferenceAsBase()220     public void testUseConstReferenceAsBase() {
221         test("useConstReferenceAsBase", 2L);
222         int l = localBarcodes.size() + allBarcodes.size();
223         test("useConstReferenceAsBase", (long) l);
224     }
225 }
226