| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- //-------------------------------------------------------------------------------------------------------
- // 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 IntBoundedValueInfo : public ValueInfo
- {
- private:
- const IntBounds *const bounds;
- // Definitely-int values are inherently not negative zero. This member variable, if true, indicates that this value was
- // produced by an int-specialized instruction that prevented a negative zero result using a negative zero bailout
- // (BailOutOnNegativeZero). Negative zero tracking in the dead-store phase tracks this information to see if some of these
- // negative zero bailout checks can be removed.
- bool wasNegativeZeroPreventedByBailout;
- protected:
- IntBoundedValueInfo(const ValueType type, const IntBounds *const bounds, const bool wasNegativeZeroPreventedByBailout)
- :
- ValueInfo(
- type.IsInt()
- ? bounds->ConstantBounds().GetValueType()
- : bounds->ConstantBounds().IsLikelyTaggable() ? type : type.ToLikelyUntaggedInt(),
- ValueStructureKind::IntBounded),
- bounds(bounds),
- wasNegativeZeroPreventedByBailout(wasNegativeZeroPreventedByBailout)
- {
- Assert(type.IsLikelyInt());
- Assert(Type().IsLikelyInt());
- Assert(Type().IsInt() == type.IsInt());
- bounds->Verify();
- // Bounds for definitely int values should have relative bounds, otherwise those values should use one of the other
- // value infos
- Assert(bounds->RequiresIntBoundedValueInfo(Type()));
- Assert(!wasNegativeZeroPreventedByBailout || type.IsInt());
- Assert(!wasNegativeZeroPreventedByBailout || bounds->ConstantLowerBound() <= 0);
- Assert(!wasNegativeZeroPreventedByBailout || bounds->ConstantUpperBound() >= 0);
- }
- public:
- static IntBoundedValueInfo *New(
- const ValueType type,
- const IntBounds *const bounds,
- const bool wasNegativeZeroPreventedByBailout,
- JitArenaAllocator *const allocator)
- {
- Assert(allocator);
- return JitAnew(allocator, IntBoundedValueInfo, type, bounds, wasNegativeZeroPreventedByBailout);
- }
- IntBoundedValueInfo *Copy(JitArenaAllocator *const allocator) const
- {
- Assert(allocator);
- return JitAnew(allocator, IntBoundedValueInfo, *this);
- }
- public:
- const IntBounds *Bounds() const
- {
- return bounds;
- }
- bool WasNegativeZeroPreventedByBailout() const
- {
- return wasNegativeZeroPreventedByBailout;
- }
- };
- class LoopCount
- {
- private:
- bool hasBeenGenerated;
- // Information needed to generate the loop count instructions
- // loopCountMinusOne = (left - right + offset) / minMagnitudeChange
- StackSym *leftSym, *rightSym;
- int offset, minMagnitudeChange;
- // Information needed to use the computed loop count
- StackSym *loopCountMinusOneSym;
- StackSym *loopCountSym; // Not generated by default and depends on loopCountMinusOneSym
- int loopCountMinusOneConstantValue;
- public:
- LoopCount(StackSym *const leftSym, StackSym *const rightSym, const int offset, const int minMagnitudeChange)
- : leftSym(leftSym), rightSym(rightSym), offset(offset), minMagnitudeChange(minMagnitudeChange), hasBeenGenerated(false), loopCountSym(nullptr)
- {
- Assert(leftSym || rightSym);
- Assert(!leftSym || leftSym->GetType() == TyInt32 || leftSym->GetType() == TyUint32);
- Assert(!rightSym || rightSym->GetType() == TyInt32 || rightSym->GetType() == TyUint32);
- Assert(minMagnitudeChange > 0);
- }
- LoopCount(StackSym *const loopCountMinusOneSym) : loopCountMinusOneSym(loopCountMinusOneSym), hasBeenGenerated(true), loopCountSym(nullptr)
- {
- Assert(loopCountMinusOneSym);
- }
- LoopCount(StackSym *const loopCountMinusOneSym, StackSym *const loopCountSym) :
- loopCountMinusOneSym(loopCountMinusOneSym),
- loopCountSym(loopCountSym),
- hasBeenGenerated(true)
- {
- Assert(loopCountMinusOneSym);
- }
- LoopCount(const int loopCountMinusOneConstantValue)
- : loopCountMinusOneSym(nullptr), loopCountMinusOneConstantValue(loopCountMinusOneConstantValue), hasBeenGenerated(true), loopCountSym(nullptr)
- {
- Assert(loopCountMinusOneConstantValue >= 0);
- }
- public:
- bool HasBeenGenerated() const
- {
- return hasBeenGenerated;
- }
- bool HasGeneratedLoopCountSym() const
- {
- // Consider loop count sym generated if there is no loopCountMinusOneSym and it has been generated
- return hasBeenGenerated && (loopCountSym != nullptr || loopCountMinusOneSym == nullptr);
- }
- StackSym *LeftSym() const
- {
- Assert(!HasBeenGenerated());
- return leftSym;
- }
- StackSym *RightSym() const
- {
- Assert(!HasBeenGenerated());
- return rightSym;
- }
- int Offset() const
- {
- Assert(!HasBeenGenerated());
- return offset;
- }
- int MinMagnitudeChange() const
- {
- Assert(!HasBeenGenerated());
- return minMagnitudeChange;
- }
- StackSym *LoopCountMinusOneSym() const
- {
- Assert(HasBeenGenerated());
- return loopCountMinusOneSym;
- }
- StackSym *LoopCountSym() const
- {
- Assert(HasGeneratedLoopCountSym());
- return loopCountSym;
- }
- void SetLoopCountSym(StackSym *const loopCountSym)
- {
- Assert(HasBeenGenerated());
- Assert(loopCountSym);
- this->loopCountSym = loopCountSym;
- }
- void SetLoopCountMinusOneSym(StackSym *const loopCountMinusOneSym)
- {
- Assert(!HasBeenGenerated());
- Assert(loopCountMinusOneSym);
- hasBeenGenerated = true;
- this->loopCountMinusOneSym = loopCountMinusOneSym;
- }
- int LoopCountMinusOneConstantValue() const
- {
- Assert(!LoopCountMinusOneSym());
- return loopCountMinusOneConstantValue;
- }
- };
- class GlobOpt::AddSubConstantInfo
- {
- private:
- StackSym *srcSym;
- Value *srcValue;
- bool srcValueIsLikelyConstant;
- int32 offset;
- public:
- AddSubConstantInfo() : srcSym(nullptr)
- {
- }
- public:
- bool HasInfo() const
- {
- return !!srcSym;
- }
- StackSym *SrcSym() const
- {
- Assert(HasInfo());
- return srcSym;
- }
- Value *SrcValue() const
- {
- Assert(HasInfo());
- return srcValue;
- }
- bool SrcValueIsLikelyConstant() const
- {
- Assert(HasInfo());
- return srcValueIsLikelyConstant;
- }
- int32 Offset() const
- {
- Assert(HasInfo());
- return offset;
- }
- public:
- void Set(StackSym *const srcSym, Value *const srcValue, const bool srcValueIsLikelyConstant, const int32 offset);
- };
- class GlobOpt::ArrayLowerBoundCheckHoistInfo
- {
- protected:
- BasicBlock *compatibleBoundCheckBlock;
- Loop *loop;
- // Info populated for a compatible bound check and for hoisting out of loop
- StackSym *indexSym;
- int indexOffset;
- int offset;
- ValueNumber indexValueNumber;
- // Info populated for hoisting out of loop
- Value *indexValue;
- IntConstantBounds indexConstantBounds; // also populated for constant index, when there's a compatible bound check
- bool isLoopCountBasedBound;
- // Info populated for hoisting out of loop using a loop count based bound, when the bound needs to be generated
- LoopCount *loopCount;
- int maxMagnitudeChange;
- public:
- ArrayLowerBoundCheckHoistInfo() : compatibleBoundCheckBlock(nullptr), loop(nullptr)
- {
- }
- public:
- bool HasAnyInfo() const
- {
- return CompatibleBoundCheckBlock() || Loop();
- }
- BasicBlock *CompatibleBoundCheckBlock() const
- {
- Assert(!(compatibleBoundCheckBlock && loop));
- return compatibleBoundCheckBlock;
- }
- Loop *Loop() const
- {
- Assert(!(compatibleBoundCheckBlock && loop));
- return loop;
- }
- StackSym *IndexSym() const
- {
- Assert(HasAnyInfo());
- return indexSym;
- }
- int Offset() const
- {
- Assert(HasAnyInfo());
- return offset;
- }
- int32 IndexOffset() const
- {
- Assert(HasAnyInfo());
- return indexOffset;
- }
- void UpdateOffset(int newOffset)
- {
- Assert(HasAnyInfo());
- offset = newOffset;
- }
- ValueNumber IndexValueNumber() const
- {
- Assert(HasAnyInfo());
- Assert(IndexSym());
- return indexValueNumber;
- }
- Value *IndexValue() const
- {
- Assert(Loop());
- return indexValue;
- }
- const IntConstantBounds &IndexConstantBounds() const
- {
- Assert(Loop() || CompatibleBoundCheckBlock() && !IndexSym());
- return indexConstantBounds;
- }
- bool IsLoopCountBasedBound() const
- {
- Assert(Loop());
- return isLoopCountBasedBound;
- }
- LoopCount *LoopCount() const
- {
- Assert(Loop());
- return loopCount;
- }
- int MaxMagnitudeChange() const
- {
- Assert(LoopCount());
- return maxMagnitudeChange;
- }
- public:
- void SetCompatibleBoundCheck(BasicBlock *const compatibleBoundCheckBlock, StackSym *const indexSym, const int offset, const ValueNumber indexValueNumber);
- void SetLoop(::Loop *const loop, const int indexConstantValue, const bool isLoopCountBasedBound = false);
- void SetLoop(::Loop *const loop, StackSym *const indexSym, const int indexOffset, const int offset, Value *const indexValue, const IntConstantBounds &indexConstantBounds, const bool isLoopCountBasedBound = false);
- void SetLoopCount(::LoopCount *const loopCount, const int maxMagnitudeChange);
- };
- class GlobOpt::ArrayUpperBoundCheckHoistInfo : protected ArrayLowerBoundCheckHoistInfo
- {
- private:
- typedef ArrayLowerBoundCheckHoistInfo Base;
- private:
- // Info populated for hoisting out of loop
- Value *headSegmentLengthValue;
- IntConstantBounds headSegmentLengthConstantBounds;
- public:
- using Base::HasAnyInfo;
- using Base::CompatibleBoundCheckBlock;
- using Base::Loop;
- using Base::IndexSym;
- using Base::IndexOffset;
- using Base::Offset;
- using Base::UpdateOffset;
- using Base::IndexValueNumber;
- using Base::IndexValue;
- using Base::IndexConstantBounds;
- using Base::IsLoopCountBasedBound;
- using Base::LoopCount;
- using Base::MaxMagnitudeChange;
- public:
- Value *HeadSegmentLengthValue() const
- {
- Assert(Loop());
- return headSegmentLengthValue;
- }
- const IntConstantBounds &HeadSegmentLengthConstantBounds() const
- {
- Assert(Loop());
- return headSegmentLengthConstantBounds;
- }
- public:
- using Base::SetCompatibleBoundCheck;
- using Base::SetLoopCount;
- protected:
- using Base::SetLoop;
- public:
- void SetCompatibleBoundCheck(BasicBlock *const compatibleBoundCheckBlock, const int indexConstantValue);
- void SetLoop(::Loop *const loop, const int indexConstantValue, Value *const headSegmentLengthValue, const IntConstantBounds &headSegmentLengthConstantBounds, const bool isLoopCountBasedBound = false);
- void SetLoop(::Loop *const loop, StackSym *const indexSym, const int indexOffset, const int offset, Value *const indexValue, const IntConstantBounds &indexConstantBounds, Value *const headSegmentLengthValue, const IntConstantBounds &headSegmentLengthConstantBounds, const bool isLoopCountBasedBound = false);
- };
|