66
77using namespace libscratchcpp ;
88
9+ static const std::unordered_set<LLVMInstruction::Type>
10+ BEGIN_LOOP_INSTRUCTIONS = { LLVMInstruction::Type::BeginRepeatLoop, LLVMInstruction::Type::BeginWhileLoop, LLVMInstruction::Type::BeginRepeatUntilLoop };
11+
912bool LLVMLoopAnalyzer::variableTypeChanges (LLVMVariablePtr *varPtr, LLVMInstruction *loopBody, Compiler::StaticType preLoopType) const
1013{
1114 if (!varPtr || !loopBody)
@@ -14,23 +17,80 @@ bool LLVMLoopAnalyzer::variableTypeChanges(LLVMVariablePtr *varPtr, LLVMInstruct
1417 if (preLoopType == Compiler::StaticType::Unknown)
1518 return true ;
1619
17- // Find the last write instruction
18- LLVMInstruction *lastVarWrite = nullptr ;
19- LLVMInstruction *ins = loopBody ;
20+ // Find loop end
21+ LLVMInstruction *ins = loopBody-> next ;
22+ int loopLevel = 0 ;
2023
21- while (ins && ins->type != LLVMInstruction::Type::EndLoop) {
22- // TODO: Handle nested loops
23- if (ins->type == LLVMInstruction::Type::WriteVariable && ins->workVariable == varPtr->var )
24- lastVarWrite = ins;
24+ while (ins && !(isLoopEnd (ins) && loopLevel == 0 )) {
25+ if (isLoopStart (ins))
26+ loopLevel++;
27+ else if (isLoopEnd (ins)) {
28+ assert (loopLevel > 0 );
29+ loopLevel--;
30+ }
2531
2632 ins = ins->next ;
2733 }
2834
2935 // Loops must always have an end instruction
30- assert (ins);
36+ if (!ins) {
37+ assert (false );
38+ return true ;
39+ }
3140
32- // Check the last write instruction, if any
33- return lastVarWrite ? !typesMatch (lastVarWrite, preLoopType) : false ;
41+ return variableTypeChangesFromEnd (varPtr, ins, preLoopType);
42+ }
43+
44+ bool LLVMLoopAnalyzer::variableTypeChangesFromEnd (LLVMVariablePtr *varPtr, LLVMInstruction *loopEnd, Compiler::StaticType preLoopType) const
45+ {
46+ // Find the last write instruction
47+ LLVMInstruction *ins = loopEnd->previous ;
48+
49+ while (ins && !isLoopStart (ins)) {
50+ if (isLoopEnd (ins)) {
51+ // Nested loop
52+ if (variableTypeChangesFromEnd (varPtr, ins, preLoopType))
53+ return true ;
54+
55+ // Skip the loop
56+ int loopLevel = 0 ;
57+ ins = ins->previous ;
58+
59+ while (ins && !(isLoopStart (ins) && loopLevel == 0 )) {
60+ if (isLoopStart (ins)) {
61+ assert (loopLevel > 0 );
62+ loopLevel--;
63+ }
64+
65+ if (isLoopEnd (ins))
66+ loopLevel++;
67+
68+ ins = ins->previous ;
69+ };
70+
71+ if (!ins) {
72+ assert (false );
73+ return true ;
74+ }
75+ } else if (ins->type == LLVMInstruction::Type::WriteVariable && ins->workVariable == varPtr->var ) {
76+ // Variable write instruction
77+ return !typesMatch (ins, preLoopType);
78+ }
79+
80+ ins = ins->previous ;
81+ }
82+
83+ return false ;
84+ }
85+
86+ bool LLVMLoopAnalyzer::isLoopStart (LLVMInstruction *ins) const
87+ {
88+ return (BEGIN_LOOP_INSTRUCTIONS.find (ins->type ) != BEGIN_LOOP_INSTRUCTIONS.cend ());
89+ }
90+
91+ bool LLVMLoopAnalyzer::isLoopEnd (LLVMInstruction *ins) const
92+ {
93+ return (ins->type == LLVMInstruction::Type::EndLoop);
3494}
3595
3696Compiler::StaticType LLVMLoopAnalyzer::optimizeRegisterType (LLVMRegister *reg) const
0 commit comments