mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-11 05:59:52 +00:00
8344026: Ubsan: prevent potential integer overflow in c1_LIRGenerator_<arch>.cpp file
Reviewed-by: aph, epeter, mdoerr
This commit is contained in:
parent
3f2556b860
commit
77e493226d
@ -277,18 +277,20 @@ void LIRGenerator::cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Opr bas
|
||||
|
||||
|
||||
bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) {
|
||||
|
||||
if (is_power_of_2(c - 1)) {
|
||||
__ shift_left(left, exact_log2(c - 1), tmp);
|
||||
juint u_value = (juint)c;
|
||||
if (is_power_of_2(u_value - 1)) {
|
||||
__ shift_left(left, exact_log2(u_value - 1), tmp);
|
||||
__ add(tmp, left, result);
|
||||
return true;
|
||||
} else if (is_power_of_2(c + 1)) {
|
||||
__ shift_left(left, exact_log2(c + 1), tmp);
|
||||
} else if (is_power_of_2(u_value + 1)) {
|
||||
__ shift_left(left, exact_log2(u_value + 1), tmp);
|
||||
__ sub(tmp, left, result);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
} else if (c == -1) {
|
||||
__ negate(left, result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LIRGenerator::store_stack_parameter (LIR_Opr item, ByteSize offset_from_sp) {
|
||||
|
||||
@ -328,16 +328,20 @@ void LIRGenerator::cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Opr bas
|
||||
|
||||
bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) {
|
||||
assert(left != result, "should be different registers");
|
||||
if (is_power_of_2(c + 1)) {
|
||||
LIR_Address::Scale scale = (LIR_Address::Scale) log2i_exact(c + 1);
|
||||
juint u_value = (juint)c;
|
||||
if (is_power_of_2(u_value + 1)) {
|
||||
LIR_Address::Scale scale = (LIR_Address::Scale) log2i_exact(u_value + 1);
|
||||
LIR_Address* addr = new LIR_Address(left, left, scale, 0, T_INT);
|
||||
__ sub(LIR_OprFact::address(addr), left, result); // rsb with shifted register
|
||||
return true;
|
||||
} else if (is_power_of_2(c - 1)) {
|
||||
LIR_Address::Scale scale = (LIR_Address::Scale) log2i_exact(c - 1);
|
||||
} else if (is_power_of_2(u_value - 1)) {
|
||||
LIR_Address::Scale scale = (LIR_Address::Scale) log2i_exact(u_value - 1);
|
||||
LIR_Address* addr = new LIR_Address(left, left, scale, 0, T_INT);
|
||||
__ add(left, LIR_OprFact::address(addr), result); // add with shifted register
|
||||
return true;
|
||||
} else if (c == -1) {
|
||||
__ negate(left, result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -296,14 +296,20 @@ void LIRGenerator::cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Opr bas
|
||||
|
||||
bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) {
|
||||
assert(left != result, "should be different registers");
|
||||
if (is_power_of_2(c + 1)) {
|
||||
__ shift_left(left, log2i_exact(c + 1), result);
|
||||
// Using unsigned arithmetics to avoid undefined behavior due to integer overflow.
|
||||
// The involved operations are not sensitive to signedness.
|
||||
juint u_value = (juint)c;
|
||||
if (is_power_of_2(u_value + 1)) {
|
||||
__ shift_left(left, log2i_exact(u_value + 1), result);
|
||||
__ sub(result, left, result);
|
||||
return true;
|
||||
} else if (is_power_of_2(c - 1)) {
|
||||
__ shift_left(left, log2i_exact(c - 1), result);
|
||||
} else if (is_power_of_2(u_value - 1)) {
|
||||
__ shift_left(left, log2i_exact(u_value - 1), result);
|
||||
__ add(result, left, result);
|
||||
return true;
|
||||
} else if (c == -1) {
|
||||
__ negate(left, result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -227,19 +227,25 @@ void LIRGenerator::cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Opr bas
|
||||
}
|
||||
|
||||
bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) {
|
||||
juint u_value = (juint)c;
|
||||
if (tmp->is_valid()) {
|
||||
if (is_power_of_2(c + 1)) {
|
||||
if (is_power_of_2(u_value + 1)) {
|
||||
__ move(left, tmp);
|
||||
__ shift_left(left, log2i_exact(c + 1), left);
|
||||
__ shift_left(left, log2i_exact(u_value + 1), left);
|
||||
__ sub(left, tmp, result);
|
||||
return true;
|
||||
} else if (is_power_of_2(c - 1)) {
|
||||
} else if (is_power_of_2(u_value - 1)) {
|
||||
__ move(left, tmp);
|
||||
__ shift_left(left, log2i_exact(c - 1), left);
|
||||
__ shift_left(left, log2i_exact(u_value - 1), left);
|
||||
__ add(left, tmp, result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == -1) {
|
||||
__ negate(left, result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -496,8 +502,8 @@ void LIRGenerator::do_ArithmeticOp_Int(ArithmeticOp* x) {
|
||||
if (x->op() == Bytecodes::_imul) {
|
||||
bool use_tmp = false;
|
||||
if (right_arg->is_constant()) {
|
||||
int iconst = right_arg->get_jint_constant();
|
||||
if (is_power_of_2(iconst - 1) || is_power_of_2(iconst + 1)) {
|
||||
juint u_const = (juint)right_arg->get_jint_constant();
|
||||
if (is_power_of_2(u_const - 1) || is_power_of_2(u_const + 1)) {
|
||||
use_tmp = true;
|
||||
}
|
||||
}
|
||||
|
||||
70
test/hotspot/jtreg/compiler/c1/StrengthReduceCheck.java
Normal file
70
test/hotspot/jtreg/compiler/c1/StrengthReduceCheck.java
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2024 IBM Corporation. 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
|
||||
* @author Amit Kumar
|
||||
* @bug 8344026
|
||||
* @library /test/lib
|
||||
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -Xbatch -XX:TieredStopAtLevel=1 compiler.c1.StrengthReduceCheck
|
||||
*/
|
||||
|
||||
package compiler.c1;
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
|
||||
public class StrengthReduceCheck {
|
||||
|
||||
static int test1(int x) {
|
||||
// Multiply by 2 ^ 30 - 1
|
||||
x = x * 1073741823;
|
||||
return x;
|
||||
}
|
||||
|
||||
static int test2(int x) {
|
||||
// Multiply by 2 ^ 30 + 1
|
||||
x = x * 1073741825;
|
||||
return x;
|
||||
}
|
||||
|
||||
static int test3(int x) {
|
||||
// Multiply by INT_MIN
|
||||
x = x * -2147483648;
|
||||
return x;
|
||||
}
|
||||
|
||||
static int test4(int x) {
|
||||
x = x * -1;
|
||||
return x;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i =0; i < 1000; ++i) {
|
||||
Asserts.assertEQ(test1(26071999), -1099813823);
|
||||
Asserts.assertEQ(test2(26071999), -1047669825);
|
||||
Asserts.assertEQ(test3(26071999), -2147483648);
|
||||
Asserts.assertEQ(test4(26071999), -26071999);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user