< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java

Print this page

        

@@ -289,21 +289,83 @@
         return super.equals(other);
     }
 
     @Override
     public JavaConstant asConstant() {
-        if (nonNaN && Double.compare(lowerBound, upperBound) == 0) {
+        if (isConstant()) {
             switch (getBits()) {
                 case 32:
                     return JavaConstant.forFloat((float) lowerBound);
                 case 64:
                     return JavaConstant.forDouble(lowerBound);
             }
         }
         return null;
     }
 
+    private boolean isConstant() {
+        /*
+         * There are many forms of NaNs and any operations on them can silently convert them into
+         * the canonical NaN.
+         */
+        return (Double.compare(lowerBound, upperBound) == 0 && nonNaN);
+    }
+
+    private static FloatStamp stampForConstant(Constant constant) {
+        FloatStamp result;
+        PrimitiveConstant value = (PrimitiveConstant) constant;
+        switch (value.getJavaKind()) {
+            case Float:
+                if (Float.isNaN(value.asFloat())) {
+                    result = new FloatStamp(32, Double.NaN, Double.NaN, false);
+                } else {
+                    result = new FloatStamp(32, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat()));
+                }
+                break;
+            case Double:
+                if (Double.isNaN(value.asDouble())) {
+                    result = new FloatStamp(64, Double.NaN, Double.NaN, false);
+                } else {
+                    result = new FloatStamp(64, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble()));
+                }
+                break;
+            default:
+                throw GraalError.shouldNotReachHere();
+        }
+        if (result.isConstant()) {
+            return result;
+        }
+        return null;
+    }
+
+    private static Stamp maybeFoldConstant(UnaryOp<?> op, FloatStamp stamp) {
+        if (stamp.isConstant()) {
+            JavaConstant constant = stamp.asConstant();
+            Constant folded = op.foldConstant(constant);
+            if (folded != null) {
+                return FloatStamp.stampForConstant(folded);
+            }
+        }
+        return null;
+    }
+
+    private static Stamp maybeFoldConstant(BinaryOp<?> op, FloatStamp stamp1, FloatStamp stamp2) {
+        if (stamp1.isConstant() && stamp2.isConstant()) {
+            JavaConstant constant1 = stamp1.asConstant();
+            JavaConstant constant2 = stamp2.asConstant();
+            Constant folded = op.foldConstant(constant1, constant2);
+            if (folded != null) {
+                FloatStamp stamp = stampForConstant(folded);
+                if (stamp != null && stamp.isConstant()) {
+                    assert stamp.asConstant().equals(folded);
+                    return stamp;
+                }
+            }
+        }
+        return null;
+    }
+
     public static final ArithmeticOpTable OPS = new ArithmeticOpTable(
 
                     new UnaryOp.Neg() {
 
                         @Override

@@ -320,12 +382,17 @@
                         }
 
                         @Override
                         public Stamp foldStamp(Stamp s) {
                             FloatStamp stamp = (FloatStamp) s;
+                            Stamp folded = maybeFoldConstant(this, stamp);
+                            if (folded != null) {
+                                return folded;
+                            }
                             return new FloatStamp(stamp.getBits(), -stamp.upperBound(), -stamp.lowerBound(), stamp.isNonNaN());
                         }
+
                     },
 
                     new BinaryOp.Add(false, true) {
 
                         @Override

@@ -342,12 +409,17 @@
                                     throw GraalError.shouldNotReachHere();
                             }
                         }
 
                         @Override
-                        public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
-                            // TODO
+                        public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            FloatStamp stamp1 = (FloatStamp) s1;
+                            FloatStamp stamp2 = (FloatStamp) s2;
+                            Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+                            if (folded != null) {
+                                return folded;
+                            }
                             return stamp1.unrestricted();
                         }
 
                         @Override
                         public boolean isNeutral(Constant value) {

@@ -379,12 +451,17 @@
                                     throw GraalError.shouldNotReachHere();
                             }
                         }
 
                         @Override
-                        public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
-                            // TODO
+                        public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            FloatStamp stamp1 = (FloatStamp) s1;
+                            FloatStamp stamp2 = (FloatStamp) s2;
+                            Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+                            if (folded != null) {
+                                return folded;
+                            }
                             return stamp1.unrestricted();
                         }
 
                         @Override
                         public boolean isNeutral(Constant value) {

@@ -416,13 +493,18 @@
                                     throw GraalError.shouldNotReachHere();
                             }
                         }
 
                         @Override
-                        public Stamp foldStamp(Stamp a, Stamp b) {
-                            // TODO
-                            return a.unrestricted();
+                        public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            FloatStamp stamp1 = (FloatStamp) s1;
+                            FloatStamp stamp2 = (FloatStamp) s2;
+                            Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+                            if (folded != null) {
+                                return folded;
+                            }
+                            return stamp1.unrestricted();
                         }
 
                         @Override
                         public boolean isNeutral(Constant value) {
                             PrimitiveConstant n = (PrimitiveConstant) value;

@@ -448,21 +530,28 @@
                             PrimitiveConstant a = (PrimitiveConstant) const1;
                             PrimitiveConstant b = (PrimitiveConstant) const2;
                             assert a.getJavaKind() == b.getJavaKind();
                             switch (a.getJavaKind()) {
                                 case Float:
-                                    return JavaConstant.forFloat(a.asFloat() / b.asFloat());
+                                    float floatDivisor = b.asFloat();
+                                    return (floatDivisor == 0) ? null : JavaConstant.forFloat(a.asFloat() / floatDivisor);
                                 case Double:
-                                    return JavaConstant.forDouble(a.asDouble() / b.asDouble());
+                                    double doubleDivisor = b.asDouble();
+                                    return (doubleDivisor == 0) ? null : JavaConstant.forDouble(a.asDouble() / doubleDivisor);
                                 default:
                                     throw GraalError.shouldNotReachHere();
                             }
                         }
 
                         @Override
