@@ -78,6 +78,7 @@ void GlobOpt::ArrayLowerBoundCheckHoistInfo::SetLoop(
7878void GlobOpt::ArrayLowerBoundCheckHoistInfo::SetLoop (
7979 ::Loop *const loop,
8080 StackSym *const indexSym,
81+ const int indexOffset,
8182 const int offset,
8283 Value *const indexValue,
8384 const IntConstantBounds &indexConstantBounds,
@@ -91,6 +92,7 @@ void GlobOpt::ArrayLowerBoundCheckHoistInfo::SetLoop(
9192
9293 this ->loop = loop;
9394 this ->indexSym = indexSym;
95+ this ->indexOffset = indexOffset;
9496 this ->offset = offset;
9597 this ->indexValueNumber = indexValue->GetValueNumber ();
9698 this ->indexValue = indexValue;
@@ -142,6 +144,7 @@ void GlobOpt::ArrayUpperBoundCheckHoistInfo::SetLoop(
142144void GlobOpt::ArrayUpperBoundCheckHoistInfo::SetLoop (
143145 ::Loop *const loop,
144146 StackSym *const indexSym,
147+ const int indexOffset,
145148 const int offset,
146149 Value *const indexValue,
147150 const IntConstantBounds &indexConstantBounds,
@@ -151,7 +154,7 @@ void GlobOpt::ArrayUpperBoundCheckHoistInfo::SetLoop(
151154{
152155 Assert (headSegmentLengthValue);
153156
154- SetLoop (loop, indexSym, offset, indexValue, indexConstantBounds, isLoopCountBasedBound);
157+ SetLoop (loop, indexSym, indexOffset, offset, indexValue, indexConstantBounds, isLoopCountBasedBound);
155158 this ->headSegmentLengthValue = headSegmentLengthValue;
156159 this ->headSegmentLengthConstantBounds = headSegmentLengthConstantBounds;
157160}
@@ -1831,8 +1834,9 @@ void GlobOpt::GenerateLoopCountPlusOne(Loop *const loop, LoopCount *const loopCo
18311834void GlobOpt::GenerateSecondaryInductionVariableBound (
18321835 Loop *const loop,
18331836 StackSym *const inductionVariableSym,
1834- const LoopCount *const loopCount,
1837+ LoopCount *const loopCount,
18351838 const int maxMagnitudeChange,
1839+ const bool needsMagnitudeAdjustment,
18361840 StackSym *const boundSym)
18371841{
18381842 Assert (loop);
@@ -1857,18 +1861,33 @@ void GlobOpt::GenerateSecondaryInductionVariableBound(
18571861 Assert (insertBeforeInstr);
18581862 Func *const func = bailOutInfo->bailOutFunc ;
18591863
1864+ StackSym* loopCountSym = nullptr ;
1865+
1866+ // If indexOffset < maxMagnitudeChange, we need to account for the difference between them in the bound check
1867+ // i.e. BoundCheck: inductionVariable + loopCountMinusOne * maxMagnitudeChange + maxMagnitudeChange - indexOffset <= length - offset
1868+ // Since the BoundCheck instruction already deals with offset, we can simplify this to
1869+ // BoundCheck: inductionVariable + loopCount * maxMagnitudeChange <= length + indexOffset - offset
1870+ if (needsMagnitudeAdjustment)
1871+ {
1872+ GenerateLoopCountPlusOne (loop, loopCount);
1873+ loopCountSym = loopCount->LoopCountSym ();
1874+ }
1875+ else
1876+ {
1877+ loopCountSym = loopCount->LoopCountMinusOneSym ();
1878+ }
18601879 // intermediateValue = loopCount * maxMagnitudeChange
18611880 StackSym *intermediateValueSym;
18621881 if (maxMagnitudeChange == 1 || maxMagnitudeChange == -1 )
18631882 {
1864- intermediateValueSym = loopCount-> LoopCountMinusOneSym () ;
1883+ intermediateValueSym = loopCountSym ;
18651884 }
18661885 else
18671886 {
18681887 IR::BailOutInstr *const instr = IR::BailOutInstr::New (Js::OpCode::Mul_I4, bailOutKind, bailOutInfo, func);
18691888
18701889 instr->SetSrc1 (
1871- IR::RegOpnd::New (loopCount-> LoopCountMinusOneSym (), loopCount-> LoopCountMinusOneSym () ->GetType (), func));
1890+ IR::RegOpnd::New (loopCountSym, loopCountSym ->GetType (), func));
18721891 instr->GetSrc1 ()->SetIsJITOptimizedReg (true );
18731892
18741893 instr->SetSrc2 (IR::IntConstOpnd::New (maxMagnitudeChange, TyInt32, func, true ));
@@ -2418,6 +2437,7 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
24182437 loop,
24192438 indexSym,
24202439 lowerOffset,
2440+ lowerOffset,
24212441 landingPadIndexValue,
24222442 landingPadIndexConstantBounds);
24232443 }
@@ -2469,11 +2489,13 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
24692489 // Normalize the offset such that:
24702490 // boundBase <= headSegmentLength + offset
24712491 // Where (offset = -1 - boundOffset), and -1 is to simulate < instead of <=.
2492+ int indexOffset = upperOffset;
24722493 upperOffset = -1 - upperOffset;
24732494
24742495 upperHoistInfo.SetLoop (
24752496 loop,
24762497 indexSym,
2498+ indexOffset,
24772499 upperOffset,
24782500 landingPadIndexValue,
24792501 landingPadIndexConstantBounds,
@@ -2619,6 +2641,7 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
26192641 loop,
26202642 indexBoundBaseSym,
26212643 offset,
2644+ offset,
26222645 landingPadIndexBoundBaseValue,
26232646 landingPadIndexBoundBaseConstantBounds);
26242647 break ;
@@ -2643,11 +2666,13 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
26432666 // Normalize the offset such that:
26442667 // boundBase <= headSegmentLength + offset
26452668 // Where (offset = -1 - boundOffset), and -1 is to simulate < instead of <=.
2669+ int indexOffset = offset;
26462670 offset = -1 - offset;
26472671
26482672 upperHoistInfo.SetLoop (
26492673 loop,
26502674 indexBoundBaseSym,
2675+ indexOffset,
26512676 offset,
26522677 landingPadIndexBoundBaseValue,
26532678 landingPadIndexBoundBaseConstantBounds,
@@ -3139,6 +3164,7 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
31393164 lowerHoistInfo.SetLoop (
31403165 currentLoop,
31413166 indexLoopCountBasedBoundBaseSym,
3167+ indexOffset,
31423168 offset,
31433169 indexLoopCountBasedBoundBaseValue,
31443170 indexLoopCountBasedBoundBaseConstantBounds,
@@ -3153,6 +3179,7 @@ void GlobOpt::DetermineArrayBoundCheckHoistability(
31533179 upperHoistInfo.SetLoop (
31543180 currentLoop,
31553181 indexLoopCountBasedBoundBaseSym,
3182+ indexOffset,
31563183 offset,
31573184 indexLoopCountBasedBoundBaseValue,
31583185 indexLoopCountBasedBoundBaseConstantBounds,
0 commit comments