| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- class Value;
- class IntConstantBounds;
- typedef JsUtil::BaseHashSet<ValueRelativeOffset, JitArenaAllocator, PowerOf2SizePolicy, ValueNumber> RelativeIntBoundSet;
- #pragma region IntBounds
- class IntBounds sealed
- {
- private:
- int constantLowerBound, constantUpperBound;
- bool wasConstantUpperBoundEstablishedExplicitly;
- RelativeIntBoundSet relativeLowerBounds, relativeUpperBounds;
- protected:
- IntBounds(const IntConstantBounds &constantBounds, const bool wasConstantUpperBoundEstablishedExplicitly, JitArenaAllocator *const allocator);
- public:
- static IntBounds *New(const IntConstantBounds &constantBounds, const bool wasConstantUpperBoundEstablishedExplicitly, JitArenaAllocator *const allocator);
- IntBounds *Clone() const;
- void Delete() const;
- public:
- void Verify() const;
- private:
- bool HasBounds() const;
- public:
- bool RequiresIntBoundedValueInfo(const ValueType valueType) const;
- bool RequiresIntBoundedValueInfo() const;
- public:
- int ConstantLowerBound() const;
- int ConstantUpperBound() const;
- IntConstantBounds ConstantBounds() const;
- bool WasConstantUpperBoundEstablishedExplicitly() const;
- public:
- const RelativeIntBoundSet &RelativeLowerBounds() const;
- const RelativeIntBoundSet &RelativeUpperBounds() const;
- public:
- void SetLowerBound(const int constantBound);
- void SetLowerBound(const int constantBoundBase, const int offset);
- void SetUpperBound(const int constantBound, const bool wasEstablishedExplicitly);
- void SetUpperBound(const int constantBoundBase, const int offset, const bool wasEstablishedExplicitly);
- private:
- template<bool Lower> void SetBound(const int constantBoundBase, const int offset, const bool wasEstablishedExplicitly);
- public:
- void SetLowerBound(const ValueNumber myValueNumber, const Value *const baseValue, const bool wasEstablishedExplicitly);
- void SetLowerBound(const ValueNumber myValueNumber, const Value *const baseValue, const int offset, const bool wasEstablishedExplicitly);
- void SetUpperBound(const ValueNumber myValueNumber, const Value *const baseValue, const bool wasEstablishedExplicitly);
- void SetUpperBound(const ValueNumber myValueNumber, const Value *const baseValue, const int offset, const bool wasEstablishedExplicitly);
- private:
- template<bool Lower> void SetBound(const ValueNumber myValueNumber, const Value *const baseValue, const int offset, const bool wasEstablishedExplicitly);
- public:
- bool SetIsNot(const int constantValue, const bool isExplicit);
- bool SetIsNot(const Value *const value, const bool isExplicit);
- public:
- static bool IsGreaterThanOrEqualTo(const int constantValue, const int constantBoundBase, const int offset);
- static bool IsLessThanOrEqualTo(const int constantValue, const int constantBoundBase, const int offset);
- public:
- bool IsGreaterThanOrEqualTo(const int constantBoundBase, const int offset = 0) const;
- bool IsLessThanOrEqualTo(const int constantBoundBase, const int offset = 0) const;
- public:
- bool IsGreaterThanOrEqualTo(const Value *const value, const int offset = 0) const;
- bool IsLessThanOrEqualTo(const Value *const value, const int offset = 0) const;
- public:
- static const IntBounds *Add(const Value *const baseValue, const int n, const bool baseValueInfoIsPrecise, const IntConstantBounds &newConstantBounds, JitArenaAllocator *const allocator);
- public:
- bool AddCannotOverflowBasedOnRelativeBounds(const int n) const;
- bool SubCannotOverflowBasedOnRelativeBounds(const int n) const;
- public:
- static const IntBounds *Merge(const Value *const bounds0Value, const IntBounds *const bounds0, const Value *const bounds1Value, const IntConstantBounds &constantBounds1);
- static const IntBounds *Merge(const Value *const bounds0Value, const IntBounds *const bounds0, const Value *const bounds1Value, const IntBounds *const bounds1);
- private:
- template<bool Lower> static void MergeBoundSets(const Value *const bounds0Value, const IntBounds *const bounds0, const Value *const bounds1Value, const IntBounds *const bounds1, IntBounds *const mergedBounds);
- PREVENT_ASSIGN(IntBounds);
- };
- #pragma endregion
- #pragma region IntBoundCheckCompatibilityId and IntBoundCheck
- // A bounds check takes the form (a <= b + offset). For instance, (i >= 0) would be represented as (0 <= i + 0), and (i < n)
- // would be represented as (i <= n - 1). When a bounds check is required, from the two value numbers, it can be determined
- // whether an existing, compatible bounds check can be updated by decreasing the offset aggressively instead of adding a new
- // bounds check. The offset may only be decreased such that it does not invalidate the invariant previously established by the
- // check.
- //
- // For instance, given that we have the bound checks (0 <= i + 0) and (i <= n - 1), suppose the bounds checks (i + 1 >= 0) and
- // (i + 1 < n) are required. (i + 1 >= 0) would be represented as (0 <= i + 1). Given that (0 <= i + 0), it is already
- // guaranteed that (0 <= i + 1), so no change is necessary for that part. (i + 1 < n) would be represented as (i <= n + 0). The
- // compatible bounds check (i <= n - 1) would be found and updated aggressively to (i <= n + 0).
- class IntBoundCheckCompatibilityId
- {
- private:
- const ValueNumber leftValueNumber, rightValueNumber;
- public:
- IntBoundCheckCompatibilityId(const ValueNumber leftValueNumber, const ValueNumber rightValueNumber);
- public:
- bool operator ==(const IntBoundCheckCompatibilityId &other) const;
- operator hash_t() const;
- };
- class IntBoundCheck
- {
- private:
- ValueNumber leftValueNumber, rightValueNumber;
- IR::Instr *instr;
- BasicBlock *block;
- public:
- IntBoundCheck();
- IntBoundCheck(const ValueNumber leftValueNumber, const ValueNumber rightValueNumber, IR::Instr *const instr, BasicBlock *const block);
- #if DBG
- public:
- bool IsValid() const;
- #endif
- public:
- ValueNumber LeftValueNumber() const;
- ValueNumber RightValueNumber() const;
- IR::Instr *Instr() const;
- BasicBlock *Block() const;
- IntBoundCheckCompatibilityId CompatibilityId() const;
- public:
- bool SetBoundOffset(const int offset, const bool isLoopCountBasedBound = false) const;
- };
- template<>
- IntBoundCheckCompatibilityId JsUtil::ValueToKey<IntBoundCheckCompatibilityId, IntBoundCheck>::ToKey(
- const IntBoundCheck &intBoundCheck)
- {
- return intBoundCheck.CompatibilityId();
- }
- typedef JsUtil::BaseHashSet<IntBoundCheck, JitArenaAllocator, PowerOf2SizePolicy, IntBoundCheckCompatibilityId> IntBoundCheckSet;
- #pragma endregion
|