Skip to content

Commit a4e5654

Browse files
wyrichtepleath
authored andcommitted
1 parent 64376de commit a4e5654

File tree

1 file changed

+52
-13
lines changed

1 file changed

+52
-13
lines changed

lib/Backend/GlobOpt.cpp

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,27 +2161,46 @@ GlobOpt::CollectMemOpInfo(IR::Instr *instrBegin, IR::Instr *instr, Value *src1Va
21612161
return false;
21622162
}
21632163
break;
2164-
case Js::OpCode::Decr_A:
2165-
isIncr = false;
2166-
case Js::OpCode::Incr_A:
2167-
isChangedByOne = true;
2168-
goto MemOpCheckInductionVariable;
21692164
case Js::OpCode::Sub_I4:
2170-
case Js::OpCode::Sub_A:
21712165
isIncr = false;
2172-
case Js::OpCode::Add_A:
21732166
case Js::OpCode::Add_I4:
21742167
{
2175-
MemOpCheckInductionVariable:
2176-
StackSym *sym = instr->GetSrc1()->GetStackSym();
2177-
if (!sym)
2168+
// The only case in which these OpCodes can contribute to an inductionVariableChangeInfo
2169+
// is when the induction variable is being modified and overwritten aswell (ex: j = j + 1)
2170+
// and not when the induction variable is modified but not overwritten (ex: k = j + 1).
2171+
// This can either be detected in IR as
2172+
// s1 = Add_I4 s1 1 // Case #1, can be seen with "j++".
2173+
// or as
2174+
// s4(s2) = Add_I4 s3(s1) 1 // Case #2, can be see with "j = j + 1".
2175+
// s1 = Ld_A s2
2176+
bool isInductionVar = false;
2177+
IR::Instr* nextInstr = instr->m_next;
2178+
if (
2179+
// Checks for Case #1 and Case #2
2180+
instr->GetDst()->GetStackSym() != nullptr &&
2181+
instr->GetDst()->IsRegOpnd() &&
2182+
(
2183+
// Checks for Case #1
2184+
(instr->GetDst()->GetStackSym() == instr->GetSrc1()->GetStackSym()) ||
2185+
2186+
// Checks for Case #2
2187+
(nextInstr&& nextInstr->m_opcode == Js::OpCode::Ld_A &&
2188+
nextInstr->GetSrc1()->IsRegOpnd() &&
2189+
nextInstr->GetDst()->IsRegOpnd() &&
2190+
GetVarSymID(instr->GetDst()->GetStackSym()) == nextInstr->GetSrc1()->GetStackSym()->m_id &&
2191+
GetVarSymID(instr->GetSrc1()->GetStackSym()) == nextInstr->GetDst()->GetStackSym()->m_id)
2192+
)
2193+
)
21782194
{
2179-
sym = instr->GetSrc2()->GetStackSym();
2195+
isInductionVar = true;
21802196
}
2197+
2198+
// Even if dstIsInductionVar then dst == src1 so it's safe to use src1 as the induction sym always.
2199+
StackSym* sym = instr->GetSrc1()->GetStackSym();
21812200

21822201
SymID inductionSymID = GetVarSymID(sym);
21832202

2184-
if (IsSymIDInductionVariable(inductionSymID, this->currentBlock->loop))
2203+
if (isInductionVar && IsSymIDInductionVariable(inductionSymID, this->currentBlock->loop))
21852204
{
21862205
if (!isChangedByOne)
21872206
{
@@ -2246,7 +2265,6 @@ GlobOpt::CollectMemOpInfo(IR::Instr *instrBegin, IR::Instr *instr, Value *src1Va
22462265
{
22472266
inductionVariableChangeInfo.unroll++;
22482267
}
2249-
22502268
inductionVariableChangeInfo.isIncremental = isIncr;
22512269
loop->memOpInfo->inductionVariableChangeInfoMap->Item(inductionSymID, inductionVariableChangeInfo);
22522270
}
@@ -2284,6 +2302,27 @@ GlobOpt::CollectMemOpInfo(IR::Instr *instrBegin, IR::Instr *instr, Value *src1Va
22842302
}
22852303
}
22862304
NEXT_INSTR_IN_RANGE;
2305+
IR::Instr* prevInstr = instr->m_prev;
2306+
2307+
// If an instr where the dst is an induction variable (and thus is being written to) is not caught by a case in the above
2308+
// switch statement (which implies that this instr does not contributes to a inductionVariableChangeInfo) and in the default
2309+
// case does not set doMemOp to false (which implies that this instr does not invalidate this MemOp), then FailFast as we
2310+
// should not be performing a MemOp under these conditions.
2311+
AssertOrFailFast(!instr->GetDst() || instr->m_opcode == Js::OpCode::IncrLoopBodyCount || !loop->memOpInfo ||
2312+
2313+
// Refer to "Case #2" described above in this function. For the following IR:
2314+
// Line #1: s4(s2) = Add_I4 s3(s1) 1
2315+
// Line #2: s3(s1) = Ld_A s4(s2)
2316+
// do not consider line #2 as a violating instr
2317+
(instr->m_opcode == Js::OpCode::Ld_I4 &&
2318+
prevInstr && (prevInstr->m_opcode == Js::OpCode::Add_I4 || prevInstr->m_opcode == Js::OpCode::Sub_I4) &&
2319+
instr->GetSrc1()->IsRegOpnd() &&
2320+
instr->GetDst()->IsRegOpnd() &&
2321+
prevInstr->GetDst()->IsRegOpnd() &&
2322+
instr->GetDst()->GetStackSym() == prevInstr->GetSrc1()->GetStackSym() &&
2323+
instr->GetSrc1()->GetStackSym() == prevInstr->GetDst()->GetStackSym()) ||
2324+
2325+
!loop->memOpInfo->inductionVariableChangeInfoMap->ContainsKey(GetVarSymID(instr->GetDst()->GetStackSym())));
22872326
}
22882327

22892328
return true;

0 commit comments

Comments
 (0)