--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Sat Mar 25 00:31:29 2017 +0100
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu Mar 30 19:55:04 2017 +0200
@@ -15501,7 +15501,7 @@
%}
instruct string_indexofUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
@@ -15520,7 +15520,7 @@
%}
instruct string_indexofLL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
@@ -15539,7 +15539,7 @@
%}
instruct string_indexofUL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
@@ -15558,7 +15558,7 @@
%}
instruct string_indexofLU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
@@ -15577,8 +15577,8 @@
%}
instruct string_indexof_conUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
- immI_le_4 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
- iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ immI_le_4 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
+ iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
@@ -15598,8 +15598,8 @@
%}
instruct string_indexof_conLL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
- immI_le_4 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
- iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ immI_le_4 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
+ iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
@@ -15619,8 +15619,8 @@
%}
instruct string_indexof_conUL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
- immI_1 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
- iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ immI_1 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
+ iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
@@ -15640,8 +15640,8 @@
%}
instruct string_indexof_conLU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
- immI_1 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
- iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ immI_1 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
+ iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
@@ -15661,8 +15661,8 @@
%}
instruct string_indexofU_char(iRegP_R1 str1, iRegI_R2 cnt1, iRegI_R3 ch,
- iRegI_R0 result, iRegI tmp1, iRegI tmp2,
- iRegI tmp3, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
+ iRegINoSp tmp3, rFlagsReg cr)
%{
match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch,
@@ -16101,7 +16101,7 @@
// ====================REDUCTION ARITHMETIC====================================
-instruct reduce_add2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegI tmp, iRegI tmp2)
+instruct reduce_add2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegINoSp tmp, iRegINoSp tmp2)
%{
match(Set dst (AddReductionVI src1 src2));
ins_cost(INSN_COST);
@@ -16120,7 +16120,7 @@
ins_pipe(pipe_class_default);
%}
-instruct reduce_add4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegI tmp2)
+instruct reduce_add4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegINoSp tmp2)
%{
match(Set dst (AddReductionVI src1 src2));
ins_cost(INSN_COST);
@@ -16138,7 +16138,7 @@
ins_pipe(pipe_class_default);
%}
-instruct reduce_mul2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegI tmp)
+instruct reduce_mul2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegINoSp tmp)
%{
match(Set dst (MulReductionVI src1 src2));
ins_cost(INSN_COST);
@@ -16157,7 +16157,7 @@
ins_pipe(pipe_class_default);
%}
-instruct reduce_mul4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegI tmp2)
+instruct reduce_mul4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegINoSp tmp2)
%{
match(Set dst (MulReductionVI src1 src2));
ins_cost(INSN_COST);
--- a/hotspot/src/share/vm/opto/convertnode.cpp Sat Mar 25 00:31:29 2017 +0100
+++ b/hotspot/src/share/vm/opto/convertnode.cpp Thu Mar 30 19:55:04 2017 +0200
@@ -294,8 +294,7 @@
}
#ifdef _LP64
- // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y)) or
- // ConvI2L(CastII(AddI(x, y))) to AddL(ConvI2L(CastII(x)), ConvI2L(CastII(y))),
+ // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y))
// but only if x and y have subranges that cannot cause 32-bit overflow,
// under the assumption that x+y is in my own subrange this->type().
@@ -319,13 +318,6 @@
Node* z = in(1);
int op = z->Opcode();
- Node* ctrl = NULL;
- if (op == Op_CastII && z->as_CastII()->has_range_check()) {
- // Skip CastII node but save control dependency
- ctrl = z->in(0);
- z = z->in(1);
- op = z->Opcode();
- }
if (op == Op_AddI || op == Op_SubI) {
Node* x = z->in(1);
Node* y = z->in(2);
@@ -385,8 +377,8 @@
}
assert(rxlo == (int)rxlo && rxhi == (int)rxhi, "x should not overflow");
assert(rylo == (int)rylo && ryhi == (int)ryhi, "y should not overflow");
- Node* cx = phase->C->constrained_convI2L(phase, x, TypeInt::make(rxlo, rxhi, widen), ctrl);
- Node* cy = phase->C->constrained_convI2L(phase, y, TypeInt::make(rylo, ryhi, widen), ctrl);
+ Node* cx = phase->C->constrained_convI2L(phase, x, TypeInt::make(rxlo, rxhi, widen), NULL);
+ Node* cy = phase->C->constrained_convI2L(phase, y, TypeInt::make(rylo, ryhi, widen), NULL);
switch (op) {
case Op_AddI: return new AddLNode(cx, cy);
case Op_SubI: return new SubLNode(cx, cy);
--- a/hotspot/test/compiler/loopopts/TestLoopPeeling.java Sat Mar 25 00:31:29 2017 +0100
+++ b/hotspot/test/compiler/loopopts/TestLoopPeeling.java Thu Mar 30 19:55:04 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8078262
+ * @bug 8078262 8177095
* @summary Tests correct dominator information after loop peeling.
*
* @run main/othervm -Xcomp
@@ -40,14 +40,16 @@
public static void main(String args[]) {
TestLoopPeeling test = new TestLoopPeeling();
try {
- test.testArrayAccess(0, 1);
+ test.testArrayAccess1(0, 1);
+ test.testArrayAccess2(0);
+ test.testArrayAccess3(0, false);
test.testArrayAllocation(0, 1);
} catch (Exception e) {
// Ignore exceptions
}
}
- public void testArrayAccess(int index, int inc) {
+ public void testArrayAccess1(int index, int inc) {
int storeIndex = -1;
for (; index < 10; index += inc) {
@@ -63,7 +65,7 @@
if (index == 42) {
// This store and the corresponding range check are moved out of the
- // loop and both used after old loop and the peeled iteration exit.
+ // loop and both used after main loop and the peeled iteration exit.
// For the peeled iteration, storeIndex is always -1 and the ConvI2L
// is replaced by TOP. However, the range check is not folded because
// we don't do the split if optimization in PhaseIdealLoop2.
@@ -77,6 +79,44 @@
}
}
+ public int testArrayAccess2(int index) {
+ // Load1 and the corresponding range check are moved out of the loop
+ // and both are used after the main loop and the peeled iteration exit.
+ // For the peeled iteration, storeIndex is always Integer.MIN_VALUE and
+ // for the main loop it is 0. Hence, the merging phi has type int:<=0.
+ // Load1 reads the array at index ConvI2L(CastII(AddI(storeIndex, -1)))
+ // where the CastII is range check dependent and has type int:>=0.
+ // The CastII gets pushed through the AddI and its type is changed to int:>=1
+ // which does not overlap with the input type of storeIndex (int:<=0).
+ // The CastII is replaced by TOP causing a cascade of other eliminations.
+ // Since the control path through the range check CmpU(AddI(storeIndex, -1))
+ // is not eliminated, the graph is in a corrupted state. We fail once we merge
+ // with the result of Load2 because we get data from a non-dominating region.
+ int storeIndex = Integer.MIN_VALUE;
+ for (; index < 10; ++index) {
+ if (index == 42) {
+ return array[storeIndex-1]; // Load1
+ }
+ storeIndex = 0;
+ }
+ return array[42]; // Load2
+ }
+
+ public int testArrayAccess3(int index, boolean b) {
+ // Same as testArrayAccess2 but manifests as crash in register allocator.
+ int storeIndex = Integer.MIN_VALUE;
+ for (; index < 10; ++index) {
+ if (b) {
+ return 0;
+ }
+ if (index == 42) {
+ return array[storeIndex-1]; // Load1
+ }
+ storeIndex = 0;
+ }
+ return array[42]; // Load2
+ }
+
public byte[] testArrayAllocation(int index, int inc) {
int allocationCount = -1;
byte[] result;
@@ -88,7 +128,7 @@
if (index == 42) {
// This allocation and the corresponding size check are moved out of the
- // loop and both used after old loop and the peeled iteration exit.
+ // loop and both used after main loop and the peeled iteration exit.
// For the peeled iteration, allocationCount is always -1 and the ConvI2L
// is replaced by TOP. However, the size check is not folded because
// we don't do the split if optimization in PhaseIdealLoop2.