forked from oracle/graal
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use add(extended) to generate array index offset for AArch64.
We want to find a better way to implement array offset calculation. The old pattern for an int array member loading is: and x4, x3, #0xffffffff lsl x4, x4, #2 add x4, x4, #0x10 ldr x0, [x2, x4] And the optimized pattern is: add x1, x2, w3, uxtw #2 ldr x0, [x1, oracle#16] Here is a jmh unit test for int array member loading: private final int func(int[] arr) { int ret = 0; for (int i=0; i < field0; i++) { ret += arr[i]; } return ret; } And the jmh performance results: without this patch with this patch units 1173501.595 948290.420 us/op Here are the additional issues fixed related to this patch: 1. Fix an issue in MatchProcessor, so that we can process platform specific node as a matchable node. 2. Close this optimization for substratevm because the derived reference is not supported yet in SVM. mx bootstrap passes. mx gate -o -t 'CTW:hosted' passes. Change-Id: Ia34f2bf044ca6863be075cf000b29524ca44c42d
- Loading branch information
Xiaohong Gong
authored and
Stefan Anzinger
committed
Jan 7, 2020
1 parent
4c4c075
commit 98b22c6
Showing
10 changed files
with
477 additions
and
26 deletions.
There are no files selected for viewing
224 changes: 224 additions & 0 deletions
224
...core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64ArrayAddressTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
/* | ||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. | ||
* Copyright (c) 2019, Arm Limited. All rights reserved. | ||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
* | ||
* This code is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License version 2 only, as | ||
* published by the Free Software Foundation. Oracle designates this | ||
* particular file as subject to the "Classpath" exception as provided | ||
* by Oracle in the LICENSE file that accompanied this code. | ||
* | ||
* This code is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
* version 2 for more details (a copy is included in the LICENSE file that | ||
* accompanied this code). | ||
* | ||
* You should have received a copy of the GNU General Public License version | ||
* 2 along with this work; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
* | ||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
* or visit www.oracle.com if you need additional information or have any | ||
* questions. | ||
*/ | ||
package org.graalvm.compiler.core.aarch64.test; | ||
|
||
import org.graalvm.compiler.lir.LIRInstruction; | ||
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp.ExtendedAddShiftOp; | ||
import org.junit.Test; | ||
|
||
import java.util.ArrayDeque; | ||
import java.util.HashSet; | ||
import java.util.Set; | ||
import java.util.function.Predicate; | ||
|
||
public class AArch64ArrayAddressTest extends AArch64MatchRuleTest { | ||
private static final Predicate<LIRInstruction> predicate = op -> (op instanceof ExtendedAddShiftOp); | ||
|
||
public static byte loadByte(byte[] arr, int n) { | ||
return arr[n]; | ||
} | ||
|
||
@Test | ||
public void testLoadByte() { | ||
byte[] arr = {3, 4, 5, 6, 7, 8}; | ||
test("loadByte", arr, 5); | ||
checkLIR("loadByte", predicate, 1, 1); | ||
} | ||
|
||
public static char loadChar(char[] arr, int n) { | ||
return arr[n]; | ||
} | ||
|
||
@Test | ||
public void testLoadChar() { | ||
char[] arr = {'a', 'b', 'c', 'd', 'e', 'f', 'g'}; | ||
test("loadChar", arr, 5); | ||
checkLIR("loadChar", predicate, 1, 1); | ||
} | ||
|
||
public static short loadShort(short[] arr, int n) { | ||
return arr[n]; | ||
} | ||
|
||
@Test | ||
public void testLoadShort() { | ||
short[] arr = {3, 4, 5, 6, 7, 8}; | ||
test("loadShort", arr, 5); | ||
checkLIR("loadShort", predicate, 1, 1); | ||
} | ||
|
||
public static int loadInt(int[] arr, int n) { | ||
return arr[n]; | ||
} | ||
|
||
@Test | ||
public void testLoadInt() { | ||
int[] arr = {3, 4, 5, 6, 7, 8}; | ||
test("loadInt", arr, 5); | ||
checkLIR("loadInt", predicate, 1, 1); | ||
} | ||
|
||
public static long loadLong(long[] arr, int n) { | ||
return arr[n]; | ||
} | ||
|
||
@Test | ||
public void testLoadLong() { | ||
long[] arr = {3L, 4L, 5L, 6L, 7L, 8L}; | ||
test("loadLong", arr, 5); | ||
checkLIR("loadLong", predicate, 1, 1); | ||
} | ||
|
||
public static float loadFloat(float[] arr, int n) { | ||
return arr[n]; | ||
} | ||
|
||
@Test | ||
public void testLoadFloat() { | ||
float[] arr = {3.0F, 4.0F, 5.0F, 6.0F, 7.0F, 8.0F}; | ||
test("loadFloat", arr, 5); | ||
checkLIR("loadFloat", predicate, 1, 1); | ||
} | ||
|
||
public static double loadDouble(double[] arr, int n) { | ||
return arr[n]; | ||
} | ||
|
||
@Test | ||
public void testLoadDouble() { | ||
double[] arr = {3.0, 4.0, 5.0, 6.0, 7.0, 8.0}; | ||
test("loadDouble", arr, 5); | ||
checkLIR("loadDouble", predicate, 1, 1); | ||
} | ||
|
||
public static String loadObject(String[] arr, int n) { | ||
return arr[n]; | ||
} | ||
|
||
@Test | ||
public void testLoadObject() { | ||
String[] arr = {"ac", "ad", "ew", "asf", "sdad", "aff"}; | ||
test("loadObject", arr, 5); | ||
checkLIRforAll("loadObject", predicate, 1); | ||
} | ||
|
||
public static int storeInt(int[] arr, int n) { | ||
arr[n] = n * n; | ||
return arr[n]; | ||
} | ||
|
||
@Test | ||
public void testStoreInt() { | ||
int[] arr = {3, 4, 5, 6, 7, 8}; | ||
test("storeInt", arr, 5); | ||
checkLIRforAll("storeInt", predicate, 1); | ||
} | ||
|
||
public static Integer loadAndStoreObject(Integer[] arr, int i) { | ||
if (arr[i] > 0) { | ||
return 0; | ||
} | ||
arr[i] += 3; | ||
return arr[i]; | ||
} | ||
|
||
@Test | ||
public void testLoadAndStoreObject() { | ||
Integer[] arr = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; | ||
test("loadAndStoreObject", arr, 2); | ||
checkLIRforAll("loadAndStoreObject", predicate, 2); | ||
} | ||
|
||
public static int useArrayInLoop(int[] arr) { | ||
int ret = 0; | ||
for (int i = 0; i < arr.length; i++) { | ||
ret += arr[i]; | ||
} | ||
return ret; | ||
} | ||
|
||
@Test | ||
public void testUseArrayInLoop() { | ||
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8}; | ||
test("useArrayInLoop", arr); | ||
checkLIRforAll("useArrayInLoop", predicate, 1); | ||
} | ||
|
||
public static int useArrayDeque(ArrayDeque<Integer> ad) { | ||
ad.addFirst(4); | ||
return ad.removeFirst(); | ||
} | ||
|
||
@Test | ||
public void testUseArrayDeque() { | ||
ArrayDeque<Integer> ad = new ArrayDeque<>(); | ||
test("useArrayDeque", ad); | ||
} | ||
|
||
// Array load test when the index is narrowed firstly. | ||
private static class Frame { | ||
int index; | ||
|
||
Frame(int index) { | ||
this.index = index; | ||
} | ||
} | ||
|
||
private static final Frame[] frameCache = new Frame[256]; | ||
|
||
private static Frame newFrame(byte data) { | ||
return frameCache[data & 255]; | ||
} | ||
|
||
public static int getFrameIndex(int n) { | ||
return newFrame((byte) n).index; | ||
} | ||
|
||
@Test | ||
public void testGetFrameIndex() { | ||
for (int i = 0; i < 256; i++) { | ||
frameCache[i] = new Frame(i * i); | ||
} | ||
test("getFrameIndex", 258); | ||
checkLIRforAll("getFrameIndex", predicate, 1); | ||
} | ||
|
||
static Set<Long> allBarcodes = new HashSet<>(); | ||
static Set<Long> localBarcodes = new HashSet<>(); | ||
|
||
public static long useConstReferenceAsBase(long l) { | ||
localBarcodes.add(l); | ||
allBarcodes.add(l); | ||
return l; | ||
} | ||
|
||
@Test | ||
public void testUseConstReferenceAsBase() { | ||
test("useConstReferenceAsBase", 2L); | ||
int l = localBarcodes.size() + allBarcodes.size(); | ||
test("useConstReferenceAsBase", (long) l); | ||
} | ||
} |
Oops, something went wrong.