Wed, 06 Feb 2019 17:32:25 +0100
8213419: C2 may hang in MulLNode::Ideal()/MulINode::Ideal() with gcc 8.2.1
Reviewed-by: kvn, dlong, aph
1.1 --- a/src/share/vm/opto/mulnode.cpp Wed Feb 06 14:59:45 2019 +0900 1.2 +++ b/src/share/vm/opto/mulnode.cpp Wed Feb 06 17:32:25 2019 +0100 1.3 @@ -169,7 +169,6 @@ 1.4 return mul_ring(t1,t2); // Local flavor of type multiplication 1.5 } 1.6 1.7 - 1.8 //============================================================================= 1.9 //------------------------------Ideal------------------------------------------ 1.10 // Check for power-of-2 multiply, then try the regular MulNode::Ideal 1.11 @@ -184,42 +183,43 @@ 1.12 } 1.13 1.14 // Now we have a constant Node on the right and the constant in con 1.15 - if( con == 0 ) return NULL; // By zero is handled by Value call 1.16 - if( con == 1 ) return NULL; // By one is handled by Identity call 1.17 + if (con == 0) return NULL; // By zero is handled by Value call 1.18 + if (con == 1) return NULL; // By one is handled by Identity call 1.19 1.20 // Check for negative constant; if so negate the final result 1.21 bool sign_flip = false; 1.22 - if( con < 0 ) { 1.23 - con = -con; 1.24 + 1.25 + unsigned int abs_con = uabs(con); 1.26 + if (abs_con != (unsigned int)con) { 1.27 sign_flip = true; 1.28 } 1.29 1.30 // Get low bit; check for being the only bit 1.31 Node *res = NULL; 1.32 - jint bit1 = con & -con; // Extract low bit 1.33 - if( bit1 == con ) { // Found a power of 2? 1.34 - res = new (phase->C) LShiftINode( in(1), phase->intcon(log2_intptr(bit1)) ); 1.35 + unsigned int bit1 = abs_con & (0-abs_con); // Extract low bit 1.36 + if (bit1 == abs_con) { // Found a power of 2? 1.37 + res = new (phase->C) LShiftINode(in(1), phase->intcon(log2_intptr(bit1))); 1.38 } else { 1.39 1.40 // Check for constant with 2 bits set 1.41 - jint bit2 = con-bit1; 1.42 - bit2 = bit2 & -bit2; // Extract 2nd bit 1.43 - if( bit2 + bit1 == con ) { // Found all bits in con? 1.44 - Node *n1 = phase->transform( new (phase->C) LShiftINode( in(1), phase->intcon(log2_intptr(bit1)) ) ); 1.45 - Node *n2 = phase->transform( new (phase->C) LShiftINode( in(1), phase->intcon(log2_intptr(bit2)) ) ); 1.46 - res = new (phase->C) AddINode( n2, n1 ); 1.47 + unsigned int bit2 = abs_con-bit1; 1.48 + bit2 = bit2 & (0-bit2); // Extract 2nd bit 1.49 + if (bit2 + bit1 == abs_con) { // Found all bits in con? 1.50 + Node *n1 = phase->transform( new (phase->C) LShiftINode(in(1), phase->intcon(log2_intptr(bit1)))); 1.51 + Node *n2 = phase->transform( new (phase->C) LShiftINode(in(1), phase->intcon(log2_intptr(bit2)))); 1.52 + res = new (phase->C) AddINode(n2, n1); 1.53 1.54 - } else if (is_power_of_2(con+1)) { 1.55 + } else if (is_power_of_2(abs_con+1)) { 1.56 // Sleezy: power-of-2 -1. Next time be generic. 1.57 - jint temp = (jint) (con + 1); 1.58 - Node *n1 = phase->transform( new (phase->C) LShiftINode( in(1), phase->intcon(log2_intptr(temp)) ) ); 1.59 - res = new (phase->C) SubINode( n1, in(1) ); 1.60 + unsigned int temp = abs_con + 1; 1.61 + Node *n1 = phase->transform(new (phase->C) LShiftINode(in(1), phase->intcon(log2_intptr(temp)))); 1.62 + res = new (phase->C) SubINode(n1, in(1)); 1.63 } else { 1.64 return MulNode::Ideal(phase, can_reshape); 1.65 } 1.66 } 1.67 1.68 - if( sign_flip ) { // Need to negate result? 1.69 + if (sign_flip) { // Need to negate result? 1.70 res = phase->transform(res);// Transform, before making the zero con 1.71 res = new (phase->C) SubINode(phase->intcon(0),res); 1.72 } 1.73 @@ -280,42 +280,42 @@ 1.74 } 1.75 1.76 // Now we have a constant Node on the right and the constant in con 1.77 - if( con == CONST64(0) ) return NULL; // By zero is handled by Value call 1.78 - if( con == CONST64(1) ) return NULL; // By one is handled by Identity call 1.79 + if (con == CONST64(0)) return NULL; // By zero is handled by Value call 1.80 + if (con == CONST64(1)) return NULL; // By one is handled by Identity call 1.81 1.82 // Check for negative constant; if so negate the final result 1.83 bool sign_flip = false; 1.84 - if( con < 0 ) { 1.85 - con = -con; 1.86 + unsigned long abs_con = uabs(con); 1.87 + if (abs_con != (unsigned long)con) { 1.88 sign_flip = true; 1.89 } 1.90 1.91 // Get low bit; check for being the only bit 1.92 Node *res = NULL; 1.93 - jlong bit1 = con & -con; // Extract low bit 1.94 - if( bit1 == con ) { // Found a power of 2? 1.95 - res = new (phase->C) LShiftLNode( in(1), phase->intcon(log2_long(bit1)) ); 1.96 + unsigned long bit1 = abs_con & (0-abs_con); // Extract low bit 1.97 + if (bit1 == abs_con) { // Found a power of 2? 1.98 + res = new (phase->C) LShiftLNode(in(1), phase->intcon(log2_long(bit1))); 1.99 } else { 1.100 1.101 // Check for constant with 2 bits set 1.102 - jlong bit2 = con-bit1; 1.103 - bit2 = bit2 & -bit2; // Extract 2nd bit 1.104 - if( bit2 + bit1 == con ) { // Found all bits in con? 1.105 - Node *n1 = phase->transform( new (phase->C) LShiftLNode( in(1), phase->intcon(log2_long(bit1)) ) ); 1.106 - Node *n2 = phase->transform( new (phase->C) LShiftLNode( in(1), phase->intcon(log2_long(bit2)) ) ); 1.107 - res = new (phase->C) AddLNode( n2, n1 ); 1.108 + unsigned long bit2 = abs_con-bit1; 1.109 + bit2 = bit2 & (0-bit2); // Extract 2nd bit 1.110 + if (bit2 + bit1 == abs_con) { // Found all bits in con? 1.111 + Node *n1 = phase->transform(new (phase->C) LShiftLNode(in(1), phase->intcon(log2_long(bit1)))); 1.112 + Node *n2 = phase->transform(new (phase->C) LShiftLNode(in(1), phase->intcon(log2_long(bit2)))); 1.113 + res = new (phase->C) AddLNode(n2, n1); 1.114 1.115 - } else if (is_power_of_2_long(con+1)) { 1.116 + } else if (is_power_of_2_long(abs_con+1)) { 1.117 // Sleezy: power-of-2 -1. Next time be generic. 1.118 - jlong temp = (jlong) (con + 1); 1.119 - Node *n1 = phase->transform( new (phase->C) LShiftLNode( in(1), phase->intcon(log2_long(temp)) ) ); 1.120 - res = new (phase->C) SubLNode( n1, in(1) ); 1.121 + unsigned long temp = abs_con + 1; 1.122 + Node *n1 = phase->transform( new (phase->C) LShiftLNode(in(1), phase->intcon(log2_long(temp)))); 1.123 + res = new (phase->C) SubLNode(n1, in(1)); 1.124 } else { 1.125 return MulNode::Ideal(phase, can_reshape); 1.126 } 1.127 } 1.128 1.129 - if( sign_flip ) { // Need to negate result? 1.130 + if (sign_flip) { // Need to negate result? 1.131 res = phase->transform(res);// Transform, before making the zero con 1.132 res = new (phase->C) SubLNode(phase->longcon(0),res); 1.133 }
2.1 --- a/src/share/vm/utilities/globalDefinitions.hpp Wed Feb 06 14:59:45 2019 +0900 2.2 +++ b/src/share/vm/utilities/globalDefinitions.hpp Wed Feb 06 17:32:25 2019 +0100 2.3 @@ -1136,10 +1136,10 @@ 2.4 2.5 //* largest i such that 2^i <= x 2.6 // A negative value of 'x' will return '31' 2.7 -inline int log2_intptr(intptr_t x) { 2.8 +inline int log2_intptr(uintptr_t x) { 2.9 int i = -1; 2.10 uintptr_t p = 1; 2.11 - while (p != 0 && p <= (uintptr_t)x) { 2.12 + while (p != 0 && p <= x) { 2.13 // p = 2^(i+1) && p <= x (i.e., 2^(i+1) <= x) 2.14 i++; p *= 2; 2.15 } 2.16 @@ -1150,10 +1150,10 @@ 2.17 2.18 //* largest i such that 2^i <= x 2.19 // A negative value of 'x' will return '63' 2.20 -inline int log2_long(jlong x) { 2.21 +inline int log2_long(unsigned long x) { 2.22 int i = -1; 2.23 julong p = 1; 2.24 - while (p != 0 && p <= (julong)x) { 2.25 + while (p != 0 && p <= x) { 2.26 // p = 2^(i+1) && p <= x (i.e., 2^(i+1) <= x) 2.27 i++; p *= 2; 2.28 } 2.29 @@ -1162,6 +1162,22 @@ 2.30 return i; 2.31 } 2.32 2.33 +inline int log2_intptr(intptr_t x) { 2.34 + return log2_intptr((uintptr_t)x); 2.35 +} 2.36 + 2.37 +inline int log2_intptr(int x) { 2.38 + return log2_intptr((uintptr_t)x); 2.39 +} 2.40 + 2.41 +inline int log2_intptr(uint x) { 2.42 + return log2_intptr((uintptr_t)x); 2.43 +} 2.44 + 2.45 +inline int log2_long(jlong x) { 2.46 + return log2_long((unsigned long)x); 2.47 +} 2.48 + 2.49 //* the argument must be exactly a power of 2 2.50 inline int exact_log2(intptr_t x) { 2.51 #ifdef ASSERT 2.52 @@ -1201,6 +1217,29 @@ 2.53 inline bool is_odd (intx x) { return x & 1; } 2.54 inline bool is_even(intx x) { return !is_odd(x); } 2.55 2.56 +// abs methods which cannot overflow and so are well-defined across 2.57 +// the entire domain of integer types. 2.58 +static inline unsigned int uabs(unsigned int n) { 2.59 + union { 2.60 + unsigned int result; 2.61 + int value; 2.62 + }; 2.63 + result = n; 2.64 + if (value < 0) result = 0-result; 2.65 + return result; 2.66 +} 2.67 +static inline unsigned long uabs(unsigned long n) { 2.68 + union { 2.69 + unsigned long result; 2.70 + long value; 2.71 + }; 2.72 + result = n; 2.73 + if (value < 0) result = 0-result; 2.74 + return result; 2.75 +} 2.76 +static inline unsigned long uabs(jlong n) { return uabs((unsigned long)n); } 2.77 +static inline unsigned int uabs(int n) { return uabs((unsigned int)n); } 2.78 + 2.79 // "to" should be greater than "from." 2.80 inline intx byte_size(void* from, void* to) { 2.81 return (address)to - (address)from;
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/compiler/integerArithmetic/MultiplyByIntegerMinHang.java Wed Feb 06 17:32:25 2019 +0100 3.3 @@ -0,0 +1,64 @@ 3.4 +/* 3.5 + * Copyright (c) 2018, Red Hat, Inc. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +/** 3.28 + * @test 3.29 + * @bug 8213419 3.30 + * @summary C2 may hang in MulLNode::Ideal()/MulINode::Ideal() with gcc 8.2.1 3.31 + * 3.32 + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement MultiplyByIntegerMinHang 3.33 + * 3.34 + */ 3.35 + 3.36 +public class MultiplyByIntegerMinHang { 3.37 + public static void main(String[] args) { 3.38 + for (int i = 0; i < 20_000; i++) { 3.39 + if (test1(0) != 0) { 3.40 + throw new RuntimeException("incorrect result"); 3.41 + } 3.42 + if (test1(1) != Integer.MIN_VALUE) { 3.43 + throw new RuntimeException("incorrect result"); 3.44 + } 3.45 + if (test1(2) != 0) { 3.46 + throw new RuntimeException("incorrect result"); 3.47 + } 3.48 + if (test2(0) != 0) { 3.49 + throw new RuntimeException("incorrect result"); 3.50 + } 3.51 + if (test2(1) != Long.MIN_VALUE) { 3.52 + throw new RuntimeException("incorrect result"); 3.53 + } 3.54 + if (test2(2) != 0) { 3.55 + throw new RuntimeException("incorrect result"); 3.56 + } 3.57 + } 3.58 + } 3.59 + 3.60 + private static int test1(int v) { 3.61 + return v * Integer.MIN_VALUE; 3.62 + } 3.63 + 3.64 + private static long test2(long v) { 3.65 + return v * Long.MIN_VALUE; 3.66 + } 3.67 +}