8254872: Optimize Rotate on AArch64

Reviewed-by: aph, kvn
This commit is contained in:
Eric Liu 2020-11-17 01:55:09 +00:00 committed by Nick Gasson
parent eabf3bace7
commit 30a2ad5501
4 changed files with 93 additions and 183 deletions
src/hotspot

@ -12757,160 +12757,96 @@ instruct extrAddI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI lshift,
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// rol expander
instruct rolL_rReg(iRegLNoSp dst, iRegL src, iRegI shift, rFlagsReg cr)
instruct rorI_imm(iRegINoSp dst, iRegI src, immI shift)
%{
effect(DEF dst, USE src, USE shift);
match(Set dst (RotateRight src shift));
format %{ "rol $dst, $src, $shift" %}
ins_cost(INSN_COST * 3);
ins_encode %{
__ subw(rscratch1, zr, as_Register($shift$$reg));
__ rorv(as_Register($dst$$reg), as_Register($src$$reg),
rscratch1);
%}
ins_pipe(ialu_reg_reg_vshift);
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// rol expander
instruct rolI_rReg(iRegINoSp dst, iRegI src, iRegI shift, rFlagsReg cr)
%{
effect(DEF dst, USE src, USE shift);
format %{ "rol $dst, $src, $shift" %}
ins_cost(INSN_COST * 3);
ins_encode %{
__ subw(rscratch1, zr, as_Register($shift$$reg));
__ rorvw(as_Register($dst$$reg), as_Register($src$$reg),
rscratch1);
%}
ins_pipe(ialu_reg_reg_vshift);
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
instruct rolL_rReg_Var_C_64(iRegLNoSp dst, iRegL src, iRegI shift, immI_64 c_64, rFlagsReg cr)
%{
match(Set dst (OrL (LShiftL src shift) (URShiftL src (SubI c_64 shift))));
expand %{
rolL_rReg(dst, src, shift, cr);
%}
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
instruct rolL_rReg_Var_C0(iRegLNoSp dst, iRegL src, iRegI shift, immI0 c0, rFlagsReg cr)
%{
match(Set dst (OrL (LShiftL src shift) (URShiftL src (SubI c0 shift))));
expand %{
rolL_rReg(dst, src, shift, cr);
%}
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
instruct rolI_rReg_Var_C_32(iRegINoSp dst, iRegI src, iRegI shift, immI_32 c_32, rFlagsReg cr)
%{
match(Set dst (OrI (LShiftI src shift) (URShiftI src (SubI c_32 shift))));
expand %{
rolI_rReg(dst, src, shift, cr);
%}
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
instruct rolI_rReg_Var_C0(iRegINoSp dst, iRegI src, iRegI shift, immI0 c0, rFlagsReg cr)
%{
match(Set dst (OrI (LShiftI src shift) (URShiftI src (SubI c0 shift))));
expand %{
rolI_rReg(dst, src, shift, cr);
%}
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// ror expander
instruct rorL_rReg(iRegLNoSp dst, iRegL src, iRegI shift, rFlagsReg cr)
%{
effect(DEF dst, USE src, USE shift);
format %{ "ror $dst, $src, $shift" %}
ins_cost(INSN_COST);
ins_encode %{
__ rorv(as_Register($dst$$reg), as_Register($src$$reg),
as_Register($shift$$reg));
%}
ins_pipe(ialu_reg_reg_vshift);
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// ror expander
instruct rorI_rReg(iRegINoSp dst, iRegI src, iRegI shift, rFlagsReg cr)
%{
effect(DEF dst, USE src, USE shift);
format %{ "ror $dst, $src, $shift" %}
ins_cost(INSN_COST);
ins_encode %{
__ rorvw(as_Register($dst$$reg), as_Register($src$$reg),
as_Register($shift$$reg));
%}
__ extrw(as_Register($dst$$reg), as_Register($src$$reg), as_Register($src$$reg),
$shift$$constant & 0x1f);
%}
ins_pipe(ialu_reg_reg_vshift);
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
instruct rorL_rReg_Var_C_64(iRegLNoSp dst, iRegL src, iRegI shift, immI_64 c_64, rFlagsReg cr)
instruct rorL_imm(iRegLNoSp dst, iRegL src, immI shift)
%{
match(Set dst (OrL (URShiftL src shift) (LShiftL src (SubI c_64 shift))));
match(Set dst (RotateRight src shift));
expand %{
rorL_rReg(dst, src, shift, cr);
ins_cost(INSN_COST);
format %{ "ror $dst, $src, $shift" %}
ins_encode %{
__ extr(as_Register($dst$$reg), as_Register($src$$reg), as_Register($src$$reg),
$shift$$constant & 0x3f);
%}
ins_pipe(ialu_reg_reg_vshift);
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
instruct rorL_rReg_Var_C0(iRegLNoSp dst, iRegL src, iRegI shift, immI0 c0, rFlagsReg cr)
instruct rorI_reg(iRegINoSp dst, iRegI src, iRegI shift)
%{
match(Set dst (OrL (URShiftL src shift) (LShiftL src (SubI c0 shift))));
match(Set dst (RotateRight src shift));
expand %{
rorL_rReg(dst, src, shift, cr);
ins_cost(INSN_COST);
format %{ "ror $dst, $src, $shift" %}
ins_encode %{
__ rorvw(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg));
%}
ins_pipe(ialu_reg_reg_vshift);
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
instruct rorI_rReg_Var_C_32(iRegINoSp dst, iRegI src, iRegI shift, immI_32 c_32, rFlagsReg cr)
instruct rorL_reg(iRegLNoSp dst, iRegL src, iRegI shift)
%{
match(Set dst (OrI (URShiftI src shift) (LShiftI src (SubI c_32 shift))));
match(Set dst (RotateRight src shift));
expand %{
rorI_rReg(dst, src, shift, cr);
ins_cost(INSN_COST);
format %{ "ror $dst, $src, $shift" %}
ins_encode %{
__ rorv(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg));
%}
ins_pipe(ialu_reg_reg_vshift);
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
instruct rorI_rReg_Var_C0(iRegINoSp dst, iRegI src, iRegI shift, immI0 c0, rFlagsReg cr)
instruct rolI_reg(iRegINoSp dst, iRegI src, iRegI shift)
%{
match(Set dst (OrI (URShiftI src shift) (LShiftI src (SubI c0 shift))));
match(Set dst (RotateLeft src shift));
expand %{
rorI_rReg(dst, src, shift, cr);
ins_cost(INSN_COST);
format %{ "rol $dst, $src, $shift" %}
ins_encode %{
__ subw(rscratch1, zr, as_Register($shift$$reg));
__ rorvw(as_Register($dst$$reg), as_Register($src$$reg), rscratch1);
%}
ins_pipe(ialu_reg_reg_vshift);
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
instruct rolL_reg(iRegLNoSp dst, iRegL src, iRegI shift)
%{
match(Set dst (RotateLeft src shift));
ins_cost(INSN_COST);
format %{ "rol $dst, $src, $shift" %}
ins_encode %{
__ subw(rscratch1, zr, as_Register($shift$$reg));
__ rorv(as_Register($dst$$reg), as_Register($src$$reg), rscratch1);
%}
ins_pipe(ialu_reg_reg_vshift);
%}

@ -329,75 +329,32 @@ EXTRACT_INSN(L, 63, Or, extr)
EXTRACT_INSN(I, 31, Or, extrw)
EXTRACT_INSN(L, 63, Add, extr)
EXTRACT_INSN(I, 31, Add, extrw)
define(`ROL_EXPAND', `// This pattern is automatically generated from aarch64_ad.m4
define(ROTATE_INSN, `// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// $2 expander
instruct $2$1_rReg(iReg$1NoSp dst, iReg$1 src, iRegI shift, rFlagsReg cr)
instruct $2$1_$3(iReg$1NoSp dst, iReg$1 src, ifelse($3, reg, iReg, imm)I shift)
%{
effect(DEF dst, USE src, USE shift);
match(Set dst (ifelse($2, ror, RotateRight, RotateLeft) src shift));
format %{ "$2 $dst, $src, $shift" %}
ins_cost(INSN_COST * 3);
ins_encode %{
__ subw(rscratch1, zr, as_Register($shift$$reg));
__ $3(as_Register($dst$$reg), as_Register($src$$reg),
rscratch1);
%}
ins_pipe(ialu_reg_reg_vshift);
%}
')
define(`ROR_EXPAND', `// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// $2 expander
instruct $2$1_rReg(iReg$1NoSp dst, iReg$1 src, iRegI shift, rFlagsReg cr)
%{
effect(DEF dst, USE src, USE shift);
format %{ "$2 $dst, $src, $shift" %}
ins_cost(INSN_COST);
ins_encode %{
__ $3(as_Register($dst$$reg), as_Register($src$$reg),
as_Register($shift$$reg));
%}
format %{ "ifelse($2, ror, ror, rol) $dst, $src, $shift" %}
ifelse($2, rol, ins_encode %{
__ subw(rscratch1, zr, as_Register($shift$$reg));, ins_encode %{)
__ ifelse($3, imm,
ifelse($1, I, extrw, extr)(as_Register($dst$$reg), as_Register($src$$reg), as_Register($src$$reg),
$shift$$constant & ifelse($1, I, 0x1f, 0x3f)),
ifelse($1, I, rorvw, rorv)(as_Register($dst$$reg), as_Register($src$$reg), ifelse($2, rol, rscratch1, as_Register($shift$$reg))));
%}
ins_pipe(ialu_reg_reg_vshift);
%}
')dnl
define(ROL_INSN, `// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
instruct $3$1_rReg_Var_C$2(iReg$1NoSp dst, iReg$1 src, iRegI shift, immI$2 c$2, rFlagsReg cr)
%{
match(Set dst (Or$1 (LShift$1 src shift) (URShift$1 src (SubI c$2 shift))));
expand %{
$3$1_rReg(dst, src, shift, cr);
%}
%}
')dnl
define(ROR_INSN, `// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
instruct $3$1_rReg_Var_C$2(iReg$1NoSp dst, iReg$1 src, iRegI shift, immI$2 c$2, rFlagsReg cr)
%{
match(Set dst (Or$1 (URShift$1 src shift) (LShift$1 src (SubI c$2 shift))));
expand %{
$3$1_rReg(dst, src, shift, cr);
%}
%}
')dnl
ROL_EXPAND(L, rol, rorv)
ROL_EXPAND(I, rol, rorvw)
ROL_INSN(L, _64, rol)
ROL_INSN(L, 0, rol)
ROL_INSN(I, _32, rol)
ROL_INSN(I, 0, rol)
ROR_EXPAND(L, ror, rorv)
ROR_EXPAND(I, ror, rorvw)
ROR_INSN(L, _64, ror)
ROR_INSN(L, 0, ror)
ROR_INSN(I, _32, ror)
ROR_INSN(I, 0, ror)
ROTATE_INSN(I, ror, imm)
ROTATE_INSN(L, ror, imm)
ROTATE_INSN(I, ror, reg)
ROTATE_INSN(L, ror, reg)
ROTATE_INSN(I, rol, reg)
ROTATE_INSN(L, rol, reg)
dnl rol_imm has been transformed to ror_imm during GVN.
// Add/subtract (extended)
dnl ADD_SUB_EXTENDED(mode, size, add node, shift node, insn, shift type, wordsize

@ -1489,6 +1489,22 @@ const Type* RotateLeftNode::Value(PhaseGVN* phase) const {
}
}
Node* RotateLeftNode::Ideal(PhaseGVN *phase, bool can_reshape) {
const Type *t1 = phase->type(in(1));
const Type *t2 = phase->type(in(2));
if (t2->isa_int() && t2->is_int()->is_con()) {
if (t1->isa_int()) {
int lshift = t2->is_int()->get_con() & 31;
return new RotateRightNode(in(1), phase->intcon(32 - (lshift & 31)), TypeInt::INT);
} else {
assert(t1->isa_long(), "Type must be a long");
int lshift = t2->is_int()->get_con() & 63;
return new RotateRightNode(in(1), phase->intcon(64 - (lshift & 63)), TypeLong::LONG);
}
}
return NULL;
}
const Type* RotateRightNode::Value(PhaseGVN* phase) const {
const Type* t1 = phase->type(in(1));
const Type* t2 = phase->type(in(2));

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, 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
@ -221,6 +221,7 @@ class RotateLeftNode : public TypeNode {
}
virtual int Opcode() const;
virtual const Type* Value(PhaseGVN* phase) const;
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
};
//----------------------- RotateRightNode ----------------------------------