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 public boolean isUnrestricted() { 158 return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN; 159 } 160 161 public boolean contains(double value) { 162 if (Double.isNaN(value)) { 163 return !nonNaN; 164 } else { 165 /* 166 * Don't use Double.compare for checking the bounds as -0.0 isn't correctly tracked, so 167 * the presence of 0.0 means -0.0 might also exist in the range. 168 */ 169 return value >= lowerBound && value <= upperBound; 170 } 171 } 172 173 @Override 174 public String toString() { 175 StringBuilder str = new StringBuilder(); 176 str.append('f'); 177 str.append(getBits()); 178 str.append(nonNaN ? "!" : ""); 179 if (lowerBound == upperBound) { 180 str.append(" [").append(lowerBound).append(']'); 181 } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) { 182 str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); 183 } 184 return str.toString(); 185 } 186 187 private static double meetBounds(double a, double b, DoubleBinaryOperator op) { 188 if (Double.isNaN(a)) { 189 return b; 190 } else if (Double.isNaN(b)) { 191 return a; 192 } else { 193 return op.applyAsDouble(a, b); 194 } 195 } 196 197 @Override 198 public Stamp meet(Stamp otherStamp) { 199 if (otherStamp == this) { 200 return this; 201 } 202 FloatStamp other = (FloatStamp) otherStamp; 203 assert getBits() == other.getBits(); 204 double meetUpperBound = meetBounds(upperBound, other.upperBound, Math::max); 205 double meetLowerBound = meetBounds(lowerBound, other.lowerBound, Math::min); 206 boolean meetNonNaN = nonNaN && other.nonNaN; 207 if (Double.compare(meetLowerBound, lowerBound) == 0 && Double.compare(meetUpperBound, upperBound) == 0 && meetNonNaN == nonNaN) { 208 return this; 209 } else if (Double.compare(meetLowerBound, other.lowerBound) == 0 && Double.compare(meetUpperBound, other.upperBound) == 0 && meetNonNaN == other.nonNaN) { 210 return other; 211 } else { 212 return new FloatStamp(getBits(), meetLowerBound, meetUpperBound, meetNonNaN); 213 } 214 } 215 216 @Override 217 public Stamp join(Stamp otherStamp) { 218 if (otherStamp == this) { 219 return this; 220 } 221 FloatStamp other = (FloatStamp) otherStamp; 222 assert getBits() == other.getBits(); 223 double joinUpperBound = Math.min(upperBound, other.upperBound); 224 double joinLowerBound = Math.max(lowerBound, other.lowerBound); 225 boolean joinNonNaN = nonNaN || other.nonNaN; 226 if (Double.compare(joinLowerBound, lowerBound) == 0 && Double.compare(joinUpperBound, upperBound) == 0 && joinNonNaN == nonNaN) { 227 return this; 228 } else if (Double.compare(joinLowerBound, other.lowerBound) == 0 && Double.compare(joinUpperBound, other.upperBound) == 0 && joinNonNaN == other.nonNaN) { 229 return other; 230 } else { 231 return new FloatStamp(getBits(), joinLowerBound, joinUpperBound, joinNonNaN); 232 } 233 } 234 235 @Override 236 public int hashCode() { 237 final int prime = 31; 238 int result = 1; 239 long temp; 240 result = prime * result + super.hashCode(); 241 temp = Double.doubleToLongBits(lowerBound); 242 result = prime * result + (int) (temp ^ (temp >>> 32)); 243 result = prime * result + (nonNaN ? 1231 : 1237); 244 temp = Double.doubleToLongBits(upperBound); 245 result = prime * result + (int) (temp ^ (temp >>> 32)); 246 return result; 247 } 248 249 @Override 250 public boolean isCompatible(Stamp stamp) { 251 if (this == stamp) { 252 return true; 253 } 254 if (stamp instanceof FloatStamp) { 255 FloatStamp other = (FloatStamp) stamp; 256 return getBits() == other.getBits(); 257 } 258 return false; 259 } 260 261 @Override 262 public boolean isCompatible(Constant constant) { 263 if (constant instanceof PrimitiveConstant) { 264 PrimitiveConstant prim = (PrimitiveConstant) constant; 265 return prim.getJavaKind().isNumericFloat(); 266 } 267 return false; 268 } 269 270 @Override 271 public boolean equals(Object obj) { 272 if (this == obj) { 273 return true; 274 } 275 if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) { 276 return false; 277 } 278 FloatStamp other = (FloatStamp) obj; 279 if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) { 280 return false; 281 } 282 if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) { 283 return false; 284 } 285 if (nonNaN != other.nonNaN) { 286 return false; 287 } 288 return super.equals(other); 289 } 290 291 @Override 292 public JavaConstant asConstant() { 293 if (nonNaN && Double.compare(lowerBound, upperBound) == 0) { 294 switch (getBits()) { 295 case 32: 296 return JavaConstant.forFloat((float) lowerBound); 297 case 64: 298 return JavaConstant.forDouble(lowerBound); 299 } 300 } 301 return null; 302 } 303 304 public boolean isConstant() { 305 return (nonNaN && Double.compare(lowerBound, upperBound) == 0); 306 } 307 308 private static final ArithmeticOpTable OPS = new ArithmeticOpTable( 309 310 new UnaryOp.Neg() { 311 312 @Override 313 public Constant foldConstant(Constant c) { 314 PrimitiveConstant value = (PrimitiveConstant) c; 315 switch (value.getJavaKind()) { 316 case Float: 317 return JavaConstant.forFloat(-value.asFloat()); 318 case Double: 319 return JavaConstant.forDouble(-value.asDouble()); 320 default: 321 throw GraalError.shouldNotReachHere(); 322 } 323 } 324 325 @Override 326 public Stamp foldStamp(Stamp s) { 327 FloatStamp stamp = (FloatStamp) s; 328 return new FloatStamp(stamp.getBits(), -stamp.upperBound(), -stamp.lowerBound(), stamp.isNonNaN()); 329 } 330 }, 331 332 new BinaryOp.Add(false, true) { 333 334 @Override 335 public Constant foldConstant(Constant const1, Constant const2) { 336 PrimitiveConstant a = (PrimitiveConstant) const1; 337 PrimitiveConstant b = (PrimitiveConstant) const2; 338 assert a.getJavaKind() == b.getJavaKind(); 339 switch (a.getJavaKind()) { 340 case Float: 341 return JavaConstant.forFloat(a.asFloat() + b.asFloat()); 342 case Double: 343 return JavaConstant.forDouble(a.asDouble() + b.asDouble()); 344 default: 345 throw GraalError.shouldNotReachHere(); 346 } 347 } 348 349 @Override 350 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 351 // TODO 352 return stamp1.unrestricted(); 353 } 354 355 @Override 356 public boolean isNeutral(Constant value) { 357 PrimitiveConstant n = (PrimitiveConstant) value; 358 switch (n.getJavaKind()) { 359 case Float: 360 return Float.compare(n.asFloat(), -0.0f) == 0; 361 case Double: 362 return Double.compare(n.asDouble(), -0.0) == 0; 363 default: 364 throw GraalError.shouldNotReachHere(); 365 } 366 } 367 }, 368 369 new BinaryOp.Sub(false, false) { 370 371 @Override 372 public Constant foldConstant(Constant const1, Constant const2) { 373 PrimitiveConstant a = (PrimitiveConstant) const1; 374 PrimitiveConstant b = (PrimitiveConstant) const2; 375 assert a.getJavaKind() == b.getJavaKind(); 376 switch (a.getJavaKind()) { 377 case Float: 378 return JavaConstant.forFloat(a.asFloat() - b.asFloat()); 379 case Double: 380 return JavaConstant.forDouble(a.asDouble() - b.asDouble()); 381 default: 382 throw GraalError.shouldNotReachHere(); 383 } 384 } 385 386 @Override 387 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 388 // TODO 389 return stamp1.unrestricted(); 390 } 391 392 @Override 393 public boolean isNeutral(Constant value) { 394 PrimitiveConstant n = (PrimitiveConstant) value; 395 switch (n.getJavaKind()) { 396 case Float: 397 return Float.compare(n.asFloat(), 0.0f) == 0; 398 case Double: 399 return Double.compare(n.asDouble(), 0.0) == 0; 400 default: 401 throw GraalError.shouldNotReachHere(); 402 } 403 } 404 }, 405 406 new BinaryOp.Mul(false, true) { 407 408 @Override 409 public Constant foldConstant(Constant const1, Constant const2) { 410 PrimitiveConstant a = (PrimitiveConstant) const1; 411 PrimitiveConstant b = (PrimitiveConstant) const2; 412 assert a.getJavaKind() == b.getJavaKind(); 413 switch (a.getJavaKind()) { 414 case Float: 415 return JavaConstant.forFloat(a.asFloat() * b.asFloat()); 416 case Double: 417 return JavaConstant.forDouble(a.asDouble() * b.asDouble()); 418 default: 419 throw GraalError.shouldNotReachHere(); 420 } 421 } 422 423 @Override 424 public Stamp foldStamp(Stamp a, Stamp b) { 425 // TODO 426 return a.unrestricted(); 427 } 428 429 @Override 430 public boolean isNeutral(Constant value) { 431 PrimitiveConstant n = (PrimitiveConstant) value; 432 switch (n.getJavaKind()) { 433 case Float: 434 return Float.compare(n.asFloat(), 1.0f) == 0; 435 case Double: 436 return Double.compare(n.asDouble(), 1.0) == 0; 437 default: 438 throw GraalError.shouldNotReachHere(); 439 } 440 } 441 }, 442 443 new BinaryOp.Div(false, false) { 444 445 @Override 446 public Constant foldConstant(Constant const1, Constant const2) { 447 PrimitiveConstant a = (PrimitiveConstant) const1; 448 PrimitiveConstant b = (PrimitiveConstant) const2; 449 assert a.getJavaKind() == b.getJavaKind(); 450 switch (a.getJavaKind()) { 451 case Float: 452 return JavaConstant.forFloat(a.asFloat() / b.asFloat()); 453 case Double: 454 return JavaConstant.forDouble(a.asDouble() / b.asDouble()); 455 default: 456 throw GraalError.shouldNotReachHere(); 457 } 458 } 459 460 @Override 461 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 462 // TODO 463 return stamp1.unrestricted(); 464 } 465 466 @Override 467 public boolean isNeutral(Constant value) { 468 PrimitiveConstant n = (PrimitiveConstant) value; 469 switch (n.getJavaKind()) { 470 case Float: 471 return Float.compare(n.asFloat(), 1.0f) == 0; 472 case Double: 473 return Double.compare(n.asDouble(), 1.0) == 0; 474 default: 475 throw GraalError.shouldNotReachHere(); 476 } 477 } 478 }, 479 480 new BinaryOp.Rem(false, false) { 481 482 @Override 483 public Constant foldConstant(Constant const1, Constant const2) { 484 PrimitiveConstant a = (PrimitiveConstant) const1; 485 PrimitiveConstant b = (PrimitiveConstant) const2; 486 assert a.getJavaKind() == b.getJavaKind(); 487 switch (a.getJavaKind()) { 488 case Float: 489 return JavaConstant.forFloat(a.asFloat() % b.asFloat()); 490 case Double: 491 return JavaConstant.forDouble(a.asDouble() % b.asDouble()); 492 default: 493 throw GraalError.shouldNotReachHere(); 494 } 495 } 496 497 @Override 498 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 499 // TODO 500 return stamp1.unrestricted(); 501 } 502 }, 503 504 new UnaryOp.Not() { 505 506 @Override 507 public Constant foldConstant(Constant c) { 508 PrimitiveConstant value = (PrimitiveConstant) c; 509 switch (value.getJavaKind()) { 510 case Float: 511 int f = Float.floatToRawIntBits(value.asFloat()); 512 return JavaConstant.forFloat(Float.intBitsToFloat(~f)); 513 case Double: 514 long d = Double.doubleToRawLongBits(value.asDouble()); 515 return JavaConstant.forDouble(Double.longBitsToDouble(~d)); 516 default: 517 throw GraalError.shouldNotReachHere(); 518 } 519 } 520 521 @Override 522 public Stamp foldStamp(Stamp s) { 523 return s.unrestricted(); 524 } 525 }, 526 527 new BinaryOp.And(true, true) { 528 529 @Override 530 public Constant foldConstant(Constant const1, Constant const2) { 531 PrimitiveConstant a = (PrimitiveConstant) const1; 532 PrimitiveConstant b = (PrimitiveConstant) const2; 533 assert a.getJavaKind() == b.getJavaKind(); 534 switch (a.getJavaKind()) { 535 case Float: 536 int fa = Float.floatToRawIntBits(a.asFloat()); 537 int fb = Float.floatToRawIntBits(b.asFloat()); 538 return JavaConstant.forFloat(Float.intBitsToFloat(fa & fb)); 539 case Double: 540 long da = Double.doubleToRawLongBits(a.asDouble()); 541 long db = Double.doubleToRawLongBits(b.asDouble()); 542 return JavaConstant.forDouble(Double.longBitsToDouble(da & db)); 543 default: 544 throw GraalError.shouldNotReachHere(); 545 } 546 } 547 548 @Override 549 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 550 return stamp1.unrestricted(); 551 } 552 553 @Override 554 public boolean isNeutral(Constant n) { 555 PrimitiveConstant value = (PrimitiveConstant) n; 556 switch (value.getJavaKind()) { 557 case Float: 558 return Float.floatToRawIntBits(value.asFloat()) == 0xFFFFFFFF; 559 case Double: 560 return Double.doubleToRawLongBits(value.asDouble()) == 0xFFFFFFFFFFFFFFFFL; 561 default: 562 throw GraalError.shouldNotReachHere(); 563 } 564 } 565 }, 566 567 new BinaryOp.Or(true, true) { 568 569 @Override 570 public Constant foldConstant(Constant const1, Constant const2) { 571 PrimitiveConstant a = (PrimitiveConstant) const1; 572 PrimitiveConstant b = (PrimitiveConstant) const2; 573 assert a.getJavaKind() == b.getJavaKind(); 574 switch (a.getJavaKind()) { 575 case Float: 576 int fa = Float.floatToRawIntBits(a.asFloat()); 577 int fb = Float.floatToRawIntBits(b.asFloat()); 578 return JavaConstant.forFloat(Float.intBitsToFloat(fa | fb)); 579 case Double: 580 long da = Double.doubleToRawLongBits(a.asDouble()); 581 long db = Double.doubleToRawLongBits(b.asDouble()); 582 return JavaConstant.forDouble(Double.longBitsToDouble(da | db)); 583 default: 584 throw GraalError.shouldNotReachHere(); 585 } 586 } 587 588 @Override 589 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 590 return stamp1.unrestricted(); 591 } 592 593 @Override 594 public boolean isNeutral(Constant n) { 595 PrimitiveConstant value = (PrimitiveConstant) n; 596 switch (value.getJavaKind()) { 597 case Float: 598 return Float.floatToRawIntBits(value.asFloat()) == 0; 599 case Double: 600 return Double.doubleToRawLongBits(value.asDouble()) == 0L; 601 default: 602 throw GraalError.shouldNotReachHere(); 603 } 604 } 605 }, 606 607 new BinaryOp.Xor(true, true) { 608 609 @Override 610 public Constant foldConstant(Constant const1, Constant const2) { 611 PrimitiveConstant a = (PrimitiveConstant) const1; 612 PrimitiveConstant b = (PrimitiveConstant) const2; 613 assert a.getJavaKind() == b.getJavaKind(); 614 switch (a.getJavaKind()) { 615 case Float: 616 int fa = Float.floatToRawIntBits(a.asFloat()); 617 int fb = Float.floatToRawIntBits(b.asFloat()); 618 return JavaConstant.forFloat(Float.intBitsToFloat(fa ^ fb)); 619 case Double: 620 long da = Double.doubleToRawLongBits(a.asDouble()); 621 long db = Double.doubleToRawLongBits(b.asDouble()); 622 return JavaConstant.forDouble(Double.longBitsToDouble(da ^ db)); 623 default: 624 throw GraalError.shouldNotReachHere(); 625 } 626 } 627 628 @Override 629 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 630 return stamp1.unrestricted(); 631 } 632 633 @Override 634 public boolean isNeutral(Constant n) { 635 PrimitiveConstant value = (PrimitiveConstant) n; 636 switch (value.getJavaKind()) { 637 case Float: 638 return Float.floatToRawIntBits(value.asFloat()) == 0; 639 case Double: 640 return Double.doubleToRawLongBits(value.asDouble()) == 0L; 641 default: 642 throw GraalError.shouldNotReachHere(); 643 } 644 } 645 }, 646 647 null, null, null, 648 649 new UnaryOp.Abs() { 650 651 @Override 652 public Constant foldConstant(Constant c) { 653 PrimitiveConstant value = (PrimitiveConstant) c; 654 switch (value.getJavaKind()) { 655 case Float: 656 return JavaConstant.forFloat(Math.abs(value.asFloat())); 657 case Double: 658 return JavaConstant.forDouble(Math.abs(value.asDouble())); 659 default: 660 throw GraalError.shouldNotReachHere(); 661 } 662 } 663 664 @Override 665 public Stamp foldStamp(Stamp s) { 666 FloatStamp stamp = (FloatStamp) s; 667 if (stamp.isNaN()) { 668 return stamp; 669 } 670 return new FloatStamp(stamp.getBits(), 0, Math.max(-stamp.lowerBound(), stamp.upperBound()), stamp.isNonNaN()); 671 } 672 }, 673 674 new UnaryOp.Sqrt() { 675 676 @Override 677 public Constant foldConstant(Constant c) { 678 PrimitiveConstant value = (PrimitiveConstant) c; 679 switch (value.getJavaKind()) { 680 case Float: 681 return JavaConstant.forFloat((float) Math.sqrt(value.asFloat())); 682 case Double: 683 return JavaConstant.forDouble(Math.sqrt(value.asDouble())); 684 default: 685 throw GraalError.shouldNotReachHere(); 686 } 687 } 688 689 @Override 690 public Stamp foldStamp(Stamp s) { 691 return s.unrestricted(); 692 } 693 }, 694 695 null, null, null, 696 697 new FloatConvertOp(F2I) { 698 699 @Override 700 public Constant foldConstant(Constant c) { 701 PrimitiveConstant value = (PrimitiveConstant) c; 702 return JavaConstant.forInt((int) value.asFloat()); 703 } 704 705 @Override 706 public Stamp foldStamp(Stamp stamp) { 707 FloatStamp floatStamp = (FloatStamp) stamp; 708 assert floatStamp.getBits() == 32; 709 boolean mustHaveZero = !floatStamp.isNonNaN(); 710 int lowerBound = (int) floatStamp.lowerBound(); 711 int upperBound = (int) floatStamp.upperBound(); 712 if (mustHaveZero) { 713 if (lowerBound > 0) { 714 lowerBound = 0; 715 } else if (upperBound < 0) { 716 upperBound = 0; 717 } 718 } 719 return StampFactory.forInteger(JavaKind.Int, lowerBound, upperBound); 720 } 721 }, 722 723 new FloatConvertOp(F2L) { 724 725 @Override 726 public Constant foldConstant(Constant c) { 727 PrimitiveConstant value = (PrimitiveConstant) c; 728 return JavaConstant.forLong((long) value.asFloat()); 729 } 730 731 @Override 732 public Stamp foldStamp(Stamp stamp) { 733 FloatStamp floatStamp = (FloatStamp) stamp; 734 assert floatStamp.getBits() == 32; 735 boolean mustHaveZero = !floatStamp.isNonNaN(); 736 long lowerBound = (long) floatStamp.lowerBound(); 737 long upperBound = (long) floatStamp.upperBound(); 738 if (mustHaveZero) { 739 if (lowerBound > 0) { 740 lowerBound = 0; 741 } else if (upperBound < 0) { 742 upperBound = 0; 743 } 744 } 745 return StampFactory.forInteger(JavaKind.Long, lowerBound, upperBound); 746 } 747 }, 748 749 new FloatConvertOp(D2I) { 750 751 @Override 752 public Constant foldConstant(Constant c) { 753 PrimitiveConstant value = (PrimitiveConstant) c; 754 return JavaConstant.forInt((int) value.asDouble()); 755 } 756 757 @Override 758 public Stamp foldStamp(Stamp stamp) { 759 FloatStamp floatStamp = (FloatStamp) stamp; 760 assert floatStamp.getBits() == 64; 761 boolean mustHaveZero = !floatStamp.isNonNaN(); 762 int lowerBound = (int) floatStamp.lowerBound(); 763 int upperBound = (int) floatStamp.upperBound(); 764 if (mustHaveZero) { 765 if (lowerBound > 0) { 766 lowerBound = 0; 767 } else if (upperBound < 0) { 768 upperBound = 0; 769 } 770 } 771 return StampFactory.forInteger(JavaKind.Int, lowerBound, upperBound); 772 } 773 }, 774 775 new FloatConvertOp(D2L) { 776 777 @Override 778 public Constant foldConstant(Constant c) { 779 PrimitiveConstant value = (PrimitiveConstant) c; 780 return JavaConstant.forLong((long) value.asDouble()); 781 } 782 783 @Override 784 public Stamp foldStamp(Stamp stamp) { 785 FloatStamp floatStamp = (FloatStamp) stamp; 786 assert floatStamp.getBits() == 64; 787 boolean mustHaveZero = !floatStamp.isNonNaN(); 788 long lowerBound = (long) floatStamp.lowerBound(); 789 long upperBound = (long) floatStamp.upperBound(); 790 if (mustHaveZero) { 791 if (lowerBound > 0) { 792 lowerBound = 0; 793 } else if (upperBound < 0) { 794 upperBound = 0; 795 } 796 } 797 return StampFactory.forInteger(JavaKind.Long, lowerBound, upperBound); 798 } 799 }, 800 801 new FloatConvertOp(F2D) { 802 803 @Override 804 public Constant foldConstant(Constant c) { 805 PrimitiveConstant value = (PrimitiveConstant) c; 806 return JavaConstant.forDouble(value.asFloat()); 807 } 808 809 @Override 810 public Stamp foldStamp(Stamp stamp) { 811 FloatStamp floatStamp = (FloatStamp) stamp; 812 assert floatStamp.getBits() == 32; 813 return StampFactory.forFloat(JavaKind.Double, floatStamp.lowerBound(), floatStamp.upperBound(), floatStamp.isNonNaN()); 814 } 815 }, 816 817 new FloatConvertOp(D2F) { 818 819 @Override 820 public Constant foldConstant(Constant c) { 821 PrimitiveConstant value = (PrimitiveConstant) c; 822 return JavaConstant.forFloat((float) value.asDouble()); 823 } 824 825 @Override 826 public Stamp foldStamp(Stamp stamp) { 827 FloatStamp floatStamp = (FloatStamp) stamp; 828 assert floatStamp.getBits() == 64; 829 return StampFactory.forFloat(JavaKind.Float, (float) floatStamp.lowerBound(), (float) floatStamp.upperBound(), floatStamp.isNonNaN()); 830 } 831 }); 832 }