|
105 | 105 | #include "llvm/Analysis/MustExecute.h"
|
106 | 106 | #include "llvm/Analysis/TargetLibraryInfo.h"
|
107 | 107 | #include "llvm/IR/CallSite.h"
|
| 108 | +#include "llvm/IR/ConstantRange.h" |
108 | 109 | #include "llvm/IR/PassManager.h"
|
109 | 110 |
|
110 | 111 | namespace llvm {
|
@@ -1503,6 +1504,116 @@ struct BooleanState : public IntegerStateBase<bool, 1, 0> {
|
1503 | 1504 | }
|
1504 | 1505 | };
|
1505 | 1506 |
|
| 1507 | +/// State for an integer range. |
| 1508 | +struct IntegerRangeState : public AbstractState { |
| 1509 | + |
| 1510 | + /// Bitwidth of the associated value. |
| 1511 | + uint32_t BitWidth; |
| 1512 | + |
| 1513 | + /// State representing assumed range, initially set to empty. |
| 1514 | + ConstantRange Assumed; |
| 1515 | + |
| 1516 | + /// State representing known range, initially set to [-inf, inf]. |
| 1517 | + ConstantRange Known; |
| 1518 | + |
| 1519 | + IntegerRangeState(uint32_t BitWidth) |
| 1520 | + : BitWidth(BitWidth), Assumed(ConstantRange::getEmpty(BitWidth)), |
| 1521 | + Known(ConstantRange::getFull(BitWidth)) {} |
| 1522 | + |
| 1523 | + /// Return the worst possible representable state. |
| 1524 | + static ConstantRange getWorstState(uint32_t BitWidth) { |
| 1525 | + return ConstantRange::getFull(BitWidth); |
| 1526 | + } |
| 1527 | + |
| 1528 | + /// Return the best possible representable state. |
| 1529 | + static ConstantRange getBestState(uint32_t BitWidth) { |
| 1530 | + return ConstantRange::getEmpty(BitWidth); |
| 1531 | + } |
| 1532 | + |
| 1533 | + /// Return associated values' bit width. |
| 1534 | + uint32_t getBitWidth() const { return BitWidth; } |
| 1535 | + |
| 1536 | + /// See AbstractState::isValidState() |
| 1537 | + bool isValidState() const override { |
| 1538 | + return BitWidth > 0 && !Assumed.isFullSet(); |
| 1539 | + } |
| 1540 | + |
| 1541 | + /// See AbstractState::isAtFixpoint() |
| 1542 | + bool isAtFixpoint() const override { return Assumed == Known; } |
| 1543 | + |
| 1544 | + /// See AbstractState::indicateOptimisticFixpoint(...) |
| 1545 | + ChangeStatus indicateOptimisticFixpoint() override { |
| 1546 | + Known = Assumed; |
| 1547 | + return ChangeStatus::CHANGED; |
| 1548 | + } |
| 1549 | + |
| 1550 | + /// See AbstractState::indicatePessimisticFixpoint(...) |
| 1551 | + ChangeStatus indicatePessimisticFixpoint() override { |
| 1552 | + Assumed = Known; |
| 1553 | + return ChangeStatus::CHANGED; |
| 1554 | + } |
| 1555 | + |
| 1556 | + /// Return the known state encoding |
| 1557 | + ConstantRange getKnown() const { return Known; } |
| 1558 | + |
| 1559 | + /// Return the assumed state encoding. |
| 1560 | + ConstantRange getAssumed() const { return Assumed; } |
| 1561 | + |
| 1562 | + /// Unite assumed range with the passed state. |
| 1563 | + void unionAssumed(const ConstantRange &R) { |
| 1564 | + // Don't loose a known range. |
| 1565 | + Assumed = Assumed.unionWith(R).intersectWith(Known); |
| 1566 | + } |
| 1567 | + |
| 1568 | + /// See IntegerRangeState::unionAssumed(..). |
| 1569 | + void unionAssumed(const IntegerRangeState &R) { |
| 1570 | + unionAssumed(R.getAssumed()); |
| 1571 | + } |
| 1572 | + |
| 1573 | + /// Unite known range with the passed state. |
| 1574 | + void unionKnown(const ConstantRange &R) { |
| 1575 | + // Don't loose a known range. |
| 1576 | + Known = Known.unionWith(R); |
| 1577 | + Assumed = Assumed.unionWith(Known); |
| 1578 | + } |
| 1579 | + |
| 1580 | + /// See IntegerRangeState::unionKnown(..). |
| 1581 | + void unionKnown(const IntegerRangeState &R) { unionKnown(R.getKnown()); } |
| 1582 | + |
| 1583 | + /// Intersect known range with the passed state. |
| 1584 | + void intersectKnown(const ConstantRange &R) { |
| 1585 | + Assumed = Assumed.intersectWith(R); |
| 1586 | + Known = Known.intersectWith(R); |
| 1587 | + } |
| 1588 | + |
| 1589 | + /// See IntegerRangeState::intersectKnown(..). |
| 1590 | + void intersectKnown(const IntegerRangeState &R) { |
| 1591 | + intersectKnown(R.getKnown()); |
| 1592 | + } |
| 1593 | + |
| 1594 | + /// Equality for IntegerRangeState. |
| 1595 | + bool operator==(const IntegerRangeState &R) const { |
| 1596 | + return getAssumed() == R.getAssumed() && getKnown() == R.getKnown(); |
| 1597 | + } |
| 1598 | + |
| 1599 | + /// "Clamp" this state with \p R. The result is subtype dependent but it is |
| 1600 | + /// intended that only information assumed in both states will be assumed in |
| 1601 | + /// this one afterwards. |
| 1602 | + IntegerRangeState operator^=(const IntegerRangeState &R) { |
| 1603 | + // NOTE: `^=` operator seems like `intersect` but in this case, we need to |
| 1604 | + // take `union`. |
| 1605 | + unionAssumed(R); |
| 1606 | + return *this; |
| 1607 | + } |
| 1608 | + |
| 1609 | + IntegerRangeState operator&=(const IntegerRangeState &R) { |
| 1610 | + // NOTE: `&=` operator seems like `intersect` but in this case, we need to |
| 1611 | + // take `union`. |
| 1612 | + unionKnown(R); |
| 1613 | + unionAssumed(R); |
| 1614 | + return *this; |
| 1615 | + } |
| 1616 | +}; |
1506 | 1617 | /// Helper struct necessary as the modular build fails if the virtual method
|
1507 | 1618 | /// IRAttribute::manifest is defined in the Attributor.cpp.
|
1508 | 1619 | struct IRAttributeManifest {
|
@@ -1696,6 +1807,7 @@ template <typename base_ty, base_ty BestState, base_ty WorstState>
|
1696 | 1807 | raw_ostream &
|
1697 | 1808 | operator<<(raw_ostream &OS,
|
1698 | 1809 | const IntegerStateBase<base_ty, BestState, WorstState> &State);
|
| 1810 | +raw_ostream &operator<<(raw_ostream &OS, const IntegerRangeState &State); |
1699 | 1811 | ///}
|
1700 | 1812 |
|
1701 | 1813 | struct AttributorPass : public PassInfoMixin<AttributorPass> {
|
@@ -2331,6 +2443,55 @@ struct AAMemoryBehavior
|
2331 | 2443 | static const char ID;
|
2332 | 2444 | };
|
2333 | 2445 |
|
| 2446 | +/// An abstract interface for range value analysis. |
| 2447 | +struct AAValueConstantRange : public IntegerRangeState, |
| 2448 | + public AbstractAttribute, |
| 2449 | + public IRPosition { |
| 2450 | + AAValueConstantRange(const IRPosition &IRP) |
| 2451 | + : IntegerRangeState( |
| 2452 | + IRP.getAssociatedValue().getType()->getIntegerBitWidth()), |
| 2453 | + IRPosition(IRP) {} |
| 2454 | + |
| 2455 | + /// Return an IR position, see struct IRPosition. |
| 2456 | + const IRPosition &getIRPosition() const override { return *this; } |
| 2457 | + |
| 2458 | + /// See AbstractAttribute::getState(...). |
| 2459 | + IntegerRangeState &getState() override { return *this; } |
| 2460 | + const AbstractState &getState() const override { return *this; } |
| 2461 | + |
| 2462 | + /// Create an abstract attribute view for the position \p IRP. |
| 2463 | + static AAValueConstantRange &createForPosition(const IRPosition &IRP, |
| 2464 | + Attributor &A); |
| 2465 | + |
| 2466 | + /// Return an assumed range for the assocaited value a program point \p CtxI. |
| 2467 | + /// If \p I is nullptr, simply return an assumed range. |
| 2468 | + virtual ConstantRange |
| 2469 | + getAssumedConstantRange(Attributor &A, |
| 2470 | + const Instruction *CtxI = nullptr) const = 0; |
| 2471 | + |
| 2472 | + /// Return a known range for the assocaited value at a program point \p CtxI. |
| 2473 | + /// If \p I is nullptr, simply return a known range. |
| 2474 | + virtual ConstantRange |
| 2475 | + getKnownConstantRange(Attributor &A, |
| 2476 | + const Instruction *CtxI = nullptr) const = 0; |
| 2477 | + |
| 2478 | + /// Return an assumed constant for the assocaited value a program point \p |
| 2479 | + /// CtxI. |
| 2480 | + Optional<ConstantInt *> |
| 2481 | + getAssumedConstantInt(Attributor &A, const Instruction *CtxI = nullptr) const { |
| 2482 | + ConstantRange RangeV = getAssumedConstantRange(A, CtxI); |
| 2483 | + if (auto *C = RangeV.getSingleElement()) |
| 2484 | + return cast<ConstantInt>( |
| 2485 | + ConstantInt::get(getAssociatedValue().getType(), *C)); |
| 2486 | + if (RangeV.isEmptySet()) |
| 2487 | + return llvm::None; |
| 2488 | + return nullptr; |
| 2489 | + } |
| 2490 | + |
| 2491 | + /// Unique ID (due to the unique address) |
| 2492 | + static const char ID; |
| 2493 | +}; |
| 2494 | + |
2334 | 2495 | } // end namespace llvm
|
2335 | 2496 |
|
2336 | 2497 | #endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
|
0 commit comments