1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 /**
  26  * @test
  27  * @bug 8073670
  28  * @summary Test that causes C2 to fold two NaNs with different values into a single NaN.
  29  *
  30  * @run main/othervm -XX:-TieredCompilation -Xcomp
  31  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_double_inf
  32  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_double_zero
  33  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_double_nan
  34  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_float_inf
  35  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_float_zero
  36  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_float_nan
  37  *      compiler.c2.FloatingPointFoldingTest
  38  */
  39 
  40 package compiler.c2;
  41 
  42 public class FloatingPointFoldingTest {
  43     // Double values.
  44     public static final long MINUS_INF_LONGBITS = 0xfff0000000000000L;
  45     public static final double DOUBLE_MINUS_INF = Double.longBitsToDouble(MINUS_INF_LONGBITS);
  46 
  47     public static final long PLUS_INF_LONGBITS = 0x7ff0000000000000L;
  48     public static final double DOUBLE_PLUS_INF = Double.longBitsToDouble(PLUS_INF_LONGBITS);
  49 
  50     public static final long MINUS_ZERO_LONGBITS = 0x8000000000000000L;
  51     public static final double DOUBLE_MINUS_ZERO = Double.longBitsToDouble(MINUS_ZERO_LONGBITS);
  52 
  53     // We need two different NaN values. A floating point number is
  54     // considered to be NaN is the sign bit is 0, all exponent bits
  55     // are set to 1, and at least one bit of the exponent is not zero.
  56     //
  57     // As java.lang.Double.NaN is 0x7ff8000000000000L, we use
  58     // 0x7ffc000000000000L as a second NaN double value.
  59     public static final long NAN_LONGBITS = 0x7ffc000000000000L;
  60     public static final double DOUBLE_NAN = Double.longBitsToDouble(NAN_LONGBITS);
  61 
  62     // Float values.
  63     public static final int MINUS_INF_INTBITS = 0xff800000;
  64     public static final float FLOAT_MINUS_INF = Float.intBitsToFloat(MINUS_INF_INTBITS);
  65 
  66     public static final int PLUS_INF_INTBITS = 0x7f800000;
  67     public static final float FLOAT_PLUS_INF = Float.intBitsToFloat(PLUS_INF_INTBITS);
  68 
  69     public static final int MINUS_ZERO_INTBITS = 0x80000000;
  70     public static final float FLOAT_MINUS_ZERO = Float.intBitsToFloat(MINUS_ZERO_INTBITS);
  71 
  72     // As java.lang.Float.NaN is 0x7fc00000, we use 0x7fe00000
  73     // as a second NaN float value.
  74     public static final int NAN_INTBITS = 0x7fe00000;
  75     public static final float FLOAT_NAN = Float.intBitsToFloat(NAN_INTBITS);
  76 
  77 
  78     // Double tests.
  79     static void test_double_inf(long[] result) {
  80         double d1 = DOUBLE_MINUS_INF;
  81         double d2 = DOUBLE_PLUS_INF;
  82         result[0] = Double.doubleToRawLongBits(d1);
  83         result[1] = Double.doubleToRawLongBits(d2);
  84     }
  85 
  86     static void test_double_zero(long[] result) {
  87         double d1 = DOUBLE_MINUS_ZERO;
  88         double d2 = 0;
  89         result[0] = Double.doubleToRawLongBits(d1);
  90         result[1] = Double.doubleToRawLongBits(d2);
  91     }
  92 
  93     static void test_double_nan(long[] result) {
  94         double d1 = DOUBLE_NAN;
  95         double d2 = Double.NaN;
  96         result[0] = Double.doubleToRawLongBits(d1);
  97         result[1] = Double.doubleToRawLongBits(d2);
  98     }
  99 
 100     // Float tests.
 101     static void test_float_inf(int[] result) {
 102         float f1 = FLOAT_MINUS_INF;
 103         float f2 = FLOAT_PLUS_INF;
 104         result[0] = Float.floatToRawIntBits(f1);
 105         result[1] = Float.floatToRawIntBits(f2);
 106     }
 107 
 108     static void test_float_zero(int[] result) {
 109         float f1 = FLOAT_MINUS_ZERO;
 110         float f2 = 0;
 111         result[0] = Float.floatToRawIntBits(f1);
 112         result[1] = Float.floatToRawIntBits(f2);
 113     }
 114 
 115     static void test_float_nan(int[] result) {
 116         float f1 = FLOAT_NAN;
 117         float f2 = Float.NaN;
 118         result[0] = Float.floatToRawIntBits(f1);
 119         result[1] = Float.floatToRawIntBits(f2);
 120     }
 121 
 122     // Check doubles.
 123     static void check_double(long[] result, double d1, double d2) {
 124         if (result[0] == result[1]) {
 125             throw new RuntimeException("ERROR: Two different double values are considered equal. \n"
 126                                        + String.format("\toriginal values: 0x%x 0x%x\n", Double.doubleToRawLongBits(d1), Double.doubleToRawLongBits(d2))
 127                                        + String.format("\tvalues after execution of method test(): 0x%x 0x%x", result[0], result[1]));
 128         }
 129     }
 130 
 131     // Check floats.
 132     static void check_float(int[] result, float f1, float f2) {
 133         if (result[0] == result[1]) {
 134             throw new RuntimeException("ERROR: Two different float values are considered equal. \n"
 135                                        + String.format("\toriginal values: 0x%x 0x%x\n", Float.floatToRawIntBits(f1), Float.floatToRawIntBits(f2))
 136                                        + String.format("\tvalues after execution of method test(): 0x%x 0x%x", result[0], result[1]));
 137         }
 138     }
 139 
 140     public static void main(String[] args) {
 141         // Float tests.
 142 
 143         int[] iresult = new int[2];
 144 
 145         // -Inf and +Inf.
 146         test_float_inf(iresult);
 147         check_float(iresult, FLOAT_MINUS_INF, FLOAT_PLUS_INF);
 148 
 149         // 0 and -0.
 150         test_float_zero(iresult);
 151         check_float(iresult, FLOAT_MINUS_ZERO, 0);
 152 
 153         // Diferrent NaNs.
 154         test_float_nan(iresult);
 155         check_float(iresult, FLOAT_NAN, Float.NaN);
 156 
 157         // Double tests.
 158 
 159         long[] lresult = new long[2];
 160 
 161         // -Inf and +Inf.
 162         test_double_inf(lresult);
 163         check_double(lresult, DOUBLE_MINUS_INF, DOUBLE_PLUS_INF);
 164 
 165         // 0 and -0.
 166         test_double_zero(lresult);
 167         check_double(lresult, DOUBLE_MINUS_ZERO, 0);
 168 
 169         // Diferrent NaNs.
 170         test_double_nan(lresult);
 171         check_double(lresult, DOUBLE_NAN, Double.NaN);
 172     }
 173 }