8242429: Better implementation for sign extract
Reviewed-by: vlivanov, thartmann
This commit is contained in:
parent
91220287fc
commit
babaab2edb
@ -10574,30 +10574,6 @@ instruct divI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
|
||||
ins_pipe(idiv_reg_reg);
|
||||
%}
|
||||
|
||||
instruct signExtract(iRegINoSp dst, iRegIorL2I src1, immI_31 div1, immI_31 div2) %{
|
||||
match(Set dst (URShiftI (RShiftI src1 div1) div2));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "lsrw $dst, $src1, $div1" %}
|
||||
ins_encode %{
|
||||
__ lsrw(as_Register($dst$$reg), as_Register($src1$$reg), 31);
|
||||
%}
|
||||
ins_pipe(ialu_reg_shift);
|
||||
%}
|
||||
|
||||
instruct div2Round(iRegINoSp dst, iRegIorL2I src, immI_31 div1, immI_31 div2) %{
|
||||
match(Set dst (AddI src (URShiftI (RShiftI src div1) div2)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "addw $dst, $src, LSR $div1" %}
|
||||
|
||||
ins_encode %{
|
||||
__ addw(as_Register($dst$$reg),
|
||||
as_Register($src$$reg),
|
||||
as_Register($src$$reg),
|
||||
Assembler::LSR, 31);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
// Long Divide
|
||||
|
||||
instruct divL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
|
||||
@ -10610,30 +10586,6 @@ instruct divL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
|
||||
ins_pipe(ldiv_reg_reg);
|
||||
%}
|
||||
|
||||
instruct signExtractL(iRegLNoSp dst, iRegL src1, immI_63 div1, immI_63 div2) %{
|
||||
match(Set dst (URShiftL (RShiftL src1 div1) div2));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "lsr $dst, $src1, $div1" %}
|
||||
ins_encode %{
|
||||
__ lsr(as_Register($dst$$reg), as_Register($src1$$reg), 63);
|
||||
%}
|
||||
ins_pipe(ialu_reg_shift);
|
||||
%}
|
||||
|
||||
instruct div2RoundL(iRegLNoSp dst, iRegL src, immI_63 div1, immI_63 div2) %{
|
||||
match(Set dst (AddL src (URShiftL (RShiftL src div1) div2)));
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "add $dst, $src, $div1" %}
|
||||
|
||||
ins_encode %{
|
||||
__ add(as_Register($dst$$reg),
|
||||
as_Register($src$$reg),
|
||||
as_Register($src$$reg),
|
||||
Assembler::LSR, 63);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
// Integer Remainder
|
||||
|
||||
instruct modI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -1166,6 +1166,18 @@ Node *URShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
phase->type(shl->in(2)) == t2 )
|
||||
return new AndINode( shl->in(1), phase->intcon(mask) );
|
||||
|
||||
// Check for (x >> n) >>> 31. Replace with (x >>> 31)
|
||||
Node *shr = in(1);
|
||||
if ( in1_op == Op_RShiftI ) {
|
||||
Node *in11 = shr->in(1);
|
||||
Node *in12 = shr->in(2);
|
||||
const TypeInt *t11 = phase->type(in11)->isa_int();
|
||||
const TypeInt *t12 = phase->type(in12)->isa_int();
|
||||
if ( t11 && t2 && t2->is_con(31) && t12 && t12->is_con() ) {
|
||||
return new URShiftINode(in11, phase->intcon(31));
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1295,6 +1307,17 @@ Node *URShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
phase->type(shl->in(2)) == t2 )
|
||||
return new AndLNode( shl->in(1), phase->longcon(mask) );
|
||||
|
||||
// Check for (x >> n) >>> 63. Replace with (x >>> 63)
|
||||
Node *shr = in(1);
|
||||
if ( shr->Opcode() == Op_RShiftL ) {
|
||||
Node *in11 = shr->in(1);
|
||||
Node *in12 = shr->in(2);
|
||||
const TypeLong *t11 = phase->type(in11)->isa_long();
|
||||
const TypeInt *t12 = phase->type(in12)->isa_int();
|
||||
if ( t11 && t2 && t2->is_con(63) && t12 && t12->is_con() ) {
|
||||
return new URShiftLNode(in11, phase->intcon(63));
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -252,6 +252,18 @@ Node *SubINode::Ideal(PhaseGVN *phase, bool can_reshape){
|
||||
return new SubINode( add1, in2->in(1) );
|
||||
}
|
||||
|
||||
// Convert "0-(A>>31)" into "(A>>>31)"
|
||||
if ( op2 == Op_RShiftI ) {
|
||||
Node *in21 = in2->in(1);
|
||||
Node *in22 = in2->in(2);
|
||||
const TypeInt *zero = phase->type(in1)->isa_int();
|
||||
const TypeInt *t21 = phase->type(in21)->isa_int();
|
||||
const TypeInt *t22 = phase->type(in22)->isa_int();
|
||||
if ( t21 && t22 && zero == TypeInt::ZERO && t22->is_con(31) ) {
|
||||
return new URShiftINode(in21, in22);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -361,6 +373,18 @@ Node *SubLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
return new SubLNode( add1, in2->in(1) );
|
||||
}
|
||||
|
||||
// Convert "0L-(A>>63)" into "(A>>>63)"
|
||||
if ( op2 == Op_RShiftL ) {
|
||||
Node *in21 = in2->in(1);
|
||||
Node *in22 = in2->in(2);
|
||||
const TypeLong *zero = phase->type(in1)->isa_long();
|
||||
const TypeLong *t21 = phase->type(in21)->isa_long();
|
||||
const TypeInt *t22 = phase->type(in22)->isa_int();
|
||||
if ( t21 && t22 && zero == TypeLong::ZERO && t22->is_con(63) ) {
|
||||
return new URShiftLNode(in21, in22);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
96
test/hotspot/jtreg/compiler/c2/TestSignExtract.java
Normal file
96
test/hotspot/jtreg/compiler/c2/TestSignExtract.java
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8242429
|
||||
* @summary Better implementation for sign extract.
|
||||
*
|
||||
* @run main/othervm -XX:-TieredCompilation -XX:CompileCommand=dontinline,compiler.c2.TestSignExtract::signExtract*
|
||||
* compiler.c2.TestSignExtract
|
||||
*/
|
||||
package compiler.c2;
|
||||
|
||||
public class TestSignExtract {
|
||||
|
||||
private static final long[] LONG_VALUES = {0L, 0xFFFFFFFFL, 0x12L, -1L, -123L, -0x12L, Long.MAX_VALUE, Long.MIN_VALUE};
|
||||
private static final int[] INT_VALUES = {0, 0x1234, -1, -0x12345678, Integer.MAX_VALUE, Integer.MIN_VALUE};
|
||||
|
||||
|
||||
private static int signExtractInt1(int x) {
|
||||
return (x >> 1) >>> 31;
|
||||
}
|
||||
|
||||
private static int signExtractInt2(int x) {
|
||||
return (x >> 32) >>> 31;
|
||||
}
|
||||
|
||||
private static int signExtractInt3(int x) {
|
||||
return (x >> 31) >>> 31;
|
||||
}
|
||||
|
||||
private static int signExtractInt4(int x) {
|
||||
return 0 - (x >> 31);
|
||||
}
|
||||
|
||||
private static long signExtractLong1(long x) {
|
||||
return (x >> 1) >>> 63;
|
||||
}
|
||||
|
||||
private static long signExtractLong2(long x) {
|
||||
return (x >> 54) >>> 63;
|
||||
}
|
||||
|
||||
private static long signExtractLong3(long x) {
|
||||
return (x >> 63) >>> 63;
|
||||
}
|
||||
|
||||
private static long signExtractLong4(long x) {
|
||||
return 0 - (x >> 63);
|
||||
}
|
||||
|
||||
private static int WARMUP = 5000;
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < WARMUP; i++) {
|
||||
for (int e : INT_VALUES) {
|
||||
// "(A >> n) >>> 31" => "(A >>> 31)"
|
||||
assert e >>> 31 == signExtractInt1(e);
|
||||
assert e >>> 31 == signExtractInt2(e);
|
||||
assert e >>> 31 == signExtractInt3(e);
|
||||
// "0 - (A >> 31)" => "(A >>> 31)"
|
||||
assert e >>> 31 == signExtractInt4(e);
|
||||
}
|
||||
|
||||
for (long e : LONG_VALUES) {
|
||||
// "(A >> n) >>> 63" => "(A >>> 63)"
|
||||
assert e >>> 63 == signExtractLong1(e);
|
||||
assert e >>> 63 == signExtractLong2(e);
|
||||
assert e >>> 63 == signExtractLong3(e);
|
||||
// "0 - (A >> 63)" => "(A >>> 63)"
|
||||
assert e >>> 63 == signExtractLong4(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user