8269230: C2: main loop in micro benchmark never executed

Co-authored-by: Maurizio Cimadamore <mcimadamore@openjdk.org>
Reviewed-by: kvn, iveresov
This commit is contained in:
Roland Westrelin 2021-07-01 07:41:22 +00:00
parent 962f1c1a9b
commit c67a7b039d
2 changed files with 164 additions and 0 deletions

View File

@ -1011,6 +1011,33 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
adjusted_lim = igvn->transform(new SubINode(hi, lo)); adjusted_lim = igvn->transform(new SubINode(hi, lo));
} }
hook->destruct(igvn); hook->destruct(igvn);
int lo = igvn->type(adjusted_lim)->is_int()->_lo;
if (lo < 0) {
// If range check elimination applies to this comparison, it includes code to protect from overflows that may
// cause the main loop to be skipped entirely. Delay this transformation.
// Example:
// for (int i = 0; i < limit; i++) {
// if (i < max_jint && i > min_jint) {...
// }
// Comparisons folded as:
// i - min_jint - 1 <u -2
// when RC applies, main loop limit becomes:
// min(limit, max(-2 + min_jint + 1, min_jint))
// = min(limit, min_jint)
// = min_jint
if (!igvn->C->post_loop_opts_phase()) {
if (adjusted_val->outcnt() == 0) {
igvn->remove_dead_node(adjusted_val);
}
if (adjusted_lim->outcnt() == 0) {
igvn->remove_dead_node(adjusted_lim);
}
igvn->C->record_for_post_loop_opts_igvn(this);
return false;
}
}
Node* newcmp = igvn->transform(new CmpUNode(adjusted_val, adjusted_lim)); Node* newcmp = igvn->transform(new CmpUNode(adjusted_val, adjusted_lim));
Node* newbool = igvn->transform(new BoolNode(newcmp, cond)); Node* newbool = igvn->transform(new BoolNode(newcmp, cond));

View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 2021, 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.
*/
package org.openjdk.bench.jdk.incubator.foreign;
import jdk.incubator.foreign.CLinker;
import jdk.incubator.foreign.MemoryAccess;
import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.MemorySegment;
import jdk.incubator.foreign.ResourceScope;
import jdk.incubator.vector.ByteVector;
import jdk.incubator.vector.IntVector;
import jdk.incubator.vector.VectorSpecies;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.CompilerControl;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 1, jvmArgsAppend = {
"--add-modules=jdk.incubator.foreign",
"-Dforeign.restricted=permit",
"--enable-native-access", "ALL-UNNAMED"})
public class TestLoadBytes {
@Param("1024")
private int size;
private byte[] srcArray;
private ByteBuffer srcBufferNative;
private MemorySegment srcSegmentImplicit;
@Setup
public void setup() {
srcArray = new byte[size];
for (int i = 0; i < srcArray.length; i++) {
srcArray[i] = (byte) i;
}
srcBufferNative = ByteBuffer.allocateDirect(size);
srcSegmentImplicit = MemorySegment.allocateNative(size, ResourceScope.newImplicitScope());
}
@Benchmark
public int arrayScalar() {
int size = 0;
for (int i = 0; i < srcArray.length; i ++) {
var v = srcArray[i];
size += v;
}
return size;
}
@Benchmark
public int arrayScalarConst() {
int size = 0;
for (int i = 0; i < 1024; i ++) {
var v = srcArray[i];
size += v;
}
return size;
}
@Benchmark
public int bufferNativeScalar() {
int size = 0;
for (int i = 0; i < srcArray.length; i++) {
var v = srcBufferNative.get(i);
size += v;
}
return size;
}
@Benchmark
public int bufferNativeScalarConst() {
int size = 0;
for (int i = 0; i < 1024; i++) {
var v = srcBufferNative.get(i);
size += v;
}
return size;
}
@Benchmark
public int segmentNativeScalar() {
int size = 0;
for (int i = 0; i < srcArray.length; i++) {
var v = MemoryAccess.getByteAtOffset(srcSegmentImplicit, i);
size += v;
}
return size;
}
@Benchmark
public int segmentNativeScalarConst() {
int size = 0;
for (int i = 0; i < 1024; i++) {
var v = MemoryAccess.getByteAtOffset(srcSegmentImplicit, i);
size += v;
}
return size;
}
}