| //------------------------------------------------------------------------------------------------------- |
| // Copyright (C) Microsoft. All rights reserved. |
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. |
| //------------------------------------------------------------------------------------------------------- |
| #include "Backend.h" |
| |
| const int InductionVariable::ChangeMagnitudeLimitForLoopCountBasedHoisting = 64 << 10; |
| |
| InductionVariable::InductionVariable() |
| #if DBG |
| : sym(nullptr) |
| #endif |
| { |
| Assert(!IsValid()); |
| } |
| |
| InductionVariable::InductionVariable(StackSym *const sym, const ValueNumber symValueNumber, const int change) |
| : sym(sym), symValueNumber(symValueNumber), changeBounds(change, change), isChangeDeterminate(true) |
| { |
| Assert(sym); |
| Assert(!sym->IsTypeSpec()); |
| Assert(IsValid()); |
| } |
| |
| #if DBG |
| |
| bool InductionVariable::IsValid() const |
| { |
| return !!sym; |
| } |
| |
| #endif |
| |
| StackSym *InductionVariable::Sym() const |
| { |
| Assert(IsValid()); |
| return sym; |
| } |
| |
| ValueNumber InductionVariable::SymValueNumber() const |
| { |
| Assert(IsChangeDeterminate()); |
| return symValueNumber; |
| } |
| |
| void InductionVariable::SetSymValueNumber(const ValueNumber symValueNumber) |
| { |
| Assert(IsChangeDeterminate()); |
| this->symValueNumber = symValueNumber; |
| } |
| |
| bool InductionVariable::IsChangeDeterminate() const |
| { |
| Assert(IsValid()); |
| return isChangeDeterminate; |
| } |
| |
| void InductionVariable::SetChangeIsIndeterminate() |
| { |
| Assert(IsValid()); |
| isChangeDeterminate = false; |
| } |
| |
| const IntConstantBounds &InductionVariable::ChangeBounds() const |
| { |
| Assert(IsChangeDeterminate()); |
| return changeBounds; |
| } |
| |
| bool InductionVariable::IsChangeUnidirectional() const |
| { |
| return |
| (ChangeBounds().LowerBound() >= 0 && ChangeBounds().UpperBound() != 0) || |
| (ChangeBounds().UpperBound() <= 0 && ChangeBounds().LowerBound() != 0); |
| } |
| |
| bool InductionVariable::Add(const int n) |
| { |
| Assert(IsChangeDeterminate()); |
| |
| if(n == 0) |
| return true; |
| |
| int newLowerBound; |
| if(changeBounds.LowerBound() == IntConstMin) |
| { |
| if(n >= 0) |
| { |
| isChangeDeterminate = false; |
| return false; |
| } |
| newLowerBound = IntConstMin; |
| } |
| else if(changeBounds.LowerBound() == IntConstMax) |
| { |
| if(n < 0) |
| { |
| isChangeDeterminate = false; |
| return false; |
| } |
| newLowerBound = IntConstMax; |
| } |
| else if(Int32Math::Add(changeBounds.LowerBound(), n, &newLowerBound)) |
| newLowerBound = n < 0 ? IntConstMin : IntConstMax; |
| |
| int newUpperBound; |
| if(changeBounds.UpperBound() == IntConstMin) |
| { |
| if(n >= 0) |
| { |
| isChangeDeterminate = false; |
| return false; |
| } |
| newUpperBound = IntConstMin; |
| } |
| else if(changeBounds.UpperBound() == IntConstMax) |
| { |
| if(n < 0) |
| { |
| isChangeDeterminate = false; |
| return false; |
| } |
| newUpperBound = IntConstMax; |
| } |
| else if(Int32Math::Add(changeBounds.UpperBound(), n, &newUpperBound)) |
| newUpperBound = n < 0 ? IntConstMin : IntConstMax; |
| |
| changeBounds = IntConstantBounds(newLowerBound, newUpperBound); |
| return true; |
| } |
| |
| void InductionVariable::ExpandInnerLoopChange() |
| { |
| Assert(IsValid()); |
| |
| if(!isChangeDeterminate) |
| return; |
| |
| changeBounds = |
| IntConstantBounds( |
| changeBounds.LowerBound() < 0 ? IntConstMin : changeBounds.LowerBound(), |
| changeBounds.UpperBound() > 0 ? IntConstMax : changeBounds.UpperBound()); |
| } |
| |
| void InductionVariable::Merge(const InductionVariable &other) |
| { |
| Assert(Sym() == other.Sym()); |
| // The value number may be different, the caller will give the merged info the appropriate value number |
| |
| isChangeDeterminate &= other.isChangeDeterminate; |
| if(!isChangeDeterminate) |
| return; |
| |
| changeBounds = |
| IntConstantBounds( |
| min(changeBounds.LowerBound(), other.changeBounds.LowerBound()), |
| max(changeBounds.UpperBound(), other.changeBounds.UpperBound())); |
| } |