8267239: C1: RangeCheckElimination for % operator if divisor is IntConstant
Reviewed-by: thartmann, neliasso
This commit is contained in:
parent
2d407e12fa
commit
0cf7e5784b
src/hotspot/share/c1
test/hotspot/jtreg/compiler/c1
@ -228,6 +228,24 @@ void RangeCheckEliminator::Visitor::do_ArithmeticOp(ArithmeticOp *ao) {
|
||||
Bound* y_bound = _rce->get_bound(y);
|
||||
if (x_bound->lower() >= 0 && x_bound->lower_instr() == NULL && y->as_ArrayLength() != NULL) {
|
||||
_bound = new Bound(0, NULL, -1, y);
|
||||
} else if (y->type()->as_IntConstant() && y->type()->as_IntConstant()->value() != 0) {
|
||||
// The binary % operator is said to yield the remainder of its operands from an implied division; the
|
||||
// left-hand operand is the dividend and the right-hand operand is the divisor.
|
||||
//
|
||||
// % operator follows from this rule that the result of the remainder operation can be negative only
|
||||
// if the dividend is negative, and can be positive only if the dividend is positive. Moreover, the
|
||||
// magnitude of the result is always less than the magnitude of the divisor(See JLS 15.17.3).
|
||||
//
|
||||
// So if y is a constant integer and not equal to 0, then we can deduce the bound of remainder operation:
|
||||
// x % -y ==> [0, y - 1] Apply RCE
|
||||
// x % y ==> [0, y - 1] Apply RCE
|
||||
// -x % y ==> [-y + 1, 0]
|
||||
// -x % -y ==> [-y + 1, 0]
|
||||
if (x_bound->has_lower() && x_bound->lower() >= 0) {
|
||||
_bound = new Bound(0, NULL, y->type()->as_IntConstant()->value() - 1, NULL);
|
||||
} else {
|
||||
_bound = new Bound();
|
||||
}
|
||||
} else {
|
||||
_bound = new Bound();
|
||||
}
|
||||
@ -805,6 +823,15 @@ void RangeCheckEliminator::process_access_indexed(BlockBegin *loop_header, Block
|
||||
array_bound = get_bound(ai->array());
|
||||
}
|
||||
|
||||
TRACE_RANGE_CHECK_ELIMINATION(
|
||||
tty->fill_to(block->dominator_depth()*2);
|
||||
tty->print("Index bound: ");
|
||||
index_bound->print();
|
||||
tty->print(", Array bound: ");
|
||||
array_bound->print();
|
||||
tty->cr();
|
||||
);
|
||||
|
||||
if (in_array_bound(index_bound, ai->array()) ||
|
||||
(index_bound && array_bound && index_bound->is_smaller(array_bound) && !index_bound->lower_instr() && index_bound->lower() >= 0)) {
|
||||
TRACE_RANGE_CHECK_ELIMINATION(
|
||||
@ -1250,7 +1277,6 @@ RangeCheckEliminator::Bound::~Bound() {
|
||||
|
||||
// Bound constructor
|
||||
RangeCheckEliminator::Bound::Bound() {
|
||||
init();
|
||||
this->_lower = min_jint;
|
||||
this->_upper = max_jint;
|
||||
this->_lower_instr = NULL;
|
||||
@ -1259,7 +1285,6 @@ RangeCheckEliminator::Bound::Bound() {
|
||||
|
||||
// Bound constructor
|
||||
RangeCheckEliminator::Bound::Bound(int lower, Value lower_instr, int upper, Value upper_instr) {
|
||||
init();
|
||||
assert(!lower_instr || !lower_instr->as_Constant() || !lower_instr->type()->as_IntConstant(), "Must not be constant!");
|
||||
assert(!upper_instr || !upper_instr->as_Constant() || !upper_instr->type()->as_IntConstant(), "Must not be constant!");
|
||||
this->_lower = lower;
|
||||
@ -1273,7 +1298,6 @@ RangeCheckEliminator::Bound::Bound(Instruction::Condition cond, Value v, int con
|
||||
assert(!v || (v->type() && (v->type()->as_IntType() || v->type()->as_ObjectType())), "Type must be array or integer!");
|
||||
assert(!v || !v->as_Constant() || !v->type()->as_IntConstant(), "Must not be constant!");
|
||||
|
||||
init();
|
||||
if (cond == Instruction::eql) {
|
||||
_lower = constant;
|
||||
_lower_instr = v;
|
||||
@ -1327,10 +1351,6 @@ void RangeCheckEliminator::Bound::add_constant(int value) {
|
||||
this->_upper += value;
|
||||
}
|
||||
|
||||
// Init
|
||||
void RangeCheckEliminator::Bound::init() {
|
||||
}
|
||||
|
||||
// or
|
||||
void RangeCheckEliminator::Bound::or_op(Bound *b) {
|
||||
// Watch out, bound is not guaranteed not to overflow!
|
||||
|
@ -104,9 +104,6 @@ public:
|
||||
void remove_lower();
|
||||
void add_constant(int value);
|
||||
Bound *copy();
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
|
||||
|
||||
|
72
test/hotspot/jtreg/compiler/c1/ArithmeticRemRCE.java
Normal file
72
test/hotspot/jtreg/compiler/c1/ArithmeticRemRCE.java
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Alibaba Group Holding 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 8267239
|
||||
* @author Yi Yang
|
||||
* @summary apply RCE for % operations
|
||||
* @requires vm.compiler1.enabled
|
||||
* @library /test/lib
|
||||
* @run main/othervm -XX:TieredStopAtLevel=1 -XX:+TieredCompilation
|
||||
* -XX:CompileCommand=compileonly,*ArithmeticRemRCE.test*
|
||||
* compiler.c1.ArithmeticRemRCE
|
||||
*/
|
||||
|
||||
package compiler.c1;
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
|
||||
public class ArithmeticRemRCE {
|
||||
static int field = 1000;
|
||||
|
||||
static void test1() {
|
||||
// seq should be loop invariant, so we can not put it into static fields
|
||||
int[] seq = new int[1000];
|
||||
for (int i = 0; i < seq.length; i++) {
|
||||
seq[i] = i;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
int constVal = 10;
|
||||
Asserts.assertTrue(0 <= seq[i % 5] && seq[i % 5] <= 4);
|
||||
Asserts.assertTrue(0 <= seq[i % -5] && seq[i % -5] <= 4);
|
||||
|
||||
Asserts.assertTrue(0 <= seq[i % constVal] && seq[i % constVal] <= 9);
|
||||
Asserts.assertTrue(0 <= seq[i % -constVal] && seq[i % -constVal] <= 9);
|
||||
|
||||
Asserts.assertTrue(seq[i % 1] == 0);
|
||||
|
||||
// will not apply RCE
|
||||
Asserts.assertTrue(0 <= seq[i % field] && seq[i % field] <= 999);
|
||||
Asserts.assertTrue(0 <= seq[i % -field] && seq[i % -field] <= 999);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
for (int i = 0; i < 10_000; i++) {
|
||||
test1();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user