001/* 002 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.compiler.common.type; 024 025import static com.oracle.graal.compiler.common.calc.FloatConvert.*; 026 027import java.nio.*; 028import java.util.function.*; 029 030import jdk.internal.jvmci.common.*; 031import jdk.internal.jvmci.meta.*; 032 033import com.oracle.graal.compiler.common.spi.*; 034import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; 035import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp; 036import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp; 037 038public class FloatStamp extends PrimitiveStamp { 039 040 private final double lowerBound; 041 private final double upperBound; 042 private final boolean nonNaN; 043 044 protected FloatStamp(int bits) { 045 this(bits, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false); 046 } 047 048 public FloatStamp(int bits, double lowerBound, double upperBound, boolean nonNaN) { 049 super(bits, OPS); 050 assert bits == 64 || (bits == 32 && (Double.isNaN(lowerBound) || (float) lowerBound == lowerBound) && (Double.isNaN(upperBound) || (float) upperBound == upperBound)); 051 assert Double.isNaN(lowerBound) == Double.isNaN(upperBound); 052 this.lowerBound = lowerBound; 053 this.upperBound = upperBound; 054 this.nonNaN = nonNaN; 055 } 056 057 @Override 058 public Stamp unrestricted() { 059 return new FloatStamp(getBits()); 060 } 061 062 @Override 063 public Stamp empty() { 064 return new FloatStamp(getBits(), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, true); 065 } 066 067 @Override 068 public Stamp constant(Constant c, MetaAccessProvider meta) { 069 JavaConstant jc = (JavaConstant) c; 070 assert jc.getKind().isNumericFloat() && jc.getKind().getBitCount() == getBits(); 071 return StampFactory.forConstant(jc); 072 } 073 074 @Override 075 public SerializableConstant deserialize(ByteBuffer buffer) { 076 switch (getBits()) { 077 case 32: 078 return JavaConstant.forFloat(buffer.getFloat()); 079 case 64: 080 return JavaConstant.forDouble(buffer.getDouble()); 081 default: 082 throw JVMCIError.shouldNotReachHere(); 083 } 084 } 085 086 @Override 087 public boolean hasValues() { 088 return lowerBound <= upperBound || !nonNaN; 089 } 090 091 @Override 092 public Kind getStackKind() { 093 if (getBits() > 32) { 094 return Kind.Double; 095 } else { 096 return Kind.Float; 097 } 098 } 099 100 @Override 101 public LIRKind getLIRKind(LIRKindTool tool) { 102 return tool.getFloatingKind(getBits()); 103 } 104 105 @Override 106 public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { 107 switch (getBits()) { 108 case 32: 109 return metaAccess.lookupJavaType(Float.TYPE); 110 case 64: 111 return metaAccess.lookupJavaType(Double.TYPE); 112 default: 113 throw JVMCIError.shouldNotReachHere(); 114 } 115 } 116 117 /** 118 * The (inclusive) lower bound on the value described by this stamp. 119 */ 120 public double lowerBound() { 121 return lowerBound; 122 } 123 124 /** 125 * The (inclusive) upper bound on the value described by this stamp. 126 */ 127 public double upperBound() { 128 return upperBound; 129 } 130 131 public boolean isNonNaN() { 132 return nonNaN; 133 } 134 135 public boolean isNaN() { 136 return Double.isNaN(lowerBound); 137 } 138 139 public boolean isUnrestricted() { 140 return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN; 141 } 142 143 public boolean contains(double value) { 144 if (Double.isNaN(value)) { 145 return !nonNaN; 146 } else { 147 return value >= lowerBound && value <= upperBound; 148 } 149 } 150 151 @Override 152 public String toString() { 153 StringBuilder str = new StringBuilder(); 154 str.append('f'); 155 str.append(getBits()); 156 str.append(nonNaN ? "!" : ""); 157 if (lowerBound == upperBound) { 158 str.append(" [").append(lowerBound).append(']'); 159 } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) { 160 str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); 161 } 162 return str.toString(); 163 } 164 165 private static double meetBounds(double a, double b, DoubleBinaryOperator op) { 166 if (Double.isNaN(a)) { 167 return b; 168 } else if (Double.isNaN(b)) { 169 return a; 170 } else { 171 return op.applyAsDouble(a, b); 172 } 173 } 174 175 @Override 176 public Stamp meet(Stamp otherStamp) { 177 if (otherStamp == this) { 178 return this; 179 } 180 FloatStamp other = (FloatStamp) otherStamp; 181 assert getBits() == other.getBits(); 182 double meetUpperBound = meetBounds(upperBound, other.upperBound, Math::max); 183 double meetLowerBound = meetBounds(lowerBound, other.lowerBound, Math::min); 184 boolean meetNonNaN = nonNaN && other.nonNaN; 185 if (Double.compare(meetLowerBound, lowerBound) == 0 && Double.compare(meetUpperBound, upperBound) == 0 && meetNonNaN == nonNaN) { 186 return this; 187 } else if (Double.compare(meetLowerBound, other.lowerBound) == 0 && Double.compare(meetUpperBound, other.upperBound) == 0 && meetNonNaN == other.nonNaN) { 188 return other; 189 } else { 190 return new FloatStamp(getBits(), meetLowerBound, meetUpperBound, meetNonNaN); 191 } 192 } 193 194 @Override 195 public Stamp join(Stamp otherStamp) { 196 if (otherStamp == this) { 197 return this; 198 } 199 FloatStamp other = (FloatStamp) otherStamp; 200 assert getBits() == other.getBits(); 201 double joinUpperBound = Math.min(upperBound, other.upperBound); 202 double joinLowerBound = Math.max(lowerBound, other.lowerBound); 203 boolean joinNonNaN = nonNaN || other.nonNaN; 204 if (Double.compare(joinLowerBound, lowerBound) == 0 && Double.compare(joinUpperBound, upperBound) == 0 && joinNonNaN == nonNaN) { 205 return this; 206 } else if (Double.compare(joinLowerBound, other.lowerBound) == 0 && Double.compare(joinUpperBound, other.upperBound) == 0 && joinNonNaN == other.nonNaN) { 207 return other; 208 } else { 209 return new FloatStamp(getBits(), joinLowerBound, joinUpperBound, joinNonNaN); 210 } 211 } 212 213 @Override 214 public int hashCode() { 215 final int prime = 31; 216 int result = 1; 217 long temp; 218 result = prime * result + super.hashCode(); 219 temp = Double.doubleToLongBits(lowerBound); 220 result = prime * result + (int) (temp ^ (temp >>> 32)); 221 result = prime * result + (nonNaN ? 1231 : 1237); 222 temp = Double.doubleToLongBits(upperBound); 223 result = prime * result + (int) (temp ^ (temp >>> 32)); 224 return result; 225 } 226 227 @Override 228 public boolean isCompatible(Stamp stamp) { 229 if (this == stamp) { 230 return true; 231 } 232 if (stamp instanceof FloatStamp) { 233 FloatStamp other = (FloatStamp) stamp; 234 return getBits() == other.getBits(); 235 } 236 return false; 237 } 238 239 @Override 240 public boolean equals(Object obj) { 241 if (this == obj) { 242 return true; 243 } 244 if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) { 245 return false; 246 } 247 FloatStamp other = (FloatStamp) obj; 248 if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) { 249 return false; 250 } 251 if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) { 252 return false; 253 } 254 if (nonNaN != other.nonNaN) { 255 return false; 256 } 257 return super.equals(other); 258 } 259 260 @Override 261 public JavaConstant asConstant() { 262 if (nonNaN && Double.compare(lowerBound, upperBound) == 0) { 263 switch (getBits()) { 264 case 32: 265 return JavaConstant.forFloat((float) lowerBound); 266 case 64: 267 return JavaConstant.forDouble(lowerBound); 268 } 269 } 270 return null; 271 } 272 273 private static final ArithmeticOpTable OPS = new ArithmeticOpTable( 274 275 new UnaryOp.Neg() { 276 277 @Override 278 public Constant foldConstant(Constant c) { 279 PrimitiveConstant value = (PrimitiveConstant) c; 280 switch (value.getKind()) { 281 case Float: 282 return JavaConstant.forFloat(-value.asFloat()); 283 case Double: 284 return JavaConstant.forDouble(-value.asDouble()); 285 default: 286 throw JVMCIError.shouldNotReachHere(); 287 } 288 } 289 290 @Override 291 public Stamp foldStamp(Stamp s) { 292 FloatStamp stamp = (FloatStamp) s; 293 return new FloatStamp(stamp.getBits(), -stamp.upperBound(), -stamp.lowerBound(), stamp.isNonNaN()); 294 } 295 }, 296 297 new BinaryOp.Add(false, true) { 298 299 @Override 300 public Constant foldConstant(Constant const1, Constant const2) { 301 PrimitiveConstant a = (PrimitiveConstant) const1; 302 PrimitiveConstant b = (PrimitiveConstant) const2; 303 assert a.getKind() == b.getKind(); 304 switch (a.getKind()) { 305 case Float: 306 return JavaConstant.forFloat(a.asFloat() + b.asFloat()); 307 case Double: 308 return JavaConstant.forDouble(a.asDouble() + b.asDouble()); 309 default: 310 throw JVMCIError.shouldNotReachHere(); 311 } 312 } 313 314 @Override 315 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 316 // TODO 317 return stamp1.unrestricted(); 318 } 319 320 @Override 321 public boolean isNeutral(Constant value) { 322 PrimitiveConstant n = (PrimitiveConstant) value; 323 switch (n.getKind()) { 324 case Float: 325 return Float.compare(n.asFloat(), -0.0f) == 0; 326 case Double: 327 return Double.compare(n.asDouble(), -0.0) == 0; 328 default: 329 throw JVMCIError.shouldNotReachHere(); 330 } 331 } 332 }, 333 334 new BinaryOp.Sub(false, false) { 335 336 @Override 337 public Constant foldConstant(Constant const1, Constant const2) { 338 PrimitiveConstant a = (PrimitiveConstant) const1; 339 PrimitiveConstant b = (PrimitiveConstant) const2; 340 assert a.getKind() == b.getKind(); 341 switch (a.getKind()) { 342 case Float: 343 return JavaConstant.forFloat(a.asFloat() - b.asFloat()); 344 case Double: 345 return JavaConstant.forDouble(a.asDouble() - b.asDouble()); 346 default: 347 throw JVMCIError.shouldNotReachHere(); 348 } 349 } 350 351 @Override 352 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 353 // TODO 354 return stamp1.unrestricted(); 355 } 356 357 @Override 358 public boolean isNeutral(Constant value) { 359 PrimitiveConstant n = (PrimitiveConstant) value; 360 switch (n.getKind()) { 361 case Float: 362 return Float.compare(n.asFloat(), 0.0f) == 0; 363 case Double: 364 return Double.compare(n.asDouble(), 0.0) == 0; 365 default: 366 throw JVMCIError.shouldNotReachHere(); 367 } 368 } 369 }, 370 371 new BinaryOp.Mul(false, true) { 372 373 @Override 374 public Constant foldConstant(Constant const1, Constant const2) { 375 PrimitiveConstant a = (PrimitiveConstant) const1; 376 PrimitiveConstant b = (PrimitiveConstant) const2; 377 assert a.getKind() == b.getKind(); 378 switch (a.getKind()) { 379 case Float: 380 return JavaConstant.forFloat(a.asFloat() * b.asFloat()); 381 case Double: 382 return JavaConstant.forDouble(a.asDouble() * b.asDouble()); 383 default: 384 throw JVMCIError.shouldNotReachHere(); 385 } 386 } 387 388 @Override 389 public Stamp foldStamp(Stamp a, Stamp b) { 390 // TODO 391 return a.unrestricted(); 392 } 393 394 @Override 395 public boolean isNeutral(Constant value) { 396 PrimitiveConstant n = (PrimitiveConstant) value; 397 switch (n.getKind()) { 398 case Float: 399 return Float.compare(n.asFloat(), 1.0f) == 0; 400 case Double: 401 return Double.compare(n.asDouble(), 1.0) == 0; 402 default: 403 throw JVMCIError.shouldNotReachHere(); 404 } 405 } 406 }, 407 408 new BinaryOp.Div(false, false) { 409 410 @Override 411 public Constant foldConstant(Constant const1, Constant const2) { 412 PrimitiveConstant a = (PrimitiveConstant) const1; 413 PrimitiveConstant b = (PrimitiveConstant) const2; 414 assert a.getKind() == b.getKind(); 415 switch (a.getKind()) { 416 case Float: 417 return JavaConstant.forFloat(a.asFloat() / b.asFloat()); 418 case Double: 419 return JavaConstant.forDouble(a.asDouble() / b.asDouble()); 420 default: 421 throw JVMCIError.shouldNotReachHere(); 422 } 423 } 424 425 @Override 426 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 427 // TODO 428 return stamp1.unrestricted(); 429 } 430 431 @Override 432 public boolean isNeutral(Constant value) { 433 PrimitiveConstant n = (PrimitiveConstant) value; 434 switch (n.getKind()) { 435 case Float: 436 return Float.compare(n.asFloat(), 1.0f) == 0; 437 case Double: 438 return Double.compare(n.asDouble(), 1.0) == 0; 439 default: 440 throw JVMCIError.shouldNotReachHere(); 441 } 442 } 443 }, 444 445 new BinaryOp.Rem(false, false) { 446 447 @Override 448 public Constant foldConstant(Constant const1, Constant const2) { 449 PrimitiveConstant a = (PrimitiveConstant) const1; 450 PrimitiveConstant b = (PrimitiveConstant) const2; 451 assert a.getKind() == b.getKind(); 452 switch (a.getKind()) { 453 case Float: 454 return JavaConstant.forFloat(a.asFloat() % b.asFloat()); 455 case Double: 456 return JavaConstant.forDouble(a.asDouble() % b.asDouble()); 457 default: 458 throw JVMCIError.shouldNotReachHere(); 459 } 460 } 461 462 @Override 463 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 464 // TODO 465 return stamp1.unrestricted(); 466 } 467 }, 468 469 new UnaryOp.Not() { 470 471 @Override 472 public Constant foldConstant(Constant c) { 473 PrimitiveConstant value = (PrimitiveConstant) c; 474 switch (value.getKind()) { 475 case Float: 476 int f = Float.floatToRawIntBits(value.asFloat()); 477 return JavaConstant.forFloat(Float.intBitsToFloat(~f)); 478 case Double: 479 long d = Double.doubleToRawLongBits(value.asDouble()); 480 return JavaConstant.forDouble(Double.longBitsToDouble(~d)); 481 default: 482 throw JVMCIError.shouldNotReachHere(); 483 } 484 } 485 486 @Override 487 public Stamp foldStamp(Stamp s) { 488 return s.unrestricted(); 489 } 490 }, 491 492 new BinaryOp.And(true, true) { 493 494 @Override 495 public Constant foldConstant(Constant const1, Constant const2) { 496 PrimitiveConstant a = (PrimitiveConstant) const1; 497 PrimitiveConstant b = (PrimitiveConstant) const2; 498 assert a.getKind() == b.getKind(); 499 switch (a.getKind()) { 500 case Float: 501 int fa = Float.floatToRawIntBits(a.asFloat()); 502 int fb = Float.floatToRawIntBits(b.asFloat()); 503 return JavaConstant.forFloat(Float.intBitsToFloat(fa & fb)); 504 case Double: 505 long da = Double.doubleToRawLongBits(a.asDouble()); 506 long db = Double.doubleToRawLongBits(b.asDouble()); 507 return JavaConstant.forDouble(Double.longBitsToDouble(da & db)); 508 default: 509 throw JVMCIError.shouldNotReachHere(); 510 } 511 } 512 513 @Override 514 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 515 return stamp1.unrestricted(); 516 } 517 518 @Override 519 public boolean isNeutral(Constant n) { 520 PrimitiveConstant value = (PrimitiveConstant) n; 521 switch (value.getKind()) { 522 case Float: 523 return Float.floatToRawIntBits(value.asFloat()) == 0xFFFFFFFF; 524 case Double: 525 return Double.doubleToRawLongBits(value.asDouble()) == 0xFFFFFFFFFFFFFFFFL; 526 default: 527 throw JVMCIError.shouldNotReachHere(); 528 } 529 } 530 }, 531 532 new BinaryOp.Or(true, true) { 533 534 @Override 535 public Constant foldConstant(Constant const1, Constant const2) { 536 PrimitiveConstant a = (PrimitiveConstant) const1; 537 PrimitiveConstant b = (PrimitiveConstant) const2; 538 assert a.getKind() == b.getKind(); 539 switch (a.getKind()) { 540 case Float: 541 int fa = Float.floatToRawIntBits(a.asFloat()); 542 int fb = Float.floatToRawIntBits(b.asFloat()); 543 return JavaConstant.forFloat(Float.intBitsToFloat(fa | fb)); 544 case Double: 545 long da = Double.doubleToRawLongBits(a.asDouble()); 546 long db = Double.doubleToRawLongBits(b.asDouble()); 547 return JavaConstant.forDouble(Double.longBitsToDouble(da | db)); 548 default: 549 throw JVMCIError.shouldNotReachHere(); 550 } 551 } 552 553 @Override 554 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 555 return stamp1.unrestricted(); 556 } 557 558 @Override 559 public boolean isNeutral(Constant n) { 560 PrimitiveConstant value = (PrimitiveConstant) n; 561 switch (value.getKind()) { 562 case Float: 563 return Float.floatToRawIntBits(value.asFloat()) == 0; 564 case Double: 565 return Double.doubleToRawLongBits(value.asDouble()) == 0L; 566 default: 567 throw JVMCIError.shouldNotReachHere(); 568 } 569 } 570 }, 571 572 new BinaryOp.Xor(true, true) { 573 574 @Override 575 public Constant foldConstant(Constant const1, Constant const2) { 576 PrimitiveConstant a = (PrimitiveConstant) const1; 577 PrimitiveConstant b = (PrimitiveConstant) const2; 578 assert a.getKind() == b.getKind(); 579 switch (a.getKind()) { 580 case Float: 581 int fa = Float.floatToRawIntBits(a.asFloat()); 582 int fb = Float.floatToRawIntBits(b.asFloat()); 583 return JavaConstant.forFloat(Float.intBitsToFloat(fa ^ fb)); 584 case Double: 585 long da = Double.doubleToRawLongBits(a.asDouble()); 586 long db = Double.doubleToRawLongBits(b.asDouble()); 587 return JavaConstant.forDouble(Double.longBitsToDouble(da ^ db)); 588 default: 589 throw JVMCIError.shouldNotReachHere(); 590 } 591 } 592 593 @Override 594 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 595 return stamp1.unrestricted(); 596 } 597 598 @Override 599 public boolean isNeutral(Constant n) { 600 PrimitiveConstant value = (PrimitiveConstant) n; 601 switch (value.getKind()) { 602 case Float: 603 return Float.floatToRawIntBits(value.asFloat()) == 0; 604 case Double: 605 return Double.doubleToRawLongBits(value.asDouble()) == 0L; 606 default: 607 throw JVMCIError.shouldNotReachHere(); 608 } 609 } 610 }, 611 612 null, null, null, 613 614 new UnaryOp.Abs() { 615 616 @Override 617 public Constant foldConstant(Constant c) { 618 PrimitiveConstant value = (PrimitiveConstant) c; 619 switch (value.getKind()) { 620 case Float: 621 return JavaConstant.forFloat(Math.abs(value.asFloat())); 622 case Double: 623 return JavaConstant.forDouble(Math.abs(value.asDouble())); 624 default: 625 throw JVMCIError.shouldNotReachHere(); 626 } 627 } 628 629 @Override 630 public Stamp foldStamp(Stamp s) { 631 FloatStamp stamp = (FloatStamp) s; 632 if (stamp.isNaN()) { 633 return stamp; 634 } 635 return new FloatStamp(stamp.getBits(), 0, Math.max(-stamp.lowerBound(), stamp.upperBound()), stamp.isNonNaN()); 636 } 637 }, 638 639 new UnaryOp.Sqrt() { 640 641 @Override 642 public Constant foldConstant(Constant c) { 643 PrimitiveConstant value = (PrimitiveConstant) c; 644 switch (value.getKind()) { 645 case Float: 646 return JavaConstant.forFloat((float) Math.sqrt(value.asFloat())); 647 case Double: 648 return JavaConstant.forDouble(Math.sqrt(value.asDouble())); 649 default: 650 throw JVMCIError.shouldNotReachHere(); 651 } 652 } 653 654 @Override 655 public Stamp foldStamp(Stamp s) { 656 return s.unrestricted(); 657 } 658 }, 659 660 null, null, null, 661 662 new FloatConvertOp(F2I) { 663 664 @Override 665 public Constant foldConstant(Constant c) { 666 PrimitiveConstant value = (PrimitiveConstant) c; 667 return JavaConstant.forInt((int) value.asFloat()); 668 } 669 670 @Override 671 public Stamp foldStamp(Stamp stamp) { 672 FloatStamp floatStamp = (FloatStamp) stamp; 673 assert floatStamp.getBits() == 32; 674 boolean mustHaveZero = !floatStamp.isNonNaN(); 675 int lowerBound = (int) floatStamp.lowerBound(); 676 int upperBound = (int) floatStamp.upperBound(); 677 if (mustHaveZero) { 678 if (lowerBound > 0) { 679 lowerBound = 0; 680 } else if (upperBound < 0) { 681 upperBound = 0; 682 } 683 } 684 return StampFactory.forInteger(Kind.Int, lowerBound, upperBound); 685 } 686 }, 687 688 new FloatConvertOp(F2L) { 689 690 @Override 691 public Constant foldConstant(Constant c) { 692 PrimitiveConstant value = (PrimitiveConstant) c; 693 return JavaConstant.forLong((long) value.asFloat()); 694 } 695 696 @Override 697 public Stamp foldStamp(Stamp stamp) { 698 FloatStamp floatStamp = (FloatStamp) stamp; 699 assert floatStamp.getBits() == 32; 700 boolean mustHaveZero = !floatStamp.isNonNaN(); 701 long lowerBound = (long) floatStamp.lowerBound(); 702 long upperBound = (long) floatStamp.upperBound(); 703 if (mustHaveZero) { 704 if (lowerBound > 0) { 705 lowerBound = 0; 706 } else if (upperBound < 0) { 707 upperBound = 0; 708 } 709 } 710 return StampFactory.forInteger(Kind.Long, lowerBound, upperBound); 711 } 712 }, 713 714 new FloatConvertOp(D2I) { 715 716 @Override 717 public Constant foldConstant(Constant c) { 718 PrimitiveConstant value = (PrimitiveConstant) c; 719 return JavaConstant.forInt((int) value.asDouble()); 720 } 721 722 @Override 723 public Stamp foldStamp(Stamp stamp) { 724 FloatStamp floatStamp = (FloatStamp) stamp; 725 assert floatStamp.getBits() == 64; 726 boolean mustHaveZero = !floatStamp.isNonNaN(); 727 int lowerBound = (int) floatStamp.lowerBound(); 728 int upperBound = (int) floatStamp.upperBound(); 729 if (mustHaveZero) { 730 if (lowerBound > 0) { 731 lowerBound = 0; 732 } else if (upperBound < 0) { 733 upperBound = 0; 734 } 735 } 736 return StampFactory.forInteger(Kind.Int, lowerBound, upperBound); 737 } 738 }, 739 740 new FloatConvertOp(D2L) { 741 742 @Override 743 public Constant foldConstant(Constant c) { 744 PrimitiveConstant value = (PrimitiveConstant) c; 745 return JavaConstant.forLong((long) value.asDouble()); 746 } 747 748 @Override 749 public Stamp foldStamp(Stamp stamp) { 750 FloatStamp floatStamp = (FloatStamp) stamp; 751 assert floatStamp.getBits() == 64; 752 boolean mustHaveZero = !floatStamp.isNonNaN(); 753 long lowerBound = (long) floatStamp.lowerBound(); 754 long upperBound = (long) floatStamp.upperBound(); 755 if (mustHaveZero) { 756 if (lowerBound > 0) { 757 lowerBound = 0; 758 } else if (upperBound < 0) { 759 upperBound = 0; 760 } 761 } 762 return StampFactory.forInteger(Kind.Long, lowerBound, upperBound); 763 } 764 }, 765 766 new FloatConvertOp(F2D) { 767 768 @Override 769 public Constant foldConstant(Constant c) { 770 PrimitiveConstant value = (PrimitiveConstant) c; 771 return JavaConstant.forDouble(value.asFloat()); 772 } 773 774 @Override 775 public Stamp foldStamp(Stamp stamp) { 776 FloatStamp floatStamp = (FloatStamp) stamp; 777 assert floatStamp.getBits() == 32; 778 return StampFactory.forFloat(Kind.Double, floatStamp.lowerBound(), floatStamp.upperBound(), floatStamp.isNonNaN()); 779 } 780 }, 781 782 new FloatConvertOp(D2F) { 783 784 @Override 785 public Constant foldConstant(Constant c) { 786 PrimitiveConstant value = (PrimitiveConstant) c; 787 return JavaConstant.forFloat((float) value.asDouble()); 788 } 789 790 @Override 791 public Stamp foldStamp(Stamp stamp) { 792 FloatStamp floatStamp = (FloatStamp) stamp; 793 assert floatStamp.getBits() == 64; 794 return StampFactory.forFloat(Kind.Float, (float) floatStamp.lowerBound(), (float) floatStamp.upperBound(), floatStamp.isNonNaN()); 795 } 796 }); 797}