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  * @test
26  * @bug 8073670
27  * @summary Test that causes C2 to fold two NaNs with different values into a single NaN.
28  *
29  * @run main/othervm -XX:-TieredCompilation -Xcomp
30  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_double_inf
31  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_double_zero
32  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_double_nan
33  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_float_inf
34  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_float_zero
35  *      -XX:CompileCommand=compileonly,compiler.c2.FloatingPointFoldingTest::test_float_nan
36  *      compiler.c2.FloatingPointFoldingTest
37  */
38 
39 package compiler.c2;
40 
41 public class FloatingPointFoldingTest {
42     // Double values.
43     public static final long MINUS_INF_LONGBITS = 0xfff0000000000000L;
44     public static final double DOUBLE_MINUS_INF = Double.longBitsToDouble(MINUS_INF_LONGBITS);
45 
46     public static final long PLUS_INF_LONGBITS = 0x7ff0000000000000L;
47     public static final double DOUBLE_PLUS_INF = Double.longBitsToDouble(PLUS_INF_LONGBITS);
48 
49     public static final long MINUS_ZERO_LONGBITS = 0x8000000000000000L;
50     public static final double DOUBLE_MINUS_ZERO = Double.longBitsToDouble(MINUS_ZERO_LONGBITS);
51 
52     // We need two different NaN values. A floating point number is
53     // considered to be NaN is the sign bit is 0, all exponent bits
54     // are set to 1, and at least one bit of the exponent is not zero.
55     //
56     // As java.lang.Double.NaN is 0x7ff8000000000000L, we use
57     // 0x7ffc000000000000L as a second NaN double value.
58     public static final long NAN_LONGBITS = 0x7ffc000000000000L;
59     public static final double DOUBLE_NAN = Double.longBitsToDouble(NAN_LONGBITS);
60 
61     // Float values.
62     public static final int MINUS_INF_INTBITS = 0xff800000;
63     public static final float FLOAT_MINUS_INF = Float.intBitsToFloat(MINUS_INF_INTBITS);
64 
65     public static final int PLUS_INF_INTBITS = 0x7f800000;
66     public static final float FLOAT_PLUS_INF = Float.intBitsToFloat(PLUS_INF_INTBITS);
67 
68     public static final int MINUS_ZERO_INTBITS = 0x80000000;
69     public static final float FLOAT_MINUS_ZERO = Float.intBitsToFloat(MINUS_ZERO_INTBITS);
70 
71     // As java.lang.Float.NaN is 0x7fc00000, we use 0x7fe00000
72     // as a second NaN float value.
73     public static final int NAN_INTBITS = 0x7fe00000;
74     public static final float FLOAT_NAN = Float.intBitsToFloat(NAN_INTBITS);
75 
76 
77     // Double tests.
test_double_inf(long[] result)78     static void test_double_inf(long[] result) {
79         double d1 = DOUBLE_MINUS_INF;
80         double d2 = DOUBLE_PLUS_INF;
81         result[0] = Double.doubleToRawLongBits(d1);
82         result[1] = Double.doubleToRawLongBits(d2);
83     }
84 
test_double_zero(long[] result)85     static void test_double_zero(long[] result) {
86         double d1 = DOUBLE_MINUS_ZERO;
87         double d2 = 0;
88         result[0] = Double.doubleToRawLongBits(d1);
89         result[1] = Double.doubleToRawLongBits(d2);
90     }
91 
test_double_nan(long[] result)92     static void test_double_nan(long[] result) {
93         double d1 = DOUBLE_NAN;
94         double d2 = Double.NaN;
95         result[0] = Double.doubleToRawLongBits(d1);
96         result[1] = Double.doubleToRawLongBits(d2);
97     }
98 
99     // Float tests.
test_float_inf(int[] result)100     static void test_float_inf(int[] result) {
101         float f1 = FLOAT_MINUS_INF;
102         float f2 = FLOAT_PLUS_INF;
103         result[0] = Float.floatToRawIntBits(f1);
104         result[1] = Float.floatToRawIntBits(f2);
105     }
106 
test_float_zero(int[] result)107     static void test_float_zero(int[] result) {
108         float f1 = FLOAT_MINUS_ZERO;
109         float f2 = 0;
110         result[0] = Float.floatToRawIntBits(f1);
111         result[1] = Float.floatToRawIntBits(f2);
112     }
113 
test_float_nan(int[] result)114     static void test_float_nan(int[] result) {
115         float f1 = FLOAT_NAN;
116         float f2 = Float.NaN;
117         result[0] = Float.floatToRawIntBits(f1);
118         result[1] = Float.floatToRawIntBits(f2);
119     }
120 
121     // Check doubles.
check_double(long[] result, double d1, double d2)122     static void check_double(long[] result, double d1, double d2) {
123         if (result[0] == result[1]) {
124             throw new RuntimeException("ERROR: Two different double values are considered equal. \n"
125                                        + String.format("\toriginal values: 0x%x 0x%x\n", Double.doubleToRawLongBits(d1), Double.doubleToRawLongBits(d2))
126                                        + String.format("\tvalues after execution of method test(): 0x%x 0x%x", result[0], result[1]));
127         }
128     }
129 
130     // Check floats.
check_float(int[] result, float f1, float f2)131     static void check_float(int[] result, float f1, float f2) {
132         if (result[0] == result[1]) {
133             throw new RuntimeException("ERROR: Two different float values are considered equal. \n"
134                                        + String.format("\toriginal values: 0x%x 0x%x\n", Float.floatToRawIntBits(f1), Float.floatToRawIntBits(f2))
135                                        + String.format("\tvalues after execution of method test(): 0x%x 0x%x", result[0], result[1]));
136         }
137     }
138 
main(String[] args)139     public static void main(String[] args) {
140         // Float tests.
141 
142         int[] iresult = new int[2];
143 
144         // -Inf and +Inf.
145         test_float_inf(iresult);
146         check_float(iresult, FLOAT_MINUS_INF, FLOAT_PLUS_INF);
147 
148         // 0 and -0.
149         test_float_zero(iresult);
150         check_float(iresult, FLOAT_MINUS_ZERO, 0);
151 
152         // Diferrent NaNs.
153         test_float_nan(iresult);
154         check_float(iresult, FLOAT_NAN, Float.NaN);
155 
156         // Double tests.
157 
158         long[] lresult = new long[2];
159 
160         // -Inf and +Inf.
161         test_double_inf(lresult);
162         check_double(lresult, DOUBLE_MINUS_INF, DOUBLE_PLUS_INF);
163 
164         // 0 and -0.
165         test_double_zero(lresult);
166         check_double(lresult, DOUBLE_MINUS_ZERO, 0);
167 
168         // Diferrent NaNs.
169         test_double_nan(lresult);
170         check_double(lresult, DOUBLE_NAN, Double.NaN);
171     }
172 }
173