@@ -647,6 +647,128 @@ TEST(LLVMLoopAnalyzer_VariableTypeChanges, MultipleWritesBoolToStringNumberOptim
647647 ASSERT_TRUE (analyzer.variableTypeChanges (&varPtr, start.get (), Compiler::StaticType::Bool));
648648}
649649
650+ TEST (LLVMLoopAnalyzer_VariableTypeChanges, TypeChangeInIfBranch)
651+ {
652+ LLVMLoopAnalyzer analyzer;
653+ LLVMInstructionList list;
654+ LLVMVariablePtr varPtr;
655+ Variable var (" " , " " );
656+ varPtr.var = &var;
657+
658+ auto start = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginRepeatLoop, nullptr , false );
659+ list.addInstruction (start);
660+
661+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr , false );
662+ list.addInstruction (ifStart);
663+
664+ // First write - changes type
665+ auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
666+ LLVMConstantRegister value1 (Compiler::StaticType::String, " test" );
667+ setVar1->workVariable = &var;
668+ setVar1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
669+ list.addInstruction (setVar1);
670+
671+ auto elseStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginElse, nullptr , false );
672+ list.addInstruction (elseStart);
673+
674+ // Second write - does not change type
675+ auto setVar2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
676+ LLVMConstantRegister value2 (Compiler::StaticType::Number, 42 );
677+ setVar2->workVariable = &var;
678+ setVar2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
679+ list.addInstruction (setVar2);
680+
681+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr , false );
682+ list.addInstruction (ifEnd);
683+
684+ auto end = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndLoop, nullptr , false );
685+ list.addInstruction (end);
686+
687+ // Returns true because the type-changing branch might run
688+ ASSERT_TRUE (analyzer.variableTypeChanges (&varPtr, start.get (), Compiler::StaticType::Number));
689+ }
690+
691+ TEST (LLVMLoopAnalyzer_VariableTypeChanges, TypeChangeInElseBranch)
692+ {
693+ LLVMLoopAnalyzer analyzer;
694+ LLVMInstructionList list;
695+ LLVMVariablePtr varPtr;
696+ Variable var (" " , " " );
697+ varPtr.var = &var;
698+
699+ auto start = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginRepeatLoop, nullptr , false );
700+ list.addInstruction (start);
701+
702+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr , false );
703+ list.addInstruction (ifStart);
704+
705+ // First write - does not change type
706+ auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
707+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 42 );
708+ setVar1->workVariable = &var;
709+ setVar1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
710+ list.addInstruction (setVar1);
711+
712+ auto elseStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginElse, nullptr , false );
713+ list.addInstruction (elseStart);
714+
715+ // Second write - changes type
716+ auto setVar2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
717+ LLVMConstantRegister value2 (Compiler::StaticType::String, " test" );
718+ setVar2->workVariable = &var;
719+ setVar2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
720+ list.addInstruction (setVar2);
721+
722+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr , false );
723+ list.addInstruction (ifEnd);
724+
725+ auto end = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndLoop, nullptr , false );
726+ list.addInstruction (end);
727+
728+ // Returns true because the type-changing branch might run
729+ ASSERT_TRUE (analyzer.variableTypeChanges (&varPtr, start.get (), Compiler::StaticType::Number));
730+ }
731+
732+ TEST (LLVMLoopAnalyzer_VariableTypeChanges, IfElseWithoutTypeChange)
733+ {
734+ LLVMLoopAnalyzer analyzer;
735+ LLVMInstructionList list;
736+ LLVMVariablePtr varPtr;
737+ Variable var (" " , " " );
738+ varPtr.var = &var;
739+
740+ auto start = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginRepeatLoop, nullptr , false );
741+ list.addInstruction (start);
742+
743+ auto ifStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginIf, nullptr , false );
744+ list.addInstruction (ifStart);
745+
746+ // First write - does not change type
747+ auto setVar1 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
748+ LLVMConstantRegister value1 (Compiler::StaticType::Number, 42 );
749+ setVar1->workVariable = &var;
750+ setVar1->args .push_back ({ Compiler::StaticType::Unknown, &value1 });
751+ list.addInstruction (setVar1);
752+
753+ auto elseStart = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::BeginElse, nullptr , false );
754+ list.addInstruction (elseStart);
755+
756+ // Second write - does not change type
757+ auto setVar2 = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::WriteVariable, nullptr , false );
758+ LLVMConstantRegister value2 (Compiler::StaticType::Number, 1.25 );
759+ setVar2->workVariable = &var;
760+ setVar2->args .push_back ({ Compiler::StaticType::Unknown, &value2 });
761+ list.addInstruction (setVar2);
762+
763+ auto ifEnd = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndIf, nullptr , false );
764+ list.addInstruction (ifEnd);
765+
766+ auto end = std::make_shared<LLVMInstruction>(LLVMInstruction::Type::EndLoop, nullptr , false );
767+ list.addInstruction (end);
768+
769+ ASSERT_FALSE (analyzer.variableTypeChanges (&varPtr, start.get (), Compiler::StaticType::Number));
770+ }
771+
650772TEST (LLVMLoopAnalyzer_VariableTypeChanges, NestedLoopWithTypeChange)
651773{
652774 LLVMLoopAnalyzer analyzer;
0 commit comments