8285390: PPC64: Handle integral division overflow during parsing

Reviewed-by: lucy
This commit is contained in:
Martin Doerr 2022-04-29 08:33:23 +00:00
parent f42631e354
commit d3606a34fa
2 changed files with 67 additions and 126 deletions

View 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

View File

@ -2407,10 +2407,6 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() {
return RegMask();
}
bool Parse::do_one_bytecode_targeted() {
return false;
}
%}
//----------ENCODING BLOCK-----------------------------------------------------
@ -8857,26 +8853,10 @@ instruct mulL_reg_imm16(iRegLdst dst, iRegLsrc src1, immL16 src2) %{
ins_pipe(pipe_class_default);
%}
// Integer Division with Immediate -1: Negate.
instruct divI_reg_immIvalueMinus1(iRegIdst dst, iRegIsrc src1, immI_minus1 src2) %{
match(Set dst (DivI src1 src2));
ins_cost(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);
// Integer Division, but not min_jint / -1
instruct noOvfDivI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
match(Set dst (NoOvfDivI src1 src2));
ins_cost(3*DEFAULT_COST);
format %{ "DIVW $dst, $src1, $src2 \t// /not-1" %}
size(4);
@ -8886,56 +8866,10 @@ instruct divI_reg_regnotMinus1(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
ins_pipe(pipe_class_default);
%}
instruct cmovI_bne_negI_reg(iRegIdst dst, flagsRegSrc crx, iRegIsrc 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);
%}
// 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);
// Long Division, but not min_jlong / -1
instruct noOvfDivL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
match(Set dst (NoOvfDivL src1 src2));
ins_cost(3*DEFAULT_COST);
format %{ "DIVD $dst, $src1, $src2 \t// /not-1, long" %}
size(4);
@ -8945,71 +8879,31 @@ instruct divL_reg_regnotMinus1(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
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.
instruct modI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
match(Set dst (ModI src1 src2));
ins_cost(10*DEFAULT_COST);
match(Set dst (NoOvfModI src1 src2));
ins_cost(5*DEFAULT_COST);
expand %{
immI16 imm %{ (int)-1 %}
flagsReg tmp1;
iRegIdst tmp1;
iRegIdst tmp2;
iRegIdst tmp3;
cmpI_reg_imm16(tmp1, src2, imm); // check src2 == -1
divI_reg_regnotMinus1(tmp2, src1, src2); // tmp2 = src1 / src2
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
noOvfDivI_reg_reg(tmp1, src1, src2);
mulI_reg_reg(tmp2, src2, tmp1);
subI_reg_reg(dst, src1, tmp2);
%}
%}
// Long Remainder with registers
instruct modL_reg_reg_Ex(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
match(Set dst (ModL src1 src2));
ins_cost(10*DEFAULT_COST);
match(Set dst (NoOvfModL src1 src2));
ins_cost(5*DEFAULT_COST);
expand %{
immL16 imm %{ (int)-1 %}
flagsReg tmp1;
iRegLdst tmp1;
iRegLdst tmp2;
iRegLdst tmp3;
cmpL_reg_imm16(tmp1, src2, imm); // check src2 == -1
divL_reg_regnotMinus1(tmp2, src1, src2); // tmp2 = src1 / src2
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
noOvfDivL_reg_reg(tmp1, src1, src2);
mulL_reg_reg(tmp2, src2, tmp1);
subL_reg_reg(dst, src1, tmp2);
%}
%}