8267687: ModXNode::Ideal optimization is better than Parse::do_irem

Reviewed-by: neliasso, kvn
This commit is contained in:
Yi Yang 2021-06-04 23:29:35 +00:00
parent 48dc72b74d
commit 4e6748c543
3 changed files with 144 additions and 59 deletions

View File

@ -502,8 +502,6 @@ class Parse : public GraphKit {
void modd();
void l2f();
void do_irem();
// implementation of _get* and _put* bytecodes
void do_getstatic() { do_field_access(true, false); }
void do_getfield () { do_field_access(true, true); }
@ -544,7 +542,6 @@ class Parse : public GraphKit {
Node* val, const Type* tval);
void maybe_add_predicate_after_if(Block* path);
IfNode* jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask, float prob, float cnt);
Node* jump_if_join(Node* iffalse, Node* iftrue);
void jump_if_true_fork(IfNode *ifNode, int dest_bci_if_true, bool unc);
void jump_if_false_fork(IfNode *ifNode, int dest_bci_if_false, bool unc);
void jump_if_always_fork(int dest_bci_if_true, bool unc);

View File

@ -218,17 +218,6 @@ IfNode* Parse::jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask, float pro
return iff;
}
// return Region node
Node* Parse::jump_if_join(Node* iffalse, Node* iftrue) {
Node *region = new RegionNode(3); // 2 results
record_for_igvn(region);
region->init_req(1, iffalse);
region->init_req(2, iftrue );
_gvn.set_type(region, Type::CONTROL);
region = _gvn.transform(region);
set_control (region);
return region;
}
// sentinel value for the target bci to mark never taken branches
// (according to profiling)
@ -1158,50 +1147,6 @@ void Parse::l2f() {
push(res);
}
void Parse::do_irem() {
// Must keep both values on the expression-stack during null-check
zero_check_int(peek());
// Compile-time detect of null-exception?
if (stopped()) return;
Node* b = pop();
Node* a = pop();
const Type *t = _gvn.type(b);
if (t != Type::TOP) {
const TypeInt *ti = t->is_int();
if (ti->is_con()) {
int divisor = ti->get_con();
// check for positive power of 2
if (divisor > 0 &&
(divisor & ~(divisor-1)) == divisor) {
// yes !
Node *mask = _gvn.intcon((divisor - 1));
// Sigh, must handle negative dividends
Node *zero = _gvn.intcon(0);
IfNode *ifff = jump_if_fork_int(a, zero, BoolTest::lt, PROB_FAIR, COUNT_UNKNOWN);
Node *iff = _gvn.transform( new IfFalseNode(ifff) );
Node *ift = _gvn.transform( new IfTrueNode (ifff) );
Node *reg = jump_if_join(ift, iff);
Node *phi = PhiNode::make(reg, NULL, TypeInt::INT);
// Negative path; negate/and/negate
Node *neg = _gvn.transform( new SubINode(zero, a) );
Node *andn= _gvn.transform( new AndINode(neg, mask) );
Node *negn= _gvn.transform( new SubINode(zero, andn) );
phi->init_req(1, negn);
// Fast positive case
Node *andx = _gvn.transform( new AndINode(a, mask) );
phi->init_req(2, andx);
// Push the merge
push( _gvn.transform(phi) );
return;
}
}
}
// Default case
push( _gvn.transform( new ModINode(control(),a,b) ) );
}
// Handle jsr and jsr_w bytecode
void Parse::do_jsr() {
assert(bc() == Bytecodes::_jsr || bc() == Bytecodes::_jsr_w, "wrong bytecode");
@ -2196,7 +2141,13 @@ void Parse::do_one_bytecode() {
break;
case Bytecodes::_irem:
do_irem();
// Must keep both values on the expression-stack during null-check
zero_check_int(peek());
// Compile-time detect of null-exception?
if (stopped()) return;
b = pop();
a = pop();
push(_gvn.transform(new ModINode(control(), a, b)));
break;
case Bytecodes::_idiv:
// Must keep both values on the expression-stack during null-check

View File

@ -0,0 +1,137 @@
/*
* 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.
*
*/
package org.openjdk.bench.vm.compiler;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* Test for x % 2^n (n is constant)
*/
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
public class ModPowerOf2 {
@Benchmark
public int testPositivePowerOf2() {
int sum = 0;
for (int i = 0; i < 1000; i++) {
sum += i % 1;
sum += i % 2;
sum += i % 4;
sum += i % 8;
sum += i % 16;
sum += i % 32;
sum += i % 64;
sum += i % 128;
sum += i % 256;
sum += i % 512;
sum += i % 1024;
sum += i % 2048;
sum += i % 4096;
sum += i % 8192;
sum += i % 16384;
sum += i % 32768;
sum += i % 65536;
}
return sum;
}
@Benchmark
public int testNegativePowerOf2() {
int sum = 0;
for (int i = 0; i < 1000; i++) {
sum += i % -1;
sum += i % -2;
sum += i % -4;
sum += i % -8;
sum += i % -16;
sum += i % -32;
sum += i % -64;
sum += i % -128;
sum += i % -256;
sum += i % -512;
sum += i % -1024;
sum += i % -2048;
sum += i % -4096;
sum += i % -8192;
sum += i % -16384;
sum += i % -32768;
sum += i % -65536;
}
return sum;
}
@Benchmark
public int testMixedPowerOf2() {
int sum = 0;
for (int i = 0; i < 1000; i++) {
sum += i % -1;
sum += i % 1;
sum += i % -2;
sum += i % 2;
sum += i % -4;
sum += i % 4;
sum += i % -8;
sum += i % 8;
sum += i % -16;
sum += i % 16;
sum += i % -32;
sum += i % 32;
sum += i % -64;
sum += i % 64;
sum += i % -128;
sum += i % 128;
sum += i % -256;
sum += i % 256;
sum += i % -512;
sum += i % 512;
sum += i % -1024;
sum += i % 1024;
sum += i % -2048;
sum += i % 2048;
sum += i % -4096;
sum += i % 4096;
sum += i % -8192;
sum += i % 8192;
sum += i % -16384;
sum += i % 16384;
sum += i % -32768;
sum += i % 32768;
sum += i % -65536;
sum += i % 65536;
}
return sum;
}
}