Skip to content

Commit

Permalink
AArch64: Add match rules for bitfield move.
Browse files Browse the repository at this point in the history
This patch adds the following match rules to generate bitfield
move instruction on AArch64:
* (RightShift (LeftShift value a) b)         -> SBFX/SBFIZ
* (UnsignedRightShift (LeftShift value a) b) -> UBFX/UBFIZ
* (LeftShift (SignExtend value) a)           -> SBFIZ
Eg:
  lsl    w0, w1, oracle#8
  asr    w0, w0, oracle#15
is optimized to:
  sbfx   w0, w1, oracle#7, oracle#17

It also adds the rules to integrate the ZeroExtend with unsigned
bitfield move operation.
Eg:
  ubfiz  w0, w1, oracle#5, oracle#12
  and    x0, x0, #0xffffffff
is optimized to:
  ubfiz  x0, x1, oracle#5, oracle#12

Change-Id: I2b635d4895db0d5f4c30630176f336e9a226ccaf
  • Loading branch information
Xiaohong Gong committed Feb 24, 2020
1 parent a372222 commit 5b1d4e2
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 51 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 @@ -218,7 +218,7 @@ public void ubfm(int size, Register dst, Register src, int r, int s) {
}

@Override
protected void sbfm(int size, Register dst, Register src, int r, int s) {
public void sbfm(int size, Register dst, Register src, int r, int s) {
super.sbfm(size, dst, src, r, s);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1850,7 +1850,7 @@ public void ubfm(int size, Register dst, Register src, int r, int s) {
* @param r must be in the range 0 to size - 1
* @param s must be in the range 0 to size - 1
*/
protected void sbfm(int size, Register dst, Register src, int r, int s) {
public void sbfm(int size, Register dst, Register src, int r, int s) {
bitfieldInstruction(SBFM, dst, src, r, s, generalFromSize(size));
}

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 and affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Arm Limited and 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 @@ -36,12 +36,16 @@ public class AArch64BitFieldTest extends AArch64MatchRuleTest {
private static final Predicate<LIRInstruction> predicate = op -> (op instanceof AArch64BitFieldOp);

private void testAndCheckLIR(String method, String negativeMethod, Object input) {
test(method, input);
checkLIR(method, predicate, 1);
testAndCheckLIR(method, input);
test(negativeMethod, input);
checkLIR(negativeMethod, predicate, 0);
}

private void testAndCheckLIR(String method, Object input) {
test(method, input);
checkLIR(method, predicate, 1);
}

/**
* unsigned bit field extract int.
*/
Expand Down Expand Up @@ -133,4 +137,174 @@ public static long invalidInsertLong(long input) {
public void testInsertLong() {
testAndCheckLIR("insertLong", "invalidInsertLong", 0xdeadbeefdeadbeefL);
}

// Tests for unsigned bitfield move, with integration of zero extend (I2L) operation.
//
// UBFIZ with I2L.
public static long unsignedInsertExtend(int input) {
return ((long) (input & 0xffff)) << 8;
}

@Test
public void testUnsignedInsertExtend() {
testAndCheckLIR("unsignedInsertExtend", 0x234);
}

// I2L with UBFIZ.
public static long unsignedExtendInsert(int input) {
return (input & 0xfff) << 5;
}

@Test
public void testUnsignedExtendInsert() {
testAndCheckLIR("unsignedExtendInsert", 0x4334);
}

// I2L with UBFX.
public static long unsignedExtendExtract(int input) {
return (input >>> 6) & 0xffffff;
}

@Test
public void testUnsignedExtendExtract() {
testAndCheckLIR("unsignedExtendExtract", 0x325ab);
}

// Signed bitfield insert with extend, generated by (LeftShift (SignExtend value) a) match
// rule.
// SBFIZ with B2L.
public long signedB2LInsert(long input) {
byte b = (byte) input;
return ((long) b) << 2;
}

@Test
public void testSignedB2LInsert() {
testAndCheckLIR("signedB2LInsert", 0xab3213efL);
}

// SBFIZ with S2L.
public long signedS2LInsert(long input) {
short s = (short) input;
return ((long) s) << -5;
}

@Test
public void testSignedS2LInsert() {
testAndCheckLIR("signedS2LInsert", 0x328032bL);
}

// SBFIZ with I2L.
public static long signedI2LInsert(int input) {
return ((long) input) << 1;
}

@Test
public void testSignedI2LInsert() {
testAndCheckLIR("signedI2LInsert", 31);
}

// SBFIZ with B2I.
public int signedB2IInsert(int input) {
byte b = (byte) input;
return b << 31;
}

@Test
public void testSignedB2IInsert() {
testAndCheckLIR("signedB2IInsert", 0x23);
}

// SBFIZ with S2I.
public int signedS2IInsert(int input) {
short s = (short) input;
return s << 2;
}

@Test
public void testSignedS2IInsert() {
testAndCheckLIR("signedS2IInsert", 0x92);
}

// Tests for bitfield move generated by ([Unsigned]RightShift (LeftShift value a) b) match
// rules.
// SBFX for int.
public static int signedExtractInt(int input) {
return (input << 8) >> 15;
}

@Test
public void testSignedExtractInt() {
testAndCheckLIR("signedExtractInt", 0x123);
}

// SBFX for long.
public static long signedExtractLong(long input) {
return (input << 8) >> 15;
}

@Test
public void testSignedExtractLong() {
testAndCheckLIR("signedExtractLong", 0x125L);
}

// SBFIZ for int.
public static int signedInsertInt(int input) {
return (input << 15) >> 8;
}

@Test
public void testSignedInsertInt() {
testAndCheckLIR("signedInsertInt", 0x1253);
}

// SBFIZ for long.
public static long signedInsertLong(long input) {
return (input << 15) >> 8;
}

@Test
public void testSignedInsertLong() {
testAndCheckLIR("signedInsertLong", 0xabcddbc325L);
}

// UBFX for int.
public static int unsignedExtractInt(int input) {
return (input << 8) >>> 31;
}

@Test
public void testUnsignedExtractInt() {
testAndCheckLIR("unsignedExtractInt", 0x125);
}

// UBFX for long.
public static long unsignedExtractLong(long input) {
return (input << 8) >>> 12;
}

@Test
public void testUnsignedExtractLong() {
testAndCheckLIR("unsignedExtractLong", 0x32222e125L);
}

// UBFIZ for int.
public static int unsignedInsertInt(int input) {
return (input << 15) >>> 8;
}

@Test
public void testUnsignedInsertInt() {
testAndCheckLIR("unsignedInsertInt", 125);
}

// UBFIZ for long.
public static long unsignedInsertLong(long input) {
return (input << 63) >>> 1;
}

@Test
public void testUnsignedInsertLong() {
testAndCheckLIR("unsignedInsertLong", 0x2339fb125L);
}
}
Loading

0 comments on commit 5b1d4e2

Please sign in to comment.