/ jdk Public

## Commit

8267239: C1: RangeCheckElimination for % operator if divisor is IntCo…
Browse the repository at this point in the history
```…nstant

Reviewed-by: thartmann, neliasso```
y1yang0 authored and TobiHartmann committed May 19, 2021
1 parent 2d407e1 commit 0cf7e57
Showing 3 changed files with 99 additions and 10 deletions.
34 changes: 27 additions & 7 deletions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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!
Expand Down
3 changes: 0 additions & 3 deletions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Expand Up @@ -104,9 +104,6 @@ class RangeCheckEliminator {
void remove_lower();
Bound *copy();

private:
void init();
};

Expand Down
72 changes: 72 additions & 0 deletions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
@@ -0,0 +1,72 @@
/*
* 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
*
* 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.
*
* 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();
}
}
}