@@ -2161,27 +2161,46 @@ GlobOpt::CollectMemOpInfo(IR::Instr *instrBegin, IR::Instr *instr, Value *src1Va
2161
2161
return false;
2162
2162
}
2163
2163
break;
2164
- case Js::OpCode::Decr_A:
2165
- isIncr = false;
2166
- case Js::OpCode::Incr_A:
2167
- isChangedByOne = true;
2168
- goto MemOpCheckInductionVariable;
2169
2164
case Js::OpCode::Sub_I4:
2170
- case Js::OpCode::Sub_A:
2171
2165
isIncr = false;
2172
- case Js::OpCode::Add_A:
2173
2166
case Js::OpCode::Add_I4:
2174
2167
{
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
+ )
2178
2194
{
2179
- sym = instr->GetSrc2()->GetStackSym() ;
2195
+ isInductionVar = true ;
2180
2196
}
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();
2181
2200
2182
2201
SymID inductionSymID = GetVarSymID(sym);
2183
2202
2184
- if (IsSymIDInductionVariable(inductionSymID, this->currentBlock->loop))
2203
+ if (isInductionVar && IsSymIDInductionVariable(inductionSymID, this->currentBlock->loop))
2185
2204
{
2186
2205
if (!isChangedByOne)
2187
2206
{
@@ -2246,7 +2265,6 @@ GlobOpt::CollectMemOpInfo(IR::Instr *instrBegin, IR::Instr *instr, Value *src1Va
2246
2265
{
2247
2266
inductionVariableChangeInfo.unroll++;
2248
2267
}
2249
-
2250
2268
inductionVariableChangeInfo.isIncremental = isIncr;
2251
2269
loop->memOpInfo->inductionVariableChangeInfoMap->Item(inductionSymID, inductionVariableChangeInfo);
2252
2270
}
@@ -2284,6 +2302,27 @@ GlobOpt::CollectMemOpInfo(IR::Instr *instrBegin, IR::Instr *instr, Value *src1Va
2284
2302
}
2285
2303
}
2286
2304
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())));
2287
2326
}
2288
2327
2289
2328
return true;
0 commit comments