8285390: PPC64: Handle integral division overflow during parsing
Reviewed-by: lucy
This commit is contained in:
parent
f42631e354
commit
d3606a34fa
47
src/hotspot/cpu/ppc/parse_ppc.cpp
Normal file
47
src/hotspot/cpu/ppc/parse_ppc.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
|
||||||
|
#ifdef COMPILER2
|
||||||
|
|
||||||
|
#include "opto/parse.hpp"
|
||||||
|
#include "interpreter/bytecodes.hpp"
|
||||||
|
|
||||||
|
bool Parse::do_one_bytecode_targeted() {
|
||||||
|
switch (bc()) {
|
||||||
|
case Bytecodes::_idiv: // fallthrough
|
||||||
|
case Bytecodes::_irem: // fallthrough
|
||||||
|
#ifdef _LP64
|
||||||
|
case Bytecodes::_ldiv: // fallthrough
|
||||||
|
case Bytecodes::_lrem:
|
||||||
|
#endif
|
||||||
|
do_divmod_fixup();
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // COMPILER2
|
@ -2407,10 +2407,6 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
|||||||
return RegMask();
|
return RegMask();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parse::do_one_bytecode_targeted() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
//----------ENCODING BLOCK-----------------------------------------------------
|
//----------ENCODING BLOCK-----------------------------------------------------
|
||||||
@ -8857,26 +8853,10 @@ instruct mulL_reg_imm16(iRegLdst dst, iRegLsrc src1, immL16 src2) %{
|
|||||||
ins_pipe(pipe_class_default);
|
ins_pipe(pipe_class_default);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// Integer Division with Immediate -1: Negate.
|
// Integer Division, but not min_jint / -1
|
||||||
instruct divI_reg_immIvalueMinus1(iRegIdst dst, iRegIsrc src1, immI_minus1 src2) %{
|
instruct noOvfDivI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
|
||||||
match(Set dst (DivI src1 src2));
|
match(Set dst (NoOvfDivI src1 src2));
|
||||||
ins_cost(DEFAULT_COST);
|
ins_cost(3*DEFAULT_COST);
|
||||||
|
|
||||||
format %{ "NEG $dst, $src1 \t// /-1" %}
|
|
||||||
size(4);
|
|
||||||
ins_encode %{
|
|
||||||
__ neg($dst$$Register, $src1$$Register);
|
|
||||||
%}
|
|
||||||
ins_pipe(pipe_class_default);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Integer Division with constant, but not -1.
|
|
||||||
// We should be able to improve this by checking the type of src2.
|
|
||||||
// It might well be that src2 is known to be positive.
|
|
||||||
instruct divI_reg_regnotMinus1(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
|
|
||||||
match(Set dst (DivI src1 src2));
|
|
||||||
predicate(n->in(2)->find_int_con(-1) != -1); // src2 is a constant, but not -1
|
|
||||||
ins_cost(2*DEFAULT_COST);
|
|
||||||
|
|
||||||
format %{ "DIVW $dst, $src1, $src2 \t// /not-1" %}
|
format %{ "DIVW $dst, $src1, $src2 \t// /not-1" %}
|
||||||
size(4);
|
size(4);
|
||||||
@ -8886,56 +8866,10 @@ instruct divI_reg_regnotMinus1(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
|
|||||||
ins_pipe(pipe_class_default);
|
ins_pipe(pipe_class_default);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct cmovI_bne_negI_reg(iRegIdst dst, flagsRegSrc crx, iRegIsrc src1) %{
|
// Long Division, but not min_jlong / -1
|
||||||
effect(USE_DEF dst, USE src1, USE crx);
|
instruct noOvfDivL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
|
||||||
predicate(false);
|
match(Set dst (NoOvfDivL src1 src2));
|
||||||
|
ins_cost(3*DEFAULT_COST);
|
||||||
ins_variable_size_depending_on_alignment(true);
|
|
||||||
|
|
||||||
format %{ "CMOVE $dst, neg($src1), $crx" %}
|
|
||||||
// Worst case is branch + move + stop, no stop without scheduler.
|
|
||||||
size(8);
|
|
||||||
ins_encode %{
|
|
||||||
Label done;
|
|
||||||
__ bne($crx$$CondRegister, done);
|
|
||||||
__ neg($dst$$Register, $src1$$Register);
|
|
||||||
__ bind(done);
|
|
||||||
%}
|
|
||||||
ins_pipe(pipe_class_default);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Integer Division with Registers not containing constants.
|
|
||||||
instruct divI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
|
|
||||||
match(Set dst (DivI src1 src2));
|
|
||||||
ins_cost(10*DEFAULT_COST);
|
|
||||||
|
|
||||||
expand %{
|
|
||||||
immI16 imm %{ (int)-1 %}
|
|
||||||
flagsReg tmp1;
|
|
||||||
cmpI_reg_imm16(tmp1, src2, imm); // check src2 == -1
|
|
||||||
divI_reg_regnotMinus1(dst, src1, src2); // dst = src1 / src2
|
|
||||||
cmovI_bne_negI_reg(dst, tmp1, src1); // cmove dst = neg(src1) if src2 == -1
|
|
||||||
%}
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Long Division with Immediate -1: Negate.
|
|
||||||
instruct divL_reg_immLvalueMinus1(iRegLdst dst, iRegLsrc src1, immL_minus1 src2) %{
|
|
||||||
match(Set dst (DivL src1 src2));
|
|
||||||
ins_cost(DEFAULT_COST);
|
|
||||||
|
|
||||||
format %{ "NEG $dst, $src1 \t// /-1, long" %}
|
|
||||||
size(4);
|
|
||||||
ins_encode %{
|
|
||||||
__ neg($dst$$Register, $src1$$Register);
|
|
||||||
%}
|
|
||||||
ins_pipe(pipe_class_default);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Long Division with constant, but not -1.
|
|
||||||
instruct divL_reg_regnotMinus1(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
|
|
||||||
match(Set dst (DivL src1 src2));
|
|
||||||
predicate(n->in(2)->find_long_con(-1L) != -1L); // Src2 is a constant, but not -1.
|
|
||||||
ins_cost(2*DEFAULT_COST);
|
|
||||||
|
|
||||||
format %{ "DIVD $dst, $src1, $src2 \t// /not-1, long" %}
|
format %{ "DIVD $dst, $src1, $src2 \t// /not-1, long" %}
|
||||||
size(4);
|
size(4);
|
||||||
@ -8945,71 +8879,31 @@ instruct divL_reg_regnotMinus1(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
|
|||||||
ins_pipe(pipe_class_default);
|
ins_pipe(pipe_class_default);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct cmovL_bne_negL_reg(iRegLdst dst, flagsRegSrc crx, iRegLsrc src1) %{
|
|
||||||
effect(USE_DEF dst, USE src1, USE crx);
|
|
||||||
predicate(false);
|
|
||||||
|
|
||||||
ins_variable_size_depending_on_alignment(true);
|
|
||||||
|
|
||||||
format %{ "CMOVE $dst, neg($src1), $crx" %}
|
|
||||||
// Worst case is branch + move + stop, no stop without scheduler.
|
|
||||||
size(8);
|
|
||||||
ins_encode %{
|
|
||||||
Label done;
|
|
||||||
__ bne($crx$$CondRegister, done);
|
|
||||||
__ neg($dst$$Register, $src1$$Register);
|
|
||||||
__ bind(done);
|
|
||||||
%}
|
|
||||||
ins_pipe(pipe_class_default);
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Long Division with Registers not containing constants.
|
|
||||||
instruct divL_reg_reg_Ex(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
|
|
||||||
match(Set dst (DivL src1 src2));
|
|
||||||
ins_cost(10*DEFAULT_COST);
|
|
||||||
|
|
||||||
expand %{
|
|
||||||
immL16 imm %{ (int)-1 %}
|
|
||||||
flagsReg tmp1;
|
|
||||||
cmpL_reg_imm16(tmp1, src2, imm); // check src2 == -1
|
|
||||||
divL_reg_regnotMinus1(dst, src1, src2); // dst = src1 / src2
|
|
||||||
cmovL_bne_negL_reg(dst, tmp1, src1); // cmove dst = neg(src1) if src2 == -1
|
|
||||||
%}
|
|
||||||
%}
|
|
||||||
|
|
||||||
// Integer Remainder with registers.
|
// Integer Remainder with registers.
|
||||||
instruct modI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
|
instruct modI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
|
||||||
match(Set dst (ModI src1 src2));
|
match(Set dst (NoOvfModI src1 src2));
|
||||||
ins_cost(10*DEFAULT_COST);
|
ins_cost(5*DEFAULT_COST);
|
||||||
|
|
||||||
expand %{
|
expand %{
|
||||||
immI16 imm %{ (int)-1 %}
|
iRegIdst tmp1;
|
||||||
flagsReg tmp1;
|
|
||||||
iRegIdst tmp2;
|
iRegIdst tmp2;
|
||||||
iRegIdst tmp3;
|
noOvfDivI_reg_reg(tmp1, src1, src2);
|
||||||
cmpI_reg_imm16(tmp1, src2, imm); // check src2 == -1
|
mulI_reg_reg(tmp2, src2, tmp1);
|
||||||
divI_reg_regnotMinus1(tmp2, src1, src2); // tmp2 = src1 / src2
|
subI_reg_reg(dst, src1, tmp2);
|
||||||
cmovI_bne_negI_reg(tmp2, tmp1, src1); // cmove tmp2 = neg(src1) if src2 == -1
|
|
||||||
mulI_reg_reg(tmp3, src2, tmp2); // tmp3 = src2 * tmp2
|
|
||||||
subI_reg_reg(dst, src1, tmp3); // dst = src1 - tmp3
|
|
||||||
%}
|
%}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// Long Remainder with registers
|
// Long Remainder with registers
|
||||||
instruct modL_reg_reg_Ex(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
|
instruct modL_reg_reg_Ex(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
|
||||||
match(Set dst (ModL src1 src2));
|
match(Set dst (NoOvfModL src1 src2));
|
||||||
ins_cost(10*DEFAULT_COST);
|
ins_cost(5*DEFAULT_COST);
|
||||||
|
|
||||||
expand %{
|
expand %{
|
||||||
immL16 imm %{ (int)-1 %}
|
iRegLdst tmp1;
|
||||||
flagsReg tmp1;
|
|
||||||
iRegLdst tmp2;
|
iRegLdst tmp2;
|
||||||
iRegLdst tmp3;
|
noOvfDivL_reg_reg(tmp1, src1, src2);
|
||||||
cmpL_reg_imm16(tmp1, src2, imm); // check src2 == -1
|
mulL_reg_reg(tmp2, src2, tmp1);
|
||||||
divL_reg_regnotMinus1(tmp2, src1, src2); // tmp2 = src1 / src2
|
subL_reg_reg(dst, src1, tmp2);
|
||||||
cmovL_bne_negL_reg(tmp2, tmp1, src1); // cmove tmp2 = neg(src1) if src2 == -1
|
|
||||||
mulL_reg_reg(tmp3, src2, tmp2); // tmp3 = src2 * tmp2
|
|
||||||
subL_reg_reg(dst, src1, tmp3); // dst = src1 - tmp3
|
|
||||||
%}
|
%}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user