-                        public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
-                            // TODO
+                        public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            FloatStamp stamp1 = (FloatStamp) s1;
+                            FloatStamp stamp2 = (FloatStamp) s2;
+                            Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+                            if (folded != null) {
+                                return folded;
+                            }
                             return stamp1.unrestricted();
                         }
 
                         @Override
                         public boolean isNeutral(Constant value) {

@@ -494,12 +583,17 @@
                                     throw GraalError.shouldNotReachHere();
                             }
                         }
 
                         @Override
-                        public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
-                            // TODO
+                        public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            FloatStamp stamp1 = (FloatStamp) s1;
+                            FloatStamp stamp2 = (FloatStamp) s2;
+                            Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+                            if (folded != null) {
+                                return folded;
+                            }
                             return stamp1.unrestricted();
                         }
                     },
 
                     new UnaryOp.Not() {

@@ -519,10 +613,21 @@
                             }
                         }
 
                         @Override
                         public Stamp foldStamp(Stamp s) {
+                            FloatStamp stamp = (FloatStamp) s;
+                            JavaConstant constant = stamp.asConstant();
+                            if (constant != null) {
+                                Constant folded = foldConstant(constant);
+                                if (folded != null) {
+                                    FloatStamp result = stampForConstant(folded);
+                                    if (result != null && result.isConstant()) {
+                                        return result;
+                                    }
+                                }
+                            }
                             return s.unrestricted();
                         }
                     },
 
                     new BinaryOp.And(true, true) {

@@ -545,11 +650,17 @@
                                     throw GraalError.shouldNotReachHere();
                             }
                         }
 
                         @Override
-                        public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                        public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            FloatStamp stamp1 = (FloatStamp) s1;
+                            FloatStamp stamp2 = (FloatStamp) s2;
+                            Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+                            if (folded != null) {
+                                return folded;
+                            }
                             return stamp1.unrestricted();
                         }
 
                         @Override
                         public boolean isNeutral(Constant n) {

@@ -574,22 +685,30 @@
                             assert a.getJavaKind() == b.getJavaKind();
                             switch (a.getJavaKind()) {
                                 case Float:
                                     int fa = Float.floatToRawIntBits(a.asFloat());
                                     int fb = Float.floatToRawIntBits(b.asFloat());
-                                    return JavaConstant.forFloat(Float.intBitsToFloat(fa | fb));
+                                    float floatOr = Float.intBitsToFloat(fa | fb);
+                                    assert (fa | fb) == Float.floatToRawIntBits((floatOr));
+                                    return JavaConstant.forFloat(floatOr);
                                 case Double:
                                     long da = Double.doubleToRawLongBits(a.asDouble());
                                     long db = Double.doubleToRawLongBits(b.asDouble());
                                     return JavaConstant.forDouble(Double.longBitsToDouble(da | db));
                                 default:
                                     throw GraalError.shouldNotReachHere();
                             }
                         }
 
                         @Override
-                        public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                        public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            FloatStamp stamp1 = (FloatStamp) s1;
+                            FloatStamp stamp2 = (FloatStamp) s2;
+                            Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+                            if (folded != null) {
+                                return folded;
+                            }
                             return stamp1.unrestricted();
                         }
 
                         @Override
                         public boolean isNeutral(Constant n) {

@@ -625,11 +744,17 @@
                                     throw GraalError.shouldNotReachHere();
                             }
                         }
 
                         @Override
-                        public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                        public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            FloatStamp stamp1 = (FloatStamp) s1;
+                            FloatStamp stamp2 = (FloatStamp) s2;
+                            Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+                            if (folded != null) {
+                                return folded;
+                            }
                             return stamp1.unrestricted();
                         }
 
                         @Override
                         public boolean isNeutral(Constant n) {

@@ -663,10 +788,14 @@
                         }
 
                         @Override
                         public Stamp foldStamp(Stamp s) {
                             FloatStamp stamp = (FloatStamp) s;
+                            Stamp folded = maybeFoldConstant(this, stamp);
+                            if (folded != null) {
+                                return folded;
+                            }
                             if (stamp.isNaN()) {
                                 return stamp;
                             }
                             return new FloatStamp(stamp.getBits(), 0, Math.max(-stamp.lowerBound(), stamp.upperBound()), stamp.isNonNaN());
                         }

@@ -687,10 +816,15 @@
                             }
                         }
 
                         @Override
                         public Stamp foldStamp(Stamp s) {
+                            FloatStamp stamp = (FloatStamp) s;
+                            Stamp folded = maybeFoldConstant(this, stamp);
+                            if (folded != null) {
+                                return folded;
+                            }
                             return s.unrestricted();
                         }
                     },
 
                     null, null, null,
< prev index next >