@@ -40,7 +40,7 @@ Compiler::StaticType LLVMTypeAnalyzer::variableType(LLVMVariablePtr *varPtr, LLV
4040
4141 if (loopStart) {
4242 // Analyze the first loop that was found
43- if (variableTypeChangesInLoop (varPtr, loopStart, previousType))
43+ if (variableTypeChangesInBranch (varPtr, loopStart, previousType))
4444 return write ? writeValueType (write) : Compiler::StaticType::Unknown;
4545 } else if (write) {
4646 // There wasn't any loop found, so we can just check the last write operation
@@ -51,65 +51,56 @@ Compiler::StaticType LLVMTypeAnalyzer::variableType(LLVMVariablePtr *varPtr, LLV
5151 return previousType;
5252}
5353
54- bool LLVMTypeAnalyzer::variableTypeChangesInLoop (LLVMVariablePtr *varPtr, LLVMInstruction *loopBody, Compiler::StaticType preLoopType) const
54+ bool LLVMTypeAnalyzer::variableTypeChangesInBranch (LLVMVariablePtr *varPtr, LLVMInstruction *loopBody, Compiler::StaticType preLoopType) const
5555{
5656 if (!varPtr || !loopBody)
5757 return false ;
5858
59- // Find loop end
59+ assert (isLoopStart (loopBody) || isIfStart (loopBody) || isElse (loopBody));
60+
61+ // Find loop/if statement end or else branch
6062 LLVMInstruction *ins = loopBody->next ;
61- int loopLevel = 0 ;
62-
63- while (ins && !(isLoopEnd (ins) && loopLevel == 0 )) {
64- if (isLoopStart (ins))
65- loopLevel ++;
66- else if (isLoopEnd (ins)) {
67- assert (loopLevel > 0 );
68- loopLevel --;
63+ int level = 0 ;
64+
65+ while (ins && !(( isLoopEnd (ins) || isIfEnd (ins) || isElse (ins)) && level == 0 )) {
66+ if (isLoopStart (ins) || isIfStart (ins) )
67+ level ++;
68+ else if (isLoopEnd (ins) || isIfEnd (ins) ) {
69+ assert (level > 0 );
70+ level --;
6971 }
7072
7173 ins = ins->next ;
7274 }
7375
74- // Loops must always have an end instruction
7576 if (!ins) {
7677 assert (false );
7778 return true ;
7879 }
7980
80- return variableTypeChangesInLoopFromEnd (varPtr, ins, preLoopType);
81+ // Process the branch from end
82+ return variableTypeChangesInBranchFromEnd (varPtr, ins, preLoopType);
8183}
8284
83- bool LLVMTypeAnalyzer::variableTypeChangesInLoopFromEnd (LLVMVariablePtr *varPtr, LLVMInstruction *loopEnd, Compiler::StaticType preLoopType) const
85+ bool LLVMTypeAnalyzer::variableTypeChangesInBranchFromEnd (LLVMVariablePtr *varPtr, LLVMInstruction *loopEnd, Compiler::StaticType preLoopType) const
8486{
8587 // Find the last write instruction
8688 LLVMInstruction *ins = loopEnd->previous ;
8789
88- while (ins && !isLoopStart (ins)) {
90+ while (ins && !isLoopStart (ins) && ! isIfStart (ins) ) {
8991 if (isLoopEnd (ins) || isIfEnd (ins) || isElse (ins)) {
90- // Nested loop or if statement
91- if (variableTypeChangesInLoopFromEnd (varPtr, ins, preLoopType))
92+ // Process the nested loop or if statement
93+ if (variableTypeChangesInBranchFromEnd (varPtr, ins, preLoopType))
9294 return true ;
9395
94- // Skip the loop or if statement
95- int level = 0 ;
96- ins = ins->previous ;
97-
98- while (ins && !((isLoopStart (ins) || isIfStart (ins) || isElse (ins)) && level == 0 )) {
99- if (isLoopStart (ins) || isIfStart (ins)) {
100- assert (level > 0 );
101- level--;
102- }
96+ ins = skipBranch (ins);
10397
104- if (isLoopEnd (ins) || isIfEnd (ins) || isElse (ins))
105- level++;
98+ if (isElse (ins)) {
99+ // Process if branch (the else branch is already processed)
100+ if (variableTypeChangesInBranchFromEnd (varPtr, ins, preLoopType))
101+ return true ;
106102
107- ins = ins->previous ;
108- };
109-
110- if (!ins) {
111- assert (false );
112- return true ;
103+ ins = skipBranch (ins);
113104 }
114105 } else if (ins->type == LLVMInstruction::Type::WriteVariable && ins->workVariable == varPtr->var ) {
115106 // Variable write instruction
@@ -122,6 +113,31 @@ bool LLVMTypeAnalyzer::variableTypeChangesInLoopFromEnd(LLVMVariablePtr *varPtr,
122113 return false ;
123114}
124115
116+ LLVMInstruction *LLVMTypeAnalyzer::skipBranch (LLVMInstruction *pos) const
117+ {
118+ int level = 0 ;
119+ pos = pos->previous ;
120+
121+ while (pos && !((isLoopStart (pos) || isIfStart (pos)) && level == 0 )) {
122+ if (isLoopStart (pos) || isIfStart (pos)) {
123+ assert (level > 0 );
124+ level--;
125+ }
126+
127+ if (isLoopEnd (pos) || isIfEnd (pos) || isElse (pos)) {
128+ if (isElse (pos) && level == 0 )
129+ break ;
130+
131+ level++;
132+ }
133+
134+ pos = pos->previous ;
135+ };
136+
137+ assert (pos);
138+ return pos;
139+ }
140+
125141bool LLVMTypeAnalyzer::isLoopStart (LLVMInstruction *ins) const
126142{
127143 return (BEGIN_LOOP_INSTRUCTIONS.find (ins->type ) != BEGIN_LOOP_INSTRUCTIONS.cend ());
0 commit comments