Browse Source

feat: temp commit

Shellmiao 5 days ago
parent
commit
bcf50102eb

+ 4 - 1
Scripts/ModuleFusionScript.sh

@@ -4,4 +4,7 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 # 切换到项目根目录
 cd "$SCRIPT_DIR/.."
 
-opt -load ./build/ModuleFusion.so -codefusion < proprocess_output/combined_tagged.ll > output/module_fusion.ll 2> output/log_module_fusion.txt
+opt -load ./build/ModuleFusion.so -codefusion < proprocess_output/combined_tagged.ll > output/module_fusion.bc 2> output/log_module_fusion.txt
+
+llvm-dis output/module_fusion.bc -o output/module_fusion_text.ll
+llvm-cbe output/module_fusion_text.ll

BIN
build/ModuleFusion.so


+ 934 - 69
output/log_module_fusion.txt

@@ -1206,73 +1206,12 @@ graph TD
 [INFO][countFusionPoints] Counted 2 fusion points for bunker function validateMatrix
 [INFO][matchFunctionsForFusion] Starting function matching process
 [INFO][matchFunctionsForFusion] Matched target longestIncreasingSubsequence (4 slices) with bunker projectA_main (7 fusion points)
-[INFO][matchFunctionsForFusion] Remaining bunker functions after matching longestIncreasingSubsequence:
-[INFO][matchFunctionsForFusion]     calculateCircleArea (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     calculateDistance (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     createDynamicArray (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     createMatrix (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     factorial (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     findCentroid (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     getErrorMessage (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     insertNode (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     multiplyMatrices (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     projectA_main (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     pushBack (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     quickSort (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     removeDuplicates (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     setErrorMessage (Critical Points: 3)
-[INFO][matchFunctionsForFusion]     validateMatrix (Critical Points: 2)
 [INFO][matchFunctionsForFusion] Matched target projectB_main (3 slices) with bunker setErrorMessage (3 fusion points)
-[INFO][matchFunctionsForFusion] Remaining bunker functions after matching projectB_main:
-[INFO][matchFunctionsForFusion]     calculateCircleArea (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     createDynamicArray (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     createMatrix (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     factorial (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     findCentroid (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     insertNode (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     projectA_main (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     quickSort (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     removeDuplicates (Critical Points: 2)
 [INFO][matchFunctionsForFusion] Matched target countSetBits (2 slices) with bunker removeDuplicates (2 fusion points)
-[INFO][matchFunctionsForFusion] Remaining bunker functions after matching countSetBits:
-[INFO][matchFunctionsForFusion]     calculateCircleArea (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     createDynamicArray (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     createMatrix (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     factorial (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     findCentroid (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     insertNode (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     projectA_main (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     removeDuplicates (Critical Points: 2)
 [INFO][matchFunctionsForFusion] Matched target processMatrix (2 slices) with bunker createMatrix (2 fusion points)
-[INFO][matchFunctionsForFusion] Remaining bunker functions after matching processMatrix:
-[INFO][matchFunctionsForFusion]     calculateCircleArea (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     createMatrix (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     factorial (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     findCentroid (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     insertNode (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     projectA_main (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     removeDuplicates (Critical Points: 2)
 [INFO][matchFunctionsForFusion] Matched target reverseString (2 slices) with bunker factorial (2 fusion points)
-[INFO][matchFunctionsForFusion] Remaining bunker functions after matching reverseString:
-[INFO][matchFunctionsForFusion]     calculateCircleArea (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     factorial (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     findCentroid (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     insertNode (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     projectA_main (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     removeDuplicates (Critical Points: 2)
 [INFO][matchFunctionsForFusion] Matched target testPoints (2 slices) with bunker matchFunctionsFo (2 fusion points)
-[INFO][matchFunctionsForFusion] Remaining bunker functions after matching testPoints:
-[INFO][matchFunctionsForFusion]     calculateCircleArea (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     factorial (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     findCentroid (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     insertNode (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     projectA_main (Critical Points: 2)
-[INFO][matchFunctionsForFusion] Matched target memoizedFib (1 slices) with bunker  ñ‘‹ (2 fusion points)
-[INFO][matchFunctionsForFusion] Remaining bunker functions after matching memoizedFib:
-[INFO][matchFunctionsForFusion]     calculateCircleArea (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     factorial (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     findCentroid (Critical Points: 2)
-[INFO][matchFunctionsForFusion]     insertNode (Critical Points: 2)
+[INFO][matchFunctionsForFusion] Matched target memoizedFib (1 slices) with bunker ÐRk< e< (2 fusion points)
 [INFO][generateFusionMatchGraph] Generating fusion match visualization
 ```mermaid
 graph LR
@@ -1281,13 +1220,13 @@ graph LR
 
     subgraph Target["Target Project"]
         direction TB
-        countSetBits["countSetBits\nCritical Points: 3"]:::target
-        longestIncreasingSubsequence["longestIncreasingSubsequence\nCritical Points: 7"]:::target
-        memoizedFib["memoizedFib\nCritical Points: 2"]:::target
-        processMatrix["processMatrix\nCritical Points: 3"]:::target
-        projectB_main["projectB_main\nCritical Points: 5"]:::target
-        reverseString["reverseString\nCritical Points: 3"]:::target
-        testPoints["testPoints\nCritical Points: 3"]:::target
+        countSetBits["countSetBits\nSliceNum: 2"]:::target
+        longestIncreasingSubsequence["longestIncreasingSubsequence\nSliceNum: 4"]:::target
+        memoizedFib["memoizedFib\nSliceNum: 1"]:::target
+        processMatrix["processMatrix\nSliceNum: 2"]:::target
+        projectB_main["projectB_main\nSliceNum: 3"]:::target
+        reverseString["reverseString\nSliceNum: 2"]:::target
+        testPoints["testPoints\nSliceNum: 2"]:::target
     end
 
     subgraph Bunker["Bunker Project"]
@@ -1327,3 +1266,929 @@ graph LR
 
 [INFO][generateFusionMatchGraph] Generated visualization with 7 target functions and 16 bunker functions
 [INFO][generateFusionMatchGraph] Total fusion matches: 7
+[INFO][performCodeFusion] Starting code fusion
+[INFO][performCodeFusion] Processing function pair: target=countSetBits, bunker=quickSort
+[DEBUG][performCodeFusion] Processing return values for fused function: fused_quickSort
+[DEBUG][performCodeFusion] Fused function return type: i32
+[DEBUG][performCodeFusion] Non-struct return type detected: i32
+[DEBUG][performCodeFusion] Updated bunker return in block %264 with value type i32
+[DEBUG][performCodeFusion] Updated target return in block %262 with value type i32
+[DEBUG][updateCallSite] Original call instruction:
+    call void @quickSort(i32* %237, i32 %239, i32 %240, i32* %241)
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32*
+[DEBUG][updateCallSite]   Argument 1: type=i32
+[DEBUG][updateCallSite]   Argument 2: type=i32
+[DEBUG][updateCallSite]   Argument 3: type=i32*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite] New call instruction:
+    %242 = call i32 @fused_quickSort(i1 false, i32* %237, i32 %239, i32 %240, i32* %241, i32 0)
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @quickSort(i32* %237, i32 %239, i32 %240, i32* %241) to   %242 = call i32 @fused_quickSort(i1 false, i32* %237, i32 %239, i32 %240, i32* %241, i32 0)
+[DEBUG][updateCallSite] Original call instruction:
+    call void @quickSort(i32* %226, i32 %227, i32 %228, i32* %229)
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32*
+[DEBUG][updateCallSite]   Argument 1: type=i32
+[DEBUG][updateCallSite]   Argument 2: type=i32
+[DEBUG][updateCallSite]   Argument 3: type=i32*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite] New call instruction:
+    %230 = call i32 @fused_quickSort(i1 false, i32* %226, i32 %227, i32 %228, i32* %229, i32 0)
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @quickSort(i32* %226, i32 %227, i32 %228, i32* %229) to   %230 = call i32 @fused_quickSort(i1 false, i32* %226, i32 %227, i32 %228, i32* %229, i32 0)
+[DEBUG][updateCallSite] Original call instruction:
+    call void @quickSort(i32* %23, i32 0, i32 %27, i32* %3)
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32*
+[DEBUG][updateCallSite]   Argument 1: type=i32
+[DEBUG][updateCallSite]   Argument 2: type=i32
+[DEBUG][updateCallSite]   Argument 3: type=i32*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite] New call instruction:
+    %28 = call i32 @fused_quickSort(i1 false, i32* %23, i32 0, i32 %27, i32* %3, i32 0)
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @quickSort(i32* %23, i32 0, i32 %27, i32* %3) to   %28 = call i32 @fused_quickSort(i1 false, i32* %23, i32 0, i32 %27, i32* %3, i32 0)
+[DEBUG][updateCallSite] Original call instruction:
+    call void @quickSort(i32* %232, i32 %234, i32 %235, i32* %236)
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32*
+[DEBUG][updateCallSite]   Argument 1: type=i32
+[DEBUG][updateCallSite]   Argument 2: type=i32
+[DEBUG][updateCallSite]   Argument 3: type=i32*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite] New call instruction:
+    %237 = call i32 @fused_quickSort(i1 false, i32* %232, i32 %234, i32 %235, i32* %236, i32 0)
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @quickSort(i32* %232, i32 %234, i32 %235, i32* %236) to   %237 = call i32 @fused_quickSort(i1 false, i32* %232, i32 %234, i32 %235, i32* %236, i32 0)
+[DEBUG][updateCallSite] Original call instruction:
+    call void @quickSort(i32* %221, i32 %222, i32 %223, i32* %224)
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32*
+[DEBUG][updateCallSite]   Argument 1: type=i32
+[DEBUG][updateCallSite]   Argument 2: type=i32
+[DEBUG][updateCallSite]   Argument 3: type=i32*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite] New call instruction:
+    %225 = call i32 @fused_quickSort(i1 false, i32* %221, i32 %222, i32 %223, i32* %224, i32 0)
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @quickSort(i32* %221, i32 %222, i32 %223, i32* %224) to   %225 = call i32 @fused_quickSort(i1 false, i32* %221, i32 %222, i32 %223, i32* %224, i32 0)
+[DEBUG][updateCallSite] Original call instruction:
+    %38 = call i32 @countSetBits(i32 %37)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite]   Parameter type: i32*
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite]   Parameter type: i32*
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite] New call instruction:
+    %38 = call i32 @fused_quickSort(i1 true, i32* null, i32 0, i32 0, i32* null, i32 %37)
+[DEBUG][updateCallSite] Processing non-void return value of type: i32
+[DEBUG][updateCallSite] Using direct return value
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %38 = call i32 @countSetBits(i32 %37) to   %38 = call i32 @fused_quickSort(i1 true, i32* null, i32 0, i32 0, i32* null, i32 %37)
+[DEBUG][updateCallSite] Original call instruction:
+    %68 = call i32 @countSetBits(i32 %67)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite]   Parameter type: i32*
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite]   Parameter type: i32*
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite] New call instruction:
+    %68 = call i32 @fused_quickSort(i1 true, i32* null, i32 0, i32 0, i32* null, i32 %67)
+[DEBUG][updateCallSite] Processing non-void return value of type: i32
+[DEBUG][updateCallSite] Using direct return value
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %68 = call i32 @countSetBits(i32 %67) to   %68 = call i32 @fused_quickSort(i1 true, i32* null, i32 0, i32 0, i32* null, i32 %67)
+[INFO][performCodeFusion] Listing all return instructions in fused function: fused_quickSort
+[INFO][performCodeFusion] Return instruction in block :
+    ret i32 %265
+[INFO][performCodeFusion]   Return value type: i32
+[INFO][performCodeFusion] Return instruction in block :
+    ret i32 0
+[INFO][performCodeFusion]   Return value type: i32
+[INFO][performCodeFusion] Completed function fusion: fused_quickSort
+[INFO][performCodeFusion] Processing function pair: target=longestIncreasingSubsequence, bunker=performSimpleCalculations
+[DEBUG][performCodeFusion] Processing return values for fused function: fused_performSimpleCalculations
+[DEBUG][performCodeFusion] Fused function return type: i32
+[DEBUG][performCodeFusion] Non-struct return type detected: i32
+[DEBUG][performCodeFusion] Updated bunker return in block %159 with value type i32
+[DEBUG][performCodeFusion] Updated target return in block %121 with value type i32
+[DEBUG][updateCallSite] Original call instruction:
+    call void @performSimpleCalculations()
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite]   Parameter type: i32*
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite] New call instruction:
+    %322 = call i32 @fused_performSimpleCalculations(i1 false, i32* null, i32 0)
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @performSimpleCalculations() to   %322 = call i32 @fused_performSimpleCalculations(i1 false, i32* null, i32 0)
+[DEBUG][updateCallSite] Original call instruction:
+    %15 = call i32 @longestIncreasingSubsequence(i32* %13, i32 %14)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32*
+[DEBUG][updateCallSite]   Argument 1: type=i32
+[DEBUG][updateCallSite] New call instruction:
+    %15 = call i32 @fused_performSimpleCalculations(i1 true, i32* %13, i32 %14)
+[DEBUG][updateCallSite] Processing non-void return value of type: i32
+[DEBUG][updateCallSite] Using direct return value
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %15 = call i32 @longestIncreasingSubsequence(i32* %13, i32 %14) to   %15 = call i32 @fused_performSimpleCalculations(i1 true, i32* %13, i32 %14)
+[INFO][performCodeFusion] Listing all return instructions in fused function: fused_performSimpleCalculations
+[INFO][performCodeFusion] Return instruction in block :
+    ret i32 %122
+[INFO][performCodeFusion]   Return value type: i32
+[INFO][performCodeFusion] Return instruction in block :
+    ret i32 0
+[INFO][performCodeFusion]   Return value type: i32
+[INFO][performCodeFusion] Completed function fusion: fused_performSimpleCalculations
+[INFO][performCodeFusion] Processing function pair: target=memoizedFib, bunker=projectA_main
+[DEBUG][performCodeFusion] Processing return values for fused function: fused_projectA_main
+[DEBUG][performCodeFusion] Fused function return type: fused_return_projectA_main_memoizedFib
+[DEBUG][performCodeFusion] Processing struct return type with 2 elements
+[DEBUG][performCodeFusion] Setting default target return value
+[DEBUG][performCodeFusion] Target type is integer type, setting to 0
+[DEBUG][performCodeFusion] Created struct return for bunker block: %360 with types: target=i32, bunker=i32
+[DEBUG][performCodeFusion] Created struct return for target block: %18 with types: target=i32, bunker=i32
+[DEBUG][updateCallSite] Original call instruction:
+    %29 = call i32 @memoizedFib(i32 %28)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite] New call instruction:
+    %29 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %28)
+[DEBUG][updateCallSite] Processing non-void return value of type: i32
+[DEBUG][updateCallSite] Extracting value from struct return type
+[DEBUG][updateCallSite] Extracted value type: i32
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %29 = call i32 @memoizedFib(i32 %28) to   %29 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %28)
+[DEBUG][updateCallSite] Original call instruction:
+    %26 = call i32 @memoizedFib(i32 %25)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite] New call instruction:
+    %26 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %25)
+[DEBUG][updateCallSite] Processing non-void return value of type: i32
+[DEBUG][updateCallSite] Extracting value from struct return type
+[DEBUG][updateCallSite] Extracted value type: i32
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %26 = call i32 @memoizedFib(i32 %25) to   %26 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %25)
+[DEBUG][updateCallSite] Original call instruction:
+    %35 = call i32 @memoizedFib(i32 %34)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite] New call instruction:
+    %35 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %34)
+[DEBUG][updateCallSite] Processing non-void return value of type: i32
+[DEBUG][updateCallSite] Extracting value from struct return type
+[DEBUG][updateCallSite] Extracted value type: i32
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %35 = call i32 @memoizedFib(i32 %34) to   %35 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %34)
+[DEBUG][updateCallSite] Original call instruction:
+    %21 = call i32 @memoizedFib(i32 %20)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite] New call instruction:
+    %21 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %20)
+[DEBUG][updateCallSite] Processing non-void return value of type: i32
+[DEBUG][updateCallSite] Extracting value from struct return type
+[DEBUG][updateCallSite] Extracted value type: i32
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %21 = call i32 @memoizedFib(i32 %20) to   %21 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %20)
+[DEBUG][updateCallSite] Original call instruction:
+    %25 = call i32 @memoizedFib(i32 %24)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite] New call instruction:
+    %25 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %24)
+[DEBUG][updateCallSite] Processing non-void return value of type: i32
+[DEBUG][updateCallSite] Extracting value from struct return type
+[DEBUG][updateCallSite] Extracted value type: i32
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %25 = call i32 @memoizedFib(i32 %24) to   %25 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %24)
+[DEBUG][updateCallSite] Original call instruction:
+    %22 = call i32 @memoizedFib(i32 %21)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite] New call instruction:
+    %22 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %21)
+[DEBUG][updateCallSite] Processing non-void return value of type: i32
+[DEBUG][updateCallSite] Extracting value from struct return type
+[DEBUG][updateCallSite] Extracted value type: i32
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %22 = call i32 @memoizedFib(i32 %21) to   %22 = call %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1 true, i32 %21)
+[INFO][performCodeFusion] Listing all return instructions in fused function: fused_projectA_main
+[INFO][performCodeFusion] Return instruction in block :
+    ret %fused_return_projectA_main_memoizedFib %20
+[INFO][performCodeFusion]   Return value type: fused_return_projectA_main_memoizedFib
+[INFO][performCodeFusion] Return instruction in block :
+    ret %fused_return_projectA_main_memoizedFib %363
+[INFO][performCodeFusion]   Return value type: fused_return_projectA_main_memoizedFib
+[INFO][performCodeFusion] Completed function fusion: fused_projectA_main
+[INFO][performCodeFusion] Processing function pair: target=processMatrix, bunker=createDynamicArray
+[DEBUG][performCodeFusion] Processing return values for fused function: fused_createDynamicArray
+[DEBUG][performCodeFusion] Fused function return type: fused_return_createDynamicArray_processMatrix
+[DEBUG][performCodeFusion] Processing struct return type with 2 elements
+[DEBUG][performCodeFusion] Setting default target return value
+[DEBUG][performCodeFusion] Target type is integer type, setting to 0
+[DEBUG][performCodeFusion] Created struct return for bunker block: %127 with types: target=i32, bunker=struct.DynamicArray*
+[DEBUG][performCodeFusion] Created struct return for target block: %58 with types: target=i32, bunker=struct.DynamicArray*
+[DEBUG][updateCallSite] Original call instruction:
+    %60 = call %struct.DynamicArray* @createDynamicArray(i32 10)
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite]   Parameter type: array of i32*
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite] New call instruction:
+    %60 = call %fused_return_createDynamicArray_processMatrix @fused_createDynamicArray(i1 false, i32 10, [100 x i32]* null, i32 0)
+[DEBUG][updateCallSite] Processing non-void return value of type: struct.DynamicArray*
+[DEBUG][updateCallSite] Extracting value from struct return type
+[DEBUG][updateCallSite] Extracted value type: struct.DynamicArray*
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %60 = call %struct.DynamicArray* @createDynamicArray(i32 10) to   %60 = call %fused_return_createDynamicArray_processMatrix @fused_createDynamicArray(i1 false, i32 10, [100 x i32]* null, i32 0)
+[DEBUG][updateCallSite] Original call instruction:
+    %18 = call i32 @processMatrix([100 x i32]* %17, i32 3)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=array of i32*
+[DEBUG][updateCallSite]   Argument 1: type=i32
+[DEBUG][updateCallSite] New call instruction:
+    %18 = call %fused_return_createDynamicArray_processMatrix @fused_createDynamicArray(i1 true, i32 0, [100 x i32]* %17, i32 3)
+[DEBUG][updateCallSite] Processing non-void return value of type: i32
+[DEBUG][updateCallSite] Extracting value from struct return type
+[DEBUG][updateCallSite] Extracted value type: i32
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %18 = call i32 @processMatrix([100 x i32]* %17, i32 3) to   %18 = call %fused_return_createDynamicArray_processMatrix @fused_createDynamicArray(i1 true, i32 0, [100 x i32]* %17, i32 3)
+[INFO][performCodeFusion] Listing all return instructions in fused function: fused_createDynamicArray
+[INFO][performCodeFusion] Return instruction in block :
+    ret %fused_return_createDynamicArray_processMatrix %60
+[INFO][performCodeFusion]   Return value type: fused_return_createDynamicArray_processMatrix
+[INFO][performCodeFusion] Return instruction in block :
+    ret %fused_return_createDynamicArray_processMatrix %130
+[INFO][performCodeFusion]   Return value type: fused_return_createDynamicArray_processMatrix
+[INFO][performCodeFusion] Completed function fusion: fused_createDynamicArray
+[INFO][performCodeFusion] Processing function pair: target=projectB_main, bunker=setErrorMessage
+[DEBUG][performCodeFusion] Processing return values for fused function: fused_setErrorMessage
+[DEBUG][performCodeFusion] Fused function return type: i32
+[DEBUG][performCodeFusion] Non-struct return type detected: i32
+[DEBUG][performCodeFusion] Updated bunker return in block %70 with value type i32
+[DEBUG][performCodeFusion] Updated target return in block %67 with value type i32
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([35 x i8], [35 x i8]* @.str.9, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %42 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([35 x i8], [35 x i8]* @.str.9, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([35 x i8], [35 x i8]* @.str.9, i64 0, i64 0)) to   %42 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([35 x i8], [35 x i8]* @.str.9, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([49 x i8], [49 x i8]* @.str.8, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %27 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([49 x i8], [49 x i8]* @.str.8, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([49 x i8], [49 x i8]* @.str.8, i64 0, i64 0)) to   %27 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([49 x i8], [49 x i8]* @.str.8, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.6, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %17 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.6, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.6, i64 0, i64 0)) to   %17 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.6, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.7, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %22 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.7, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.7, i64 0, i64 0)) to   %22 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.7, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.31, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %317 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.31, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.31, i64 0, i64 0)) to   %317 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.31, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.15, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %47 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.15, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.15, i64 0, i64 0)) to   %47 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.15, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.14, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %31 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.14, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.14, i64 0, i64 0)) to   %31 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.14, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.13, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %24 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.13, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.13, i64 0, i64 0)) to   %24 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.13, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.55, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %139 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.55, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.55, i64 0, i64 0)) to   %139 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.55, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.54, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %128 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.54, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.54, i64 0, i64 0)) to   %128 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.54, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.53, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %48 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.53, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.53, i64 0, i64 0)) to   %48 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.53, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.52, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %33 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.52, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.52, i64 0, i64 0)) to   %33 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.52, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.51, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %26 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.51, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.51, i64 0, i64 0)) to   %26 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.51, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.50, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %21 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.50, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.50, i64 0, i64 0)) to   %21 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.50, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.49, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %14 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.49, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.49, i64 0, i64 0)) to   %14 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.49, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.48, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %71 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.48, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.48, i64 0, i64 0)) to   %71 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.48, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.47, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %53 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.47, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.47, i64 0, i64 0)) to   %53 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.47, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.46, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %36 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.46, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.46, i64 0, i64 0)) to   %36 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.46, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.16, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %25 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.16, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.16, i64 0, i64 0)) to   %25 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.16, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.45, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %14 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.45, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.45, i64 0, i64 0)) to   %14 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.45, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.21, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %8 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.21, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.21, i64 0, i64 0)) to   %8 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.21, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.44, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %85 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.44, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.44, i64 0, i64 0)) to   %85 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.44, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([35 x i8], [35 x i8]* @.str.43, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %77 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([35 x i8], [35 x i8]* @.str.43, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([35 x i8], [35 x i8]* @.str.43, i64 0, i64 0)) to   %77 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([35 x i8], [35 x i8]* @.str.43, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str.40, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %58 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str.40, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str.40, i64 0, i64 0)) to   %58 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str.40, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([45 x i8], [45 x i8]* @.str.39, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %38 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([45 x i8], [45 x i8]* @.str.39, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([45 x i8], [45 x i8]* @.str.39, i64 0, i64 0)) to   %38 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([45 x i8], [45 x i8]* @.str.39, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str.38, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %24 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str.38, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str.38, i64 0, i64 0)) to   %24 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str.38, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.37, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %18 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.37, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.37, i64 0, i64 0)) to   %18 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.37, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.36, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %12 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.36, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.36, i64 0, i64 0)) to   %12 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.36, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.35, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %99 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.35, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.35, i64 0, i64 0)) to   %99 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.35, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.34, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %77 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.34, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.34, i64 0, i64 0)) to   %77 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.34, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.33, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %41 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.33, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.33, i64 0, i64 0)) to   %41 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.33, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.32, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %19 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.32, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.32, i64 0, i64 0)) to   %19 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.32, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([34 x i8], [34 x i8]* @.str.26, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %55 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([34 x i8], [34 x i8]* @.str.26, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([34 x i8], [34 x i8]* @.str.26, i64 0, i64 0)) to   %55 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([34 x i8], [34 x i8]* @.str.26, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([38 x i8], [38 x i8]* @.str.25, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %15 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([38 x i8], [38 x i8]* @.str.25, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([38 x i8], [38 x i8]* @.str.25, i64 0, i64 0)) to   %15 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([38 x i8], [38 x i8]* @.str.25, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([42 x i8], [42 x i8]* @.str.24, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %118 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([42 x i8], [42 x i8]* @.str.24, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([42 x i8], [42 x i8]* @.str.24, i64 0, i64 0)) to   %118 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([42 x i8], [42 x i8]* @.str.24, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.17, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %51 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.17, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.17, i64 0, i64 0)) to   %51 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.17, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([45 x i8], [45 x i8]* @.str.23, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %40 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([45 x i8], [45 x i8]* @.str.23, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([45 x i8], [45 x i8]* @.str.23, i64 0, i64 0)) to   %40 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([45 x i8], [45 x i8]* @.str.23, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.22, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %31 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.22, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.22, i64 0, i64 0)) to   %31 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.22, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.21, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %20 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.21, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.21, i64 0, i64 0)) to   %20 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.21, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([44 x i8], [44 x i8]* @.str.20, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %105 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([44 x i8], [44 x i8]* @.str.20, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([44 x i8], [44 x i8]* @.str.20, i64 0, i64 0)) to   %105 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([44 x i8], [44 x i8]* @.str.20, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([41 x i8], [41 x i8]* @.str.19, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %57 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([41 x i8], [41 x i8]* @.str.19, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([41 x i8], [41 x i8]* @.str.19, i64 0, i64 0)) to   %57 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([41 x i8], [41 x i8]* @.str.19, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.18, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %28 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.18, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.18, i64 0, i64 0)) to   %28 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.18, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.17, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %22 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.17, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.17, i64 0, i64 0)) to   %22 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.17, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.16, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %15 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.16, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.16, i64 0, i64 0)) to   %15 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.16, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.12, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %45 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.12, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.12, i64 0, i64 0)) to   %45 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.12, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.11, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %16 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.11, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.11, i64 0, i64 0)) to   %16 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.11, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.10, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %10 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.10, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.10, i64 0, i64 0)) to   %10 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.10, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.5, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %43 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.5, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.5, i64 0, i64 0)) to   %43 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.5, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.4, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %22 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.4, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.4, i64 0, i64 0)) to   %22 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.4, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str.3, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %16 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str.3, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str.3, i64 0, i64 0)) to   %16 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str.3, i64 0, i64 0))
+[DEBUG][updateCallSite] Original call instruction:
+    call void @setErrorMessage(i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str.2, i64 0, i64 0))
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite] New call instruction:
+    %10 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str.2, i64 0, i64 0))
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @setErrorMessage(i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str.2, i64 0, i64 0)) to   %10 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str.2, i64 0, i64 0))
+[INFO][performCodeFusion] Listing all return instructions in fused function: fused_setErrorMessage
+[INFO][performCodeFusion] Return instruction in block :
+    ret i32 %68
+[INFO][performCodeFusion]   Return value type: i32
+[INFO][performCodeFusion] Return instruction in block :
+    ret i32 0
+[INFO][performCodeFusion]   Return value type: i32
+[INFO][performCodeFusion] Completed function fusion: fused_setErrorMessage
+[INFO][performCodeFusion] Processing function pair: target=reverseString, bunker=createMatrix
+[DEBUG][performCodeFusion] Processing return values for fused function: fused_createMatrix
+[DEBUG][performCodeFusion] Fused function return type: struct.Matrix*
+[DEBUG][performCodeFusion] Non-struct return type detected: struct.Matrix*
+[DEBUG][performCodeFusion] Updated bunker return in block %161 with value type struct.Matrix*
+[DEBUG][performCodeFusion] Updated target return in block %157 with value type struct.Matrix*
+[DEBUG][updateCallSite] Original call instruction:
+    %85 = call %struct.Matrix* @createMatrix(i32 3, i32 3)
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite]   Argument 1: type=i32
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite]   Parameter type: i8*
+[DEBUG][updateCallSite] New call instruction:
+    %85 = call %struct.Matrix* @fused_createMatrix(i1 false, i32 3, i32 3, i8* null)
+[DEBUG][updateCallSite] Processing non-void return value of type: struct.Matrix*
+[DEBUG][updateCallSite] Using direct return value
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %85 = call %struct.Matrix* @createMatrix(i32 3, i32 3) to   %85 = call %struct.Matrix* @fused_createMatrix(i1 false, i32 3, i32 3, i8* null)
+[DEBUG][updateCallSite] Original call instruction:
+    %84 = call %struct.Matrix* @createMatrix(i32 3, i32 3)
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite]   Argument 1: type=i32
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite]   Parameter type: i8*
+[DEBUG][updateCallSite] New call instruction:
+    %84 = call %struct.Matrix* @fused_createMatrix(i1 false, i32 3, i32 3, i8* null)
+[DEBUG][updateCallSite] Processing non-void return value of type: struct.Matrix*
+[DEBUG][updateCallSite] Using direct return value
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %84 = call %struct.Matrix* @createMatrix(i32 3, i32 3) to   %84 = call %struct.Matrix* @fused_createMatrix(i1 false, i32 3, i32 3, i8* null)
+[DEBUG][updateCallSite] Original call instruction:
+    %62 = call %struct.Matrix* @createMatrix(i32 %58, i32 %61)
+[DEBUG][updateCallSite] Adding bunker control parameter
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite]   Argument 1: type=i32
+[DEBUG][updateCallSite] Adding default target parameters:
+[DEBUG][updateCallSite]   Parameter type: i8*
+[DEBUG][updateCallSite] New call instruction:
+    %62 = call %struct.Matrix* @fused_createMatrix(i1 false, i32 %58, i32 %61, i8* null)
+[DEBUG][updateCallSite] Processing non-void return value of type: struct.Matrix*
+[DEBUG][updateCallSite] Using direct return value
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %62 = call %struct.Matrix* @createMatrix(i32 %58, i32 %61) to   %62 = call %struct.Matrix* @fused_createMatrix(i1 false, i32 %58, i32 %61, i8* null)
+[DEBUG][updateCallSite] Original call instruction:
+    call void @reverseString(i8* %13)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite]   Parameter type: i32
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i8*
+[DEBUG][updateCallSite] New call instruction:
+    %14 = call %struct.Matrix* @fused_createMatrix(i1 true, i32 0, i32 0, i8* %13)
+[DEBUG][updateCallSite] Void return type, no value processing needed
+[INFO][updateCallSite] Successfully updated call site from   call void @reverseString(i8* %13) to   %14 = call %struct.Matrix* @fused_createMatrix(i1 true, i32 0, i32 0, i8* %13)
+[INFO][performCodeFusion] Listing all return instructions in fused function: fused_createMatrix
+[INFO][performCodeFusion] Return instruction in block :
+    ret %struct.Matrix* null
+[INFO][performCodeFusion]   Return value type: struct.Matrix*
+[INFO][performCodeFusion] Return instruction in block :
+    ret %struct.Matrix* %162
+[INFO][performCodeFusion]   Return value type: struct.Matrix*
+[INFO][performCodeFusion] Completed function fusion: fused_createMatrix
+[INFO][performCodeFusion] Processing function pair: target=testPoints, bunker=removeDuplicates
+[DEBUG][performCodeFusion] Processing return values for fused function: fused_removeDuplicates
+[DEBUG][performCodeFusion] Fused function return type: i32
+[DEBUG][performCodeFusion] Non-struct return type detected: i32
+[DEBUG][performCodeFusion] Updated bunker return in block %107 with value type i32
+[DEBUG][performCodeFusion] Updated target return in block %102 with value type i32
+[DEBUG][updateCallSite] Original call instruction:
+    %11 = call i32 @testPoints(i32 5)
+[DEBUG][updateCallSite] Adding target control parameter
+[DEBUG][updateCallSite] Adding default bunker parameters:
+[DEBUG][updateCallSite]   Parameter type: struct.DynamicArray*
+[DEBUG][updateCallSite] Adding original call parameters:
+[DEBUG][updateCallSite]   Argument 0: type=i32
+[DEBUG][updateCallSite] New call instruction:
+    %11 = call i32 @fused_removeDuplicates(i1 true, %struct.DynamicArray* null, i32 5)
+[DEBUG][updateCallSite] Processing non-void return value of type: i32
+[DEBUG][updateCallSite] Using direct return value
+[DEBUG][updateCallSite] Successfully replaced all uses of original call
+[INFO][updateCallSite] Successfully updated call site from   %11 = call i32 @testPoints(i32 5) to   %11 = call i32 @fused_removeDuplicates(i1 true, %struct.DynamicArray* null, i32 5)
+[INFO][performCodeFusion] Listing all return instructions in fused function: fused_removeDuplicates
+[INFO][performCodeFusion] Return instruction in block :
+    ret i32 %103
+[INFO][performCodeFusion]   Return value type: i32
+[INFO][performCodeFusion] Return instruction in block :
+    ret i32 0
+[INFO][performCodeFusion]   Return value type: i32
+[INFO][performCodeFusion] Completed function fusion: fused_removeDuplicates
+[INFO][performCodeFusion] Code fusion completed, processed 7 function pairs
+Invalid InsertValueInst operands!
+  %20 = insertvalue %fused_return_projectA_main_memoizedFib { i32 undef, i32 0 }, Stack dump:
+0.	Program arguments: opt -load ./build/ModuleFusion.so -codefusion 
+1.	Running pass 'Function Pass Manager' on module '<stdin>'.
+2.	Running pass 'Module Verifier' on function '@fused_projectA_main'
+#0 0x00007fb5e4a734ff llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0x9814ff)
+#1 0x00007fb5e4a717b0 llvm::sys::RunSignalHandlers() (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0x97f7b0)
+#2 0x00007fb5e4a73ac5 (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0x981ac5)
+#3 0x00007fb5e879a420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
+#4 0x00007fb5e4a7db82 (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0x98bb82)
+#5 0x000000003c6e1dd8 

+ 0 - 0
output/module_fusion.bc


BIN
output/module_fusion.ll


File diff suppressed because it is too large
+ 437 - 0
output/module_fusion_text.cbe.c


+ 1599 - 0
output/module_fusion_text.ll

@@ -0,0 +1,1599 @@
+; ModuleID = 'output/module_fusion.bc'
+source_filename = "llvm-link"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, %struct._IO_codecvt*, %struct._IO_wide_data*, %struct._IO_FILE*, i8*, i64, i32, [20 x i8] }
+%struct._IO_marker = type opaque
+%struct._IO_codecvt = type opaque
+%struct._IO_wide_data = type opaque
+%struct.DynamicArray = type { i32*, i32, i32, i32, i32 }
+%struct.Matrix = type { i32**, i32, i32, i32, double }
+%struct.Node = type { i32, %struct.Node*, %struct.Node*, i32, i32 }
+%struct.Point = type { i32, i32, [256 x i8], double }
+%struct.Circle = type { %struct.Point, double, i32, [256 x i8] }
+%fused_return_projectA_main_memoizedFib = type { i32, i32 }
+%fused_return_createDynamicArray_processMatrix = type { i32, %struct.DynamicArray* }
+
+@globalCounter = dso_local global i32 0, align 4
+@globalErrorMessage = dso_local global i8* null, align 8
+@recursionDepth = dso_local global i32 0, align 4
+@.str = private unnamed_addr constant [9 x i8] c"No error\00", align 1
+@stderr = external dso_local global %struct._IO_FILE*, align 8
+@.str.1 = private unnamed_addr constant [55 x i8] c"Critical: Failed to allocate memory for error message\0A\00", align 1
+@.str.2 = private unnamed_addr constant [33 x i8] c"Maximum recursion depth exceeded\00", align 1
+@.str.3 = private unnamed_addr constant [29 x i8] c"Factorial of negative number\00", align 1
+@.str.4 = private unnamed_addr constant [36 x i8] c"Input too large, potential overflow\00", align 1
+@.str.5 = private unnamed_addr constant [31 x i8] c"Factorial calculation overflow\00", align 1
+@.str.6 = private unnamed_addr constant [25 x i8] c"Invalid initial capacity\00", align 1
+@.str.7 = private unnamed_addr constant [46 x i8] c"Initial capacity exceeds maximum allowed size\00", align 1
+@.str.8 = private unnamed_addr constant [49 x i8] c"Memory allocation failed for DynamicArray struct\00", align 1
+@.str.9 = private unnamed_addr constant [35 x i8] c"Memory allocation failed for array\00", align 1
+@.str.10 = private unnamed_addr constant [19 x i8] c"Null array pointer\00", align 1
+@.str.11 = private unnamed_addr constant [25 x i8] c"Array size limit reached\00", align 1
+@.str.12 = private unnamed_addr constant [27 x i8] c"Memory reallocation failed\00", align 1
+@.str.13 = private unnamed_addr constant [46 x i8] c"Maximum recursion depth exceeded in quickSort\00", align 1
+@.str.14 = private unnamed_addr constant [32 x i8] c"Null array pointer in quickSort\00", align 1
+@.str.15 = private unnamed_addr constant [39 x i8] c"Array index out of bounds in quickSort\00", align 1
+@.str.16 = private unnamed_addr constant [28 x i8] c"Matrix dimensions too small\00", align 1
+@.str.17 = private unnamed_addr constant [46 x i8] c"Matrix dimensions exceed maximum allowed size\00", align 1
+@.str.18 = private unnamed_addr constant [43 x i8] c"Memory allocation failed for matrix struct\00", align 1
+@.str.19 = private unnamed_addr constant [41 x i8] c"Memory allocation failed for matrix rows\00", align 1
+@.str.20 = private unnamed_addr constant [44 x i8] c"Memory allocation failed for matrix columns\00", align 1
+@.str.21 = private unnamed_addr constant [20 x i8] c"Null matrix pointer\00", align 1
+@.str.22 = private unnamed_addr constant [20 x i8] c"Invalid matrix data\00", align 1
+@.str.23 = private unnamed_addr constant [45 x i8] c"Invalid matrix dimensions for multiplication\00", align 1
+@.str.24 = private unnamed_addr constant [42 x i8] c"Integer overflow in matrix multiplication\00", align 1
+@.str.25 = private unnamed_addr constant [38 x i8] c"Memory allocation failed for new node\00", align 1
+@insertNode.maxDepth = internal global i32 0, align 4
+@.str.26 = private unnamed_addr constant [34 x i8] c"List exceeds maximum allowed size\00", align 1
+@calculationResult = internal global i32 0, align 4
+@.str.27 = private unnamed_addr constant [30 x i8] c"Final calculation result: %d\0A\00", align 1
+@.str.28 = private unnamed_addr constant [11 x i8] c"Error: %s\0A\00", align 1
+@.str.29 = private unnamed_addr constant [29 x i8] c"Error during array push: %s\0A\00", align 1
+@.str.30 = private unnamed_addr constant [33 x i8] c"Error during list insertion: %s\0A\00", align 1
+@.str.31 = private unnamed_addr constant [43 x i8] c"Circular reference detected in linked list\00", align 1
+@.str.32 = private unnamed_addr constant [22 x i8] c"Invalid point weights\00", align 1
+@.str.33 = private unnamed_addr constant [31 x i8] c"Coordinates out of valid range\00", align 1
+@.str.34 = private unnamed_addr constant [30 x i8] c"Distance calculation overflow\00", align 1
+@.str.35 = private unnamed_addr constant [36 x i8] c"Invalid distance calculation result\00", align 1
+@.str.36 = private unnamed_addr constant [15 x i8] c"Invalid circle\00", align 1
+@.str.37 = private unnamed_addr constant [22 x i8] c"Invalid circle radius\00", align 1
+@.str.38 = private unnamed_addr constant [24 x i8] c"Circle radius too large\00", align 1
+@.str.39 = private unnamed_addr constant [45 x i8] c"Circle center coordinates out of valid range\00", align 1
+@.str.40 = private unnamed_addr constant [26 x i8] c"Area calculation overflow\00", align 1
+@.str.41 = private unnamed_addr constant [9 x i8] c"standard\00", align 1
+@.str.42 = private unnamed_addr constant [9 x i8] c"weighted\00", align 1
+@.str.43 = private unnamed_addr constant [35 x i8] c"Invalid weight for weighted circle\00", align 1
+@.str.44 = private unnamed_addr constant [20 x i8] c"Unknown circle type\00", align 1
+@.str.45 = private unnamed_addr constant [17 x i8] c"Null matrix data\00", align 1
+@.str.46 = private unnamed_addr constant [28 x i8] c"Matrix dimensions too large\00", align 1
+@.str.47 = private unnamed_addr constant [27 x i8] c"Invalid matrix row pointer\00", align 1
+@.str.48 = private unnamed_addr constant [32 x i8] c"Inconsistent square matrix flag\00", align 1
+@.str.49 = private unnamed_addr constant [14 x i8] c"Invalid array\00", align 1
+@.str.50 = private unnamed_addr constant [21 x i8] c"Invalid points array\00", align 1
+@.str.51 = private unnamed_addr constant [16 x i8] c"Too many points\00", align 1
+@.str.52 = private unnamed_addr constant [39 x i8] c"Failed to allocate memory for centroid\00", align 1
+@.str.53 = private unnamed_addr constant [21 x i8] c"Invalid point weight\00", align 1
+@.str.54 = private unnamed_addr constant [30 x i8] c"Centroid calculation overflow\00", align 1
+@.str.55 = private unnamed_addr constant [21 x i8] c"Total weight is zero\00", align 1
+@.str.56 = private unnamed_addr constant [9 x i8] c"Centroid\00", align 1
+@cache = internal global [100 x i32] zeroinitializer, align 16
+@__const.projectB_main.str = private unnamed_addr constant [14 x i8] c"Hello, World!\00", align 1
+@__const.projectB_main.arr = private unnamed_addr constant [8 x i32] [i32 10, i32 22, i32 9, i32 33, i32 21, i32 50, i32 41, i32 60], align 16
+@__const.projectB_main.matrix = private unnamed_addr constant <{ <{ i32, i32, i32, [97 x i32] }>, <{ i32, i32, i32, [97 x i32] }>, <{ i32, i32, i32, [97 x i32] }>, [97 x <{ i32, i32, i32, [97 x i32] }>] }> <{ <{ i32, i32, i32, [97 x i32] }> <{ i32 1, i32 2, i32 3, [97 x i32] zeroinitializer }>, <{ i32, i32, i32, [97 x i32] }> <{ i32 4, i32 5, i32 6, [97 x i32] zeroinitializer }>, <{ i32, i32, i32, [97 x i32] }> <{ i32 7, i32 8, i32 9, [97 x i32] zeroinitializer }>, [97 x <{ i32, i32, i32, [97 x i32] }>] zeroinitializer }>, align 16
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local i8* @getErrorMessage() #0 !project_source !2 {
+  %1 = load i8*, i8** @globalErrorMessage, align 8
+  %2 = icmp ne i8* %1, null
+  br i1 %2, label %3, label %5
+
+3:                                                ; preds = %0
+  %4 = load i8*, i8** @globalErrorMessage, align 8
+  br label %6
+
+5:                                                ; preds = %0
+  br label %6
+
+6:                                                ; preds = %5, %3
+  %7 = phi i8* [ %4, %3 ], [ getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i64 0, i64 0), %5 ]
+  ret i8* %7
+}
+
+; Function Attrs: nounwind
+declare dso_local void @free(i8*) #1
+
+; Function Attrs: nounwind
+declare dso_local noalias i8* @strdup(i8*) #1
+
+declare dso_local i32 @fprintf(%struct._IO_FILE*, i8*, ...) #2
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local i32 @factorial(i32 %0) #0 !project_source !2 {
+  %2 = alloca i32, align 4
+  %3 = alloca i32, align 4
+  %4 = alloca i32, align 4
+  %5 = alloca i32, align 4
+  store i32 %0, i32* %3, align 4
+  %6 = load i32, i32* @recursionDepth, align 4
+  %7 = add nsw i32 %6, 1
+  store i32 %7, i32* @recursionDepth, align 4
+  %8 = icmp sgt i32 %7, 1000
+  br i1 %8, label %9, label %13
+
+9:                                                ; preds = %1
+  %10 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str.2, i64 0, i64 0))
+  %11 = load i32, i32* @recursionDepth, align 4
+  %12 = add nsw i32 %11, -1
+  store i32 %12, i32* @recursionDepth, align 4
+  store i32 -1, i32* %2, align 4
+  br label %57
+
+13:                                               ; preds = %1
+  %14 = load i32, i32* %3, align 4
+  %15 = icmp slt i32 %14, 0
+  br i1 %15, label %16, label %20
+
+16:                                               ; preds = %13
+  %17 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str.3, i64 0, i64 0))
+  %18 = load i32, i32* @recursionDepth, align 4
+  %19 = add nsw i32 %18, -1
+  store i32 %19, i32* @recursionDepth, align 4
+  store i32 -1, i32* %2, align 4
+  br label %57
+
+20:                                               ; preds = %13
+  %21 = load i32, i32* %3, align 4
+  %22 = icmp sgt i32 %21, 20
+  br i1 %22, label %23, label %27
+
+23:                                               ; preds = %20
+  %24 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.4, i64 0, i64 0))
+  %25 = load i32, i32* @recursionDepth, align 4
+  %26 = add nsw i32 %25, -1
+  store i32 %26, i32* @recursionDepth, align 4
+  store i32 -1, i32* %2, align 4
+  br label %57
+
+27:                                               ; preds = %20
+  %28 = load i32, i32* %3, align 4
+  %29 = icmp sle i32 %28, 1
+  br i1 %29, label %30, label %31
+
+30:                                               ; preds = %27
+  store i32 1, i32* %4, align 4
+  br label %53
+
+31:                                               ; preds = %27
+  %32 = load i32, i32* %3, align 4
+  %33 = sub nsw i32 %32, 1
+  %34 = call i32 @factorial(i32 %33)
+  store i32 %34, i32* %5, align 4
+  %35 = load i32, i32* %5, align 4
+  %36 = icmp eq i32 %35, -1
+  br i1 %36, label %37, label %40
+
+37:                                               ; preds = %31
+  %38 = load i32, i32* @recursionDepth, align 4
+  %39 = add nsw i32 %38, -1
+  store i32 %39, i32* @recursionDepth, align 4
+  store i32 -1, i32* %2, align 4
+  br label %57
+
+40:                                               ; preds = %31
+  %41 = load i32, i32* %5, align 4
+  %42 = load i32, i32* %3, align 4
+  %43 = sdiv i32 2147483647, %42
+  %44 = icmp sgt i32 %41, %43
+  br i1 %44, label %45, label %49
+
+45:                                               ; preds = %40
+  %46 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.5, i64 0, i64 0))
+  %47 = load i32, i32* @recursionDepth, align 4
+  %48 = add nsw i32 %47, -1
+  store i32 %48, i32* @recursionDepth, align 4
+  store i32 -1, i32* %2, align 4
+  br label %57
+
+49:                                               ; preds = %40
+  %50 = load i32, i32* %3, align 4
+  %51 = load i32, i32* %5, align 4
+  %52 = mul nsw i32 %50, %51
+  store i32 %52, i32* %4, align 4
+  br label %53
+
+53:                                               ; preds = %49, %30
+  %54 = load i32, i32* @recursionDepth, align 4
+  %55 = add nsw i32 %54, -1
+  store i32 %55, i32* @recursionDepth, align 4
+  %56 = load i32, i32* %4, align 4
+  store i32 %56, i32* %2, align 4
+  br label %57
+
+57:                                               ; preds = %53, %45, %37, %23, %16, %9
+  %58 = load i32, i32* %2, align 4
+  ret i32 %58
+}
+
+; Function Attrs: nounwind
+declare dso_local noalias i8* @malloc(i64) #1
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local void @pushBack(%struct.DynamicArray* %0, i32 %1) #0 !project_source !2 {
+  %3 = alloca %struct.DynamicArray*, align 8
+  %4 = alloca i32, align 4
+  %5 = alloca i32, align 4
+  %6 = alloca i32*, align 8
+  store %struct.DynamicArray* %0, %struct.DynamicArray** %3, align 8
+  store i32 %1, i32* %4, align 4
+  %7 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %8 = icmp ne %struct.DynamicArray* %7, null
+  br i1 %8, label %11, label %9
+
+9:                                                ; preds = %2
+  %10 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.10, i64 0, i64 0))
+  br label %94
+
+11:                                               ; preds = %2
+  %12 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %13 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %12, i32 0, i32 1
+  %14 = load i32, i32* %13, align 8
+  %15 = icmp sge i32 %14, 1000
+  br i1 %15, label %16, label %18
+
+16:                                               ; preds = %11
+  %17 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.11, i64 0, i64 0))
+  br label %94
+
+18:                                               ; preds = %11
+  %19 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %20 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %19, i32 0, i32 1
+  %21 = load i32, i32* %20, align 8
+  %22 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %23 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %22, i32 0, i32 2
+  %24 = load i32, i32* %23, align 4
+  %25 = icmp sge i32 %21, %24
+  br i1 %25, label %26, label %55
+
+26:                                               ; preds = %18
+  %27 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %28 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %27, i32 0, i32 2
+  %29 = load i32, i32* %28, align 4
+  %30 = mul nsw i32 %29, 2
+  store i32 %30, i32* %5, align 4
+  %31 = load i32, i32* %5, align 4
+  %32 = icmp sgt i32 %31, 1000
+  br i1 %32, label %33, label %34
+
+33:                                               ; preds = %26
+  store i32 1000, i32* %5, align 4
+  br label %34
+
+34:                                               ; preds = %33, %26
+  %35 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %36 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %35, i32 0, i32 0
+  %37 = load i32*, i32** %36, align 8
+  %38 = bitcast i32* %37 to i8*
+  %39 = load i32, i32* %5, align 4
+  %40 = sext i32 %39 to i64
+  %41 = mul i64 4, %40
+  %42 = call i8* @realloc(i8* %38, i64 %41) #7
+  %43 = bitcast i8* %42 to i32*
+  store i32* %43, i32** %6, align 8
+  %44 = load i32*, i32** %6, align 8
+  %45 = icmp ne i32* %44, null
+  br i1 %45, label %48, label %46
+
+46:                                               ; preds = %34
+  %47 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.12, i64 0, i64 0))
+  br label %94
+
+48:                                               ; preds = %34
+  %49 = load i32*, i32** %6, align 8
+  %50 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %51 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %50, i32 0, i32 0
+  store i32* %49, i32** %51, align 8
+  %52 = load i32, i32* %5, align 4
+  %53 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %54 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %53, i32 0, i32 2
+  store i32 %52, i32* %54, align 4
+  br label %55
+
+55:                                               ; preds = %48, %18
+  %56 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %57 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %56, i32 0, i32 3
+  %58 = load i32, i32* %57, align 8
+  %59 = icmp ne i32 %58, 0
+  br i1 %59, label %60, label %81
+
+60:                                               ; preds = %55
+  %61 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %62 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %61, i32 0, i32 1
+  %63 = load i32, i32* %62, align 8
+  %64 = icmp sgt i32 %63, 0
+  br i1 %64, label %65, label %81
+
+65:                                               ; preds = %60
+  %66 = load i32, i32* %4, align 4
+  %67 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %68 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %67, i32 0, i32 0
+  %69 = load i32*, i32** %68, align 8
+  %70 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %71 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %70, i32 0, i32 1
+  %72 = load i32, i32* %71, align 8
+  %73 = sub nsw i32 %72, 1
+  %74 = sext i32 %73 to i64
+  %75 = getelementptr inbounds i32, i32* %69, i64 %74
+  %76 = load i32, i32* %75, align 4
+  %77 = icmp slt i32 %66, %76
+  br i1 %77, label %78, label %81
+
+78:                                               ; preds = %65
+  %79 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %80 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %79, i32 0, i32 3
+  store i32 0, i32* %80, align 8
+  br label %81
+
+81:                                               ; preds = %78, %65, %60, %55
+  %82 = load i32, i32* %4, align 4
+  %83 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %84 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %83, i32 0, i32 0
+  %85 = load i32*, i32** %84, align 8
+  %86 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %87 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %86, i32 0, i32 1
+  %88 = load i32, i32* %87, align 8
+  %89 = add nsw i32 %88, 1
+  store i32 %89, i32* %87, align 8
+  %90 = sext i32 %88 to i64
+  %91 = getelementptr inbounds i32, i32* %85, i64 %90
+  store i32 %82, i32* %91, align 4
+  %92 = load %struct.DynamicArray*, %struct.DynamicArray** %3, align 8
+  %93 = getelementptr inbounds %struct.DynamicArray, %struct.DynamicArray* %92, i32 0, i32 4
+  store i32 1, i32* %93, align 4
+  br label %94
+
+94:                                               ; preds = %81, %46, %16, %9
+  ret void
+}
+
+; Function Attrs: nounwind
+declare dso_local i8* @realloc(i8*, i64) #1
+
+; Function Attrs: nounwind
+declare dso_local noalias i8* @calloc(i64, i64) #1
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local %struct.Matrix* @multiplyMatrices(%struct.Matrix* %0, %struct.Matrix* %1) #0 !project_source !2 {
+  %3 = alloca %struct.Matrix*, align 8
+  %4 = alloca %struct.Matrix*, align 8
+  %5 = alloca %struct.Matrix*, align 8
+  %6 = alloca %struct.Matrix*, align 8
+  %7 = alloca i64, align 8
+  %8 = alloca i32, align 4
+  %9 = alloca i32, align 4
+  %10 = alloca i64, align 8
+  %11 = alloca i32, align 4
+  %12 = alloca i64, align 8
+  %13 = alloca i32, align 4
+  store %struct.Matrix* %0, %struct.Matrix** %4, align 8
+  store %struct.Matrix* %1, %struct.Matrix** %5, align 8
+  %14 = load %struct.Matrix*, %struct.Matrix** %4, align 8
+  %15 = icmp ne %struct.Matrix* %14, null
+  br i1 %15, label %16, label %19
+
+16:                                               ; preds = %2
+  %17 = load %struct.Matrix*, %struct.Matrix** %5, align 8
+  %18 = icmp ne %struct.Matrix* %17, null
+  br i1 %18, label %21, label %19
+
+19:                                               ; preds = %16, %2
+  %20 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.21, i64 0, i64 0))
+  store %struct.Matrix* null, %struct.Matrix** %3, align 8
+  br label %214
+
+21:                                               ; preds = %16
+  %22 = load %struct.Matrix*, %struct.Matrix** %4, align 8
+  %23 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %22, i32 0, i32 0
+  %24 = load i32**, i32*** %23, align 8
+  %25 = icmp ne i32** %24, null
+  br i1 %25, label %26, label %31
+
+26:                                               ; preds = %21
+  %27 = load %struct.Matrix*, %struct.Matrix** %5, align 8
+  %28 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %27, i32 0, i32 0
+  %29 = load i32**, i32*** %28, align 8
+  %30 = icmp ne i32** %29, null
+  br i1 %30, label %33, label %31
+
+31:                                               ; preds = %26, %21
+  %32 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.22, i64 0, i64 0))
+  store %struct.Matrix* null, %struct.Matrix** %3, align 8
+  br label %214
+
+33:                                               ; preds = %26
+  %34 = load %struct.Matrix*, %struct.Matrix** %4, align 8
+  %35 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %34, i32 0, i32 2
+  %36 = load i32, i32* %35, align 4
+  %37 = load %struct.Matrix*, %struct.Matrix** %5, align 8
+  %38 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %37, i32 0, i32 1
+  %39 = load i32, i32* %38, align 8
+  %40 = icmp ne i32 %36, %39
+  br i1 %40, label %41, label %43
+
+41:                                               ; preds = %33
+  %42 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([45 x i8], [45 x i8]* @.str.23, i64 0, i64 0))
+  store %struct.Matrix* null, %struct.Matrix** %3, align 8
+  br label %214
+
+43:                                               ; preds = %33
+  %44 = load %struct.Matrix*, %struct.Matrix** %4, align 8
+  %45 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %44, i32 0, i32 2
+  %46 = load i32, i32* %45, align 4
+  %47 = icmp sgt i32 %46, 100
+  br i1 %47, label %53, label %48
+
+48:                                               ; preds = %43
+  %49 = load %struct.Matrix*, %struct.Matrix** %5, align 8
+  %50 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %49, i32 0, i32 1
+  %51 = load i32, i32* %50, align 8
+  %52 = icmp sgt i32 %51, 100
+  br i1 %52, label %53, label %55
+
+53:                                               ; preds = %48, %43
+  %54 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([46 x i8], [46 x i8]* @.str.17, i64 0, i64 0))
+  store %struct.Matrix* null, %struct.Matrix** %3, align 8
+  br label %214
+
+55:                                               ; preds = %48
+  %56 = load %struct.Matrix*, %struct.Matrix** %4, align 8
+  %57 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %56, i32 0, i32 1
+  %58 = load i32, i32* %57, align 8
+  %59 = load %struct.Matrix*, %struct.Matrix** %5, align 8
+  %60 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %59, i32 0, i32 2
+  %61 = load i32, i32* %60, align 4
+  %62 = call %struct.Matrix* @fused_createMatrix(i1 false, i32 %58, i32 %61, i8* null)
+  store %struct.Matrix* %62, %struct.Matrix** %6, align 8
+  %63 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  %64 = icmp ne %struct.Matrix* %63, null
+  br i1 %64, label %66, label %65
+
+65:                                               ; preds = %55
+  store %struct.Matrix* null, %struct.Matrix** %3, align 8
+  br label %214
+
+66:                                               ; preds = %55
+  store i64 0, i64* %7, align 8
+  store i32 0, i32* %8, align 4
+  br label %67
+
+67:                                               ; preds = %199, %66
+  %68 = load i32, i32* %8, align 4
+  %69 = load %struct.Matrix*, %struct.Matrix** %4, align 8
+  %70 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %69, i32 0, i32 1
+  %71 = load i32, i32* %70, align 8
+  %72 = icmp slt i32 %68, %71
+  br i1 %72, label %73, label %202
+
+73:                                               ; preds = %67
+  store i32 0, i32* %9, align 4
+  br label %74
+
+74:                                               ; preds = %195, %73
+  %75 = load i32, i32* %9, align 4
+  %76 = load %struct.Matrix*, %struct.Matrix** %5, align 8
+  %77 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %76, i32 0, i32 2
+  %78 = load i32, i32* %77, align 4
+  %79 = icmp slt i32 %75, %78
+  br i1 %79, label %80, label %198
+
+80:                                               ; preds = %74
+  store i64 0, i64* %10, align 8
+  store i32 0, i32* %11, align 4
+  br label %81
+
+81:                                               ; preds = %149, %80
+  %82 = load i32, i32* %11, align 4
+  %83 = load %struct.Matrix*, %struct.Matrix** %4, align 8
+  %84 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %83, i32 0, i32 2
+  %85 = load i32, i32* %84, align 4
+  %86 = icmp slt i32 %82, %85
+  br i1 %86, label %87, label %152
+
+87:                                               ; preds = %81
+  %88 = load %struct.Matrix*, %struct.Matrix** %4, align 8
+  %89 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %88, i32 0, i32 0
+  %90 = load i32**, i32*** %89, align 8
+  %91 = load i32, i32* %8, align 4
+  %92 = sext i32 %91 to i64
+  %93 = getelementptr inbounds i32*, i32** %90, i64 %92
+  %94 = load i32*, i32** %93, align 8
+  %95 = load i32, i32* %11, align 4
+  %96 = sext i32 %95 to i64
+  %97 = getelementptr inbounds i32, i32* %94, i64 %96
+  %98 = load i32, i32* %97, align 4
+  %99 = sext i32 %98 to i64
+  %100 = load %struct.Matrix*, %struct.Matrix** %5, align 8
+  %101 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %100, i32 0, i32 0
+  %102 = load i32**, i32*** %101, align 8
+  %103 = load i32, i32* %11, align 4
+  %104 = sext i32 %103 to i64
+  %105 = getelementptr inbounds i32*, i32** %102, i64 %104
+  %106 = load i32*, i32** %105, align 8
+  %107 = load i32, i32* %9, align 4
+  %108 = sext i32 %107 to i64
+  %109 = getelementptr inbounds i32, i32* %106, i64 %108
+  %110 = load i32, i32* %109, align 4
+  %111 = sext i32 %110 to i64
+  %112 = mul nsw i64 %99, %111
+  store i64 %112, i64* %12, align 8
+  %113 = load i64, i64* %12, align 8
+  %114 = load i64, i64* %10, align 8
+  %115 = add nsw i64 %114, %113
+  store i64 %115, i64* %10, align 8
+  %116 = load i64, i64* %10, align 8
+  %117 = icmp sgt i64 %116, 2147483647
+  br i1 %117, label %121, label %118
+
+118:                                              ; preds = %87
+  %119 = load i64, i64* %10, align 8
+  %120 = icmp slt i64 %119, -2147483648
+  br i1 %120, label %121, label %148
+
+121:                                              ; preds = %118, %87
+  %122 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([42 x i8], [42 x i8]* @.str.24, i64 0, i64 0))
+  store i32 0, i32* %13, align 4
+  br label %123
+
+123:                                              ; preds = %138, %121
+  %124 = load i32, i32* %13, align 4
+  %125 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  %126 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %125, i32 0, i32 1
+  %127 = load i32, i32* %126, align 8
+  %128 = icmp slt i32 %124, %127
+  br i1 %128, label %129, label %141
+
+129:                                              ; preds = %123
+  %130 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  %131 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %130, i32 0, i32 0
+  %132 = load i32**, i32*** %131, align 8
+  %133 = load i32, i32* %13, align 4
+  %134 = sext i32 %133 to i64
+  %135 = getelementptr inbounds i32*, i32** %132, i64 %134
+  %136 = load i32*, i32** %135, align 8
+  %137 = bitcast i32* %136 to i8*
+  call void @free(i8* %137) #7
+  br label %138
+
+138:                                              ; preds = %129
+  %139 = load i32, i32* %13, align 4
+  %140 = add nsw i32 %139, 1
+  store i32 %140, i32* %13, align 4
+  br label %123
+
+141:                                              ; preds = %123
+  %142 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  %143 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %142, i32 0, i32 0
+  %144 = load i32**, i32*** %143, align 8
+  %145 = bitcast i32** %144 to i8*
+  call void @free(i8* %145) #7
+  %146 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  %147 = bitcast %struct.Matrix* %146 to i8*
+  call void @free(i8* %147) #7
+  store %struct.Matrix* null, %struct.Matrix** %3, align 8
+  br label %214
+
+148:                                              ; preds = %118
+  br label %149
+
+149:                                              ; preds = %148
+  %150 = load i32, i32* %11, align 4
+  %151 = add nsw i32 %150, 1
+  store i32 %151, i32* %11, align 4
+  br label %81
+
+152:                                              ; preds = %81
+  %153 = load i64, i64* %10, align 8
+  %154 = trunc i64 %153 to i32
+  %155 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  %156 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %155, i32 0, i32 0
+  %157 = load i32**, i32*** %156, align 8
+  %158 = load i32, i32* %8, align 4
+  %159 = sext i32 %158 to i64
+  %160 = getelementptr inbounds i32*, i32** %157, i64 %159
+  %161 = load i32*, i32** %160, align 8
+  %162 = load i32, i32* %9, align 4
+  %163 = sext i32 %162 to i64
+  %164 = getelementptr inbounds i32, i32* %161, i64 %163
+  store i32 %154, i32* %164, align 4
+  %165 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  %166 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %165, i32 0, i32 0
+  %167 = load i32**, i32*** %166, align 8
+  %168 = load i32, i32* %8, align 4
+  %169 = sext i32 %168 to i64
+  %170 = getelementptr inbounds i32*, i32** %167, i64 %169
+  %171 = load i32*, i32** %170, align 8
+  %172 = load i32, i32* %9, align 4
+  %173 = sext i32 %172 to i64
+  %174 = getelementptr inbounds i32, i32* %171, i64 %173
+  %175 = load i32, i32* %174, align 4
+  %176 = call i32 @abs(i32 %175) #8
+  %177 = sext i32 %176 to i64
+  %178 = load i64, i64* %7, align 8
+  %179 = icmp sgt i64 %177, %178
+  br i1 %179, label %180, label %194
+
+180:                                              ; preds = %152
+  %181 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  %182 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %181, i32 0, i32 0
+  %183 = load i32**, i32*** %182, align 8
+  %184 = load i32, i32* %8, align 4
+  %185 = sext i32 %184 to i64
+  %186 = getelementptr inbounds i32*, i32** %183, i64 %185
+  %187 = load i32*, i32** %186, align 8
+  %188 = load i32, i32* %9, align 4
+  %189 = sext i32 %188 to i64
+  %190 = getelementptr inbounds i32, i32* %187, i64 %189
+  %191 = load i32, i32* %190, align 4
+  %192 = call i32 @abs(i32 %191) #8
+  %193 = sext i32 %192 to i64
+  store i64 %193, i64* %7, align 8
+  br label %194
+
+194:                                              ; preds = %180, %152
+  br label %195
+
+195:                                              ; preds = %194
+  %196 = load i32, i32* %9, align 4
+  %197 = add nsw i32 %196, 1
+  store i32 %197, i32* %9, align 4
+  br label %74
+
+198:                                              ; preds = %74
+  br label %199
+
+199:                                              ; preds = %198
+  %200 = load i32, i32* %8, align 4
+  %201 = add nsw i32 %200, 1
+  store i32 %201, i32* %8, align 4
+  br label %67
+
+202:                                              ; preds = %67
+  %203 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  %204 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %203, i32 0, i32 1
+  %205 = load i32, i32* %204, align 8
+  %206 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  %207 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %206, i32 0, i32 2
+  %208 = load i32, i32* %207, align 4
+  %209 = icmp eq i32 %205, %208
+  %210 = zext i1 %209 to i32
+  %211 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  %212 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %211, i32 0, i32 3
+  store i32 %210, i32* %212, align 8
+  %213 = load %struct.Matrix*, %struct.Matrix** %6, align 8
+  store %struct.Matrix* %213, %struct.Matrix** %3, align 8
+  br label %214
+
+214:                                              ; preds = %202, %141, %65, %53, %41, %31, %19
+  %215 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  ret %struct.Matrix* %215
+}
+
+; Function Attrs: nounwind readnone
+declare dso_local i32 @abs(i32) #3
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local %struct.Node* @insertNode(%struct.Node* %0, i32 %1) #0 !project_source !2 {
+  %3 = alloca %struct.Node*, align 8
+  %4 = alloca %struct.Node*, align 8
+  %5 = alloca i32, align 4
+  %6 = alloca %struct.Node*, align 8
+  %7 = alloca %struct.Node*, align 8
+  %8 = alloca %struct.Node*, align 8
+  %9 = alloca i32, align 4
+  store %struct.Node* %0, %struct.Node** %4, align 8
+  store i32 %1, i32* %5, align 4
+  %10 = call noalias i8* @malloc(i64 32) #7
+  %11 = bitcast i8* %10 to %struct.Node*
+  store %struct.Node* %11, %struct.Node** %6, align 8
+  %12 = load %struct.Node*, %struct.Node** %6, align 8
+  %13 = icmp ne %struct.Node* %12, null
+  br i1 %13, label %17, label %14
+
+14:                                               ; preds = %2
+  %15 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([38 x i8], [38 x i8]* @.str.25, i64 0, i64 0))
+  %16 = load %struct.Node*, %struct.Node** %4, align 8
+  store %struct.Node* %16, %struct.Node** %3, align 8
+  br label %94
+
+17:                                               ; preds = %2
+  %18 = load i32, i32* %5, align 4
+  %19 = load %struct.Node*, %struct.Node** %6, align 8
+  %20 = getelementptr inbounds %struct.Node, %struct.Node* %19, i32 0, i32 0
+  store i32 %18, i32* %20, align 8
+  %21 = load %struct.Node*, %struct.Node** %6, align 8
+  %22 = getelementptr inbounds %struct.Node, %struct.Node* %21, i32 0, i32 1
+  store %struct.Node* null, %struct.Node** %22, align 8
+  %23 = load %struct.Node*, %struct.Node** %6, align 8
+  %24 = getelementptr inbounds %struct.Node, %struct.Node* %23, i32 0, i32 2
+  store %struct.Node* null, %struct.Node** %24, align 8
+  %25 = load %struct.Node*, %struct.Node** %6, align 8
+  %26 = getelementptr inbounds %struct.Node, %struct.Node* %25, i32 0, i32 3
+  store i32 0, i32* %26, align 8
+  %27 = load %struct.Node*, %struct.Node** %4, align 8
+  %28 = icmp ne %struct.Node* %27, null
+  br i1 %28, label %33, label %29
+
+29:                                               ; preds = %17
+  %30 = load %struct.Node*, %struct.Node** %6, align 8
+  %31 = getelementptr inbounds %struct.Node, %struct.Node* %30, i32 0, i32 4
+  store i32 0, i32* %31, align 4
+  store i32 0, i32* @insertNode.maxDepth, align 4
+  %32 = load %struct.Node*, %struct.Node** %6, align 8
+  store %struct.Node* %32, %struct.Node** %3, align 8
+  br label %94
+
+33:                                               ; preds = %17
+  %34 = load %struct.Node*, %struct.Node** %4, align 8
+  store %struct.Node* %34, %struct.Node** %7, align 8
+  store %struct.Node* null, %struct.Node** %8, align 8
+  store i32 0, i32* %9, align 4
+  br label %35
+
+35:                                               ; preds = %60, %33
+  %36 = load %struct.Node*, %struct.Node** %7, align 8
+  %37 = icmp ne %struct.Node* %36, null
+  br i1 %37, label %38, label %44
+
+38:                                               ; preds = %35
+  %39 = load %struct.Node*, %struct.Node** %7, align 8
+  %40 = getelementptr inbounds %struct.Node, %struct.Node* %39, i32 0, i32 0
+  %41 = load i32, i32* %40, align 8
+  %42 = load i32, i32* %5, align 4
+  %43 = icmp slt i32 %41, %42
+  br label %44
+
+44:                                               ; preds = %38, %35
+  %45 = phi i1 [ false, %35 ], [ %43, %38 ]
+  br i1 %45, label %46, label %61
+
+46:                                               ; preds = %44
+  %47 = load %struct.Node*, %struct.Node** %7, align 8
+  store %struct.Node* %47, %struct.Node** %8, align 8
+  %48 = load %struct.Node*, %struct.Node** %7, align 8
+  %49 = getelementptr inbounds %struct.Node, %struct.Node* %48, i32 0, i32 1
+  %50 = load %struct.Node*, %struct.Node** %49, align 8
+  store %struct.Node* %50, %struct.Node** %7, align 8
+  %51 = load i32, i32* %9, align 4
+  %52 = add nsw i32 %51, 1
+  store i32 %52, i32* %9, align 4
+  %53 = load i32, i32* %9, align 4
+  %54 = icmp sgt i32 %53, 1000
+  br i1 %54, label %55, label %60
+
+55:                                               ; preds = %46
+  %56 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([34 x i8], [34 x i8]* @.str.26, i64 0, i64 0))
+  %57 = load %struct.Node*, %struct.Node** %6, align 8
+  %58 = bitcast %struct.Node* %57 to i8*
+  call void @free(i8* %58) #7
+  %59 = load %struct.Node*, %struct.Node** %4, align 8
+  store %struct.Node* %59, %struct.Node** %3, align 8
+  br label %94
+
+60:                                               ; preds = %46
+  br label %35
+
+61:                                               ; preds = %44
+  %62 = load i32, i32* %9, align 4
+  %63 = load i32, i32* @insertNode.maxDepth, align 4
+  %64 = icmp sgt i32 %62, %63
+  br i1 %64, label %65, label %67
+
+65:                                               ; preds = %61
+  %66 = load i32, i32* %9, align 4
+  store i32 %66, i32* @insertNode.maxDepth, align 4
+  br label %67
+
+67:                                               ; preds = %65, %61
+  %68 = load i32, i32* %9, align 4
+  %69 = load %struct.Node*, %struct.Node** %6, align 8
+  %70 = getelementptr inbounds %struct.Node, %struct.Node* %69, i32 0, i32 4
+  store i32 %68, i32* %70, align 4
+  %71 = load %struct.Node*, %struct.Node** %7, align 8
+  %72 = load %struct.Node*, %struct.Node** %6, align 8
+  %73 = getelementptr inbounds %struct.Node, %struct.Node* %72, i32 0, i32 1
+  store %struct.Node* %71, %struct.Node** %73, align 8
+  %74 = load %struct.Node*, %struct.Node** %8, align 8
+  %75 = icmp ne %struct.Node* %74, null
+  br i1 %75, label %76, label %83
+
+76:                                               ; preds = %67
+  %77 = load %struct.Node*, %struct.Node** %6, align 8
+  %78 = load %struct.Node*, %struct.Node** %8, align 8
+  %79 = getelementptr inbounds %struct.Node, %struct.Node* %78, i32 0, i32 1
+  store %struct.Node* %77, %struct.Node** %79, align 8
+  %80 = load %struct.Node*, %struct.Node** %8, align 8
+  %81 = load %struct.Node*, %struct.Node** %6, align 8
+  %82 = getelementptr inbounds %struct.Node, %struct.Node* %81, i32 0, i32 2
+  store %struct.Node* %80, %struct.Node** %82, align 8
+  br label %85
+
+83:                                               ; preds = %67
+  %84 = load %struct.Node*, %struct.Node** %6, align 8
+  store %struct.Node* %84, %struct.Node** %3, align 8
+  br label %94
+
+85:                                               ; preds = %76
+  %86 = load %struct.Node*, %struct.Node** %7, align 8
+  %87 = icmp ne %struct.Node* %86, null
+  br i1 %87, label %88, label %92
+
+88:                                               ; preds = %85
+  %89 = load %struct.Node*, %struct.Node** %6, align 8
+  %90 = load %struct.Node*, %struct.Node** %7, align 8
+  %91 = getelementptr inbounds %struct.Node, %struct.Node* %90, i32 0, i32 2
+  store %struct.Node* %89, %struct.Node** %91, align 8
+  br label %92
+
+92:                                               ; preds = %88, %85
+  %93 = load %struct.Node*, %struct.Node** %4, align 8
+  store %struct.Node* %93, %struct.Node** %3, align 8
+  br label %94
+
+94:                                               ; preds = %92, %83, %55, %29, %14
+  %95 = load %struct.Node*, %struct.Node** %3, align 8
+  ret %struct.Node* %95
+}
+
+declare dso_local i32 @printf(i8*, ...) #2
+
+; Function Attrs: nounwind
+declare dso_local i64 @time(i64*) #1
+
+; Function Attrs: nounwind
+declare dso_local void @srand(i32) #1
+
+; Function Attrs: nounwind
+declare dso_local i32 @rand() #1
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local double @calculateDistance(%struct.Point* byval(%struct.Point) align 8 %0, %struct.Point* byval(%struct.Point) align 8 %1, i32* %2) #0 !project_source !2 {
+  %4 = alloca double, align 8
+  %5 = alloca i32*, align 8
+  %6 = alloca double, align 8
+  %7 = alloca double, align 8
+  %8 = alloca double, align 8
+  store i32* %2, i32** %5, align 8
+  %9 = load i32*, i32** %5, align 8
+  store i32 0, i32* %9, align 4
+  %10 = getelementptr inbounds %struct.Point, %struct.Point* %0, i32 0, i32 3
+  %11 = load double, double* %10, align 8
+  %12 = fcmp ole double %11, 0.000000e+00
+  br i1 %12, label %17, label %13
+
+13:                                               ; preds = %3
+  %14 = getelementptr inbounds %struct.Point, %struct.Point* %1, i32 0, i32 3
+  %15 = load double, double* %14, align 8
+  %16 = fcmp ole double %15, 0.000000e+00
+  br i1 %16, label %17, label %20
+
+17:                                               ; preds = %13, %3
+  %18 = load i32*, i32** %5, align 8
+  store i32 1, i32* %18, align 4
+  %19 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.32, i64 0, i64 0))
+  store double -1.000000e+00, double* %4, align 8
+  br label %105
+
+20:                                               ; preds = %13
+  %21 = getelementptr inbounds %struct.Point, %struct.Point* %0, i32 0, i32 0
+  %22 = load i32, i32* %21, align 8
+  %23 = call i32 @abs(i32 %22) #8
+  %24 = icmp sgt i32 %23, 1000
+  br i1 %24, label %40, label %25
+
+25:                                               ; preds = %20
+  %26 = getelementptr inbounds %struct.Point, %struct.Point* %0, i32 0, i32 1
+  %27 = load i32, i32* %26, align 4
+  %28 = call i32 @abs(i32 %27) #8
+  %29 = icmp sgt i32 %28, 1000
+  br i1 %29, label %40, label %30
+
+30:                                               ; preds = %25
+  %31 = getelementptr inbounds %struct.Point, %struct.Point* %1, i32 0, i32 0
+  %32 = load i32, i32* %31, align 8
+  %33 = call i32 @abs(i32 %32) #8
+  %34 = icmp sgt i32 %33, 1000
+  br i1 %34, label %40, label %35
+
+35:                                               ; preds = %30
+  %36 = getelementptr inbounds %struct.Point, %struct.Point* %1, i32 0, i32 1
+  %37 = load i32, i32* %36, align 4
+  %38 = call i32 @abs(i32 %37) #8
+  %39 = icmp sgt i32 %38, 1000
+  br i1 %39, label %40, label %43
+
+40:                                               ; preds = %35, %30, %25, %20
+  %41 = load i32*, i32** %5, align 8
+  store i32 3, i32* %41, align 4
+  %42 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.33, i64 0, i64 0))
+  store double -1.000000e+00, double* %4, align 8
+  br label %105
+
+43:                                               ; preds = %35
+  %44 = getelementptr inbounds %struct.Point, %struct.Point* %1, i32 0, i32 0
+  %45 = load i32, i32* %44, align 8
+  %46 = getelementptr inbounds %struct.Point, %struct.Point* %0, i32 0, i32 0
+  %47 = load i32, i32* %46, align 8
+  %48 = sub nsw i32 %45, %47
+  %49 = sitofp i32 %48 to double
+  %50 = getelementptr inbounds %struct.Point, %struct.Point* %1, i32 0, i32 3
+  %51 = load double, double* %50, align 8
+  %52 = getelementptr inbounds %struct.Point, %struct.Point* %0, i32 0, i32 3
+  %53 = load double, double* %52, align 8
+  %54 = fdiv double %51, %53
+  %55 = call double @sqrt(double %54) #7
+  %56 = fmul double %49, %55
+  store double %56, double* %6, align 8
+  %57 = getelementptr inbounds %struct.Point, %struct.Point* %1, i32 0, i32 1
+  %58 = load i32, i32* %57, align 4
+  %59 = getelementptr inbounds %struct.Point, %struct.Point* %0, i32 0, i32 1
+  %60 = load i32, i32* %59, align 4
+  %61 = sub nsw i32 %58, %60
+  %62 = sitofp i32 %61 to double
+  %63 = getelementptr inbounds %struct.Point, %struct.Point* %1, i32 0, i32 3
+  %64 = load double, double* %63, align 8
+  %65 = getelementptr inbounds %struct.Point, %struct.Point* %0, i32 0, i32 3
+  %66 = load double, double* %65, align 8
+  %67 = fdiv double %64, %66
+  %68 = call double @sqrt(double %67) #7
+  %69 = fmul double %62, %68
+  store double %69, double* %7, align 8
+  %70 = load double, double* %6, align 8
+  %71 = call double @llvm.fabs.f64(double %70)
+  %72 = fcmp ogt double %71, 1.000000e+03
+  br i1 %72, label %77, label %73
+
+73:                                               ; preds = %43
+  %74 = load double, double* %7, align 8
+  %75 = call double @llvm.fabs.f64(double %74)
+  %76 = fcmp ogt double %75, 1.000000e+03
+  br i1 %76, label %77, label %80
+
+77:                                               ; preds = %73, %43
+  %78 = load i32*, i32** %5, align 8
+  store i32 5, i32* %78, align 4
+  %79 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.34, i64 0, i64 0))
+  store double -1.000000e+00, double* %4, align 8
+  br label %105
+
+80:                                               ; preds = %73
+  %81 = load double, double* %6, align 8
+  %82 = load double, double* %6, align 8
+  %83 = fmul double %81, %82
+  %84 = load double, double* %7, align 8
+  %85 = load double, double* %7, align 8
+  %86 = fmul double %84, %85
+  %87 = fadd double %83, %86
+  %88 = call double @sqrt(double %87) #7
+  store double %88, double* %8, align 8
+  %89 = load double, double* %8, align 8
+  %90 = fcmp uno double %89, %89
+  br i1 %90, label %100, label %91
+
+91:                                               ; preds = %80
+  %92 = load double, double* %8, align 8
+  %93 = call double @llvm.fabs.f64(double %92) #9
+  %94 = fcmp oeq double %93, 0x7FF0000000000000
+  %95 = bitcast double %92 to i64
+  %96 = icmp slt i64 %95, 0
+  %97 = select i1 %96, i32 -1, i32 1
+  %98 = select i1 %94, i32 %97, i32 0
+  %99 = icmp ne i32 %98, 0
+  br i1 %99, label %100, label %103
+
+100:                                              ; preds = %91, %80
+  %101 = load i32*, i32** %5, align 8
+  store i32 8, i32* %101, align 4
+  %102 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.35, i64 0, i64 0))
+  store double -1.000000e+00, double* %4, align 8
+  br label %105
+
+103:                                              ; preds = %91
+  %104 = load double, double* %8, align 8
+  store double %104, double* %4, align 8
+  br label %105
+
+105:                                              ; preds = %103, %100, %77, %40, %17
+  %106 = load double, double* %4, align 8
+  ret double %106
+}
+
+; Function Attrs: nounwind
+declare dso_local double @sqrt(double) #1
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare double @llvm.fabs.f64(double) #4
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local double @calculateCircleArea(%struct.Circle* byval(%struct.Circle) align 8 %0, i32* %1) #0 !project_source !2 {
+  %3 = alloca double, align 8
+  %4 = alloca i32*, align 8
+  %5 = alloca double, align 8
+  store i32* %1, i32** %4, align 8
+  %6 = load i32*, i32** %4, align 8
+  store i32 0, i32* %6, align 4
+  %7 = getelementptr inbounds %struct.Circle, %struct.Circle* %0, i32 0, i32 2
+  %8 = load i32, i32* %7, align 8
+  %9 = icmp ne i32 %8, 0
+  br i1 %9, label %13, label %10
+
+10:                                               ; preds = %2
+  %11 = load i32*, i32** %4, align 8
+  store i32 1, i32* %11, align 4
+  %12 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.36, i64 0, i64 0))
+  store double -1.000000e+00, double* %3, align 8
+  br label %92
+
+13:                                               ; preds = %2
+  %14 = getelementptr inbounds %struct.Circle, %struct.Circle* %0, i32 0, i32 1
+  %15 = load double, double* %14, align 8
+  %16 = fcmp ole double %15, 0.000000e+00
+  br i1 %16, label %17, label %20
+
+17:                                               ; preds = %13
+  %18 = load i32*, i32** %4, align 8
+  store i32 1, i32* %18, align 4
+  %19 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.37, i64 0, i64 0))
+  store double -1.000000e+00, double* %3, align 8
+  br label %92
+
+20:                                               ; preds = %13
+  %21 = getelementptr inbounds %struct.Circle, %struct.Circle* %0, i32 0, i32 1
+  %22 = load double, double* %21, align 8
+  %23 = fcmp ogt double %22, 1.000000e+03
+  br i1 %23, label %24, label %27
+
+24:                                               ; preds = %20
+  %25 = load i32*, i32** %4, align 8
+  store i32 3, i32* %25, align 4
+  %26 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str.38, i64 0, i64 0))
+  store double -1.000000e+00, double* %3, align 8
+  br label %92
+
+27:                                               ; preds = %20
+  %28 = getelementptr inbounds %struct.Circle, %struct.Circle* %0, i32 0, i32 0
+  %29 = getelementptr inbounds %struct.Point, %struct.Point* %28, i32 0, i32 0
+  %30 = load i32, i32* %29, align 8
+  %31 = call i32 @abs(i32 %30) #8
+  %32 = icmp sgt i32 %31, 1000
+  br i1 %32, label %39, label %33
+
+33:                                               ; preds = %27
+  %34 = getelementptr inbounds %struct.Circle, %struct.Circle* %0, i32 0, i32 0
+  %35 = getelementptr inbounds %struct.Point, %struct.Point* %34, i32 0, i32 1
+  %36 = load i32, i32* %35, align 4
+  %37 = call i32 @abs(i32 %36) #8
+  %38 = icmp sgt i32 %37, 1000
+  br i1 %38, label %39, label %42
+
+39:                                               ; preds = %33, %27
+  %40 = load i32*, i32** %4, align 8
+  store i32 3, i32* %40, align 4
+  %41 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([45 x i8], [45 x i8]* @.str.39, i64 0, i64 0))
+  store double -1.000000e+00, double* %3, align 8
+  br label %92
+
+42:                                               ; preds = %33
+  %43 = getelementptr inbounds %struct.Circle, %struct.Circle* %0, i32 0, i32 1
+  %44 = load double, double* %43, align 8
+  %45 = fmul double 3.141590e+00, %44
+  %46 = getelementptr inbounds %struct.Circle, %struct.Circle* %0, i32 0, i32 1
+  %47 = load double, double* %46, align 8
+  %48 = fmul double %45, %47
+  store double %48, double* %5, align 8
+  %49 = load double, double* %5, align 8
+  %50 = fcmp uno double %49, %49
+  br i1 %50, label %60, label %51
+
+51:                                               ; preds = %42
+  %52 = load double, double* %5, align 8
+  %53 = call double @llvm.fabs.f64(double %52) #9
+  %54 = fcmp oeq double %53, 0x7FF0000000000000
+  %55 = bitcast double %52 to i64
+  %56 = icmp slt i64 %55, 0
+  %57 = select i1 %56, i32 -1, i32 1
+  %58 = select i1 %54, i32 %57, i32 0
+  %59 = icmp ne i32 %58, 0
+  br i1 %59, label %60, label %63
+
+60:                                               ; preds = %51, %42
+  %61 = load i32*, i32** %4, align 8
+  store i32 5, i32* %61, align 4
+  %62 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str.40, i64 0, i64 0))
+  store double -1.000000e+00, double* %3, align 8
+  br label %92
+
+63:                                               ; preds = %51
+  %64 = getelementptr inbounds %struct.Circle, %struct.Circle* %0, i32 0, i32 3
+  %65 = getelementptr inbounds [256 x i8], [256 x i8]* %64, i64 0, i64 0
+  %66 = call i32 @strcmp(i8* %65, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.41, i64 0, i64 0)) #10
+  %67 = icmp eq i32 %66, 0
+  br i1 %67, label %68, label %70
+
+68:                                               ; preds = %63
+  %69 = load double, double* %5, align 8
+  store double %69, double* %3, align 8
+  br label %92
+
+70:                                               ; preds = %63
+  %71 = getelementptr inbounds %struct.Circle, %struct.Circle* %0, i32 0, i32 3
+  %72 = getelementptr inbounds [256 x i8], [256 x i8]* %71, i64 0, i64 0
+  %73 = call i32 @strcmp(i8* %72, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.42, i64 0, i64 0)) #10
+  %74 = icmp eq i32 %73, 0
+  br i1 %74, label %75, label %89
+
+75:                                               ; preds = %70
+  %76 = getelementptr inbounds %struct.Circle, %struct.Circle* %0, i32 0, i32 0
+  %77 = getelementptr inbounds %struct.Point, %struct.Point* %76, i32 0, i32 3
+  %78 = load double, double* %77, align 8
+  %79 = fcmp ole double %78, 0.000000e+00
+  br i1 %79, label %80, label %83
+
+80:                                               ; preds = %75
+  %81 = load i32*, i32** %4, align 8
+  store i32 1, i32* %81, align 4
+  %82 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([35 x i8], [35 x i8]* @.str.43, i64 0, i64 0))
+  store double -1.000000e+00, double* %3, align 8
+  br label %92
+
+83:                                               ; preds = %75
+  %84 = load double, double* %5, align 8
+  %85 = getelementptr inbounds %struct.Circle, %struct.Circle* %0, i32 0, i32 0
+  %86 = getelementptr inbounds %struct.Point, %struct.Point* %85, i32 0, i32 3
+  %87 = load double, double* %86, align 8
+  %88 = fmul double %84, %87
+  store double %88, double* %3, align 8
+  br label %92
+
+89:                                               ; preds = %70
+  %90 = load i32*, i32** %4, align 8
+  store i32 1, i32* %90, align 4
+  %91 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.44, i64 0, i64 0))
+  store double -1.000000e+00, double* %3, align 8
+  br label %92
+
+92:                                               ; preds = %89, %83, %80, %68, %60, %39, %24, %17, %10
+  %93 = load double, double* %3, align 8
+  ret double %93
+}
+
+; Function Attrs: nounwind readonly
+declare dso_local i32 @strcmp(i8*, i8*) #5
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local i32 @validateMatrix(%struct.Matrix* %0) #0 !project_source !2 {
+  %2 = alloca i32, align 4
+  %3 = alloca %struct.Matrix*, align 8
+  %4 = alloca i32, align 4
+  store %struct.Matrix* %0, %struct.Matrix** %3, align 8
+  %5 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  %6 = icmp ne %struct.Matrix* %5, null
+  br i1 %6, label %9, label %7
+
+7:                                                ; preds = %1
+  %8 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.21, i64 0, i64 0))
+  store i32 7, i32* %2, align 4
+  br label %78
+
+9:                                                ; preds = %1
+  %10 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  %11 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %10, i32 0, i32 0
+  %12 = load i32**, i32*** %11, align 8
+  %13 = icmp ne i32** %12, null
+  br i1 %13, label %16, label %14
+
+14:                                               ; preds = %9
+  %15 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.45, i64 0, i64 0))
+  store i32 7, i32* %2, align 4
+  br label %78
+
+16:                                               ; preds = %9
+  %17 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  %18 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %17, i32 0, i32 1
+  %19 = load i32, i32* %18, align 8
+  %20 = icmp slt i32 %19, 1
+  br i1 %20, label %26, label %21
+
+21:                                               ; preds = %16
+  %22 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  %23 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %22, i32 0, i32 2
+  %24 = load i32, i32* %23, align 4
+  %25 = icmp slt i32 %24, 1
+  br i1 %25, label %26, label %28
+
+26:                                               ; preds = %21, %16
+  %27 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.16, i64 0, i64 0))
+  store i32 1, i32* %2, align 4
+  br label %78
+
+28:                                               ; preds = %21
+  %29 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  %30 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %29, i32 0, i32 1
+  %31 = load i32, i32* %30, align 8
+  %32 = icmp sgt i32 %31, 100
+  br i1 %32, label %38, label %33
+
+33:                                               ; preds = %28
+  %34 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  %35 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %34, i32 0, i32 2
+  %36 = load i32, i32* %35, align 4
+  %37 = icmp sgt i32 %36, 100
+  br i1 %37, label %38, label %40
+
+38:                                               ; preds = %33, %28
+  %39 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.46, i64 0, i64 0))
+  store i32 3, i32* %2, align 4
+  br label %78
+
+40:                                               ; preds = %33
+  store i32 0, i32* %4, align 4
+  br label %41
+
+41:                                               ; preds = %59, %40
+  %42 = load i32, i32* %4, align 4
+  %43 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  %44 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %43, i32 0, i32 1
+  %45 = load i32, i32* %44, align 8
+  %46 = icmp slt i32 %42, %45
+  br i1 %46, label %47, label %62
+
+47:                                               ; preds = %41
+  %48 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  %49 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %48, i32 0, i32 0
+  %50 = load i32**, i32*** %49, align 8
+  %51 = load i32, i32* %4, align 4
+  %52 = sext i32 %51 to i64
+  %53 = getelementptr inbounds i32*, i32** %50, i64 %52
+  %54 = load i32*, i32** %53, align 8
+  %55 = icmp ne i32* %54, null
+  br i1 %55, label %58, label %56
+
+56:                                               ; preds = %47
+  %57 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.47, i64 0, i64 0))
+  store i32 7, i32* %2, align 4
+  br label %78
+
+58:                                               ; preds = %47
+  br label %59
+
+59:                                               ; preds = %58
+  %60 = load i32, i32* %4, align 4
+  %61 = add nsw i32 %60, 1
+  store i32 %61, i32* %4, align 4
+  br label %41
+
+62:                                               ; preds = %41
+  %63 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  %64 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %63, i32 0, i32 1
+  %65 = load i32, i32* %64, align 8
+  %66 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  %67 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %66, i32 0, i32 2
+  %68 = load i32, i32* %67, align 4
+  %69 = icmp eq i32 %65, %68
+  %70 = zext i1 %69 to i32
+  %71 = load %struct.Matrix*, %struct.Matrix** %3, align 8
+  %72 = getelementptr inbounds %struct.Matrix, %struct.Matrix* %71, i32 0, i32 3
+  %73 = load i32, i32* %72, align 8
+  %74 = icmp ne i32 %70, %73
+  br i1 %74, label %75, label %77
+
+75:                                               ; preds = %62
+  %76 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.48, i64 0, i64 0))
+  store i32 1, i32* %2, align 4
+  br label %78
+
+77:                                               ; preds = %62
+  store i32 0, i32* %2, align 4
+  br label %78
+
+78:                                               ; preds = %77, %75, %56, %38, %26, %14, %7
+  %79 = load i32, i32* %2, align 4
+  ret i32 %79
+}
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local %struct.Point* @findCentroid(%struct.Point* %0, i32 %1, i32* %2) #0 !project_source !2 {
+  %4 = alloca %struct.Point*, align 8
+  %5 = alloca %struct.Point*, align 8
+  %6 = alloca i32, align 4
+  %7 = alloca i32*, align 8
+  %8 = alloca %struct.Point*, align 8
+  %9 = alloca double, align 8
+  %10 = alloca double, align 8
+  %11 = alloca double, align 8
+  %12 = alloca i32, align 4
+  store %struct.Point* %0, %struct.Point** %5, align 8
+  store i32 %1, i32* %6, align 4
+  store i32* %2, i32** %7, align 8
+  %13 = load i32*, i32** %7, align 8
+  store i32 0, i32* %13, align 4
+  %14 = load %struct.Point*, %struct.Point** %5, align 8
+  %15 = icmp ne %struct.Point* %14, null
+  br i1 %15, label %16, label %19
+
+16:                                               ; preds = %3
+  %17 = load i32, i32* %6, align 4
+  %18 = icmp sle i32 %17, 0
+  br i1 %18, label %19, label %22
+
+19:                                               ; preds = %16, %3
+  %20 = load i32*, i32** %7, align 8
+  store i32 1, i32* %20, align 4
+  %21 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.50, i64 0, i64 0))
+  store %struct.Point* null, %struct.Point** %4, align 8
+  br label %171
+
+22:                                               ; preds = %16
+  %23 = load i32, i32* %6, align 4
+  %24 = icmp sgt i32 %23, 1000
+  br i1 %24, label %25, label %28
+
+25:                                               ; preds = %22
+  %26 = load i32*, i32** %7, align 8
+  store i32 3, i32* %26, align 4
+  %27 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.51, i64 0, i64 0))
+  store %struct.Point* null, %struct.Point** %4, align 8
+  br label %171
+
+28:                                               ; preds = %22
+  %29 = call noalias i8* @malloc(i64 272) #7
+  %30 = bitcast i8* %29 to %struct.Point*
+  store %struct.Point* %30, %struct.Point** %8, align 8
+  %31 = load %struct.Point*, %struct.Point** %8, align 8
+  %32 = icmp ne %struct.Point* %31, null
+  br i1 %32, label %36, label %33
+
+33:                                               ; preds = %28
+  %34 = load i32*, i32** %7, align 8
+  store i32 2, i32* %34, align 4
+  %35 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.52, i64 0, i64 0))
+  store %struct.Point* null, %struct.Point** %4, align 8
+  br label %171
+
+36:                                               ; preds = %28
+  store double 0.000000e+00, double* %9, align 8
+  store double 0.000000e+00, double* %10, align 8
+  store double 0.000000e+00, double* %11, align 8
+  store i32 0, i32* %12, align 4
+  br label %37
+
+37:                                               ; preds = %136, %36
+  %38 = load i32, i32* %12, align 4
+  %39 = load i32, i32* %6, align 4
+  %40 = icmp slt i32 %38, %39
+  br i1 %40, label %41, label %139
+
+41:                                               ; preds = %37
+  %42 = load %struct.Point*, %struct.Point** %5, align 8
+  %43 = load i32, i32* %12, align 4
+  %44 = sext i32 %43 to i64
+  %45 = getelementptr inbounds %struct.Point, %struct.Point* %42, i64 %44
+  %46 = getelementptr inbounds %struct.Point, %struct.Point* %45, i32 0, i32 3
+  %47 = load double, double* %46, align 8
+  %48 = fcmp ole double %47, 0.000000e+00
+  br i1 %48, label %49, label %54
+
+49:                                               ; preds = %41
+  %50 = load i32*, i32** %7, align 8
+  store i32 1, i32* %50, align 4
+  %51 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.53, i64 0, i64 0))
+  %52 = load %struct.Point*, %struct.Point** %8, align 8
+  %53 = bitcast %struct.Point* %52 to i8*
+  call void @free(i8* %53) #7
+  store %struct.Point* null, %struct.Point** %4, align 8
+  br label %171
+
+54:                                               ; preds = %41
+  %55 = load %struct.Point*, %struct.Point** %5, align 8
+  %56 = load i32, i32* %12, align 4
+  %57 = sext i32 %56 to i64
+  %58 = getelementptr inbounds %struct.Point, %struct.Point* %55, i64 %57
+  %59 = getelementptr inbounds %struct.Point, %struct.Point* %58, i32 0, i32 3
+  %60 = load double, double* %59, align 8
+  %61 = load double, double* %9, align 8
+  %62 = fadd double %61, %60
+  store double %62, double* %9, align 8
+  %63 = load %struct.Point*, %struct.Point** %5, align 8
+  %64 = load i32, i32* %12, align 4
+  %65 = sext i32 %64 to i64
+  %66 = getelementptr inbounds %struct.Point, %struct.Point* %63, i64 %65
+  %67 = getelementptr inbounds %struct.Point, %struct.Point* %66, i32 0, i32 0
+  %68 = load i32, i32* %67, align 8
+  %69 = sitofp i32 %68 to double
+  %70 = load %struct.Point*, %struct.Point** %5, align 8
+  %71 = load i32, i32* %12, align 4
+  %72 = sext i32 %71 to i64
+  %73 = getelementptr inbounds %struct.Point, %struct.Point* %70, i64 %72
+  %74 = getelementptr inbounds %struct.Point, %struct.Point* %73, i32 0, i32 3
+  %75 = load double, double* %74, align 8
+  %76 = fmul double %69, %75
+  %77 = load double, double* %10, align 8
+  %78 = fadd double %77, %76
+  store double %78, double* %10, align 8
+  %79 = load %struct.Point*, %struct.Point** %5, align 8
+  %80 = load i32, i32* %12, align 4
+  %81 = sext i32 %80 to i64
+  %82 = getelementptr inbounds %struct.Point, %struct.Point* %79, i64 %81
+  %83 = getelementptr inbounds %struct.Point, %struct.Point* %82, i32 0, i32 1
+  %84 = load i32, i32* %83, align 4
+  %85 = sitofp i32 %84 to double
+  %86 = load %struct.Point*, %struct.Point** %5, align 8
+  %87 = load i32, i32* %12, align 4
+  %88 = sext i32 %87 to i64
+  %89 = getelementptr inbounds %struct.Point, %struct.Point* %86, i64 %88
+  %90 = getelementptr inbounds %struct.Point, %struct.Point* %89, i32 0, i32 3
+  %91 = load double, double* %90, align 8
+  %92 = fmul double %85, %91
+  %93 = load double, double* %11, align 8
+  %94 = fadd double %93, %92
+  store double %94, double* %11, align 8
+  %95 = load double, double* %9, align 8
+  %96 = fcmp uno double %95, %95
+  br i1 %96, label %130, label %97
+
+97:                                               ; preds = %54
+  %98 = load double, double* %10, align 8
+  %99 = fcmp uno double %98, %98
+  br i1 %99, label %130, label %100
+
+100:                                              ; preds = %97
+  %101 = load double, double* %11, align 8
+  %102 = fcmp uno double %101, %101
+  br i1 %102, label %130, label %103
+
+103:                                              ; preds = %100
+  %104 = load double, double* %9, align 8
+  %105 = call double @llvm.fabs.f64(double %104) #9
+  %106 = fcmp oeq double %105, 0x7FF0000000000000
+  %107 = bitcast double %104 to i64
+  %108 = icmp slt i64 %107, 0
+  %109 = select i1 %108, i32 -1, i32 1
+  %110 = select i1 %106, i32 %109, i32 0
+  %111 = icmp ne i32 %110, 0
+  br i1 %111, label %130, label %112
+
+112:                                              ; preds = %103
+  %113 = load double, double* %10, align 8
+  %114 = call double @llvm.fabs.f64(double %113) #9
+  %115 = fcmp oeq double %114, 0x7FF0000000000000
+  %116 = bitcast double %113 to i64
+  %117 = icmp slt i64 %116, 0
+  %118 = select i1 %117, i32 -1, i32 1
+  %119 = select i1 %115, i32 %118, i32 0
+  %120 = icmp ne i32 %119, 0
+  br i1 %120, label %130, label %121
+
+121:                                              ; preds = %112
+  %122 = load double, double* %11, align 8
+  %123 = call double @llvm.fabs.f64(double %122) #9
+  %124 = fcmp oeq double %123, 0x7FF0000000000000
+  %125 = bitcast double %122 to i64
+  %126 = icmp slt i64 %125, 0
+  %127 = select i1 %126, i32 -1, i32 1
+  %128 = select i1 %124, i32 %127, i32 0
+  %129 = icmp ne i32 %128, 0
+  br i1 %129, label %130, label %135
+
+130:                                              ; preds = %121, %112, %103, %100, %97, %54
+  %131 = load i32*, i32** %7, align 8
+  store i32 5, i32* %131, align 4
+  %132 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([30 x i8], [30 x i8]* @.str.54, i64 0, i64 0))
+  %133 = load %struct.Point*, %struct.Point** %8, align 8
+  %134 = bitcast %struct.Point* %133 to i8*
+  call void @free(i8* %134) #7
+  store %struct.Point* null, %struct.Point** %4, align 8
+  br label %171
+
+135:                                              ; preds = %121
+  br label %136
+
+136:                                              ; preds = %135
+  %137 = load i32, i32* %12, align 4
+  %138 = add nsw i32 %137, 1
+  store i32 %138, i32* %12, align 4
+  br label %37
+
+139:                                              ; preds = %37
+  %140 = load double, double* %9, align 8
+  %141 = fcmp oeq double %140, 0.000000e+00
+  br i1 %141, label %142, label %147
+
+142:                                              ; preds = %139
+  %143 = load i32*, i32** %7, align 8
+  store i32 1, i32* %143, align 4
+  %144 = call i32 @fused_setErrorMessage(i1 false, i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.55, i64 0, i64 0))
+  %145 = load %struct.Point*, %struct.Point** %8, align 8
+  %146 = bitcast %struct.Point* %145 to i8*
+  call void @free(i8* %146) #7
+  store %struct.Point* null, %struct.Point** %4, align 8
+  br label %171
+
+147:                                              ; preds = %139
+  %148 = load double, double* %10, align 8
+  %149 = load double, double* %9, align 8
+  %150 = fdiv double %148, %149
+  %151 = fptosi double %150 to i32
+  %152 = load %struct.Point*, %struct.Point** %8, align 8
+  %153 = getelementptr inbounds %struct.Point, %struct.Point* %152, i32 0, i32 0
+  store i32 %151, i32* %153, align 8
+  %154 = load double, double* %11, align 8
+  %155 = load double, double* %9, align 8
+  %156 = fdiv double %154, %155
+  %157 = fptosi double %156 to i32
+  %158 = load %struct.Point*, %struct.Point** %8, align 8
+  %159 = getelementptr inbounds %struct.Point, %struct.Point* %158, i32 0, i32 1
+  store i32 %157, i32* %159, align 4
+  %160 = load double, double* %9, align 8
+  %161 = load i32, i32* %6, align 4
+  %162 = sitofp i32 %161 to double
+  %163 = fdiv double %160, %162
+  %164 = load %struct.Point*, %struct.Point** %8, align 8
+  %165 = getelementptr inbounds %struct.Point, %struct.Point* %164, i32 0, i32 3
+  store double %163, double* %165, align 8
+  %166 = load %struct.Point*, %struct.Point** %8, align 8
+  %167 = getelementptr inbounds %struct.Point, %struct.Point* %166, i32 0, i32 2
+  %168 = getelementptr inbounds [256 x i8], [256 x i8]* %167, i64 0, i64 0
+  %169 = call i8* @strcpy(i8* %168, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.56, i64 0, i64 0)) #7
+  %170 = load %struct.Point*, %struct.Point** %8, align 8
+  store %struct.Point* %170, %struct.Point** %4, align 8
+  br label %171
+
+171:                                              ; preds = %147, %142, %130, %49, %33, %25, %19
+  %172 = load %struct.Point*, %struct.Point** %4, align 8
+  ret %struct.Point* %172
+}
+
+; Function Attrs: nounwind
+declare dso_local i8* @strcpy(i8*, i8*) #1
+
+; Function Attrs: nounwind readonly
+declare dso_local i64 @strlen(i8*) #5
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #6
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #6
+
+declare i32 @fused_quickSort(i1, i32*, i32, i32, i32*, i32)
+
+declare i32 @fused_performSimpleCalculations(i1, i32*, i32)
+
+declare %fused_return_projectA_main_memoizedFib @fused_projectA_main(i1, i32)
+
+declare %fused_return_createDynamicArray_processMatrix @fused_createDynamicArray(i1, i32, [100 x i32]*, i32)
+
+declare i32 @fused_setErrorMessage(i1, i8*)
+
+declare %struct.Matrix* @fused_createMatrix(i1, i32, i32, i8*)
+
+declare i32 @fused_removeDuplicates(i1, %struct.DynamicArray*, i32)
+
+attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #4 = { nounwind readnone speculatable willreturn }
+attributes #5 = { nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #6 = { argmemonly nounwind willreturn }
+attributes #7 = { nounwind }
+attributes #8 = { nounwind readnone }
+attributes #9 = { readnone }
+attributes #10 = { nounwind readonly }
+
+!llvm.ident = !{!0, !0}
+!llvm.module.flags = !{!1}
+
+!0 = !{!"clang version 10.0.0-4ubuntu1 "}
+!1 = !{i32 1, !"wchar_size", i32 4}
+!2 = !{!"Bunker"}

+ 935 - 19
src/ModuleFusion.cpp

@@ -16,10 +16,18 @@
 #include <random>
 #include <algorithm>
 #include <string>
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/Transforms/Utils/ValueMapper.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
 
 using namespace llvm;
 
 namespace {
+    struct Slice {
+        std::vector<BasicBlock*> blocks;
+    };
+
     struct CallNode {
         std::string name;
         bool isTarget;
@@ -27,12 +35,14 @@ namespace {
         std::set<std::string> callees;
         unsigned depth;
         std::set<BasicBlock*> criticalPoints;
-        unsigned num; // 融合点个数/分片个数
+        unsigned points_num; // 融合点个数
+        unsigned slices_num; //分片个数
+        std::vector<Slice> slices; // 存储函数分片
         
-        CallNode() : name(""), isTarget(false), depth(0), num(0) {}
+        CallNode() : name(""), isTarget(false), depth(0), points_num(0), slices_num(0) {}
 
         CallNode(std::string n, bool target = false) 
-            : name(n), isTarget(target), depth(0), num(0) {}
+            : name(n), isTarget(target), depth(0), points_num(0), slices_num(0) {}
     };
 
     struct CodeFusionPass : public ModulePass {
@@ -53,7 +63,9 @@ namespace {
             logger.enableFunction("createFunctionSlices");
             logger.enableFunction("countFusionPoints");
             logger.enableFunction("generateFusionMatchGraph");
-            
+            logger.enableFunction("performCodeFusion");
+            logger.enableFunction("updateCallSite");
+
             LOG_INFO("runOnModule", "Starting analysis for module: {0}", M.getName().str());
 
             for (Function &F : M) {
@@ -92,6 +104,7 @@ namespace {
                 LOG_INFO("runOnModule", "bunkerFuncName: {0}",bunkerFuncName);
                 if (Function* F = M.getFunction(bunkerFuncName)) {
                     countFusionPoints(*F);
+                    createFunctionSlices(*F);
                 } else {
                     LOG_ERROR("runOnModule", "Could not find function {0} in module", bunkerFuncName);
                 }
@@ -99,6 +112,7 @@ namespace {
 
             if(matchFunctionsForFusion()){
                 generateFusionMatchGraph();
+                performCodeFusion(M);
             }
 
             return false;
@@ -111,10 +125,6 @@ namespace {
         std::set<std::string> bunkerFunctions;
         std::map<std::string, std::string> fusionPairs;
 
-        struct Slice {
-            std::vector<BasicBlock*> blocks;
-        };
-
         size_t getRandomIndex(size_t max) {
             static unsigned seed = 0;
             seed = (seed * 1103515245 + 12345) & 0x7fffffff;
@@ -135,14 +145,14 @@ namespace {
             std::vector<std::string> sortedTargets(targetFunctions.begin(), targetFunctions.end());
             std::sort(sortedTargets.begin(), sortedTargets.end(),
                 [this](const std::string& a, const std::string& b) {
-                    return callGraph[a].num > callGraph[b].num;  // 降序排列
+                    return callGraph[a].slices_num > callGraph[b].slices_num;  // 降序排列
                 });
 
             std::vector<std::string> availableBunkers(bunkerFunctions.begin(), bunkerFunctions.end());
 
             for (const auto& targetFunc : sortedTargets) {
                 const auto& targetNode = callGraph[targetFunc];
-                size_t requiredPoints = targetNode.num;
+                size_t requiredPoints = targetNode.slices_num;
 
                 bool matched = false;
                 while (!availableBunkers.empty() && !matched) {
@@ -150,16 +160,16 @@ namespace {
                     const auto& bunkerFunc = availableBunkers[idx];
                     const auto& bunkerNode = callGraph[bunkerFunc];
 
-                    if (bunkerNode.num >= requiredPoints) {
+                    if (bunkerNode.points_num >= requiredPoints) {
                         fusionPairs[targetFunc] = bunkerFunc;
                         availableBunkers.erase(availableBunkers.begin() + idx);
                         matched = true;
                         LOG_INFO("matchFunctionsForFusion", 
                             "Matched target {0} ({1} slices) with bunker {2} ({3} fusion points)",
                             targetFunc, 
-                            targetNode.num,
+                            targetNode.slices_num,
                             bunkerFunc,
-                            bunkerNode.num);
+                            bunkerNode.points_num);
                     } else {
                         availableBunkers.erase(availableBunkers.begin() + idx);
                     }
@@ -195,9 +205,9 @@ namespace {
             errs() << "        direction TB\n";
             for (const auto& targetFunc : targetFunctions) {
                 std::string nodeId = sanitizeNodeId(targetFunc);
-                std::string criticalPoints = std::to_string(callGraph[targetFunc].criticalPoints.size());
+                std::string sliceNum = std::to_string(callGraph[targetFunc].slices_num);
                 errs() << "        " << nodeId << "[\"" << targetFunc 
-                    << "\\nCritical Points: " << criticalPoints
+                    << "\\nSliceNum: " << sliceNum
                     << "\"]:::target\n";
             }
             errs() << "    end\n\n";
@@ -246,10 +256,10 @@ namespace {
 
             auto& criticalPoints = callGraph[fname].criticalPoints;
             if (criticalPoints.empty()) {
-                callGraph[fname].num = 0;
+                callGraph[fname].points_num = 0;
                 return;
             }
-            callGraph[fname].num = criticalPoints.size();
+            callGraph[fname].points_num = criticalPoints.size();
 
             LOG_INFO("countFusionPoints", 
                 "Counted {0} fusion points for bunker function {1}",
@@ -279,7 +289,8 @@ namespace {
                 });
 
             std::set<BasicBlock*> processedBlocks;
-            std::vector<Slice> slices;
+            std::vector<Slice>& slices = callGraph[fname].slices;
+            slices.clear(); // 确保开始前清空
 
             for (size_t i = 0; i < orderedPoints.size(); i++) {
                 BasicBlock* currentCritical = orderedPoints[i];
@@ -334,7 +345,7 @@ namespace {
                 }
             }
 
-            callGraph[fname].num = slices.size();
+            callGraph[fname].slices_num = slices.size();
 
             LOG_INFO("createFunctionSlices", 
                 "Created {0} slices for target function {1}",
@@ -688,6 +699,911 @@ namespace {
             
             return id;
         }
+
+        // 创建融合函数类型
+        FunctionType* createFusedFunctionType(Function* bunkerFunc, Function* targetFunc, LLVMContext& Context) {
+            LOG_DEBUG("createFusedFunctionType", 
+                "Creating fused type for bunker={0}({1}) and target={2}({3})", 
+                bunkerFunc->getName().str(),
+                getReadableTypeName(bunkerFunc->getReturnType()),
+                targetFunc->getName().str(),
+                getReadableTypeName(targetFunc->getReturnType()));
+
+            std::vector<Type*> paramTypes;
+            
+            // 添加控制参数
+            paramTypes.push_back(Type::getInt1Ty(Context));
+            
+            // 添加bunker函数参数
+            for (const auto& arg : bunkerFunc->args()) {
+                paramTypes.push_back(arg.getType());
+            }
+            
+            // 添加target函数参数
+            for (const auto& arg : targetFunc->args()) {
+                paramTypes.push_back(arg.getType());
+            }
+            
+            // 创建返回类型
+            Type* returnType;
+            if (bunkerFunc->getReturnType()->isVoidTy() && targetFunc->getReturnType()->isVoidTy()) {
+                LOG_DEBUG("createFusedFunctionType", "Both functions return void, creating void return type");
+                returnType = Type::getVoidTy(Context);
+            } else if (bunkerFunc->getReturnType()->isVoidTy()) {
+                LOG_DEBUG("createFusedFunctionType", 
+                    "Bunker returns void, using target return type: {0}", 
+                    getReadableTypeName(targetFunc->getReturnType()));
+                returnType = targetFunc->getReturnType();
+            } else if (targetFunc->getReturnType()->isVoidTy()) {
+                LOG_DEBUG("createFusedFunctionType", 
+                    "Target returns void, using bunker return type: {0}", 
+                    getReadableTypeName(bunkerFunc->getReturnType()));
+                returnType = bunkerFunc->getReturnType();
+            } else {
+                LOG_DEBUG("createFusedFunctionType", "Creating struct return type for non-void returns");
+                std::vector<Type*> structTypes;
+                structTypes.push_back(targetFunc->getReturnType());
+                structTypes.push_back(bunkerFunc->getReturnType());
+                returnType = StructType::create(Context, structTypes, 
+                    "fused_return_" + bunkerFunc->getName().str() + "_" + targetFunc->getName().str());
+            }
+
+            LOG_DEBUG("createFusedFunctionType", 
+                "Created fused function type with return type: {0}", 
+                getReadableTypeName(returnType));
+
+            return FunctionType::get(returnType, paramTypes, false);
+        }
+
+        // 更新调用点
+        void updateCallSite(CallInst* CI, Function* fusedFunc, Function* origFunc, Function* otherFunc, bool isTarget) {
+            // 记录原始调用指令
+            std::string originalInstStr;
+            raw_string_ostream originalOS(originalInstStr);
+            CI->print(originalOS);
+            LOG_DEBUG("updateCallSite", "Original call instruction:\n  {0}", originalInstStr);
+
+            IRBuilder<> Builder(CI);
+            std::vector<Value*> Args;
+            
+            // 添加控制参数
+            Args.push_back(ConstantInt::get(Type::getInt1Ty(CI->getContext()), isTarget));
+            
+            // 记录参数类型信息
+            LOG_DEBUG("updateCallSite", "Adding {0} control parameter", isTarget ? "target" : "bunker");
+            
+            // 如果是target调用,先添加bunker的默认参数
+            if (isTarget) {
+                LOG_DEBUG("updateCallSite", "Adding default bunker parameters:");
+                for (const auto& arg : otherFunc->args()) {
+                    Type* ArgType = arg.getType();
+                    LOG_DEBUG("updateCallSite", "  Parameter type: {0}", getReadableTypeName(ArgType));
+                    if (ArgType->isPointerTy()) {
+                        Args.push_back(ConstantPointerNull::get(cast<PointerType>(ArgType)));
+                    } else if (ArgType->isIntegerTy()) {
+                        Args.push_back(ConstantInt::get(ArgType, 0));
+                    } else if (ArgType->isFloatingPointTy()) {
+                        Args.push_back(ConstantFP::get(ArgType, 0.0));
+                    } else {
+                        Args.push_back(UndefValue::get(ArgType));
+                    }
+                }
+            }
+            
+            // 添加原始调用的参数
+            LOG_DEBUG("updateCallSite", "Adding original call parameters:");
+            for (unsigned i = 0; i < CI->getNumArgOperands(); ++i) {
+                Value* ArgVal = CI->getArgOperand(i);
+                LOG_DEBUG("updateCallSite", "  Argument {0}: type={1}", 
+                    i, getReadableTypeName(ArgVal->getType()));
+                Args.push_back(ArgVal);
+            }
+            
+            // 如果是bunker调用,后添加target的默认参数
+            if (!isTarget) {
+                LOG_DEBUG("updateCallSite", "Adding default target parameters:");
+                for (const auto& arg : otherFunc->args()) {
+                    Type* ArgType = arg.getType();
+                    LOG_DEBUG("updateCallSite", "  Parameter type: {0}", getReadableTypeName(ArgType));
+                    if (ArgType->isPointerTy()) {
+                        Args.push_back(ConstantPointerNull::get(cast<PointerType>(ArgType)));
+                    } else if (ArgType->isIntegerTy()) {
+                        Args.push_back(ConstantInt::get(ArgType, 0));
+                    } else if (ArgType->isFloatingPointTy()) {
+                        Args.push_back(ConstantFP::get(ArgType, 0.0));
+                    } else {
+                        Args.push_back(UndefValue::get(ArgType));
+                    }
+                }
+            }
+            
+            // 创建新的调用指令
+            CallInst* NewCI = Builder.CreateCall(fusedFunc, Args);
+            
+            // 记录新调用指令
+            std::string newInstStr;
+            raw_string_ostream newOS(newInstStr);
+            NewCI->print(newOS);
+            LOG_DEBUG("updateCallSite", "New call instruction:\n  {0}", newInstStr);
+            
+            // 处理返回值
+            if (!CI->getType()->isVoidTy()) {
+                LOG_DEBUG("updateCallSite", "Processing non-void return value of type: {0}",
+                    getReadableTypeName(CI->getType()));
+                    
+                Value* ExtractedValue = nullptr;
+                if (StructType* STy = dyn_cast<StructType>(fusedFunc->getReturnType())) {
+                    LOG_DEBUG("updateCallSite", "Extracting value from struct return type");
+                    
+                    // 确保返回值是有效的结构体类型
+                    if (STy->getNumElements() != 2) {
+                        LOG_ERROR("updateCallSite", "Invalid fused function return type: expected 2 elements, got {0}",
+                            STy->getNumElements());
+                        return;
+                    }
+                    
+                    // 获取正确的索引和对应的类型
+                    unsigned idx = isTarget ? 0 : 1;
+                    Type* expectedType = STy->getElementType(idx);
+                    
+                    // 创建extractvalue指令
+                    ExtractedValue = Builder.CreateExtractValue(NewCI, {idx}, 
+                        "extracted_" + std::string(isTarget ? "target" : "bunker") + "_return");
+                    
+                    LOG_DEBUG("updateCallSite", "Extracted value type: {0}",
+                        getReadableTypeName(ExtractedValue->getType()));
+                        
+                    // 验证提取的值类型
+                    if (!ExtractedValue || ExtractedValue->getType() != expectedType) {
+                        LOG_ERROR("updateCallSite", "Extracted value type mismatch: expected {0}, got {1}",
+                            getReadableTypeName(expectedType),
+                            ExtractedValue ? getReadableTypeName(ExtractedValue->getType()) : "null");
+                        return;
+                    }
+                } else {
+                    ExtractedValue = NewCI;
+                    LOG_DEBUG("updateCallSite", "Using direct return value");
+                }
+                
+                // 类型转换
+                if (ExtractedValue && ExtractedValue->getType() != CI->getType()) {
+                    LOG_DEBUG("updateCallSite", "Type conversion needed from {0} to {1}",
+                        getReadableTypeName(ExtractedValue->getType()),
+                        getReadableTypeName(CI->getType()));
+                    
+                    // 确保源类型和目标类型都是有效的
+                    if (!ExtractedValue->getType() || !CI->getType()) {
+                        LOG_ERROR("updateCallSite", "Invalid type for conversion");
+                        return;
+                    }
+                    
+                    if (CI->getType()->isPointerTy() && ExtractedValue->getType()->isPointerTy()) {
+                        ExtractedValue = Builder.CreateBitCast(ExtractedValue, CI->getType(), 
+                            "conv_ptr_" + std::string(isTarget ? "target" : "bunker"));
+                    } else if (CI->getType()->isIntegerTy() && ExtractedValue->getType()->isIntegerTy()) {
+                        ExtractedValue = Builder.CreateIntCast(ExtractedValue, CI->getType(), true,
+                            "conv_int_" + std::string(isTarget ? "target" : "bunker"));
+                    } else if (CI->getType()->isFloatingPointTy() && ExtractedValue->getType()->isFloatingPointTy()) {
+                        if (CI->getType()->isDoubleTy()) {
+                            ExtractedValue = Builder.CreateFPExt(ExtractedValue, CI->getType(),
+                                "conv_fp_ext_" + std::string(isTarget ? "target" : "bunker"));
+                        } else {
+                            ExtractedValue = Builder.CreateFPTrunc(ExtractedValue, CI->getType(),
+                                "conv_fp_trunc_" + std::string(isTarget ? "target" : "bunker"));
+                        }
+                    } else {
+                        LOG_ERROR("updateCallSite", "Unsupported type conversion");
+                        return;
+                    }
+                }
+                
+                // 验证最终的返回值
+                if (!ExtractedValue || ExtractedValue->getType() != CI->getType()) {
+                    LOG_ERROR("updateCallSite", "Final value type mismatch: expected {0}, got {1}",
+                        getReadableTypeName(CI->getType()),
+                        ExtractedValue ? getReadableTypeName(ExtractedValue->getType()) : "null");
+                    return;
+                }
+                
+                // 替换原始调用的所有使用
+                CI->replaceAllUsesWith(ExtractedValue);
+                LOG_DEBUG("updateCallSite", "Successfully replaced all uses of original call");
+            } else {
+                LOG_DEBUG("updateCallSite", "Void return type, no value processing needed");
+            }
+            
+            // 删除原始调用指令
+            CI->eraseFromParent();
+            LOG_INFO("updateCallSite", "Successfully updated call site from {0} to {1}",
+                originalInstStr, newInstStr);
+        }
+
+        // 添加一个辅助函数来获取可读的类型名称
+        std::string getReadableTypeName(Type* Ty) {
+            if (!Ty) return "null";
+            
+            if (Ty->isVoidTy()) return "void";
+            if (Ty->isIntegerTy()) return "i" + std::to_string(Ty->getIntegerBitWidth());
+            if (Ty->isFloatingPointTy()) return Ty->isDoubleTy() ? "double" : "float";
+            if (Ty->isPointerTy()) return getReadableTypeName(Ty->getPointerElementType()) + "*";
+            if (Ty->isArrayTy()) return "array of " + getReadableTypeName(Ty->getArrayElementType());
+            if (Ty->isStructTy()) {
+                if (StructType* STy = dyn_cast<StructType>(Ty)) {
+                    return STy->hasName() ? STy->getName().str() : "anonymous struct";
+                }
+                return "struct";
+            }
+            if (Ty->isFunctionTy()) return "function";
+            
+            return "unknown";
+        }
+
+        void performCodeFusion(Module &M) {
+            LOG_INFO("performCodeFusion", "Starting code fusion");
+            
+            for (const auto& fusion : fusionPairs) {
+                const std::string& targetName = fusion.first;
+                const std::string& bunkerName = fusion.second;
+                
+                Function* targetFunc = M.getFunction(targetName);
+                Function* bunkerFunc = M.getFunction(bunkerName);
+                
+                if (!targetFunc || !bunkerFunc) {
+                    LOG_ERROR("performCodeFusion", 
+                        "Cannot find functions: target={0}, bunker={1}", 
+                        targetName, bunkerName);
+                    continue;
+                }
+                
+                LOG_INFO("performCodeFusion", 
+                    "Processing function pair: target={0}, bunker={1}", 
+                    targetName, bunkerName);
+
+                // 创建融合函数类型
+                FunctionType* fusedType = createFusedFunctionType(bunkerFunc, targetFunc, M.getContext());
+                Function* fusedFunc = Function::Create(fusedType, bunkerFunc->getLinkage(),
+                    "fused_" + bunkerName, &M);
+            
+                // 创建入口基本块
+                BasicBlock* entryBlock = BasicBlock::Create(M.getContext(), "entry", fusedFunc);
+                if (!entryBlock) {
+                    LOG_ERROR("performCodeFusion", "Failed to create entry block");
+                    continue;
+                }
+                
+                IRBuilder<> Builder(entryBlock);
+            
+                // 获取控制参数(isTarget)
+                Value* isTarget = fusedFunc->arg_begin();
+            
+                // 创建参数映射
+                ValueToValueMapTy bunkerVMap, targetVMap;
+                unsigned argIdx = 1; // 跳过isTarget参数
+            
+                // 映射bunker函数参数
+                for (auto& arg : bunkerFunc->args()) {
+                    bunkerVMap[&arg] = fusedFunc->getArg(argIdx++);
+                }
+            
+                // 映射target函数参数
+                for (auto& arg : targetFunc->args()) {
+                    targetVMap[&arg] = fusedFunc->getArg(argIdx++);
+                }
+
+                // 获取target函数的分片
+                const auto& targetSlices = callGraph[targetName].slices;
+                size_t currentSliceIndex = 0;
+
+                // 获取bunker函数的关键点集合
+                const auto& criticalPoints = callGraph[bunkerName].criticalPoints;
+            
+                // 用于存储所有克隆的基本块
+                std::map<BasicBlock*, BasicBlock*> bunkerBlockMap;
+                std::map<BasicBlock*, BasicBlock*> targetBlockMap;
+                std::vector<BasicBlock*> allFusedBlocks;
+
+                // 存储条件块的映射
+                // std::map<BasicBlock*, BasicBlock*> condBlockMap;
+
+                // bool hasOpenBunkerSlice = false;
+
+                // // 遍历bunker函数的所有基本块
+                // for (BasicBlock& BB : *bunkerFunc) {
+                //     // 如果当前基本块是关键点且还有未插入的target分片
+                //     if (currentSliceIndex < targetSlices.size() && criticalPoints.count(&BB)) {
+                //         // 处理未闭合的bunker条件分片
+                //         if (hasOpenBunkerSlice) {
+                //             // 创建phi块作为bunker条件分片的结束
+                //             BasicBlock* bunkerPhiBlock = BasicBlock::Create(M.getContext(), 
+                //                 "bunker_phi_" + std::to_string(currentSliceIndex), fusedFunc);
+                            
+                //             // 将当前bunker条件分片的skip块指向phi块
+                //             IRBuilder<> Builder(currentBunkerSkipBlock);
+                //             Builder.CreateBr(bunkerPhiBlock);
+                            
+                //             // 创建target分片的条件块
+                //             BasicBlock* targetCondBlock = BasicBlock::Create(M.getContext(), 
+                //                 "target_slice_cond_" + std::to_string(currentSliceIndex), fusedFunc);
+                            
+                //             // 将bunker的phi块指向target的条件块
+                //             IRBuilder<> PhiBuilder(bunkerPhiBlock);
+                //             PhiBuilder.CreateBr(targetCondBlock);
+                            
+                //             hasOpenBunkerSlice = false;
+                //         }else {
+                //             // 直接创建target分片的条件块
+                //             BasicBlock* targetCondBlock = BasicBlock::Create(M.getContext(), 
+                //                 "target_slice_cond_" + std::to_string(currentSliceIndex), fusedFunc);
+                            
+                //             // 如果这是第一个块,从入口块跳转到这里
+                //             if (allFusedBlocks.empty()) {
+                //                 IRBuilder<> EntryBuilder(entryBlock);
+                //                 EntryBuilder.CreateBr(targetCondBlock);
+                //             }
+                //         }
+                //         BasicBlock* targetSkipBlock = BasicBlock::Create(M.getContext(), 
+                //             "target_slice_skip_" + std::to_string(currentSliceIndex), fusedFunc);
+
+                //         // 创建phi块用于合并控制流
+                //         BasicBlock* targetPhiBlock = BasicBlock::Create(M.getContext(),
+                //             "target_phi_" + std::to_string(currentSliceIndex), fusedFunc);
+
+                //         IRBuilder<> CondBuilder(targetCondBlock);
+                //         Value* shouldRunTarget = CondBuilder.CreateICmpEQ(isTarget, 
+                //             ConstantInt::getTrue(Type::getInt1Ty(M.getContext())));
+
+                //         // 克隆并插入target分片的基本块
+                //         for (BasicBlock* targetBB : currentSlice.blocks) {
+                //             BasicBlock* clonedTargetBB = CloneBasicBlock(targetBB, targetVMap, 
+                //                 "target_" + targetBB->getName(), fusedFunc);
+                //             targetBlockMap[targetBB] = clonedTargetBB;
+                //             allFusedBlocks.push_back(clonedTargetBB);
+                //         }
+
+                //         // 设置条件跳转
+                //         CondBuilder.CreateCondBr(shouldRunTarget, 
+                //             targetBlockMap[currentSlice.blocks.front()], 
+                //             targetSkipBlock);
+
+                //         // 修改target分片最后一个块的跳转到phi块
+                //         BasicBlock* lastTargetBB = targetBlockMap[currentSlice.blocks.back()];
+                //         if (BranchInst* BI = dyn_cast<BranchInst>(lastTargetBB->getTerminator())) {
+                //             IRBuilder<> Builder(lastTargetBB);
+                //             Builder.CreateBr(targetPhiBlock);
+                //             BI->eraseFromParent();
+                //         }
+
+                //         // 从skip块跳转到phi块
+                //         IRBuilder<> SkipBuilder(targetSkipBlock);
+                //         SkipBuilder.CreateBr(targetPhiBlock);
+                        
+                //         // 创建新的bunker条件分片
+                //         currentBunkerCondBlock = BasicBlock::Create(M.getContext(), 
+                //             "bunker_slice_cond_" + std::to_string(currentSliceIndex), fusedFunc);
+                //         currentBunkerSkipBlock = BasicBlock::Create(M.getContext(), 
+                //             "bunker_slice_skip_" + std::to_string(currentSliceIndex), fusedFunc);
+                            
+                //         // 从phi块跳转到下一个bunker条件块
+                //         IRBuilder<> PhiBuilder(targetPhiBlock);
+                //         PhiBuilder.CreateBr(currentBunkerCondBlock);
+                        
+                //         // 设置bunker条件块的分支
+                //         IRBuilder<> BunkerCondBuilder(currentBunkerCondBlock);
+                //         Value* shouldRunBunker = BunkerCondBuilder.CreateICmpEQ(isTarget, 
+                //             ConstantInt::getFalse(Type::getInt1Ty(M.getContext())));
+                //         BunkerCondBuilder.CreateCondBr(shouldRunBunker, 
+                //             clonedBunkerBB, 
+                //             currentBunkerSkipBlock);
+                            
+                //         hasOpenBunkerSlice = true;
+                //         currentSliceIndex++;
+                //     }
+                //     else{
+                //         // 克隆bunker基本块
+                //         BasicBlock* clonedBunkerBB = CloneBasicBlock(&BB, bunkerVMap, 
+                //             "bunker_" + BB.getName(), fusedFunc);
+                //         bunkerBlockMap[&BB] = clonedBunkerBB;
+                //         allFusedBlocks.push_back(clonedBunkerBB);
+                //     }
+                // }
+                // // 处理最后一个未闭合的bunker条件分片
+                // if (hasOpenBunkerSlice) {
+                //     BasicBlock* finalPhiBlock = BasicBlock::Create(M.getContext(), 
+                //         "bunker_final_phi", fusedFunc);
+                //     IRBuilder<> Builder(currentBunkerSkipBlock);
+                //     Builder.CreateBr(finalPhiBlock);
+                // }
+
+
+
+
+                // 遍历bunker函数的所有基本块
+                for (BasicBlock& BB : *bunkerFunc) {
+                    // 如果当前基本块是关键点且还有未插入的target分片
+                    if (currentSliceIndex < targetSlices.size() && criticalPoints.count(&BB)) {
+                        // 克隆并插入target分片的基本块
+                        for (BasicBlock* targetBB : targetSlices[currentSliceIndex].blocks) {
+                            BasicBlock* clonedTargetBB = CloneBasicBlock(targetBB, targetVMap, 
+                                "target_" + targetBB->getName(), fusedFunc);
+                            targetBlockMap[targetBB] = clonedTargetBB;
+                            allFusedBlocks.push_back(clonedTargetBB);
+                        }
+                        currentSliceIndex++;
+                    }
+                    // 克隆bunker基本块
+                    BasicBlock* clonedBunkerBB = CloneBasicBlock(&BB, bunkerVMap, 
+                        "bunker_" + BB.getName(), fusedFunc);
+                    bunkerBlockMap[&BB] = clonedBunkerBB;
+                    allFusedBlocks.push_back(clonedBunkerBB);
+                }
+
+                // 修复target分片内的跳转
+                for (const auto& slice : targetSlices) {
+                    for (BasicBlock* BB : slice.blocks) {
+                        BasicBlock* clonedBB = targetBlockMap[BB];
+                        // 先修复所有非终结指令
+                        for (Instruction &I : make_range(clonedBB->begin(), --clonedBB->end())) {
+                            RemapInstruction(&I, targetVMap, RF_NoModuleLevelChanges);
+                            
+                            // 特别处理PHI节点
+                            if (PHINode* PHI = dyn_cast<PHINode>(&I)) {
+                                for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
+                                    BasicBlock* incomingBlock = PHI->getIncomingBlock(i);
+                                    if (targetBlockMap.count(incomingBlock)) {
+                                        PHI->setIncomingBlock(i, targetBlockMap[incomingBlock]);
+                                    }
+                                }
+                            }
+                        }
+                        
+                        // 单独处理终结指令
+                        if (BranchInst* BI = dyn_cast<BranchInst>(clonedBB->getTerminator())) {
+                            RemapInstruction(BI, targetVMap, RF_NoModuleLevelChanges);
+                            for (unsigned i = 0; i < BI->getNumSuccessors(); i++) {
+                                BasicBlock* succ = BI->getSuccessor(i);
+                                if (targetBlockMap.count(succ)) {
+                                    BI->setSuccessor(i, targetBlockMap[succ]);
+                                }
+                            }
+                        }
+                    }
+                }
+
+                // 修复bunker块内的跳转
+                for (auto& pair : bunkerBlockMap) {
+                    BasicBlock* clonedBB = pair.second;
+                    // 先修复所有非终结指令
+                    for (Instruction &I : make_range(clonedBB->begin(), --clonedBB->end())) {
+                        RemapInstruction(&I, bunkerVMap, RF_NoModuleLevelChanges);
+                        
+                        // 特别处理PHI节点
+                        if (PHINode* PHI = dyn_cast<PHINode>(&I)) {
+                            for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
+                                BasicBlock* incomingBlock = PHI->getIncomingBlock(i);
+                                if (bunkerBlockMap.count(incomingBlock)) {
+                                    PHI->setIncomingBlock(i, bunkerBlockMap[incomingBlock]);
+                                }
+                            }
+                        }
+                    }
+                    
+                    // 单独处理终结指令
+                    if (BranchInst* BI = dyn_cast<BranchInst>(clonedBB->getTerminator())) {
+                        RemapInstruction(BI, bunkerVMap, RF_NoModuleLevelChanges);
+                        for (unsigned i = 0; i < BI->getNumSuccessors(); i++) {
+                            BasicBlock* succ = BI->getSuccessor(i);
+                            if (bunkerBlockMap.count(succ)) {
+                                BI->setSuccessor(i, bunkerBlockMap[succ]);
+                            }
+                        }
+                    }
+                }
+
+                // 从入口块创建跳转到第一个块
+                Builder.CreateBr(allFusedBlocks.front());
+
+                // 在处理返回值之前添加日志
+                LOG_DEBUG("performCodeFusion", 
+                    "Processing return values for fused function: {0}", 
+                    fusedFunc->getName().str());
+
+                LOG_DEBUG("performCodeFusion", 
+                    "Fused function return type: {0}", 
+                    getReadableTypeName(fusedFunc->getReturnType()));
+
+                // 处理返回值
+                if (!fusedFunc->getReturnType()->isVoidTy()) {
+                    Type* returnType = fusedFunc->getReturnType();
+
+                    if (StructType* STy = dyn_cast<StructType>(returnType)) {
+                        LOG_DEBUG("performCodeFusion", 
+                            "Processing struct return type with {0} elements",
+                            STy->getNumElements());
+
+                        // 处理 bunker 函数的返回指令
+                        for (auto& pair : bunkerBlockMap) {
+                            BasicBlock* BB = pair.second;
+                            if (!BB || BB->empty()) continue;
+                            
+                            if (ReturnInst* RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
+                                IRBuilder<> Builder(RI);
+                                Value* bunkerRetVal = RI->getReturnValue();
+                                
+                                // 创建结构体实例并正确初始化
+                                Value* structVal = UndefValue::get(STy);
+                                Type* targetType = STy->getElementType(0);
+                                Type* bunkerType = STy->getElementType(1);
+
+                                // 设置target返回值位置为默认值
+                                LOG_DEBUG("performCodeFusion", "Setting default target return value");
+                                Value* defaultTargetVal;
+                                if (targetType->isPointerTy()) {
+                                    LOG_DEBUG("performCodeFusion", "Target type is pointer type, setting null pointer");
+                                    defaultTargetVal = ConstantPointerNull::get(cast<PointerType>(targetType));
+                                } else if (targetType->isIntegerTy()) {
+                                    LOG_DEBUG("performCodeFusion", "Target type is integer type, setting to 0");
+                                    defaultTargetVal = ConstantInt::get(targetType, 0);
+                                } else if (targetType->isFloatingPointTy()) {
+                                    LOG_DEBUG("performCodeFusion", "Target type is floating point type, setting to 0.0");
+                                    defaultTargetVal = ConstantFP::get(targetType, 0.0);
+                                } else {
+                                    // 为其他类型创建零初始化的常量
+                                    LOG_DEBUG("performCodeFusion", "Target type is other type, setting null value");
+                                    defaultTargetVal = Constant::getNullValue(targetType);
+                                }
+
+                                // // 在插入之前验证结构体类型
+                                // if (!isa<StructType>(structVal->getType())) {
+                                //     LOG_ERROR("performCodeFusion", 
+                                //         "Expected struct type for return value, got {0}",
+                                //         getReadableTypeName(structVal->getType()));
+                                //     continue;
+                                // }
+
+                                // // 验证插入值的类型
+                                // if (!defaultTargetVal || defaultTargetVal->getType() != targetType) {
+                                //     LOG_ERROR("performCodeFusion", 
+                                //         "Invalid default target value type: expected {0}, got {1}",
+                                //         getReadableTypeName(targetType),
+                                //         defaultTargetVal ? getReadableTypeName(defaultTargetVal->getType()) : "null");
+                                //     continue;
+                                // }
+
+                                // 创建新的结构体值并插入target值
+                                structVal = Builder.CreateInsertValue(structVal, defaultTargetVal, 0, "struct.target");
+
+                                // // 设置bunker返回值
+                                // if (!bunkerRetVal) {
+                                //     LOG_DEBUG("performCodeFusion", "Setting default bunker return value");
+                                //     if (bunkerType->isPointerTy()) {
+                                //         LOG_DEBUG("performCodeFusion", "Bunker type is pointer type, setting null pointer");
+                                //         bunkerRetVal = ConstantPointerNull::get(cast<PointerType>(bunkerType));
+                                //     } else if (bunkerType->isIntegerTy()) {
+                                //         LOG_DEBUG("performCodeFusion", "Bunker type is integer type, setting to 0");
+                                //         bunkerRetVal = ConstantInt::get(bunkerType, 0);
+                                //     } else if (bunkerType->isFloatingPointTy()) {
+                                //         LOG_DEBUG("performCodeFusion", "Bunker type is floating point type, setting to 0.0");
+                                //         bunkerRetVal = ConstantFP::get(bunkerType, 0.0);
+                                //     } else {
+                                //         LOG_DEBUG("performCodeFusion", "Bunker type is other type, setting undef value");
+                                //         bunkerRetVal = UndefValue::get(bunkerType);
+                                //     }
+                                // } else {
+                                //     // 如果需要类型转换
+                                //     if (bunkerRetVal->getType() != bunkerType) {
+                                //         if (bunkerRetVal->getType()->isIntegerTy() && bunkerType->isIntegerTy()) {
+                                //             bunkerRetVal = Builder.CreateIntCast(bunkerRetVal, bunkerType, true);
+                                //         } else if (bunkerRetVal->getType()->isPointerTy() && bunkerType->isPointerTy()) {
+                                //             bunkerRetVal = Builder.CreateBitCast(bunkerRetVal, bunkerType);
+                                //         } else {
+                                //             LOG_ERROR("performCodeFusion", 
+                                //                 "Incompatible bunker return value type: cannot convert from {0} to {1}",
+                                //                 getReadableTypeName(bunkerRetVal->getType()),
+                                //                 getReadableTypeName(bunkerType));
+                                //             continue;
+                                //         }
+                                //     }
+                                // }
+                                
+                                // // 在插入之前验证类型
+                                // if (bunkerRetVal->getType() != bunkerType) {
+                                //     LOG_ERROR("performCodeFusion", 
+                                //         "Type mismatch for bunker value: expected {0}, got {1}",
+                                //         getReadableTypeName(bunkerType),
+                                //         getReadableTypeName(bunkerRetVal->getType()));
+                                //     continue;
+                                // }
+                                structVal = Builder.CreateInsertValue(structVal, bunkerRetVal, 1);
+                                
+                                // 创建新的返回指令
+                                ReturnInst* NewRI = ReturnInst::Create(M.getContext(), structVal, RI);
+                                ReplaceInstWithInst(RI, NewRI);
+                                
+                                LOG_DEBUG("performCodeFusion", 
+                                    "Created struct return for bunker block: {0} with types: target={1}, bunker={2}", 
+                                    getNodeId(BB),
+                                    getReadableTypeName(targetType),
+                                    getReadableTypeName(bunkerType));
+                            }
+                        }
+
+                        // 处理 target 函数的返回指令
+                        for (auto& pair : targetBlockMap) {
+                            BasicBlock* BB = pair.second;
+                            if (!BB || BB->empty()) continue;
+                            
+                            if (ReturnInst* RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
+                                IRBuilder<> Builder(RI);
+                                Value* targetRetVal = RI->getReturnValue();
+                                
+                                // 创建结构体实例并正确初始化
+                                Value* structVal = UndefValue::get(STy);
+                                Type* targetType = STy->getElementType(0);
+                                Type* bunkerType = STy->getElementType(1);
+
+                                // 设置bunker返回值位置为默认值
+                                Value* defaultBunkerVal;
+                                if (bunkerType->isPointerTy()) {
+                                    defaultBunkerVal = ConstantPointerNull::get(cast<PointerType>(bunkerType));
+                                } else if (bunkerType->isIntegerTy()) {
+                                    defaultBunkerVal = ConstantInt::get(bunkerType, 0);
+                                } else if (bunkerType->isFloatingPointTy()) {
+                                    defaultBunkerVal = ConstantFP::get(bunkerType, 0.0);
+                                } else {
+                                    // 为其他类型创建零初始化的常量
+                                    defaultBunkerVal = Constant::getNullValue(bunkerType);
+                                }
+
+                                // // 在插入之前验证结构体类型
+                                // if (!isa<StructType>(structVal->getType())) {
+                                //     LOG_ERROR("performCodeFusion", 
+                                //         "Expected struct type for return value, got {0}",
+                                //         getReadableTypeName(structVal->getType()));
+                                //     continue;
+                                // }
+
+                                // // 验证插入值的类型
+                                // if (!defaultBunkerVal || defaultBunkerVal->getType() != bunkerType) {
+                                //     LOG_ERROR("performCodeFusion", 
+                                //         "Invalid default bunker value type: expected {0}, got {1}",
+                                //         getReadableTypeName(bunkerType),
+                                //         defaultBunkerVal ? getReadableTypeName(defaultBunkerVal->getType()) : "null");
+                                //     continue;
+                                // }
+
+                                // 创建新的结构体值并插入bunker值
+                                structVal = Builder.CreateInsertValue(structVal, defaultBunkerVal, 1, "struct.bunker");
+
+                                // 设置target返回值
+                                // if (!targetRetVal) {
+                                //     if (targetType->isPointerTy()) {
+                                //         targetRetVal = ConstantPointerNull::get(cast<PointerType>(targetType));
+                                //     } else if (targetType->isIntegerTy()) {
+                                //         targetRetVal = ConstantInt::get(targetType, 0);
+                                //     } else if (targetType->isFloatingPointTy()) {
+                                //         targetRetVal = ConstantFP::get(targetType, 0.0);
+                                //     } else {
+                                //         targetRetVal = UndefValue::get(targetType);
+                                //     }
+                                // } else {
+                                //     // 如果需要类型转换
+                                //     if (targetRetVal->getType() != targetType) {
+                                //         if (targetRetVal->getType()->isIntegerTy() && targetType->isIntegerTy()) {
+                                //             targetRetVal = Builder.CreateIntCast(targetRetVal, targetType, true);
+                                //         } else if (targetRetVal->getType()->isPointerTy() && targetType->isPointerTy()) {
+                                //             targetRetVal = Builder.CreateBitCast(targetRetVal, targetType);
+                                //         } else {
+                                //             LOG_ERROR("performCodeFusion", 
+                                //                 "Incompatible target return value type: cannot convert from {0} to {1}",
+                                //                 getReadableTypeName(targetRetVal->getType()),
+                                //                 getReadableTypeName(targetType));
+                                //             continue;
+                                //         }
+                                //     }
+                                // }
+                                
+                                // // 在插入之前验证类型
+                                // if (targetRetVal->getType() != targetType) {
+                                //     LOG_ERROR("performCodeFusion", 
+                                //         "Type mismatch for target value: expected {0}, got {1}",
+                                //         getReadableTypeName(targetType),
+                                //         getReadableTypeName(targetRetVal->getType()));
+                                //     continue;
+                                // }
+                                structVal = Builder.CreateInsertValue(structVal, targetRetVal, 0);
+                                
+                                // 创建新的返回指令
+                                ReturnInst* NewRI = ReturnInst::Create(M.getContext(), structVal, RI);
+                                ReplaceInstWithInst(RI, NewRI);
+                                
+                                LOG_DEBUG("performCodeFusion", 
+                                    "Created struct return for target block: {0} with types: target={1}, bunker={2}", 
+                                    getNodeId(BB),
+                                    getReadableTypeName(targetType),
+                                    getReadableTypeName(bunkerType));
+                            }
+                        }
+                    } else {
+                        // 处理非结构体返回值的情况
+                        LOG_DEBUG("performCodeFusion", 
+                            "Non-struct return type detected: {0}", 
+                            getReadableTypeName(returnType));
+
+                        // 处理 bunker 函数的返回指令
+                        for (auto& pair : bunkerBlockMap) {
+                            BasicBlock* BB = pair.second;
+                            if (!BB || BB->empty()) continue;
+                            
+                            if (ReturnInst* RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
+                                IRBuilder<> Builder(RI);
+                                Value* bunkerRetVal = RI->getReturnValue();
+                                
+                                // 先重映射返回值
+                                if (bunkerRetVal) {
+                                    bunkerRetVal = MapValue(bunkerRetVal, bunkerVMap);
+                                }
+                                
+                                if (!bunkerRetVal) {
+                                    if (returnType->isIntegerTy()) {
+                                        bunkerRetVal = ConstantInt::get(returnType, 0);
+                                    } else if (returnType->isPointerTy()) {
+                                        bunkerRetVal = ConstantPointerNull::get(cast<PointerType>(returnType));
+                                    } else if (returnType->isFloatingPointTy()) {
+                                        bunkerRetVal = ConstantFP::get(returnType, 0.0);
+                                    } else {
+                                        bunkerRetVal = UndefValue::get(returnType);
+                                    }
+                                } else if (bunkerRetVal->getType() != returnType) {
+                                    bunkerRetVal = Builder.CreateBitCast(bunkerRetVal, returnType);
+                                }
+                                
+                                ReturnInst* NewRI = ReturnInst::Create(M.getContext(), bunkerRetVal);
+                                ReplaceInstWithInst(RI, NewRI);
+                                
+                                LOG_DEBUG("performCodeFusion", 
+                                    "Updated bunker return in block {0} with value type {1}",
+                                    getNodeId(BB),
+                                    getReadableTypeName(bunkerRetVal->getType()));
+                            }
+                        }
+
+                        // 处理 target 函数的返回指令
+                        for (auto& pair : targetBlockMap) {
+                            BasicBlock* BB = pair.second;
+                            if (!BB || BB->empty()) continue;
+                            
+                            if (ReturnInst* RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
+                                IRBuilder<> Builder(RI);
+                                Value* targetRetVal = RI->getReturnValue();
+                                
+                                // 先重映射返回值
+                                if (targetRetVal) {
+                                    targetRetVal = MapValue(targetRetVal, targetVMap);
+                                }
+                                
+                                if (!targetRetVal) {
+                                    if (returnType->isIntegerTy()) {
+                                        targetRetVal = ConstantInt::get(returnType, 0);
+                                    } else if (returnType->isPointerTy()) {
+                                        targetRetVal = ConstantPointerNull::get(cast<PointerType>(returnType));
+                                    } else if (returnType->isFloatingPointTy()) {
+                                        targetRetVal = ConstantFP::get(returnType, 0.0);
+                                    } else {
+                                        targetRetVal = UndefValue::get(returnType);
+                                    }
+                                } else if (targetRetVal->getType() != returnType) {
+                                    targetRetVal = Builder.CreateBitCast(targetRetVal, returnType);
+                                }
+                                
+                                ReturnInst* NewRI = ReturnInst::Create(M.getContext(), targetRetVal);
+                                ReplaceInstWithInst(RI, NewRI);
+                                
+                                LOG_DEBUG("performCodeFusion", 
+                                    "Updated target return in block {0} with value type {1}",
+                                    getNodeId(BB),
+                                    getReadableTypeName(targetRetVal->getType()));
+                            }
+                        }
+                    }
+                } else {
+                    LOG_INFO("performCodeFusion", 
+                        "Fused function {0} has void return type", 
+                        fusedFunc->getName().str());
+                    
+                    // 处理 void 返回类型的情况
+                    for (auto& pair : bunkerBlockMap) {
+                        BasicBlock* BB = pair.second;
+                        if (!BB || BB->empty()) continue;
+                        
+                        if (ReturnInst* RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
+                            LOG_DEBUG("performCodeFusion", 
+                                "Converting bunker return instruction to void return in block: {0}", 
+                                getNodeId(BB));
+                                
+                            ReturnInst* NewRI = ReturnInst::Create(M.getContext(), nullptr, RI);
+                            ReplaceInstWithInst(RI, NewRI);
+                        }
+                    }
+                    
+                    for (auto& pair : targetBlockMap) {
+                        BasicBlock* BB = pair.second;
+                        if (!BB || BB->empty()) continue;
+                        
+                        if (ReturnInst* RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
+                            LOG_DEBUG("performCodeFusion", 
+                                "Converting target return instruction to void return in block: {0}", 
+                                BB->getName().str());
+                                
+                            ReturnInst* NewRI = ReturnInst::Create(M.getContext(), nullptr, RI);
+                            ReplaceInstWithInst(RI, NewRI);
+                        }
+                    }
+                }
+
+                // 更新调用点
+                std::vector<CallInst*> bunkerCalls;
+                std::vector<CallInst*> targetCalls;
+
+                // 收集所有调用点
+                for (auto& U : bunkerFunc->uses()) {
+                    if (CallInst* CI = dyn_cast<CallInst>(U.getUser())) {
+                        bunkerCalls.push_back(CI);
+                    }
+                }
+
+                for (auto& U : targetFunc->uses()) {
+                    if (CallInst* CI = dyn_cast<CallInst>(U.getUser())) {
+                        targetCalls.push_back(CI);
+                    }
+                }
+
+                // 更新调用点
+                for (CallInst* CI : bunkerCalls) {
+                    updateCallSite(CI, fusedFunc, bunkerFunc, targetFunc, false);
+                }
+
+                for (CallInst* CI : targetCalls) {
+                    updateCallSite(CI, fusedFunc, targetFunc, bunkerFunc, true);
+                }
+                
+                // 删除原始函数
+                bunkerFunc->eraseFromParent();
+                targetFunc->eraseFromParent();
+
+                // 输出融合函数中的所有返回指令
+                LOG_INFO("performCodeFusion", "Listing all return instructions in fused function: {0}", 
+                    fusedFunc->getName().str());
+                    
+                for (BasicBlock &BB : *fusedFunc) {
+                    if (ReturnInst* RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
+                        std::string retInstStr;
+                        raw_string_ostream retOS(retInstStr);
+                        RI->print(retOS);
+                        
+                        LOG_INFO("performCodeFusion", 
+                            "Return instruction in block {0}:\n  {1}", 
+                            BB.getName().str(),
+                            retInstStr);
+                            
+                        if (Value* RetVal = RI->getReturnValue()) {
+                            LOG_INFO("performCodeFusion", 
+                                "  Return value type: {0}", 
+                                getReadableTypeName(RetVal->getType()));
+                        } else {
+                            LOG_INFO("performCodeFusion", "  Void return");
+                        }
+                    }
+                }
+                
+                LOG_INFO("performCodeFusion", 
+                    "Completed function fusion: {0}", 
+                    fusedFunc->getName().str());
+            }
+            
+            LOG_INFO("performCodeFusion", 
+                "Code fusion completed, processed {0} function pairs", 
+                fusionPairs.size());
+        }
     };
 }
 

Some files were not shown because too many files changed in this diff