Skip to content

Commit

Permalink
AArch64: Merge shift pair and integral narrow into add/sub
Browse files Browse the repository at this point in the history
This patch implements two types of match rules like C2.

1. Merge shift pair into add/sub.
2. Merge integral narrow into add/sub.

E.g. Below code is generated for `x + (((y << 56) >> 56) << 3)`

        lsl x0, x3, oracle#56
        asr x0, x0, oracle#56
        add x0, x2, x0, lsl oracle#3

After this patch, generated assembly above can be optimized to below:

        add x0, x2, w3, sxtb oracle#3

The test cases in this patch can show more details about those match
rules.

Change-Id: I82502186c8e9745dc07c349c3f66eae573006165
  • Loading branch information
Eric Liu committed Feb 21, 2020
1 parent 0380bc4 commit ed72d8c
Show file tree
Hide file tree
Showing 7 changed files with 695 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. 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
Expand Down Expand Up @@ -258,7 +258,7 @@ protected void adds(int size, Register dst, Register src1, Register src2, Extend
}

@Override
protected void sub(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
public void sub(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
super.sub(size, dst, src1, src2, extendType, shiftAmt);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1992,7 +1992,7 @@ protected void adds(int size, Register dst, Register src1, Register src2, Extend
* @param extendType defines how src2 is extended to the same size as src1.
* @param shiftAmt must be in range 0 to 4.
*/
protected void sub(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
public void sub(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
assert !dst.equals(zr);
assert !src1.equals(zr);
assert !src2.equals(sp);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, Arm Limited. All rights reserved.
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, 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
Expand All @@ -27,7 +27,7 @@

import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp.ExtendedAddShiftOp;
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp.ExtendedAddSubShiftOp;
import org.junit.Test;

import java.util.ArrayDeque;
Expand All @@ -36,7 +36,7 @@
import java.util.function.Predicate;

public class AArch64ArrayAddressTest extends AArch64MatchRuleTest {
private static final Predicate<LIRInstruction> predicate = op -> (op instanceof ExtendedAddShiftOp);
private static final Predicate<LIRInstruction> predicate = op -> (op instanceof ExtendedAddSubShiftOp);

public static byte loadByte(byte[] arr, int n) {
return arr[n];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 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;
import org.junit.Test;

import java.util.function.Predicate;

public class AArch64MergeExtendWithAddSubTest extends AArch64MatchRuleTest {

private static final Predicate<LIRInstruction> PRED_EXTEND_ADD_SHIFT = op -> (op instanceof AArch64ArithmeticOp.ExtendedAddSubShiftOp && op.name().equals("ADD"));
private static final Predicate<LIRInstruction> PRED_EXTEND_SUB_SHIFT = op -> (op instanceof AArch64ArithmeticOp.ExtendedAddSubShiftOp && op.name().equals("SUB"));

private static final Long[] LONG_VALUES = {-1L, 0L, 0x1234567812345678L, 0xFFFFFFFFL, 0x12L, 0x1234L, Long.MIN_VALUE, Long.MAX_VALUE};
private static final Integer[] INT_VALUES = {-1, 0, 0x1234, 0x12345678, Integer.MIN_VALUE, Integer.MAX_VALUE};

private <T> void predicateExist(String[] testCases, T[] values, Predicate<LIRInstruction> predicate) {
for (String t : testCases) {
for (T value : values) {
test(t, value, value);
checkLIR(t, predicate, 1);
}
}
}

public long addI2LShift(long x, long y) {
int z = (int) y;
return x + (z << 3);
}

public long addB2LShift(long x, long y) {
byte z = (byte) y;
return x + (z << 2);
}

public long addC2LShift(long x, long y) {
char z = (char) y;
return x + (z << 1);
}

public long addS2LShift(long x, long y) {
short z = (short) y;
return x + (z << 4);
}

public long subI2LShift(long x, long y) {
int z = (int) y;
return x - (z << 1);
}

public long subB2LShift(long x, long y) {
byte z = (byte) y;
return x - (z << 2);
}

public long subC2LShift(long x, long y) {
char z = (char) y;
return x - (z << 3);
}

public long subS2LShift(long x, long y) {
short z = (short) y;
return x - (z << 4);
}

public long addI2L(long x, long y) {
int z = (int) y;
return x + z;
}

public long addB2L(long x, long y) {
byte z = (byte) y;
return x + z;
}

public long addC2L(long x, long y) {
char z = (char) y;
return x + z;
}

public long addS2L(long x, long y) {
short z = (short) y;
return x + z;
}

public int addB2S(int x, int y) {
short a = (short) x;
byte b = (byte) y;
return a + b;
}

public int addB2SShift(int x, int y) {
short a = (short) x;
byte b = (byte) y;
return a + (b << 2);
}

public int addB2I(int x, int y) {
byte z = (byte) y;
return x + z;
}

public int addB2IShift(int x, int y) {
byte z = (byte) y;
return x + (z << 3);
}

public int addS2I(int x, int y) {
short z = (short) y;
return x + z;
}

public int addS2IShift(int x, int y) {
short z = (short) y;
return x + (z << 2);
}

public int addC2I(int x, int y) {
char z = (char) y;
return x + z;
}

public int addC2IShift(int x, int y) {
char z = (char) y;
return x + (z << 1);
}

@Test
public void mergeSignExtendIntoAdd() {
predicateExist(new String[]{"addB2S", "addB2I", "addS2I", "addC2I"}, INT_VALUES, PRED_EXTEND_ADD_SHIFT);
predicateExist(new String[]{"addB2L", "addC2L", "addI2L", "addS2L"}, LONG_VALUES, PRED_EXTEND_ADD_SHIFT);
}

@Test
public void mergeSignExtendShiftIntoAdd() {
predicateExist(new String[]{"addB2SShift", "addB2IShift", "addS2IShift", "addC2IShift"}, INT_VALUES, PRED_EXTEND_ADD_SHIFT);
predicateExist(new String[]{"addB2LShift", "addC2LShift", "addI2LShift", "addS2LShift"}, LONG_VALUES, PRED_EXTEND_ADD_SHIFT);
}

public long subI2L(long x, long y) {
int z = (int) y;
return x - z;
}

public long subB2L(long x, long y) {
byte z = (byte) y;
return x - z;
}

public long subC2L(long x, long y) {
char z = (char) y;
return x - z;
}

public long subS2L(long x, long y) {
short z = (short) y;
return x - z;
}

public int subB2S(int x, int y) {
short a = (short) x;
byte b = (byte) y;
return a - b;
}

public int subB2SShift(int x, int y) {
short a = (short) x;
byte b = (byte) y;
return a - (b << 2);
}

public int subB2I(int x, int y) {
byte z = (byte) y;
return x - z;
}

public int subB2IShift(int x, int y) {
byte z = (byte) y;
return x - (z << 3);
}

public int subS2I(int x, int y) {
short z = (short) y;
return x - z;
}

public int subS2IShift(int x, int y) {
short z = (short) y;
return x - (z << 2);
}

public int subC2I(int x, int y) {
char z = (char) y;
return x - z;
}

public int subC2IShift(int x, int y) {
char z = (char) y;
return x - (z << 1);
}

@Test
public void mergeSignExtendShiftIntoSub() {
predicateExist(new String[]{"subB2SShift", "subB2IShift", "subS2IShift", "subC2IShift"}, INT_VALUES, PRED_EXTEND_SUB_SHIFT);
predicateExist(new String[]{"subB2LShift", "subC2LShift", "subI2LShift", "subS2LShift"}, LONG_VALUES, PRED_EXTEND_SUB_SHIFT);
}

@Test
public void mergeSignExtendIntoSub() {
predicateExist(new String[]{"subB2S", "subB2I", "subS2I", "subC2I"}, INT_VALUES, PRED_EXTEND_SUB_SHIFT);
predicateExist(new String[]{"subB2L", "subC2L", "subI2L", "subS2L"}, LONG_VALUES, PRED_EXTEND_SUB_SHIFT);
}
}
Loading

0 comments on commit ed72d8c

Please sign in to comment.