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.I2D; 26 import static org.graalvm.compiler.core.common.calc.FloatConvert.I2F; 27 import static org.graalvm.compiler.core.common.calc.FloatConvert.L2D; 28 import static org.graalvm.compiler.core.common.calc.FloatConvert.L2F; 29 30 import java.nio.ByteBuffer; 31 import java.util.Formatter; 32 33 import org.graalvm.compiler.core.common.LIRKind; 34 import org.graalvm.compiler.core.common.NumUtil; 35 import org.graalvm.compiler.core.common.spi.LIRKindTool; 36 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; 37 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.FloatConvertOp; 38 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp; 39 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp; 40 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp; 41 import org.graalvm.compiler.debug.GraalError; 42 43 import jdk.vm.ci.code.CodeUtil; 44 import jdk.vm.ci.meta.Constant; 45 import jdk.vm.ci.meta.JavaConstant; 46 import jdk.vm.ci.meta.JavaKind; 47 import jdk.vm.ci.meta.MetaAccessProvider; 48 import jdk.vm.ci.meta.PrimitiveConstant; 49 import jdk.vm.ci.meta.ResolvedJavaType; 50 import jdk.vm.ci.meta.SerializableConstant; 51 52 /** 53 * Describes the possible values of a node that produces an int or long result. 54 * 55 * The description consists of (inclusive) lower and upper bounds and up (may be set) and down 56 * (always set) bit-masks. 57 */ 58 public final class IntegerStamp extends PrimitiveStamp { 59 60 private final long lowerBound; 61 private final long upperBound; 62 private final long downMask; 63 private final long upMask; 64 65 private IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) { 66 super(bits, OPS); 67 68 this.lowerBound = lowerBound; 69 this.upperBound = upperBound; 70 this.downMask = downMask; 71 this.upMask = upMask; 72 73 assert lowerBound >= CodeUtil.minValue(bits) : this; 74 assert upperBound <= CodeUtil.maxValue(bits) : this; 75 assert (downMask & CodeUtil.mask(bits)) == downMask : this; 76 assert (upMask & CodeUtil.mask(bits)) == upMask : this; 77 } 78 79 public static IntegerStamp create(int bits, long lowerBoundInput, long upperBoundInput) { 80 return create(bits, lowerBoundInput, upperBoundInput, 0, CodeUtil.mask(bits)); 81 } 82 83 public static IntegerStamp create(int bits, long lowerBoundInput, long upperBoundInput, long downMask, long upMask) { 84 assert (downMask & ~upMask) == 0 : String.format("\u21ca: %016x \u21c8: %016x", downMask, upMask); 85 86 // Set lower bound, use masks to make it more precise 87 long minValue = minValueForMasks(bits, downMask, upMask); 88 long lowerBoundTmp = Math.max(lowerBoundInput, minValue); 89 90 // Set upper bound, use masks to make it more precise 91 long maxValue = maxValueForMasks(bits, downMask, upMask); 92 long upperBoundTmp = Math.min(upperBoundInput, maxValue); 93 94 // Assign masks now with the bounds in mind. 95 final long boundedDownMask; 96 final long boundedUpMask; 97 long defaultMask = CodeUtil.mask(bits); 98 if (lowerBoundTmp == upperBoundTmp) { 99 boundedDownMask = lowerBoundTmp; 100 boundedUpMask = lowerBoundTmp; 101 } else if (lowerBoundTmp >= 0) { 102 int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBoundTmp); 103 long differentBits = lowerBoundTmp ^ upperBoundTmp; 104 int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); 105 106 boundedUpMask = upperBoundTmp | -1L >>> (upperBoundLeadingZeros + sameBitCount); 107 boundedDownMask = upperBoundTmp & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); 108 } else { 109 if (upperBoundTmp >= 0) { 110 boundedUpMask = defaultMask; 111 boundedDownMask = 0; 112 } else { 113 int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBoundTmp); 114 long differentBits = lowerBoundTmp ^ upperBoundTmp; 115 int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); 116 117 boundedUpMask = lowerBoundTmp | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); 118 boundedDownMask = lowerBoundTmp & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); 119 } 120 } 121 122 return new IntegerStamp(bits, lowerBoundTmp, upperBoundTmp, defaultMask & (downMask | boundedDownMask), defaultMask & upMask & boundedUpMask); 123 } 124 125 static long significantBit(long bits, long value) { 126 return (value >>> (bits - 1)) & 1; 127 } 128 129 static long minValueForMasks(int bits, long downMask, long upMask) { 130 if (significantBit(bits, upMask) == 0) { 131 // Value is always positive. Minimum value always positive. 132 assert significantBit(bits, downMask) == 0; 133 return downMask; 134 } else { 135 // Value can be positive or negative. Minimum value always negative. 136 return downMask | (-1L << (bits - 1)); 137 } 138 } 139 140 static long maxValueForMasks(int bits, long downMask, long upMask) { 141 if (significantBit(bits, downMask) == 1) { 142 // Value is always negative. Maximum value always negative. 143 assert significantBit(bits, upMask) == 1; 144 return CodeUtil.signExtend(upMask, bits); 145 } else { 146 // Value can be positive or negative. Maximum value always positive. 147 return upMask & (CodeUtil.mask(bits) >>> 1); 148 } 149 } 150 151 public static IntegerStamp stampForMask(int bits, long downMask, long upMask) { 152 return new IntegerStamp(bits, minValueForMasks(bits, downMask, upMask), maxValueForMasks(bits, downMask, upMask), downMask, upMask); 153 } 154 155 @Override 156 public IntegerStamp unrestricted() { 157 return new IntegerStamp(getBits(), CodeUtil.minValue(getBits()), CodeUtil.maxValue(getBits()), 0, CodeUtil.mask(getBits())); 158 } 159 160 @Override 161 public IntegerStamp empty() { 162 return new IntegerStamp(getBits(), CodeUtil.maxValue(getBits()), CodeUtil.minValue(getBits()), CodeUtil.mask(getBits()), 0); 163 } 164 165 @Override 166 public Stamp constant(Constant c, MetaAccessProvider meta) { 167 if (c instanceof PrimitiveConstant) { 168 long value = ((PrimitiveConstant) c).asLong(); 169 return StampFactory.forInteger(getBits(), value, value); 170 } 171 return this; 172 } 173 174 @Override 175 public SerializableConstant deserialize(ByteBuffer buffer) { 176 switch (getBits()) { 177 case 1: 178 return JavaConstant.forBoolean(buffer.get() != 0); 179 case 8: 180 return JavaConstant.forByte(buffer.get()); 181 case 16: 182 return JavaConstant.forShort(buffer.getShort()); 183 case 32: 184 return JavaConstant.forInt(buffer.getInt()); 185 case 64: 186 return JavaConstant.forLong(buffer.getLong()); 187 default: 188 throw GraalError.shouldNotReachHere(); 189 } 190 } 191 192 @Override 193 public boolean hasValues() { 194 return lowerBound <= upperBound; 195 } 196 197 @Override 198 public JavaKind getStackKind() { 199 if (getBits() > 32) { 200 return JavaKind.Long; 201 } else { 202 return JavaKind.Int; 203 } 204 } 205 206 @Override 207 public LIRKind getLIRKind(LIRKindTool tool) { 208 return tool.getIntegerKind(getBits()); 209 } 210 211 @Override 212 public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { 213 switch (getBits()) { 214 case 1: 215 return metaAccess.lookupJavaType(Boolean.TYPE); 216 case 8: 217 return metaAccess.lookupJavaType(Byte.TYPE); 218 case 16: 219 return metaAccess.lookupJavaType(Short.TYPE); 220 case 32: 221 return metaAccess.lookupJavaType(Integer.TYPE); 222 case 64: 223 return metaAccess.lookupJavaType(Long.TYPE); 224 default: 225 throw GraalError.shouldNotReachHere(); 226 } 227 } 228 229 /** 230 * The signed inclusive lower bound on the value described by this stamp. 231 */ 232 public long lowerBound() { 233 return lowerBound; 234 } 235 236 /** 237 * The signed inclusive upper bound on the value described by this stamp. 238 */ 239 public long upperBound() { 240 return upperBound; 241 } 242 243 /** 244 * This bit-mask describes the bits that are always set in the value described by this stamp. 245 */ 246 public long downMask() { 247 return downMask; 248 } 249 250 /** 251 * This bit-mask describes the bits that can be set in the value described by this stamp. 252 */ 253 public long upMask() { 254 return upMask; 255 } 256 257 @Override 258 public boolean isUnrestricted() { 259 return lowerBound == CodeUtil.minValue(getBits()) && upperBound == CodeUtil.maxValue(getBits()) && downMask == 0 && upMask == CodeUtil.mask(getBits()); 260 } 261 262 public boolean contains(long value) { 263 return value >= lowerBound && value <= upperBound && (value & downMask) == downMask && (value & upMask) == (value & CodeUtil.mask(getBits())); 264 } 265 266 public boolean isPositive() { 267 return lowerBound() >= 0; 268 } 269 270 public boolean isNegative() { 271 return upperBound() <= 0; 272 } 273 274 public boolean isStrictlyPositive() { 275 return lowerBound() > 0; 276 } 277 278 public boolean isStrictlyNegative() { 279 return upperBound() < 0; 280 } 281 282 public boolean canBePositive() { 283 return upperBound() > 0; 284 } 285 286 public boolean canBeNegative() { 287 return lowerBound() < 0; 288 } 289 290 @Override 291 public String toString() { 292 StringBuilder str = new StringBuilder(); 293 str.append('i'); 294 str.append(getBits()); 295 if (hasValues()) { 296 if (lowerBound == upperBound) { 297 str.append(" [").append(lowerBound).append(']'); 298 } else if (lowerBound != CodeUtil.minValue(getBits()) || upperBound != CodeUtil.maxValue(getBits())) { 299 str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); 300 } 301 if (downMask != 0) { 302 str.append(" \u21ca"); 303 new Formatter(str).format("%016x", downMask); 304 } 305 if (upMask != CodeUtil.mask(getBits())) { 306 str.append(" \u21c8"); 307 new Formatter(str).format("%016x", upMask); 308 } 309 } else { 310 str.append("<empty>"); 311 } 312 return str.toString(); 313 } 314 315 private IntegerStamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) { 316 assert getBits() == other.getBits(); 317 if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0 || (newUpMask == 0 && (newLowerBound > 0 || newUpperBound < 0))) { 318 return empty(); 319 } else if (newLowerBound == lowerBound && newUpperBound == upperBound && newDownMask == downMask && newUpMask == upMask) { 320 return this; 321 } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) { 322 return other; 323 } else { 324 return IntegerStamp.create(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask); 325 } 326 } 327 328 @Override 329 public Stamp meet(Stamp otherStamp) { 330 if (otherStamp == this) { 331 return this; 332 } 333 IntegerStamp other = (IntegerStamp) otherStamp; 334 return createStamp(other, Math.max(upperBound, other.upperBound), Math.min(lowerBound, other.lowerBound), downMask & other.downMask, upMask | other.upMask); 335 } 336 337 @Override 338 public IntegerStamp join(Stamp otherStamp) { 339 if (otherStamp == this) { 340 return this; 341 } 342 IntegerStamp other = (IntegerStamp) otherStamp; 343 long newDownMask = downMask | other.downMask; 344 long newLowerBound = Math.max(lowerBound, other.lowerBound); 345 long newUpperBound = Math.min(upperBound, other.upperBound); 346 long newUpMask = upMask & other.upMask; 347 return createStamp(other, newUpperBound, newLowerBound, newDownMask, newUpMask); 348 } 349 350 @Override 351 public boolean isCompatible(Stamp stamp) { 352 if (this == stamp) { 353 return true; 354 } 355 if (stamp instanceof IntegerStamp) { 356 IntegerStamp other = (IntegerStamp) stamp; 357 return getBits() == other.getBits(); 358 } 359 return false; 360 } 361 362 @Override 363 public boolean isCompatible(Constant constant) { 364 if (constant instanceof PrimitiveConstant) { 365 PrimitiveConstant prim = (PrimitiveConstant) constant; 366 return prim.getJavaKind().isNumericInteger(); 367 } 368 return false; 369 } 370 371 public long unsignedUpperBound() { 372 if (sameSignBounds()) { 373 return CodeUtil.zeroExtend(upperBound(), getBits()); 374 } 375 return NumUtil.maxValueUnsigned(getBits()); 376 } 377 378 public long unsignedLowerBound() { 379 if (sameSignBounds()) { 380 return CodeUtil.zeroExtend(lowerBound(), getBits()); 381 } 382 return 0; 383 } 384 385 private boolean sameSignBounds() { 386 return NumUtil.sameSign(lowerBound, upperBound); 387 } 388 389 @Override 390 public int hashCode() { 391 final int prime = 31; 392 int result = 1; 393 result = prime * result + super.hashCode(); 394 result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32)); 395 result = prime * result + (int) (upperBound ^ (upperBound >>> 32)); 396 result = prime * result + (int) (downMask ^ (downMask >>> 32)); 397 result = prime * result + (int) (upMask ^ (upMask >>> 32)); 398 return result; 399 } 400 401 @Override 402 public boolean equals(Object obj) { 403 if (this == obj) { 404 return true; 405 } 406 if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) { 407 return false; 408 } 409 IntegerStamp other = (IntegerStamp) obj; 410 if (lowerBound != other.lowerBound || upperBound != other.upperBound || downMask != other.downMask || upMask != other.upMask) { 411 return false; 412 } 413 return super.equals(other); 414 } 415 416 public static long upMaskFor(int bits, long lowerBound, long upperBound) { 417 long mask = lowerBound | upperBound; 418 if (mask == 0) { 419 return 0; 420 } else { 421 return ((-1L) >>> Long.numberOfLeadingZeros(mask)) & CodeUtil.mask(bits); 422 } 423 } 424 425 /** 426 * Checks if the 2 stamps represent values of the same sign. Returns true if the two stamps are 427 * both positive of null or if they are both strictly negative 428 * 429 * @return true if the two stamps are both positive of null or if they are both strictly 430 * negative 431 */ 432 public static boolean sameSign(IntegerStamp s1, IntegerStamp s2) { 433 return s1.isPositive() && s2.isPositive() || s1.isStrictlyNegative() && s2.isStrictlyNegative(); 434 } 435 436 @Override 437 public JavaConstant asConstant() { 438 if (lowerBound == upperBound) { 439 switch (getBits()) { 440 case 1: 441 return JavaConstant.forBoolean(lowerBound != 0); 442 case 8: 443 return JavaConstant.forByte((byte) lowerBound); 444 case 16: 445 return JavaConstant.forShort((short) lowerBound); 446 case 32: 447 return JavaConstant.forInt((int) lowerBound); 448 case 64: 449 return JavaConstant.forLong(lowerBound); 450 } 451 } 452 return null; 453 } 454 455 public static boolean addCanOverflow(IntegerStamp a, IntegerStamp b) { 456 assert a.getBits() == b.getBits(); 457 return addOverflowsPositively(a.upperBound(), b.upperBound(), a.getBits()) || 458 addOverflowsNegatively(a.lowerBound(), b.lowerBound(), a.getBits()); 459 460 } 461 462 public static boolean addOverflowsPositively(long x, long y, int bits) { 463 long result = x + y; 464 if (bits == 64) { 465 return (~x & ~y & result) < 0; 466 } else { 467 return result > CodeUtil.maxValue(bits); 468 } 469 } 470 471 public static boolean addOverflowsNegatively(long x, long y, int bits) { 472 long result = x + y; 473 if (bits == 64) { 474 return (x & y & ~result) < 0; 475 } else { 476 return result < CodeUtil.minValue(bits); 477 } 478 } 479 480 public static long carryBits(long x, long y) { 481 return (x + y) ^ x ^ y; 482 } 483 484 private static long saturate(long v, int bits) { 485 if (bits < 64) { 486 long max = CodeUtil.maxValue(bits); 487 if (v > max) { 488 return max; 489 } 490 long min = CodeUtil.minValue(bits); 491 if (v < min) { 492 return min; 493 } 494 } 495 return v; 496 } 497 498 public static boolean multiplicationOverflows(long a, long b, int bits) { 499 assert bits <= 64 && bits >= 0; 500 long result = a * b; 501 // result is positive if the sign is the same 502 boolean positive = (a >= 0 && b >= 0) || (a < 0 && b < 0); 503 if (bits == 64) { 504 if (a > 0 && b > 0) { 505 return a > 0x7FFFFFFF_FFFFFFFFL / b; 506 } else if (a > 0 && b <= 0) { 507 return b < 0x80000000_00000000L / a; 508 } else if (a <= 0 && b > 0) { 509 return a < 0x80000000_00000000L / b; 510 } else { 511 // a<=0 && b <=0 512 return a != 0 && b < 0x7FFFFFFF_FFFFFFFFL / a; 513 } 514 } else { 515 if (positive) { 516 return result > CodeUtil.maxValue(bits); 517 } else { 518 return result < CodeUtil.minValue(bits); 519 } 520 } 521 } 522 523 public static boolean multiplicationCanOverflow(IntegerStamp a, IntegerStamp b) { 524 // see IntegerStamp#foldStamp for details 525 assert a.getBits() == b.getBits(); 526 if (a.upMask() == 0) { 527 return false; 528 } else if (b.upMask() == 0) { 529 return false; 530 } 531 if (a.isUnrestricted()) { 532 return true; 533 } 534 if (b.isUnrestricted()) { 535 return true; 536 } 537 int bits = a.getBits(); 538 long minNegA = a.lowerBound(); 539 long maxNegA = Math.min(0, a.upperBound()); 540 long minPosA = Math.max(0, a.lowerBound()); 541 long maxPosA = a.upperBound(); 542 543 long minNegB = b.lowerBound(); 544 long maxNegB = Math.min(0, b.upperBound()); 545 long minPosB = Math.max(0, b.lowerBound()); 546 long maxPosB = b.upperBound(); 547 548 boolean mayOverflow = false; 549 if (a.canBePositive()) { 550 if (b.canBePositive()) { 551 mayOverflow |= IntegerStamp.multiplicationOverflows(maxPosA, maxPosB, bits); 552 mayOverflow |= IntegerStamp.multiplicationOverflows(minPosA, minPosB, bits); 553 } 554 if (b.canBeNegative()) { 555 mayOverflow |= IntegerStamp.multiplicationOverflows(minPosA, maxNegB, bits); 556 mayOverflow |= IntegerStamp.multiplicationOverflows(maxPosA, minNegB, bits); 557 558 } 559 } 560 if (a.canBeNegative()) { 561 if (b.canBePositive()) { 562 mayOverflow |= IntegerStamp.multiplicationOverflows(maxNegA, minPosB, bits); 563 mayOverflow |= IntegerStamp.multiplicationOverflows(minNegA, maxPosB, bits); 564 } 565 if (b.canBeNegative()) { 566 mayOverflow |= IntegerStamp.multiplicationOverflows(minNegA, minNegB, bits); 567 mayOverflow |= IntegerStamp.multiplicationOverflows(maxNegA, maxNegB, bits); 568 } 569 } 570 return mayOverflow; 571 } 572 573 public static boolean subtractionCanOverflow(IntegerStamp x, IntegerStamp y) { 574 assert x.getBits() == y.getBits(); 575 return subtractionOverflows(x.lowerBound(), y.upperBound(), x.getBits()) || subtractionOverflows(x.upperBound(), y.lowerBound(), x.getBits()); 576 } 577 578 public static boolean subtractionOverflows(long x, long y, int bits) { 579 long result = x - y; 580 if (bits == 64) { 581 return (((x ^ y) & (x ^ result)) < 0); 582 } 583 return result < CodeUtil.minValue(bits) || result > CodeUtil.maxValue(bits); 584 } 585 586 public static final ArithmeticOpTable OPS = new ArithmeticOpTable( 587 588 new UnaryOp.Neg() { 589 590 @Override 591 public Constant foldConstant(Constant value) { 592 PrimitiveConstant c = (PrimitiveConstant) value; 593 return JavaConstant.forIntegerKind(c.getJavaKind(), -c.asLong()); 594 } 595 596 @Override 597 public Stamp foldStamp(Stamp s) { 598 IntegerStamp stamp = (IntegerStamp) s; 599 int bits = stamp.getBits(); 600 if (stamp.lowerBound == stamp.upperBound) { 601 long value = CodeUtil.convert(-stamp.lowerBound(), stamp.getBits(), false); 602 return StampFactory.forInteger(stamp.getBits(), value, value); 603 } 604 if (stamp.lowerBound() != CodeUtil.minValue(bits)) { 605 // TODO(ls) check if the mask calculation is correct... 606 return StampFactory.forInteger(bits, -stamp.upperBound(), -stamp.lowerBound()); 607 } else { 608 return stamp.unrestricted(); 609 } 610 } 611 }, 612 613 new BinaryOp.Add(true, true) { 614 615 @Override 616 public Constant foldConstant(Constant const1, Constant const2) { 617 PrimitiveConstant a = (PrimitiveConstant) const1; 618 PrimitiveConstant b = (PrimitiveConstant) const2; 619 assert a.getJavaKind() == b.getJavaKind(); 620 return JavaConstant.forIntegerKind(a.getJavaKind(), a.asLong() + b.asLong()); 621 } 622 623 @Override 624 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 625 IntegerStamp a = (IntegerStamp) stamp1; 626 IntegerStamp b = (IntegerStamp) stamp2; 627 628 int bits = a.getBits(); 629 assert bits == b.getBits(); 630 631 if (a.lowerBound == a.upperBound && b.lowerBound == b.upperBound) { 632 long value = CodeUtil.convert(a.lowerBound() + b.lowerBound(), a.getBits(), false); 633 return StampFactory.forInteger(a.getBits(), value, value); 634 } 635 636 if (a.isUnrestricted()) { 637 return a; 638 } else if (b.isUnrestricted()) { 639 return b; 640 } 641 long defaultMask = CodeUtil.mask(bits); 642 long variableBits = (a.downMask() ^ a.upMask()) | (b.downMask() ^ b.upMask()); 643 long variableBitsWithCarry = variableBits | (carryBits(a.downMask(), b.downMask()) ^ carryBits(a.upMask(), b.upMask())); 644 long newDownMask = (a.downMask() + b.downMask()) & ~variableBitsWithCarry; 645 long newUpMask = (a.downMask() + b.downMask()) | variableBitsWithCarry; 646 647 newDownMask &= defaultMask; 648 newUpMask &= defaultMask; 649 650 long newLowerBound; 651 long newUpperBound; 652 boolean lowerOverflowsPositively = addOverflowsPositively(a.lowerBound(), b.lowerBound(), bits); 653 boolean upperOverflowsPositively = addOverflowsPositively(a.upperBound(), b.upperBound(), bits); 654 boolean lowerOverflowsNegatively = addOverflowsNegatively(a.lowerBound(), b.lowerBound(), bits); 655 boolean upperOverflowsNegatively = addOverflowsNegatively(a.upperBound(), b.upperBound(), bits); 656 if ((lowerOverflowsNegatively && !upperOverflowsNegatively) || (!lowerOverflowsPositively && upperOverflowsPositively)) { 657 newLowerBound = CodeUtil.minValue(bits); 658 newUpperBound = CodeUtil.maxValue(bits); 659 } else { 660 newLowerBound = CodeUtil.signExtend((a.lowerBound() + b.lowerBound()) & defaultMask, bits); 661 newUpperBound = CodeUtil.signExtend((a.upperBound() + b.upperBound()) & defaultMask, bits); 662 } 663 IntegerStamp limit = StampFactory.forInteger(bits, newLowerBound, newUpperBound); 664 newUpMask &= limit.upMask(); 665 newUpperBound = CodeUtil.signExtend(newUpperBound & newUpMask, bits); 666 newDownMask |= limit.downMask(); 667 newLowerBound |= newDownMask; 668 return new IntegerStamp(bits, newLowerBound, newUpperBound, newDownMask, newUpMask); 669 } 670 671 @Override 672 public boolean isNeutral(Constant value) { 673 PrimitiveConstant n = (PrimitiveConstant) value; 674 return n.asLong() == 0; 675 } 676 }, 677 678 new BinaryOp.Sub(true, false) { 679 680 @Override 681 public Constant foldConstant(Constant const1, Constant const2) { 682 PrimitiveConstant a = (PrimitiveConstant) const1; 683 PrimitiveConstant b = (PrimitiveConstant) const2; 684 assert a.getJavaKind() == b.getJavaKind(); 685 return JavaConstant.forIntegerKind(a.getJavaKind(), a.asLong() - b.asLong()); 686 } 687 688 @Override 689 public Stamp foldStamp(Stamp a, Stamp b) { 690 return OPS.getAdd().foldStamp(a, OPS.getNeg().foldStamp(b)); 691 } 692 693 @Override 694 public boolean isNeutral(Constant value) { 695 PrimitiveConstant n = (PrimitiveConstant) value; 696 return n.asLong() == 0; 697 } 698 699 @Override 700 public Constant getZero(Stamp s) { 701 IntegerStamp stamp = (IntegerStamp) s; 702 return JavaConstant.forPrimitiveInt(stamp.getBits(), 0); 703 } 704 }, 705 706 new BinaryOp.Mul(true, true) { 707 708 @Override 709 public Constant foldConstant(Constant const1, Constant const2) { 710 PrimitiveConstant a = (PrimitiveConstant) const1; 711 PrimitiveConstant b = (PrimitiveConstant) const2; 712 assert a.getJavaKind() == b.getJavaKind(); 713 return JavaConstant.forIntegerKind(a.getJavaKind(), a.asLong() * b.asLong()); 714 } 715 716 @Override 717 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 718 IntegerStamp a = (IntegerStamp) stamp1; 719 IntegerStamp b = (IntegerStamp) stamp2; 720 721 int bits = a.getBits(); 722 assert bits == b.getBits(); 723 724 if (a.lowerBound == a.upperBound && b.lowerBound == b.upperBound) { 725 long value = CodeUtil.convert(a.lowerBound() * b.lowerBound(), a.getBits(), false); 726 return StampFactory.forInteger(a.getBits(), value, value); 727 } 728 729 // if a==0 or b==0 result of a*b is always 0 730 if (a.upMask() == 0) { 731 return a; 732 } else if (b.upMask() == 0) { 733 return b; 734 } else { 735 // if a has the full range or b, the result will also have it 736 if (a.isUnrestricted()) { 737 return a; 738 } else if (b.isUnrestricted()) { 739 return b; 740 } 741 // a!=0 && b !=0 holds 742 long newLowerBound = Long.MAX_VALUE; 743 long newUpperBound = Long.MIN_VALUE; 744 /* 745 * Based on the signs of the incoming stamps lower and upper bound 746 * of the result of the multiplication may be swapped. LowerBound 747 * can become upper bound if both signs are negative, and so on. To 748 * determine the new values for lower and upper bound we need to 749 * look at the max and min of the cases blow: 750 * 751 * @formatter:off 752 * 753 * a.lowerBound * b.lowerBound 754 * a.lowerBound * b.upperBound 755 * a.upperBound * b.lowerBound 756 * a.upperBound * b.upperBound 757 * 758 * @formatter:on 759 * 760 * We are only interested in those cases that are relevant due to 761 * the sign of the involved stamps (whether a stamp includes 762 * negative and / or positive values). Based on the signs, the maximum 763 * or minimum of the above multiplications form the new lower and 764 * upper bounds. 765 * 766 * The table below contains the interesting candidates for lower and 767 * upper bound after multiplication. 768 * 769 * For example if we consider two stamps a & b that both contain 770 * negative and positive values, the product of minNegA * minNegB 771 * (both the smallest negative value for each stamp) can only be the 772 * highest positive number. The other candidates can be computed in 773 * a similar fashion. Some of them can never be a new minimum or 774 * maximum and are therefore excluded. 775 * 776 * 777 * @formatter:off 778 * 779 * [x................0................y] 780 * ------------------------------------- 781 * [minNeg maxNeg minPos maxPos] 782 * 783 * where maxNeg = min(0,y) && minPos = max(0,x) 784 * 785 * 786 * |minNegA maxNegA minPosA maxPosA 787 * _______ |____________________________________ 788 * minNegB | MAX / : / MIN 789 * maxNegB | / MIN : MAX / 790 * |------------------+----------------- 791 * minPosB | / MAX : MIN / 792 * maxPosB | MIN / : / MAX 793 * 794 * @formatter:on 795 */ 796 // We materialize all factors here. If they are needed, the signs of 797 // the stamp will ensure the correct value is used. 798 long minNegA = a.lowerBound(); 799 long maxNegA = Math.min(0, a.upperBound()); 800 long minPosA = Math.max(0, a.lowerBound()); 801 long maxPosA = a.upperBound(); 802 803 long minNegB = b.lowerBound(); 804 long maxNegB = Math.min(0, b.upperBound()); 805 long minPosB = Math.max(0, b.lowerBound()); 806 long maxPosB = b.upperBound(); 807 808 // multiplication has shift semantics 809 long newUpMask = ~CodeUtil.mask(Math.min(64, Long.numberOfTrailingZeros(a.upMask) + Long.numberOfTrailingZeros(b.upMask))) & CodeUtil.mask(bits); 810 811 if (a.canBePositive()) { 812 if (b.canBePositive()) { 813 if (multiplicationOverflows(maxPosA, maxPosB, bits)) { 814 return a.unrestricted(); 815 } 816 long maxCandidate = maxPosA * maxPosB; 817 if (multiplicationOverflows(minPosA, minPosB, bits)) { 818 return a.unrestricted(); 819 } 820 long minCandidate = minPosA * minPosB; 821 newLowerBound = Math.min(newLowerBound, minCandidate); 822 newUpperBound = Math.max(newUpperBound, maxCandidate); 823 } 824 if (b.canBeNegative()) { 825 if (multiplicationOverflows(minPosA, maxNegB, bits)) { 826 return a.unrestricted(); 827 } 828 long maxCandidate = minPosA * maxNegB; 829 if (multiplicationOverflows(maxPosA, minNegB, bits)) { 830 return a.unrestricted(); 831 } 832 long minCandidate = maxPosA * minNegB; 833 newLowerBound = Math.min(newLowerBound, minCandidate); 834 newUpperBound = Math.max(newUpperBound, maxCandidate); 835 } 836 } 837 if (a.canBeNegative()) { 838 if (b.canBePositive()) { 839 if (multiplicationOverflows(maxNegA, minPosB, bits)) { 840 return a.unrestricted(); 841 } 842 long maxCandidate = maxNegA * minPosB; 843 if (multiplicationOverflows(minNegA, maxPosB, bits)) { 844 return a.unrestricted(); 845 } 846 long minCandidate = minNegA * maxPosB; 847 newLowerBound = Math.min(newLowerBound, minCandidate); 848 newUpperBound = Math.max(newUpperBound, maxCandidate); 849 } 850 if (b.canBeNegative()) { 851 if (multiplicationOverflows(minNegA, minNegB, bits)) { 852 return a.unrestricted(); 853 } 854 long maxCandidate = minNegA * minNegB; 855 if (multiplicationOverflows(maxNegA, maxNegB, bits)) { 856 return a.unrestricted(); 857 } 858 long minCandidate = maxNegA * maxNegB; 859 newLowerBound = Math.min(newLowerBound, minCandidate); 860 newUpperBound = Math.max(newUpperBound, maxCandidate); 861 } 862 } 863 864 assert newLowerBound <= newUpperBound; 865 return StampFactory.forIntegerWithMask(bits, newLowerBound, newUpperBound, 0, newUpMask); 866 } 867 } 868 869 @Override 870 public boolean isNeutral(Constant value) { 871 PrimitiveConstant n = (PrimitiveConstant) value; 872 return n.asLong() == 1; 873 } 874 }, 875 876 new BinaryOp.MulHigh(true, true) { 877 878 @Override 879 public Constant foldConstant(Constant const1, Constant const2) { 880 PrimitiveConstant a = (PrimitiveConstant) const1; 881 PrimitiveConstant b = (PrimitiveConstant) const2; 882 assert a.getJavaKind() == b.getJavaKind(); 883 return JavaConstant.forIntegerKind(a.getJavaKind(), multiplyHigh(a.asLong(), b.asLong(), a.getJavaKind())); 884 } 885 886 @Override 887 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 888 IntegerStamp a = (IntegerStamp) stamp1; 889 IntegerStamp b = (IntegerStamp) stamp2; 890 JavaKind javaKind = a.getStackKind(); 891 892 assert a.getBits() == b.getBits(); 893 assert javaKind == b.getStackKind(); 894 assert (javaKind == JavaKind.Int || javaKind == JavaKind.Long); 895 896 if (a.isEmpty() || b.isEmpty()) { 897 return a.empty(); 898 } else if (a.isUnrestricted() || b.isUnrestricted()) { 899 return a.unrestricted(); 900 } 901 902 long[] xExtremes = {a.lowerBound(), a.upperBound()}; 903 long[] yExtremes = {b.lowerBound(), b.upperBound()}; 904 long min = Long.MAX_VALUE; 905 long max = Long.MIN_VALUE; 906 for (long x : xExtremes) { 907 for (long y : yExtremes) { 908 long result = multiplyHigh(x, y, javaKind); 909 min = Math.min(min, result); 910 max = Math.max(max, result); 911 } 912 } 913 return StampFactory.forInteger(javaKind, min, max); 914 } 915 916 @Override 917 public boolean isNeutral(Constant value) { 918 return false; 919 } 920 921 private long multiplyHigh(long x, long y, JavaKind javaKind) { 922 if (javaKind == JavaKind.Int) { 923 return (x * y) >> 32; 924 } else { 925 assert javaKind == JavaKind.Long; 926 long x0 = x & 0xFFFFFFFFL; 927 long x1 = x >> 32; 928 929 long y0 = y & 0xFFFFFFFFL; 930 long y1 = y >> 32; 931 932 long z0 = x0 * y0; 933 long t = x1 * y0 + (z0 >>> 32); 934 long z1 = t & 0xFFFFFFFFL; 935 long z2 = t >> 32; 936 z1 += x0 * y1; 937 938 return x1 * y1 + z2 + (z1 >> 32); 939 } 940 } 941 }, 942 943 new BinaryOp.UMulHigh(true, true) { 944 945 @Override 946 public Constant foldConstant(Constant const1, Constant const2) { 947 PrimitiveConstant a = (PrimitiveConstant) const1; 948 PrimitiveConstant b = (PrimitiveConstant) const2; 949 assert a.getJavaKind() == b.getJavaKind(); 950 return JavaConstant.forIntegerKind(a.getJavaKind(), multiplyHighUnsigned(a.asLong(), b.asLong(), a.getJavaKind())); 951 } 952 953 @Override 954 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 955 IntegerStamp a = (IntegerStamp) stamp1; 956 IntegerStamp b = (IntegerStamp) stamp2; 957 JavaKind javaKind = a.getStackKind(); 958 959 assert a.getBits() == b.getBits(); 960 assert javaKind == b.getStackKind(); 961 assert (javaKind == JavaKind.Int || javaKind == JavaKind.Long); 962 963 if (a.isEmpty() || b.isEmpty()) { 964 return a.empty(); 965 } else if (a.isUnrestricted() || b.isUnrestricted()) { 966 return a.unrestricted(); 967 } 968 969 // Note that the minima and maxima are calculated using signed min/max 970 // functions, while the values themselves are unsigned. 971 long[] xExtremes = getUnsignedExtremes(a); 972 long[] yExtremes = getUnsignedExtremes(b); 973 long min = Long.MAX_VALUE; 974 long max = Long.MIN_VALUE; 975 for (long x : xExtremes) { 976 for (long y : yExtremes) { 977 long result = multiplyHighUnsigned(x, y, javaKind); 978 min = Math.min(min, result); 979 max = Math.max(max, result); 980 } 981 } 982 983 // if min is negative, then the value can reach into the unsigned range 984 if (min == max || min >= 0) { 985 return StampFactory.forInteger(javaKind, min, max); 986 } else { 987 return StampFactory.forKind(javaKind); 988 } 989 } 990 991 @Override 992 public boolean isNeutral(Constant value) { 993 return false; 994 } 995 996 private long[] getUnsignedExtremes(IntegerStamp stamp) { 997 if (stamp.lowerBound() < 0 && stamp.upperBound() >= 0) { 998 /* 999 * If -1 and 0 are both in the signed range, then we can't say 1000 * anything about the unsigned range, so we have to return [0, 1001 * MAX_UNSIGNED]. 1002 */ 1003 return new long[]{0, -1L}; 1004 } else { 1005 return new long[]{stamp.lowerBound(), stamp.upperBound()}; 1006 } 1007 } 1008 1009 private long multiplyHighUnsigned(long x, long y, JavaKind javaKind) { 1010 if (javaKind == JavaKind.Int) { 1011 long xl = x & 0xFFFFFFFFL; 1012 long yl = y & 0xFFFFFFFFL; 1013 long r = xl * yl; 1014 return (int) (r >>> 32); 1015 } else { 1016 assert javaKind == JavaKind.Long; 1017 long x0 = x & 0xFFFFFFFFL; 1018 long x1 = x >>> 32; 1019 1020 long y0 = y & 0xFFFFFFFFL; 1021 long y1 = y >>> 32; 1022 1023 long z0 = x0 * y0; 1024 long t = x1 * y0 + (z0 >>> 32); 1025 long z1 = t & 0xFFFFFFFFL; 1026 long z2 = t >>> 32; 1027 z1 += x0 * y1; 1028 1029 return x1 * y1 + z2 + (z1 >>> 32); 1030 } 1031 } 1032 }, 1033 1034 new BinaryOp.Div(true, false) { 1035 1036 @Override 1037 public Constant foldConstant(Constant const1, Constant const2) { 1038 PrimitiveConstant a = (PrimitiveConstant) const1; 1039 PrimitiveConstant b = (PrimitiveConstant) const2; 1040 assert a.getJavaKind() == b.getJavaKind(); 1041 if (b.asLong() == 0) { 1042 return null; 1043 } 1044 return JavaConstant.forIntegerKind(a.getJavaKind(), a.asLong() / b.asLong()); 1045 } 1046 1047 @Override 1048 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 1049 IntegerStamp a = (IntegerStamp) stamp1; 1050 IntegerStamp b = (IntegerStamp) stamp2; 1051 assert a.getBits() == b.getBits(); 1052 if (a.lowerBound == a.upperBound && b.lowerBound == b.upperBound && b.lowerBound != 0) { 1053 long value = CodeUtil.convert(a.lowerBound() / b.lowerBound(), a.getBits(), false); 1054 return StampFactory.forInteger(a.getBits(), value, value); 1055 } else if (b.isStrictlyPositive()) { 1056 long newLowerBound = a.lowerBound() < 0 ? a.lowerBound() / b.lowerBound() : a.lowerBound() / b.upperBound(); 1057 long newUpperBound = a.upperBound() < 0 ? a.upperBound() / b.upperBound() : a.upperBound() / b.lowerBound(); 1058 return StampFactory.forInteger(a.getBits(), newLowerBound, newUpperBound); 1059 } else { 1060 return a.unrestricted(); 1061 } 1062 } 1063 1064 @Override 1065 public boolean isNeutral(Constant value) { 1066 PrimitiveConstant n = (PrimitiveConstant) value; 1067 return n.asLong() == 1; 1068 } 1069 }, 1070 1071 new BinaryOp.Rem(false, false) { 1072 1073 @Override 1074 public Constant foldConstant(Constant const1, Constant const2) { 1075 PrimitiveConstant a = (PrimitiveConstant) const1; 1076 PrimitiveConstant b = (PrimitiveConstant) const2; 1077 assert a.getJavaKind() == b.getJavaKind(); 1078 if (b.asLong() == 0) { 1079 return null; 1080 } 1081 return JavaConstant.forIntegerKind(a.getJavaKind(), a.asLong() % b.asLong()); 1082 } 1083 1084 @Override 1085 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 1086 IntegerStamp a = (IntegerStamp) stamp1; 1087 IntegerStamp b = (IntegerStamp) stamp2; 1088 assert a.getBits() == b.getBits(); 1089 1090 if (a.lowerBound == a.upperBound && b.lowerBound == b.upperBound && b.lowerBound != 0) { 1091 long value = CodeUtil.convert(a.lowerBound() % b.lowerBound(), a.getBits(), false); 1092 return StampFactory.forInteger(a.getBits(), value, value); 1093 } 1094 1095 // zero is always possible 1096 long newLowerBound = Math.min(a.lowerBound(), 0); 1097 long newUpperBound = Math.max(a.upperBound(), 0); 1098 1099 /* the maximum absolute value of the result, derived from b */ 1100 long magnitude; 1101 if (b.lowerBound() == CodeUtil.minValue(b.getBits())) { 1102 // Math.abs(...) - 1 does not work in a case 1103 magnitude = CodeUtil.maxValue(b.getBits()); 1104 } else { 1105 magnitude = Math.max(Math.abs(b.lowerBound()), Math.abs(b.upperBound())) - 1; 1106 } 1107 newLowerBound = Math.max(newLowerBound, -magnitude); 1108 newUpperBound = Math.min(newUpperBound, magnitude); 1109 1110 return StampFactory.forInteger(a.getBits(), newLowerBound, newUpperBound); 1111 } 1112 }, 1113 1114 new UnaryOp.Not() { 1115 1116 @Override 1117 public Constant foldConstant(Constant c) { 1118 PrimitiveConstant value = (PrimitiveConstant) c; 1119 return JavaConstant.forIntegerKind(value.getJavaKind(), ~value.asLong()); 1120 } 1121 1122 @Override 1123 public Stamp foldStamp(Stamp stamp) { 1124 IntegerStamp integerStamp = (IntegerStamp) stamp; 1125 int bits = integerStamp.getBits(); 1126 long defaultMask = CodeUtil.mask(bits); 1127 return new IntegerStamp(bits, ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) & defaultMask); 1128 } 1129 }, 1130 1131 new BinaryOp.And(true, true) { 1132 1133 @Override 1134 public Constant foldConstant(Constant const1, Constant const2) { 1135 PrimitiveConstant a = (PrimitiveConstant) const1; 1136 PrimitiveConstant b = (PrimitiveConstant) const2; 1137 assert a.getJavaKind() == b.getJavaKind(); 1138 return JavaConstant.forIntegerKind(a.getJavaKind(), a.asLong() & b.asLong()); 1139 } 1140 1141 @Override 1142 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 1143 IntegerStamp a = (IntegerStamp) stamp1; 1144 IntegerStamp b = (IntegerStamp) stamp2; 1145 assert a.getBits() == b.getBits(); 1146 return stampForMask(a.getBits(), a.downMask() & b.downMask(), a.upMask() & b.upMask()); 1147 } 1148 1149 @Override 1150 public boolean isNeutral(Constant value) { 1151 PrimitiveConstant n = (PrimitiveConstant) value; 1152 int bits = n.getJavaKind().getBitCount(); 1153 long mask = CodeUtil.mask(bits); 1154 return (n.asLong() & mask) == mask; 1155 } 1156 }, 1157 1158 new BinaryOp.Or(true, true) { 1159 1160 @Override 1161 public Constant foldConstant(Constant const1, Constant const2) { 1162 PrimitiveConstant a = (PrimitiveConstant) const1; 1163 PrimitiveConstant b = (PrimitiveConstant) const2; 1164 assert a.getJavaKind() == b.getJavaKind(); 1165 return JavaConstant.forIntegerKind(a.getJavaKind(), a.asLong() | b.asLong()); 1166 } 1167 1168 @Override 1169 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 1170 IntegerStamp a = (IntegerStamp) stamp1; 1171 IntegerStamp b = (IntegerStamp) stamp2; 1172 assert a.getBits() == b.getBits(); 1173 return stampForMask(a.getBits(), a.downMask() | b.downMask(), a.upMask() | b.upMask()); 1174 } 1175 1176 @Override 1177 public boolean isNeutral(Constant value) { 1178 PrimitiveConstant n = (PrimitiveConstant) value; 1179 return n.asLong() == 0; 1180 } 1181 }, 1182 1183 new BinaryOp.Xor(true, true) { 1184 1185 @Override 1186 public Constant foldConstant(Constant const1, Constant const2) { 1187 PrimitiveConstant a = (PrimitiveConstant) const1; 1188 PrimitiveConstant b = (PrimitiveConstant) const2; 1189 assert a.getJavaKind() == b.getJavaKind(); 1190 return JavaConstant.forIntegerKind(a.getJavaKind(), a.asLong() ^ b.asLong()); 1191 } 1192 1193 @Override 1194 public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { 1195 IntegerStamp a = (IntegerStamp) stamp1; 1196 IntegerStamp b = (IntegerStamp) stamp2; 1197 assert a.getBits() == b.getBits(); 1198 1199 long variableBits = (a.downMask() ^ a.upMask()) | (b.downMask() ^ b.upMask()); 1200 long newDownMask = (a.downMask() ^ b.downMask()) & ~variableBits; 1201 long newUpMask = (a.downMask() ^ b.downMask()) | variableBits; 1202 return stampForMask(a.getBits(), newDownMask, newUpMask); 1203 } 1204 1205 @Override 1206 public boolean isNeutral(Constant value) { 1207 PrimitiveConstant n = (PrimitiveConstant) value; 1208 return n.asLong() == 0; 1209 } 1210 1211 @Override 1212 public Constant getZero(Stamp s) { 1213 IntegerStamp stamp = (IntegerStamp) s; 1214 return JavaConstant.forPrimitiveInt(stamp.getBits(), 0); 1215 } 1216 }, 1217 1218 new ShiftOp.Shl() { 1219 1220 @Override 1221 public Constant foldConstant(Constant value, int amount) { 1222 PrimitiveConstant c = (PrimitiveConstant) value; 1223 switch (c.getJavaKind()) { 1224 case Int: 1225 return JavaConstant.forInt(c.asInt() << amount); 1226 case Long: 1227 return JavaConstant.forLong(c.asLong() << amount); 1228 default: 1229 throw GraalError.shouldNotReachHere(); 1230 } 1231 } 1232 1233 @Override 1234 public Stamp foldStamp(Stamp stamp, IntegerStamp shift) { 1235 IntegerStamp value = (IntegerStamp) stamp; 1236 int bits = value.getBits(); 1237 if (value.isEmpty()) { 1238 return value; 1239 } else if (shift.isEmpty()) { 1240 return StampFactory.forInteger(bits).empty(); 1241 } else if (value.upMask() == 0) { 1242 return value; 1243 } 1244 1245 int shiftMask = getShiftAmountMask(stamp); 1246 int shiftBits = Integer.bitCount(shiftMask); 1247 if (shift.lowerBound() == shift.upperBound()) { 1248 int shiftAmount = (int) (shift.lowerBound() & shiftMask); 1249 if (shiftAmount == 0) { 1250 return value; 1251 } 1252 // the mask of bits that will be lost or shifted into the sign bit 1253 long removedBits = -1L << (bits - shiftAmount - 1); 1254 if ((value.lowerBound() & removedBits) == 0 && (value.upperBound() & removedBits) == 0) { 1255 /* 1256 * use a better stamp if neither lower nor upper bound can lose 1257 * bits 1258 */ 1259 return new IntegerStamp(bits, value.lowerBound() << shiftAmount, value.upperBound() << shiftAmount, value.downMask() << shiftAmount, value.upMask() << shiftAmount); 1260 } 1261 } 1262 if ((shift.lowerBound() >>> shiftBits) == (shift.upperBound() >>> shiftBits)) { 1263 long defaultMask = CodeUtil.mask(bits); 1264 long downMask = defaultMask; 1265 long upMask = 0; 1266 for (long i = shift.lowerBound(); i <= shift.upperBound(); i++) { 1267 if (shift.contains(i)) { 1268 downMask &= value.downMask() << (i & shiftMask); 1269 upMask |= value.upMask() << (i & shiftMask); 1270 } 1271 } 1272 Stamp result = IntegerStamp.stampForMask(bits, downMask, upMask & defaultMask); 1273 return result; 1274 } 1275 return value.unrestricted(); 1276 } 1277 1278 @Override 1279 public int getShiftAmountMask(Stamp s) { 1280 IntegerStamp stamp = (IntegerStamp) s; 1281 assert CodeUtil.isPowerOf2(stamp.getBits()); 1282 return stamp.getBits() - 1; 1283 } 1284 }, 1285 1286 new ShiftOp.Shr() { 1287 1288 @Override 1289 public Constant foldConstant(Constant value, int amount) { 1290 PrimitiveConstant c = (PrimitiveConstant) value; 1291 switch (c.getJavaKind()) { 1292 case Int: 1293 return JavaConstant.forInt(c.asInt() >> amount); 1294 case Long: 1295 return JavaConstant.forLong(c.asLong() >> amount); 1296 default: 1297 throw GraalError.shouldNotReachHere(); 1298 } 1299 } 1300 1301 @Override 1302 public Stamp foldStamp(Stamp stamp, IntegerStamp shift) { 1303 IntegerStamp value = (IntegerStamp) stamp; 1304 int bits = value.getBits(); 1305 if (value.isEmpty()) { 1306 return value; 1307 } else if (shift.isEmpty()) { 1308 return StampFactory.forInteger(bits).empty(); 1309 } else if (shift.lowerBound() == shift.upperBound()) { 1310 long shiftCount = shift.lowerBound() & getShiftAmountMask(stamp); 1311 if (shiftCount == 0) { 1312 return stamp; 1313 } 1314 1315 int extraBits = 64 - bits; 1316 long defaultMask = CodeUtil.mask(bits); 1317 // shifting back and forth performs sign extension 1318 long downMask = (value.downMask() << extraBits) >> (shiftCount + extraBits) & defaultMask; 1319 long upMask = (value.upMask() << extraBits) >> (shiftCount + extraBits) & defaultMask; 1320 return new IntegerStamp(bits, value.lowerBound() >> shiftCount, value.upperBound() >> shiftCount, downMask, upMask); 1321 } 1322 long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound()); 1323 return IntegerStamp.stampForMask(bits, 0, mask); 1324 } 1325 1326 @Override 1327 public int getShiftAmountMask(Stamp s) { 1328 IntegerStamp stamp = (IntegerStamp) s; 1329 assert CodeUtil.isPowerOf2(stamp.getBits()); 1330 return stamp.getBits() - 1; 1331 } 1332 }, 1333 1334 new ShiftOp.UShr() { 1335 1336 @Override 1337 public Constant foldConstant(Constant value, int amount) { 1338 PrimitiveConstant c = (PrimitiveConstant) value; 1339 switch (c.getJavaKind()) { 1340 case Int: 1341 return JavaConstant.forInt(c.asInt() >>> amount); 1342 case Long: 1343 return JavaConstant.forLong(c.asLong() >>> amount); 1344 default: 1345 throw GraalError.shouldNotReachHere(); 1346 } 1347 } 1348 1349 @Override 1350 public Stamp foldStamp(Stamp stamp, IntegerStamp shift) { 1351 IntegerStamp value = (IntegerStamp) stamp; 1352 int bits = value.getBits(); 1353 if (value.isEmpty()) { 1354 return value; 1355 } else if (shift.isEmpty()) { 1356 return StampFactory.forInteger(bits).empty(); 1357 } 1358 1359 if (shift.lowerBound() == shift.upperBound()) { 1360 long shiftCount = shift.lowerBound() & getShiftAmountMask(stamp); 1361 if (shiftCount == 0) { 1362 return stamp; 1363 } 1364 1365 long downMask = value.downMask() >>> shiftCount; 1366 long upMask = value.upMask() >>> shiftCount; 1367 if (value.lowerBound() < 0) { 1368 return new IntegerStamp(bits, downMask, upMask, downMask, upMask); 1369 } else { 1370 return new IntegerStamp(bits, value.lowerBound() >>> shiftCount, value.upperBound() >>> shiftCount, downMask, upMask); 1371 } 1372 } 1373 long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound()); 1374 return IntegerStamp.stampForMask(bits, 0, mask); 1375 } 1376 1377 @Override 1378 public int getShiftAmountMask(Stamp s) { 1379 IntegerStamp stamp = (IntegerStamp) s; 1380 assert CodeUtil.isPowerOf2(stamp.getBits()); 1381 return stamp.getBits() - 1; 1382 } 1383 }, 1384 1385 new UnaryOp.Abs() { 1386 1387 @Override 1388 public Constant foldConstant(Constant value) { 1389 PrimitiveConstant c = (PrimitiveConstant) value; 1390 return JavaConstant.forIntegerKind(c.getJavaKind(), Math.abs(c.asLong())); 1391 } 1392 1393 @Override 1394 public Stamp foldStamp(Stamp input) { 1395 IntegerStamp stamp = (IntegerStamp) input; 1396 int bits = stamp.getBits(); 1397 if (stamp.lowerBound == stamp.upperBound) { 1398 long value = CodeUtil.convert(Math.abs(stamp.lowerBound()), stamp.getBits(), false); 1399 return StampFactory.forInteger(stamp.getBits(), value, value); 1400 } 1401 if (stamp.lowerBound() == CodeUtil.minValue(bits)) { 1402 return input.unrestricted(); 1403 } else { 1404 long limit = Math.max(-stamp.lowerBound(), stamp.upperBound()); 1405 return StampFactory.forInteger(bits, 0, limit); 1406 } 1407 } 1408 }, 1409 1410 null, 1411 1412 new IntegerConvertOp.ZeroExtend() { 1413 1414 @Override 1415 public Constant foldConstant(int inputBits, int resultBits, Constant c) { 1416 PrimitiveConstant value = (PrimitiveConstant) c; 1417 return JavaConstant.forPrimitiveInt(resultBits, CodeUtil.zeroExtend(value.asLong(), inputBits)); 1418 } 1419 1420 @Override 1421 public Stamp foldStamp(int inputBits, int resultBits, Stamp input) { 1422 IntegerStamp stamp = (IntegerStamp) input; 1423 assert inputBits == stamp.getBits(); 1424 assert inputBits <= resultBits; 1425 1426 if (inputBits == resultBits) { 1427 return input; 1428 } 1429 1430 if (input.isEmpty()) { 1431 return StampFactory.forInteger(resultBits).empty(); 1432 } 1433 1434 long downMask = CodeUtil.zeroExtend(stamp.downMask(), inputBits); 1435 long upMask = CodeUtil.zeroExtend(stamp.upMask(), inputBits); 1436 long lowerBound = stamp.unsignedLowerBound(); 1437 long upperBound = stamp.unsignedUpperBound(); 1438 return IntegerStamp.create(resultBits, lowerBound, upperBound, downMask, upMask); 1439 } 1440 1441 @Override 1442 public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { 1443 IntegerStamp stamp = (IntegerStamp) outStamp; 1444 if (stamp.isEmpty()) { 1445 return StampFactory.forInteger(inputBits).empty(); 1446 } 1447 return StampFactory.forUnsignedInteger(inputBits, stamp.lowerBound(), stamp.upperBound(), stamp.downMask(), stamp.upMask()); 1448 } 1449 }, 1450 1451 new IntegerConvertOp.SignExtend() { 1452 1453 @Override 1454 public Constant foldConstant(int inputBits, int resultBits, Constant c) { 1455 PrimitiveConstant value = (PrimitiveConstant) c; 1456 return JavaConstant.forPrimitiveInt(resultBits, CodeUtil.signExtend(value.asLong(), inputBits)); 1457 } 1458 1459 @Override 1460 public Stamp foldStamp(int inputBits, int resultBits, Stamp input) { 1461 IntegerStamp stamp = (IntegerStamp) input; 1462 assert inputBits == stamp.getBits(); 1463 assert inputBits <= resultBits; 1464 1465 long defaultMask = CodeUtil.mask(resultBits); 1466 long downMask = CodeUtil.signExtend(stamp.downMask(), inputBits) & defaultMask; 1467 long upMask = CodeUtil.signExtend(stamp.upMask(), inputBits) & defaultMask; 1468 1469 return new IntegerStamp(resultBits, stamp.lowerBound(), stamp.upperBound(), downMask, upMask); 1470 } 1471 1472 @Override 1473 public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { 1474 IntegerStamp stamp = (IntegerStamp) outStamp; 1475 long mask = CodeUtil.mask(inputBits); 1476 return StampFactory.forIntegerWithMask(inputBits, stamp.lowerBound(), stamp.upperBound(), stamp.downMask() & mask, stamp.upMask() & mask); 1477 } 1478 }, 1479 1480 new IntegerConvertOp.Narrow() { 1481 1482 @Override 1483 public Constant foldConstant(int inputBits, int resultBits, Constant c) { 1484 PrimitiveConstant value = (PrimitiveConstant) c; 1485 return JavaConstant.forPrimitiveInt(resultBits, CodeUtil.narrow(value.asLong(), resultBits)); 1486 } 1487 1488 @Override 1489 public Stamp foldStamp(int inputBits, int resultBits, Stamp input) { 1490 IntegerStamp stamp = (IntegerStamp) input; 1491 assert inputBits == stamp.getBits(); 1492 assert resultBits <= inputBits; 1493 if (resultBits == inputBits) { 1494 return stamp; 1495 } 1496 1497 final long upperBound; 1498 if (stamp.lowerBound() < CodeUtil.minValue(resultBits)) { 1499 upperBound = CodeUtil.maxValue(resultBits); 1500 } else { 1501 upperBound = saturate(stamp.upperBound(), resultBits); 1502 } 1503 final long lowerBound; 1504 if (stamp.upperBound() > CodeUtil.maxValue(resultBits)) { 1505 lowerBound = CodeUtil.minValue(resultBits); 1506 } else { 1507 lowerBound = saturate(stamp.lowerBound(), resultBits); 1508 } 1509 1510 long defaultMask = CodeUtil.mask(resultBits); 1511 long newDownMask = stamp.downMask() & defaultMask; 1512 long newUpMask = stamp.upMask() & defaultMask; 1513 long newLowerBound = CodeUtil.signExtend((lowerBound | newDownMask) & newUpMask, resultBits); 1514 long newUpperBound = CodeUtil.signExtend((upperBound | newDownMask) & newUpMask, resultBits); 1515 return new IntegerStamp(resultBits, newLowerBound, newUpperBound, newDownMask, newUpMask); 1516 } 1517 }, 1518 1519 new FloatConvertOp(I2F) { 1520 1521 @Override 1522 public Constant foldConstant(Constant c) { 1523 PrimitiveConstant value = (PrimitiveConstant) c; 1524 return JavaConstant.forFloat(value.asInt()); 1525 } 1526 1527 @Override 1528 public Stamp foldStamp(Stamp input) { 1529 IntegerStamp stamp = (IntegerStamp) input; 1530 assert stamp.getBits() == 32; 1531 float lowerBound = stamp.lowerBound(); 1532 float upperBound = stamp.upperBound(); 1533 return StampFactory.forFloat(JavaKind.Float, lowerBound, upperBound, true); 1534 } 1535 }, 1536 1537 new FloatConvertOp(L2F) { 1538 1539 @Override 1540 public Constant foldConstant(Constant c) { 1541 PrimitiveConstant value = (PrimitiveConstant) c; 1542 return JavaConstant.forFloat(value.asLong()); 1543 } 1544 1545 @Override 1546 public Stamp foldStamp(Stamp input) { 1547 IntegerStamp stamp = (IntegerStamp) input; 1548 assert stamp.getBits() == 64; 1549 float lowerBound = stamp.lowerBound(); 1550 float upperBound = stamp.upperBound(); 1551 return StampFactory.forFloat(JavaKind.Float, lowerBound, upperBound, true); 1552 } 1553 }, 1554 1555 new FloatConvertOp(I2D) { 1556 1557 @Override 1558 public Constant foldConstant(Constant c) { 1559 PrimitiveConstant value = (PrimitiveConstant) c; 1560 return JavaConstant.forDouble(value.asInt()); 1561 } 1562 1563 @Override 1564 public Stamp foldStamp(Stamp input) { 1565 IntegerStamp stamp = (IntegerStamp) input; 1566 assert stamp.getBits() == 32; 1567 double lowerBound = stamp.lowerBound(); 1568 double upperBound = stamp.upperBound(); 1569 return StampFactory.forFloat(JavaKind.Double, lowerBound, upperBound, true); 1570 } 1571 }, 1572 1573 new FloatConvertOp(L2D) { 1574 1575 @Override 1576 public Constant foldConstant(Constant c) { 1577 PrimitiveConstant value = (PrimitiveConstant) c; 1578 return JavaConstant.forDouble(value.asLong()); 1579 } 1580 1581 @Override 1582 public Stamp foldStamp(Stamp input) { 1583 IntegerStamp stamp = (IntegerStamp) input; 1584 assert stamp.getBits() == 64; 1585 double lowerBound = stamp.lowerBound(); 1586 double upperBound = stamp.upperBound(); 1587 return StampFactory.forFloat(JavaKind.Double, lowerBound, upperBound, true); 1588 } 1589 }); 1590 }