8213419: C2 may hang in MulLNode::Ideal()/MulINode::Ideal() with gcc 8.2.1

Wed, 06 Feb 2019 17:32:25 +0100

author
roland
date
Wed, 06 Feb 2019 17:32:25 +0100
changeset 9613
67aa2bb0d84e
parent 9612
58ffe5f227a6
child 9614
bb44c0e88235

8213419: C2 may hang in MulLNode::Ideal()/MulINode::Ideal() with gcc 8.2.1
Reviewed-by: kvn, dlong, aph

src/share/vm/opto/mulnode.cpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/globalDefinitions.hpp file | annotate | diff | comparison | revisions
test/compiler/integerArithmetic/MultiplyByIntegerMinHang.java file | annotate | diff | comparison | revisions
     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 +}

mercurial