8261812: C2 compilation fails with assert(!had_error) failed: bad dominance
Reviewed-by: kvn, thartmann
This commit is contained in:
parent
97557826f5
commit
2c0507ecd6
@ -4793,3 +4793,27 @@ void Compile::igv_print_method_to_network(const char* phase_name) {
|
||||
void Compile::add_native_invoker(RuntimeStub* stub) {
|
||||
_native_invokers.append(stub);
|
||||
}
|
||||
|
||||
Node* Compile::narrow_value(BasicType bt, Node* value, const Type* type, PhaseGVN* phase, bool transform_res) {
|
||||
if (type != NULL && phase->type(value)->higher_equal(type)) {
|
||||
return value;
|
||||
}
|
||||
Node* result = NULL;
|
||||
if (bt == T_BYTE) {
|
||||
result = phase->transform(new LShiftINode(value, phase->intcon(24)));
|
||||
result = new RShiftINode(result, phase->intcon(24));
|
||||
} else if (bt == T_BOOLEAN) {
|
||||
result = new AndINode(value, phase->intcon(0xFF));
|
||||
} else if (bt == T_CHAR) {
|
||||
result = new AndINode(value,phase->intcon(0xFFFF));
|
||||
} else {
|
||||
assert(bt == T_SHORT, "unexpected narrow type");
|
||||
result = phase->transform(new LShiftINode(value, phase->intcon(16)));
|
||||
result = new RShiftINode(result, phase->intcon(16));
|
||||
}
|
||||
if (transform_res) {
|
||||
result = phase->transform(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1192,9 +1192,10 @@ class Compile : public Phase {
|
||||
bool has_exception_backedge() const { return _exception_backedge; }
|
||||
#endif
|
||||
|
||||
static bool
|
||||
push_thru_add(PhaseGVN* phase, Node* z, const TypeInteger* tz, const TypeInteger*& rx, const TypeInteger*& ry,
|
||||
BasicType bt);
|
||||
static bool push_thru_add(PhaseGVN* phase, Node* z, const TypeInteger* tz, const TypeInteger*& rx, const TypeInteger*& ry,
|
||||
BasicType bt);
|
||||
|
||||
static Node* narrow_value(BasicType bt, Node* value, const Type* type, PhaseGVN* phase, bool transform_res);
|
||||
};
|
||||
|
||||
#endif // SHARE_OPTO_COMPILE_HPP
|
||||
|
@ -450,6 +450,9 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *
|
||||
Node* n = val->in(MemNode::ValueIn);
|
||||
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
|
||||
n = bs->step_over_gc_barrier(n);
|
||||
if (is_subword_type(ft)) {
|
||||
n = Compile::narrow_value(ft, n, phi_type, &_igvn, true);
|
||||
}
|
||||
values.at_put(j, n);
|
||||
} else if(val->is_Proj() && val->in(0) == alloc) {
|
||||
values.at_put(j, _igvn.zerocon(ft));
|
||||
|
@ -2079,12 +2079,14 @@ uint LoadNode::match_edge(uint idx) const {
|
||||
// with the value stored truncated to a byte. If no truncation is
|
||||
// needed, the replacement is done in LoadNode::Identity().
|
||||
//
|
||||
Node *LoadBNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
Node* LoadBNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||
Node* mem = in(MemNode::Memory);
|
||||
Node* value = can_see_stored_value(mem,phase);
|
||||
if( value && !phase->type(value)->higher_equal( _type ) ) {
|
||||
Node *result = phase->transform( new LShiftINode(value, phase->intcon(24)) );
|
||||
return new RShiftINode(result, phase->intcon(24));
|
||||
if (value != NULL) {
|
||||
Node* narrow = Compile::narrow_value(T_BYTE, value, _type, phase, false);
|
||||
if (narrow != value) {
|
||||
return narrow;
|
||||
}
|
||||
}
|
||||
// Identity call will handle the case where truncation is not needed.
|
||||
return LoadNode::Ideal(phase, can_reshape);
|
||||
@ -2114,8 +2116,12 @@ const Type* LoadBNode::Value(PhaseGVN* phase) const {
|
||||
Node* LoadUBNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||
Node* mem = in(MemNode::Memory);
|
||||
Node* value = can_see_stored_value(mem, phase);
|
||||
if (value && !phase->type(value)->higher_equal(_type))
|
||||
return new AndINode(value, phase->intcon(0xFF));
|
||||
if (value != NULL) {
|
||||
Node* narrow = Compile::narrow_value(T_BOOLEAN, value, _type, phase, false);
|
||||
if (narrow != value) {
|
||||
return narrow;
|
||||
}
|
||||
}
|
||||
// Identity call will handle the case where truncation is not needed.
|
||||
return LoadNode::Ideal(phase, can_reshape);
|
||||
}
|
||||
@ -2141,11 +2147,15 @@ const Type* LoadUBNode::Value(PhaseGVN* phase) const {
|
||||
// with the value stored truncated to a char. If no truncation is
|
||||
// needed, the replacement is done in LoadNode::Identity().
|
||||
//
|
||||
Node *LoadUSNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
Node* LoadUSNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||
Node* mem = in(MemNode::Memory);
|
||||
Node* value = can_see_stored_value(mem,phase);
|
||||
if( value && !phase->type(value)->higher_equal( _type ) )
|
||||
return new AndINode(value,phase->intcon(0xFFFF));
|
||||
if (value != NULL) {
|
||||
Node* narrow = Compile::narrow_value(T_CHAR, value, _type, phase, false);
|
||||
if (narrow != value) {
|
||||
return narrow;
|
||||
}
|
||||
}
|
||||
// Identity call will handle the case where truncation is not needed.
|
||||
return LoadNode::Ideal(phase, can_reshape);
|
||||
}
|
||||
@ -2171,12 +2181,14 @@ const Type* LoadUSNode::Value(PhaseGVN* phase) const {
|
||||
// with the value stored truncated to a short. If no truncation is
|
||||
// needed, the replacement is done in LoadNode::Identity().
|
||||
//
|
||||
Node *LoadSNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
Node* LoadSNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||
Node* mem = in(MemNode::Memory);
|
||||
Node* value = can_see_stored_value(mem,phase);
|
||||
if( value && !phase->type(value)->higher_equal( _type ) ) {
|
||||
Node *result = phase->transform( new LShiftINode(value, phase->intcon(16)) );
|
||||
return new RShiftINode(result, phase->intcon(16));
|
||||
if (value != NULL) {
|
||||
Node* narrow = Compile::narrow_value(T_SHORT, value, _type, phase, false);
|
||||
if (narrow != value) {
|
||||
return narrow;
|
||||
}
|
||||
}
|
||||
// Identity call will handle the case where truncation is not needed.
|
||||
return LoadNode::Ideal(phase, can_reshape);
|
||||
|
@ -2586,19 +2586,18 @@ void Parse::do_one_bytecode() {
|
||||
case Bytecodes::_i2b:
|
||||
// Sign extend
|
||||
a = pop();
|
||||
a = _gvn.transform( new LShiftINode(a,_gvn.intcon(24)) );
|
||||
a = _gvn.transform( new RShiftINode(a,_gvn.intcon(24)) );
|
||||
push( a );
|
||||
a = Compile::narrow_value(T_BYTE, a, NULL, &_gvn, true);
|
||||
push(a);
|
||||
break;
|
||||
case Bytecodes::_i2s:
|
||||
a = pop();
|
||||
a = _gvn.transform( new LShiftINode(a,_gvn.intcon(16)) );
|
||||
a = _gvn.transform( new RShiftINode(a,_gvn.intcon(16)) );
|
||||
push( a );
|
||||
a = Compile::narrow_value(T_SHORT, a, NULL, &_gvn, true);
|
||||
push(a);
|
||||
break;
|
||||
case Bytecodes::_i2c:
|
||||
a = pop();
|
||||
push( _gvn.transform( new AndINode(a,_gvn.intcon(0xFFFF)) ) );
|
||||
a = Compile::narrow_value(T_CHAR, a, NULL, &_gvn, true);
|
||||
push(a);
|
||||
break;
|
||||
|
||||
case Bytecodes::_i2f:
|
||||
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Red Hat, Inc. 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 8261812
|
||||
* @summary C2 compilation fails with assert(!had_error) failed: bad dominance
|
||||
*
|
||||
* @run main/othervm -XX:-BackgroundCompilation TestValAtSafepointOverflowsInt
|
||||
*
|
||||
*/
|
||||
|
||||
public class TestValAtSafepointOverflowsInt {
|
||||
private static volatile int volatileField;
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 20_000; i++) {
|
||||
testByte(true, false);
|
||||
testByte(false, false);
|
||||
testShort(true, false);
|
||||
testShort(false, false);
|
||||
testChar(true, false);
|
||||
testChar(false, false);
|
||||
}
|
||||
testByte(true, true);
|
||||
testShort(true, true);
|
||||
testChar(true, true);
|
||||
}
|
||||
|
||||
private static Object testByte(boolean flag, boolean flag2) {
|
||||
int i;
|
||||
// loop to delay constant folding
|
||||
for (i = 0; i < 9; i++) {
|
||||
}
|
||||
C obj = new C();
|
||||
if (flag) {
|
||||
obj.byteField = (byte)(1 << i);
|
||||
} else {
|
||||
obj.byteField = (byte)(1 << (i+1));
|
||||
}
|
||||
// Phi for byte here for uncommon trap in never taken path below
|
||||
// Phi inputs don't fit in a byte. Phi transfomed to top.
|
||||
if (flag2) {
|
||||
return obj;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Object testShort(boolean flag, boolean flag2) {
|
||||
int i;
|
||||
for (i = 0; i < 17; i++) {
|
||||
}
|
||||
C obj = new C();
|
||||
if (flag) {
|
||||
obj.shortField = (short)(1 << i);
|
||||
} else {
|
||||
obj.shortField = (short)(1 << (i+1));
|
||||
}
|
||||
if (flag2) {
|
||||
return obj;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Object testChar(boolean flag, boolean flag2) {
|
||||
int i;
|
||||
for (i = 0; i < 17; i++) {
|
||||
}
|
||||
C obj = new C();
|
||||
if (flag) {
|
||||
obj.charField = (char)(1 << i);
|
||||
} else {
|
||||
obj.charField = (char)(1 << (i+1));
|
||||
}
|
||||
if (flag2) {
|
||||
return obj;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
static class C {
|
||||
byte byteField;
|
||||
short shortField;
|
||||
char charField;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user