changeset 5785:e5f0cf5b5627

more sophisticated float stamp
author Lukas Stadler <lukas.stadler@jku.at>
date Fri, 06 Jul 2012 16:25:59 +0200
parents 182d5b57967e
children f69a406355b2
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java
diffstat 3 files changed, 107 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Fri Jul 06 16:21:46 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Fri Jul 06 16:25:59 2012 +0200
@@ -27,25 +27,116 @@
 
 public class FloatStamp extends Stamp {
 
+    private final double lowerBound;
+    private final double upperBound;
+    private final boolean nonNaN;
+
     protected FloatStamp(Kind kind) {
+        this(kind, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false);
+        assert kind == Kind.Float || kind == Kind.Double;
+    }
+
+    protected FloatStamp(Kind kind, double lowerBound, double upperBound, boolean nonNaN) {
         super(kind);
-        assert kind == Kind.Float || kind == Kind.Double;
+        assert lowerBound <= upperBound;
+        this.lowerBound = lowerBound;
+        this.upperBound = upperBound;
+        this.nonNaN = nonNaN;
+    }
+
+    /**
+     * The (inclusive) lower bound on the value described by this stamp.
+     */
+    public double lowerBound() {
+        return lowerBound;
+    }
+
+    /**
+     * The (inclusive) upper bound on the value described by this stamp.
+     */
+    public double upperBound() {
+        return upperBound;
+    }
+
+    public boolean isUnrestricted() {
+        return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN;
+    }
+
+    public boolean contains(double value) {
+        if (Double.isNaN(value)) {
+            return !nonNaN;
+        } else {
+            return value >= lowerBound && value <= upperBound;
+        }
     }
 
     @Override
     public String toString() {
-        return "" + kind().typeChar;
+        StringBuilder str = new StringBuilder();
+        str.append(kind().typeChar);
+        str.append(nonNaN ? "!" : "");
+        if (lowerBound == upperBound) {
+            str.append(" [").append(lowerBound).append(']');
+        } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) {
+            str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
+        }
+        return str.toString();
+    }
+
+    @Override
+    public boolean alwaysDistinct(Stamp otherStamp) {
+        FloatStamp other = (FloatStamp) otherStamp;
+        return (nonNaN || other.nonNaN) && (lowerBound > other.upperBound || upperBound < other.lowerBound);
+    }
+
+    @Override
+    public Stamp meet(Stamp otherStamp) {
+        FloatStamp other = (FloatStamp) otherStamp;
+        assert kind() == other.kind();
+        double meetUpperBound = Math.max(upperBound, other.upperBound);
+        double meetLowerBound = Math.min(lowerBound, other.lowerBound);
+        boolean meetNonNaN = nonNaN && other.nonNaN;
+        if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetNonNaN == nonNaN) {
+            return this;
+        } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetNonNaN == other.nonNaN) {
+            return other;
+        } else {
+            return new FloatStamp(kind(), meetLowerBound, meetUpperBound, meetNonNaN);
+        }
     }
 
     @Override
-    public boolean alwaysDistinct(Stamp other) {
-        return false;
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        long temp;
+        temp = Double.doubleToLongBits(lowerBound);
+        result = prime * result + (int) (temp ^ (temp >>> 32));
+        result = prime * result + (nonNaN ? 1231 : 1237);
+        temp = Double.doubleToLongBits(upperBound);
+        result = prime * result + (int) (temp ^ (temp >>> 32));
+        return result;
     }
 
     @Override
-    public Stamp meet(Stamp other) {
-        assert kind() == other.kind();
-        return this;
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        FloatStamp other = (FloatStamp) obj;
+        if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) {
+            return false;
+        }
+        if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) {
+            return false;
+        }
+        if (nonNaN != other.nonNaN) {
+            return false;
+        }
+        return true;
     }
 
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Fri Jul 06 16:21:46 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Fri Jul 06 16:25:59 2012 +0200
@@ -111,6 +111,8 @@
         long meetMask = mask | other.mask;
         if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetMask == mask) {
             return this;
+        } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetMask == other.mask) {
+            return other;
         } else {
             return new IntegerStamp(kind(), meetLowerBound, meetUpperBound, meetMask);
         }
@@ -122,6 +124,7 @@
         int result = 1;
         result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32));
         result = prime * result + (int) (upperBound ^ (upperBound >>> 32));
+        result = prime * result + (int) (mask ^ (mask >>> 32));
         return result;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Fri Jul 06 16:21:46 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Fri Jul 06 16:25:59 2012 +0200
@@ -102,6 +102,10 @@
         return new IntegerStamp(kind, lowerBound, upperBound, mask);
     }
 
+    public static Stamp forFloat(Kind kind, double lowerBound, double upperBound, boolean nonNaN) {
+        return new FloatStamp(kind, lowerBound, upperBound, nonNaN);
+    }
+
     public static Stamp forConstant(Constant value) {
         assert value.kind != Kind.Object;
         if (value.kind == Kind.Object) {
@@ -109,6 +113,8 @@
         } else {
             if (value.kind == Kind.Int || value.kind == Kind.Long) {
                 return forInteger(value.kind, value.asLong(), value.asLong(), value.asLong() & IntegerStamp.defaultMask(value.kind));
+            } else if (value.kind == Kind.Float || value.kind == Kind.Double) {
+                return forFloat(value.kind, value.asDouble(), value.asDouble(), true);
             }
             return forKind(value.kind.stackKind());
         }