1 /*
   2  * Copyright (c) 2012, 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 package org.graalvm.compiler.core.common.type;
  24 
  25 import static org.graalvm.compiler.core.common.calc.FloatConvert.D2F;
  26 import static org.graalvm.compiler.core.common.calc.FloatConvert.D2I;
  27 import static org.graalvm.compiler.core.common.calc.FloatConvert.D2L;
  28 import static org.graalvm.compiler.core.common.calc.FloatConvert.F2D;
  29 import static org.graalvm.compiler.core.common.calc.FloatConvert.F2I;
  30 import static org.graalvm.compiler.core.common.calc.FloatConvert.F2L;
  31 
  32 import java.nio.ByteBuffer;
  33 import java.util.function.DoubleBinaryOperator;
  34 
  35 import org.graalvm.compiler.core.common.LIRKind;
  36 import org.graalvm.compiler.core.common.spi.LIRKindTool;
  37 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
  38 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.FloatConvertOp;
  39 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp;
  40 import org.graalvm.compiler.debug.GraalError;
  41 
  42 import jdk.vm.ci.meta.Constant;
  43 import jdk.vm.ci.meta.JavaConstant;
  44 import jdk.vm.ci.meta.JavaKind;
  45 import jdk.vm.ci.meta.MetaAccessProvider;
  46 import jdk.vm.ci.meta.PrimitiveConstant;
  47 import jdk.vm.ci.meta.ResolvedJavaType;
  48 import jdk.vm.ci.meta.SerializableConstant;
  49 
  50 public class FloatStamp extends PrimitiveStamp {
  51 
  52     private final double lowerBound;
  53     private final double upperBound;
  54     private final boolean nonNaN;
  55 
  56     protected FloatStamp(int bits) {
  57         this(bits, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false);
  58     }
  59 
  60     public FloatStamp(int bits, double lowerBound, double upperBound, boolean nonNaN) {
  61         super(bits, OPS);
  62         assert bits == 64 || (bits == 32 && (Double.isNaN(lowerBound) || (float) lowerBound == lowerBound) && (Double.isNaN(upperBound) || (float) upperBound == upperBound));
  63         assert Double.isNaN(lowerBound) == Double.isNaN(upperBound);
  64         this.lowerBound = lowerBound;
  65         this.upperBound = upperBound;
  66         this.nonNaN = nonNaN;
  67     }
  68 
  69     @Override
  70     public Stamp unrestricted() {
  71         return new FloatStamp(getBits());
  72     }
  73 
  74     @Override
  75     public Stamp empty() {
  76         return new FloatStamp(getBits(), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, true);
  77     }
  78 
  79     @Override
  80     public Stamp constant(Constant c, MetaAccessProvider meta) {
  81         JavaConstant jc = (JavaConstant) c;
  82         assert jc.getJavaKind().isNumericFloat() && jc.getJavaKind().getBitCount() == getBits();
  83         return StampFactory.forConstant(jc);
  84     }
  85 
  86     @Override
  87     public SerializableConstant deserialize(ByteBuffer buffer) {
  88         switch (getBits()) {
  89             case 32:
  90                 return JavaConstant.forFloat(buffer.getFloat());
  91             case 64:
  92                 return JavaConstant.forDouble(buffer.getDouble());
  93             default:
  94                 throw GraalError.shouldNotReachHere();
  95         }
  96     }
  97 
  98     @Override
  99     public boolean hasValues() {
 100         return lowerBound <= upperBound || !nonNaN;
 101     }
 102 
 103     @Override
 104     public JavaKind getStackKind() {
 105         if (getBits() > 32) {
 106             return JavaKind.Double;
 107         } else {
 108             return JavaKind.Float;
 109         }
 110     }
 111 
 112     @Override
 113     public LIRKind getLIRKind(LIRKindTool tool) {
 114         return tool.getFloatingKind(getBits());
 115     }
 116 
 117     @Override
 118     public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
 119         switch (getBits()) {
 120             case 32:
 121                 return metaAccess.lookupJavaType(Float.TYPE);
 122             case 64:
 123                 return metaAccess.lookupJavaType(Double.TYPE);
 124             default:
 125                 throw GraalError.shouldNotReachHere();
 126         }
 127     }
 128 
 129     /**
 130      * The (inclusive) lower bound on the value described by this stamp.
 131      */
 132     public double lowerBound() {
 133         return lowerBound;
 134     }
 135 
 136     /**
 137      * The (inclusive) upper bound on the value described by this stamp.
 138      */
 139     public double upperBound() {
 140         return upperBound;
 141     }
 142 
 143     /**
 144      * Returns true if NaN is non included in the value described by this stamp.
 145      */
 146     public boolean isNonNaN() {
 147         return nonNaN;
 148     }
 149 
 150     /**
 151      * Returns true if this stamp represents the NaN value.
 152      */
 153     public boolean isNaN() {
 154         return Double.isNaN(lowerBound);
 155     }
 156 
 157     @Override
 158     public boolean isUnrestricted() {
 159         return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN;
 160     }
 161 
 162     public boolean contains(double value) {
 163         if (Double.isNaN(value)) {
 164             return !nonNaN;
 165         } else {
 166             /*
 167              * Don't use Double.compare for checking the bounds as -0.0 isn't correctly tracked, so
 168              * the presence of 0.0 means -0.0 might also exist in the range.
 169              */
 170             return value >= lowerBound && value <= upperBound;
 171         }
 172     }
 173 
 174     @Override
 175     public String toString() {
 176         StringBuilder str = new StringBuilder();
 177         str.append('f');
 178         str.append(getBits());
 179         str.append(nonNaN ? "!" : "");
 180         if (lowerBound == upperBound) {
 181             str.append(" [").append(lowerBound).append(']');
 182         } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) {
 183             str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
 184         }
 185         return str.toString();
 186     }
 187 
 188     private static double meetBounds(double a, double b, DoubleBinaryOperator op) {
 189         if (Double.isNaN(a)) {
 190             return b;
 191         } else if (Double.isNaN(b)) {
 192             return a;
 193         } else {
 194             return op.applyAsDouble(a, b);
 195         }
 196     }
 197 
 198     @Override
 199     public Stamp meet(Stamp otherStamp) {
 200         if (otherStamp == this) {
 201             return this;
 202         }
 203         FloatStamp other = (FloatStamp) otherStamp;
 204         assert getBits() == other.getBits();
 205         double meetUpperBound = meetBounds(upperBound, other.upperBound, Math::max);
 206         double meetLowerBound = meetBounds(lowerBound, other.lowerBound, Math::min);
 207         boolean meetNonNaN = nonNaN && other.nonNaN;
 208         if (Double.compare(meetLowerBound, lowerBound) == 0 && Double.compare(meetUpperBound, upperBound) == 0 && meetNonNaN == nonNaN) {
 209             return this;
 210         } else if (Double.compare(meetLowerBound, other.lowerBound) == 0 && Double.compare(meetUpperBound, other.upperBound) == 0 && meetNonNaN == other.nonNaN) {
 211             return other;
 212         } else {
 213             return new FloatStamp(getBits(), meetLowerBound, meetUpperBound, meetNonNaN);
 214         }
 215     }
 216 
 217     @Override
 218     public Stamp join(Stamp otherStamp) {
 219         if (otherStamp == this) {
 220             return this;
 221         }
 222         FloatStamp other = (FloatStamp) otherStamp;
 223         assert getBits() == other.getBits();
 224         double joinUpperBound = Math.min(upperBound, other.upperBound);
 225         double joinLowerBound = Math.max(lowerBound, other.lowerBound);
 226         boolean joinNonNaN = nonNaN || other.nonNaN;
 227         if (Double.compare(joinLowerBound, lowerBound) == 0 && Double.compare(joinUpperBound, upperBound) == 0 && joinNonNaN == nonNaN) {
 228             return this;
 229         } else if (Double.compare(joinLowerBound, other.lowerBound) == 0 && Double.compare(joinUpperBound, other.upperBound) == 0 && joinNonNaN == other.nonNaN) {
 230             return other;
 231         } else {
 232             return new FloatStamp(getBits(), joinLowerBound, joinUpperBound, joinNonNaN);
 233         }
 234     }
 235 
 236     @Override
 237     public int hashCode() {
 238         final int prime = 31;
 239         int result = 1;
 240         long temp;
 241         result = prime * result + super.hashCode();
 242         temp = Double.doubleToLongBits(lowerBound);
 243         result = prime * result + (int) (temp ^ (temp >>> 32));
 244         result = prime * result + (nonNaN ? 1231 : 1237);
 245         temp = Double.doubleToLongBits(upperBound);
 246         result = prime * result + (int) (temp ^ (temp >>> 32));
 247         return result;
 248     }
 249 
 250     @Override
 251     public boolean isCompatible(Stamp stamp) {
 252         if (this == stamp) {
 253             return true;
 254         }
 255         if (stamp instanceof FloatStamp) {
 256             FloatStamp other = (FloatStamp) stamp;
 257             return getBits() == other.getBits();
 258         }
 259         return false;
 260     }
 261 
 262     @Override
 263     public boolean isCompatible(Constant constant) {
 264         if (constant instanceof PrimitiveConstant) {
 265             PrimitiveConstant prim = (PrimitiveConstant) constant;
 266             return prim.getJavaKind().isNumericFloat();
 267         }
 268         return false;
 269     }
 270 
 271     @Override
 272     public boolean equals(Object obj) {
 273         if (this == obj) {
 274             return true;
 275         }
 276         if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) {
 277             return false;
 278         }
 279         FloatStamp other = (FloatStamp) obj;
 280         if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) {
 281             return false;
 282         }
 283         if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) {
 284             return false;
 285         }
 286         if (nonNaN != other.nonNaN) {
 287             return false;
 288         }
 289         return super.equals(other);
 290     }
 291 
 292     @Override
 293     public JavaConstant asConstant() {
 294         if (nonNaN && Double.compare(lowerBound, upperBound) == 0) {
 295             switch (getBits()) {
 296                 case 32:
 297                     return JavaConstant.forFloat((float) lowerBound);
 298                 case 64:
 299                     return JavaConstant.forDouble(lowerBound);
 300             }
 301         }
 302         return null;
 303     }
 304 






























































 305     public static final ArithmeticOpTable OPS = new ArithmeticOpTable(
 306 
 307                     new UnaryOp.Neg() {
 308 
 309                         @Override
 310                         public Constant foldConstant(Constant c) {
 311                             PrimitiveConstant value = (PrimitiveConstant) c;
 312                             switch (value.getJavaKind()) {
 313                                 case Float:
 314                                     return JavaConstant.forFloat(-value.asFloat());
 315                                 case Double:
 316                                     return JavaConstant.forDouble(-value.asDouble());
 317                                 default:
 318                                     throw GraalError.shouldNotReachHere();
 319                             }
 320                         }
 321 
 322                         @Override
 323                         public Stamp foldStamp(Stamp s) {
 324                             FloatStamp stamp = (FloatStamp) s;




 325                             return new FloatStamp(stamp.getBits(), -stamp.upperBound(), -stamp.lowerBound(), stamp.isNonNaN());
 326                         }

 327                     },
 328 
 329                     new BinaryOp.Add(false, true) {
 330 
 331                         @Override
 332                         public Constant foldConstant(Constant const1, Constant const2) {
 333                             PrimitiveConstant a = (PrimitiveConstant) const1;
 334                             PrimitiveConstant b = (PrimitiveConstant) const2;
 335                             assert a.getJavaKind() == b.getJavaKind();
 336                             switch (a.getJavaKind()) {
 337                                 case Float:
 338                                     return JavaConstant.forFloat(a.asFloat() + b.asFloat());
 339                                 case Double:
 340                                     return JavaConstant.forDouble(a.asDouble() + b.asDouble());
 341                                 default:
 342                                     throw GraalError.shouldNotReachHere();
 343                             }
 344                         }
 345 
 346                         @Override
 347                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
 348                             // TODO





 349                             return stamp1.unrestricted();
 350                         }
 351 
 352                         @Override
 353                         public boolean isNeutral(Constant value) {
 354                             PrimitiveConstant n = (PrimitiveConstant) value;
 355                             switch (n.getJavaKind()) {
 356                                 case Float:
 357                                     return Float.compare(n.asFloat(), -0.0f) == 0;
 358                                 case Double:
 359                                     return Double.compare(n.asDouble(), -0.0) == 0;
 360                                 default:
 361                                     throw GraalError.shouldNotReachHere();
 362                             }
 363                         }
 364                     },
 365 
 366                     new BinaryOp.Sub(false, false) {
 367 
 368                         @Override
 369                         public Constant foldConstant(Constant const1, Constant const2) {
 370                             PrimitiveConstant a = (PrimitiveConstant) const1;
 371                             PrimitiveConstant b = (PrimitiveConstant) const2;
 372                             assert a.getJavaKind() == b.getJavaKind();
 373                             switch (a.getJavaKind()) {
 374                                 case Float:
 375                                     return JavaConstant.forFloat(a.asFloat() - b.asFloat());
 376                                 case Double:
 377                                     return JavaConstant.forDouble(a.asDouble() - b.asDouble());
 378                                 default:
 379                                     throw GraalError.shouldNotReachHere();
 380                             }
 381                         }
 382 
 383                         @Override
 384                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
 385                             // TODO





 386                             return stamp1.unrestricted();
 387                         }
 388 
 389                         @Override
 390                         public boolean isNeutral(Constant value) {
 391                             PrimitiveConstant n = (PrimitiveConstant) value;
 392                             switch (n.getJavaKind()) {
 393                                 case Float:
 394                                     return Float.compare(n.asFloat(), 0.0f) == 0;
 395                                 case Double:
 396                                     return Double.compare(n.asDouble(), 0.0) == 0;
 397                                 default:
 398                                     throw GraalError.shouldNotReachHere();
 399                             }
 400                         }
 401                     },
 402 
 403                     new BinaryOp.Mul(false, true) {
 404 
 405                         @Override
 406                         public Constant foldConstant(Constant const1, Constant const2) {
 407                             PrimitiveConstant a = (PrimitiveConstant) const1;
 408                             PrimitiveConstant b = (PrimitiveConstant) const2;
 409                             assert a.getJavaKind() == b.getJavaKind();
 410                             switch (a.getJavaKind()) {
 411                                 case Float:
 412                                     return JavaConstant.forFloat(a.asFloat() * b.asFloat());
 413                                 case Double:
 414                                     return JavaConstant.forDouble(a.asDouble() * b.asDouble());
 415                                 default:
 416                                     throw GraalError.shouldNotReachHere();
 417                             }
 418                         }
 419 
 420                         @Override
 421                         public Stamp foldStamp(Stamp a, Stamp b) {
 422                             // TODO
 423                             return a.unrestricted();





 424                         }
 425 
 426                         @Override
 427                         public boolean isNeutral(Constant value) {
 428                             PrimitiveConstant n = (PrimitiveConstant) value;
 429                             switch (n.getJavaKind()) {
 430                                 case Float:
 431                                     return Float.compare(n.asFloat(), 1.0f) == 0;
 432                                 case Double:
 433                                     return Double.compare(n.asDouble(), 1.0) == 0;
 434                                 default:
 435                                     throw GraalError.shouldNotReachHere();
 436                             }
 437                         }
 438                     },
 439 
 440                     null,
 441 
 442                     null,
 443 
 444                     new BinaryOp.Div(false, false) {
 445 
 446                         @Override
 447                         public Constant foldConstant(Constant const1, Constant const2) {
 448                             PrimitiveConstant a = (PrimitiveConstant) const1;
 449                             PrimitiveConstant b = (PrimitiveConstant) const2;
 450                             assert a.getJavaKind() == b.getJavaKind();
 451                             switch (a.getJavaKind()) {
 452                                 case Float:
 453                                     return JavaConstant.forFloat(a.asFloat() / b.asFloat());

 454                                 case Double:
 455                                     return JavaConstant.forDouble(a.asDouble() / b.asDouble());

 456                                 default:
 457                                     throw GraalError.shouldNotReachHere();
 458                             }
 459                         }
 460 
 461                         @Override
 462                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
 463                             // TODO





 464                             return stamp1.unrestricted();
 465                         }
 466 
 467                         @Override
 468                         public boolean isNeutral(Constant value) {
 469                             PrimitiveConstant n = (PrimitiveConstant) value;
 470                             switch (n.getJavaKind()) {
 471                                 case Float:
 472                                     return Float.compare(n.asFloat(), 1.0f) == 0;
 473                                 case Double:
 474                                     return Double.compare(n.asDouble(), 1.0) == 0;
 475                                 default:
 476                                     throw GraalError.shouldNotReachHere();
 477                             }
 478                         }
 479                     },
 480 
 481                     new BinaryOp.Rem(false, false) {
 482 
 483                         @Override
 484                         public Constant foldConstant(Constant const1, Constant const2) {
 485                             PrimitiveConstant a = (PrimitiveConstant) const1;
 486                             PrimitiveConstant b = (PrimitiveConstant) const2;
 487                             assert a.getJavaKind() == b.getJavaKind();
 488                             switch (a.getJavaKind()) {
 489                                 case Float:
 490                                     return JavaConstant.forFloat(a.asFloat() % b.asFloat());
 491                                 case Double:
 492                                     return JavaConstant.forDouble(a.asDouble() % b.asDouble());
 493                                 default:
 494                                     throw GraalError.shouldNotReachHere();
 495                             }
 496                         }
 497 
 498                         @Override
 499                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
 500                             // TODO





 501                             return stamp1.unrestricted();
 502                         }
 503                     },
 504 
 505                     new UnaryOp.Not() {
 506 
 507                         @Override
 508                         public Constant foldConstant(Constant c) {
 509                             PrimitiveConstant value = (PrimitiveConstant) c;
 510                             switch (value.getJavaKind()) {
 511                                 case Float:
 512                                     int f = Float.floatToRawIntBits(value.asFloat());
 513                                     return JavaConstant.forFloat(Float.intBitsToFloat(~f));
 514                                 case Double:
 515                                     long d = Double.doubleToRawLongBits(value.asDouble());
 516                                     return JavaConstant.forDouble(Double.longBitsToDouble(~d));
 517                                 default:
 518                                     throw GraalError.shouldNotReachHere();
 519                             }
 520                         }
 521 
 522                         @Override
 523                         public Stamp foldStamp(Stamp s) {











 524                             return s.unrestricted();
 525                         }
 526                     },
 527 
 528                     new BinaryOp.And(true, true) {
 529 
 530                         @Override
 531                         public Constant foldConstant(Constant const1, Constant const2) {
 532                             PrimitiveConstant a = (PrimitiveConstant) const1;
 533                             PrimitiveConstant b = (PrimitiveConstant) const2;
 534                             assert a.getJavaKind() == b.getJavaKind();
 535                             switch (a.getJavaKind()) {
 536                                 case Float:
 537                                     int fa = Float.floatToRawIntBits(a.asFloat());
 538                                     int fb = Float.floatToRawIntBits(b.asFloat());
 539                                     return JavaConstant.forFloat(Float.intBitsToFloat(fa & fb));
 540                                 case Double:
 541                                     long da = Double.doubleToRawLongBits(a.asDouble());
 542                                     long db = Double.doubleToRawLongBits(b.asDouble());
 543                                     return JavaConstant.forDouble(Double.longBitsToDouble(da & db));
 544                                 default:
 545                                     throw GraalError.shouldNotReachHere();
 546                             }
 547                         }
 548 
 549                         @Override
 550                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {






 551                             return stamp1.unrestricted();
 552                         }
 553 
 554                         @Override
 555                         public boolean isNeutral(Constant n) {
 556                             PrimitiveConstant value = (PrimitiveConstant) n;
 557                             switch (value.getJavaKind()) {
 558                                 case Float:
 559                                     return Float.floatToRawIntBits(value.asFloat()) == 0xFFFFFFFF;
 560                                 case Double:
 561                                     return Double.doubleToRawLongBits(value.asDouble()) == 0xFFFFFFFFFFFFFFFFL;
 562                                 default:
 563                                     throw GraalError.shouldNotReachHere();
 564                             }
 565                         }
 566                     },
 567 
 568                     new BinaryOp.Or(true, true) {
 569 
 570                         @Override
 571                         public Constant foldConstant(Constant const1, Constant const2) {
 572                             PrimitiveConstant a = (PrimitiveConstant) const1;
 573                             PrimitiveConstant b = (PrimitiveConstant) const2;
 574                             assert a.getJavaKind() == b.getJavaKind();
 575                             switch (a.getJavaKind()) {
 576                                 case Float:
 577                                     int fa = Float.floatToRawIntBits(a.asFloat());
 578                                     int fb = Float.floatToRawIntBits(b.asFloat());
 579                                     return JavaConstant.forFloat(Float.intBitsToFloat(fa | fb));


 580                                 case Double:
 581                                     long da = Double.doubleToRawLongBits(a.asDouble());
 582                                     long db = Double.doubleToRawLongBits(b.asDouble());
 583                                     return JavaConstant.forDouble(Double.longBitsToDouble(da | db));
 584                                 default:
 585                                     throw GraalError.shouldNotReachHere();
 586                             }
 587                         }
 588 
 589                         @Override
 590                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {






 591                             return stamp1.unrestricted();
 592                         }
 593 
 594                         @Override
 595                         public boolean isNeutral(Constant n) {
 596                             PrimitiveConstant value = (PrimitiveConstant) n;
 597                             switch (value.getJavaKind()) {
 598                                 case Float:
 599                                     return Float.floatToRawIntBits(value.asFloat()) == 0;
 600                                 case Double:
 601                                     return Double.doubleToRawLongBits(value.asDouble()) == 0L;
 602                                 default:
 603                                     throw GraalError.shouldNotReachHere();
 604                             }
 605                         }
 606                     },
 607 
 608                     new BinaryOp.Xor(true, true) {
 609 
 610                         @Override
 611                         public Constant foldConstant(Constant const1, Constant const2) {
 612                             PrimitiveConstant a = (PrimitiveConstant) const1;
 613                             PrimitiveConstant b = (PrimitiveConstant) const2;
 614                             assert a.getJavaKind() == b.getJavaKind();
 615                             switch (a.getJavaKind()) {
 616                                 case Float:
 617                                     int fa = Float.floatToRawIntBits(a.asFloat());
 618                                     int fb = Float.floatToRawIntBits(b.asFloat());
 619                                     return JavaConstant.forFloat(Float.intBitsToFloat(fa ^ fb));
 620                                 case Double:
 621                                     long da = Double.doubleToRawLongBits(a.asDouble());
 622                                     long db = Double.doubleToRawLongBits(b.asDouble());
 623                                     return JavaConstant.forDouble(Double.longBitsToDouble(da ^ db));
 624                                 default:
 625                                     throw GraalError.shouldNotReachHere();
 626                             }
 627                         }
 628 
 629                         @Override
 630                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {






 631                             return stamp1.unrestricted();
 632                         }
 633 
 634                         @Override
 635                         public boolean isNeutral(Constant n) {
 636                             PrimitiveConstant value = (PrimitiveConstant) n;
 637                             switch (value.getJavaKind()) {
 638                                 case Float:
 639                                     return Float.floatToRawIntBits(value.asFloat()) == 0;
 640                                 case Double:
 641                                     return Double.doubleToRawLongBits(value.asDouble()) == 0L;
 642                                 default:
 643                                     throw GraalError.shouldNotReachHere();
 644                             }
 645                         }
 646                     },
 647 
 648                     null, null, null,
 649 
 650                     new UnaryOp.Abs() {
 651 
 652                         @Override
 653                         public Constant foldConstant(Constant c) {
 654                             PrimitiveConstant value = (PrimitiveConstant) c;
 655                             switch (value.getJavaKind()) {
 656                                 case Float:
 657                                     return JavaConstant.forFloat(Math.abs(value.asFloat()));
 658                                 case Double:
 659                                     return JavaConstant.forDouble(Math.abs(value.asDouble()));
 660                                 default:
 661                                     throw GraalError.shouldNotReachHere();
 662                             }
 663                         }
 664 
 665                         @Override
 666                         public Stamp foldStamp(Stamp s) {
 667                             FloatStamp stamp = (FloatStamp) s;




 668                             if (stamp.isNaN()) {
 669                                 return stamp;
 670                             }
 671                             return new FloatStamp(stamp.getBits(), 0, Math.max(-stamp.lowerBound(), stamp.upperBound()), stamp.isNonNaN());
 672                         }
 673                     },
 674 
 675                     new UnaryOp.Sqrt() {
 676 
 677                         @Override
 678                         public Constant foldConstant(Constant c) {
 679                             PrimitiveConstant value = (PrimitiveConstant) c;
 680                             switch (value.getJavaKind()) {
 681                                 case Float:
 682                                     return JavaConstant.forFloat((float) Math.sqrt(value.asFloat()));
 683                                 case Double:
 684                                     return JavaConstant.forDouble(Math.sqrt(value.asDouble()));
 685                                 default:
 686                                     throw GraalError.shouldNotReachHere();
 687                             }
 688                         }
 689 
 690                         @Override
 691                         public Stamp foldStamp(Stamp s) {





 692                             return s.unrestricted();
 693                         }
 694                     },
 695 
 696                     null, null, null,
 697 
 698                     new FloatConvertOp(F2I) {
 699 
 700                         @Override
 701                         public Constant foldConstant(Constant c) {
 702                             PrimitiveConstant value = (PrimitiveConstant) c;
 703                             return JavaConstant.forInt((int) value.asFloat());
 704                         }
 705 
 706                         @Override
 707                         public Stamp foldStamp(Stamp stamp) {
 708                             FloatStamp floatStamp = (FloatStamp) stamp;
 709                             assert floatStamp.getBits() == 32;
 710                             boolean mustHaveZero = !floatStamp.isNonNaN();
 711                             int lowerBound = (int) floatStamp.lowerBound();
 712                             int upperBound = (int) floatStamp.upperBound();
 713                             if (mustHaveZero) {
 714                                 if (lowerBound > 0) {
 715                                     lowerBound = 0;
 716                                 } else if (upperBound < 0) {
 717                                     upperBound = 0;
 718                                 }
 719                             }
 720                             return StampFactory.forInteger(JavaKind.Int, lowerBound, upperBound);
 721                         }
 722                     },
 723 
 724                     new FloatConvertOp(F2L) {
 725 
 726                         @Override
 727                         public Constant foldConstant(Constant c) {
 728                             PrimitiveConstant value = (PrimitiveConstant) c;
 729                             return JavaConstant.forLong((long) value.asFloat());
 730                         }
 731 
 732                         @Override
 733                         public Stamp foldStamp(Stamp stamp) {
 734                             FloatStamp floatStamp = (FloatStamp) stamp;
 735                             assert floatStamp.getBits() == 32;
 736                             boolean mustHaveZero = !floatStamp.isNonNaN();
 737                             long lowerBound = (long) floatStamp.lowerBound();
 738                             long upperBound = (long) floatStamp.upperBound();
 739                             if (mustHaveZero) {
 740                                 if (lowerBound > 0) {
 741                                     lowerBound = 0;
 742                                 } else if (upperBound < 0) {
 743                                     upperBound = 0;
 744                                 }
 745                             }
 746                             return StampFactory.forInteger(JavaKind.Long, lowerBound, upperBound);
 747                         }
 748                     },
 749 
 750                     new FloatConvertOp(D2I) {
 751 
 752                         @Override
 753                         public Constant foldConstant(Constant c) {
 754                             PrimitiveConstant value = (PrimitiveConstant) c;
 755                             return JavaConstant.forInt((int) value.asDouble());
 756                         }
 757 
 758                         @Override
 759                         public Stamp foldStamp(Stamp stamp) {
 760                             FloatStamp floatStamp = (FloatStamp) stamp;
 761                             assert floatStamp.getBits() == 64;
 762                             boolean mustHaveZero = !floatStamp.isNonNaN();
 763                             int lowerBound = (int) floatStamp.lowerBound();
 764                             int upperBound = (int) floatStamp.upperBound();
 765                             if (mustHaveZero) {
 766                                 if (lowerBound > 0) {
 767                                     lowerBound = 0;
 768                                 } else if (upperBound < 0) {
 769                                     upperBound = 0;
 770                                 }
 771                             }
 772                             return StampFactory.forInteger(JavaKind.Int, lowerBound, upperBound);
 773                         }
 774                     },
 775 
 776                     new FloatConvertOp(D2L) {
 777 
 778                         @Override
 779                         public Constant foldConstant(Constant c) {
 780                             PrimitiveConstant value = (PrimitiveConstant) c;
 781                             return JavaConstant.forLong((long) value.asDouble());
 782                         }
 783 
 784                         @Override
 785                         public Stamp foldStamp(Stamp stamp) {
 786                             FloatStamp floatStamp = (FloatStamp) stamp;
 787                             assert floatStamp.getBits() == 64;
 788                             boolean mustHaveZero = !floatStamp.isNonNaN();
 789                             long lowerBound = (long) floatStamp.lowerBound();
 790                             long upperBound = (long) floatStamp.upperBound();
 791                             if (mustHaveZero) {
 792                                 if (lowerBound > 0) {
 793                                     lowerBound = 0;
 794                                 } else if (upperBound < 0) {
 795                                     upperBound = 0;
 796                                 }
 797                             }
 798                             return StampFactory.forInteger(JavaKind.Long, lowerBound, upperBound);
 799                         }
 800                     },
 801 
 802                     new FloatConvertOp(F2D) {
 803 
 804                         @Override
 805                         public Constant foldConstant(Constant c) {
 806                             PrimitiveConstant value = (PrimitiveConstant) c;
 807                             return JavaConstant.forDouble(value.asFloat());
 808                         }
 809 
 810                         @Override
 811                         public Stamp foldStamp(Stamp stamp) {
 812                             FloatStamp floatStamp = (FloatStamp) stamp;
 813                             assert floatStamp.getBits() == 32;
 814                             return StampFactory.forFloat(JavaKind.Double, floatStamp.lowerBound(), floatStamp.upperBound(), floatStamp.isNonNaN());
 815                         }
 816                     },
 817 
 818                     new FloatConvertOp(D2F) {
 819 
 820                         @Override
 821                         public Constant foldConstant(Constant c) {
 822                             PrimitiveConstant value = (PrimitiveConstant) c;
 823                             return JavaConstant.forFloat((float) value.asDouble());
 824                         }
 825 
 826                         @Override
 827                         public Stamp foldStamp(Stamp stamp) {
 828                             FloatStamp floatStamp = (FloatStamp) stamp;
 829                             assert floatStamp.getBits() == 64;
 830                             return StampFactory.forFloat(JavaKind.Float, (float) floatStamp.lowerBound(), (float) floatStamp.upperBound(), floatStamp.isNonNaN());
 831                         }
 832                     });
 833 }
--- EOF ---