GCC Code Coverage Report


Directory: ../
File: src/iroptimizer/IROptimizer.cpp
Date: 2025-12-07 00:53:49
Coverage Exec Excl Total
Lines: 98.5% 67 9 77
Functions: 100.0% 7 0 7
Branches: 55.9% 38 36 104

Line Branch Exec Source
1 // Copyright (c) 2021-2025 ChilliBits. All rights reserved.
2
3 #include "IROptimizer.h"
4
5 #include <llvm/Analysis/ModuleSummaryAnalysis.h>
6 #include <llvm/Transforms/Instrumentation/AddressSanitizer.h>
7 #include <llvm/Transforms/Instrumentation/MemorySanitizer.h>
8 #include <llvm/Transforms/Instrumentation/ThreadSanitizer.h>
9 #include <llvm/Transforms/Instrumentation/TypeSanitizer.h>
10
11 #include <driver/Driver.h>
12
13 namespace spice::compiler {
14
15 894 void IROptimizer::prepare() {
16
1/2
✓ Branch 2 → 3 taken 894 times.
✗ Branch 2 → 25 not taken.
894 llvm::PipelineTuningOptions pto;
17
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 894 times.
894 if (!resourceManager.cliOptions.testMode)
18 si.registerCallbacks(pic, &moduleAnalysisMgr);
19
1/2
✓ Branch 6 → 7 taken 894 times.
✗ Branch 6 → 21 not taken.
894 passBuilder = std::make_unique<llvm::PassBuilder>(sourceFile->targetMachine.get(), pto, std::nullopt, &pic);
20
21
1/2
✓ Branch 9 → 10 taken 894 times.
✗ Branch 9 → 24 not taken.
1788 functionAnalysisMgr.registerPass([&] { return passBuilder->buildDefaultAAPipeline(); });
22
23
1/2
✓ Branch 11 → 12 taken 894 times.
✗ Branch 11 → 25 not taken.
894 passBuilder->registerModuleAnalyses(moduleAnalysisMgr);
24
1/2
✓ Branch 13 → 14 taken 894 times.
✗ Branch 13 → 25 not taken.
894 passBuilder->registerCGSCCAnalyses(cgsccAnalysisMgr);
25
1/2
✓ Branch 15 → 16 taken 894 times.
✗ Branch 15 → 25 not taken.
894 passBuilder->registerFunctionAnalyses(functionAnalysisMgr);
26
1/2
✓ Branch 17 → 18 taken 894 times.
✗ Branch 17 → 25 not taken.
894 passBuilder->registerLoopAnalyses(loopAnalysisMgr);
27
1/2
✓ Branch 19 → 20 taken 894 times.
✗ Branch 19 → 25 not taken.
894 passBuilder->crossRegisterProxies(loopAnalysisMgr, functionAnalysisMgr, cgsccAnalysisMgr, moduleAnalysisMgr);
28 894 }
29
30 891 void IROptimizer::optimizeDefault() {
31 if (cliOptions.printDebugOutput && cliOptions.dump.dumpIR && !cliOptions.dump.dumpToFiles) // GCOV_EXCL_LINE
32 std::cout << "\nOptimizing on level " + std::to_string(static_cast<uint8_t>(cliOptions.optLevel)) // GCOV_EXCL_LINE
33 << " ...\n"; // GCOV_EXCL_LINE
34
35 // Prepare pipeline
36 891 const llvm::OptimizationLevel llvmOptLevel = getLLVMOptLevelFromSpiceOptLevel();
37
1/2
✓ Branch 14 → 15 taken 891 times.
✗ Branch 14 → 30 not taken.
891 llvm::ModulePassManager modulePassMgr = passBuilder->buildPerModuleDefaultPipeline(llvmOptLevel);
38
39 // Add optional passes
40
1/2
✓ Branch 15 → 16 taken 891 times.
✗ Branch 15 → 28 not taken.
891 addInstrumentationPassToPipeline(modulePassMgr);
41
42 // Run pipeline
43
1/2
✓ Branch 17 → 18 taken 891 times.
✗ Branch 17 → 27 not taken.
891 modulePassMgr.run(*sourceFile->llvmModule, moduleAnalysisMgr);
44 891 }
45
46 2 void IROptimizer::optimizePreLink() {
47 if (cliOptions.printDebugOutput && cliOptions.dump.dumpIR && !cliOptions.dump.dumpToFiles) // GCOV_EXCL_LINE
48 std::cout << "\nOptimizing on level " + std::to_string(static_cast<uint8_t>(cliOptions.optLevel)) // GCOV_EXCL_LINE
49 << " (pre-link) ...\n"; // GCOV_EXCL_LINE
50
51 // Prepare pipeline
52 2 const llvm::OptimizationLevel llvmOptLevel = getLLVMOptLevelFromSpiceOptLevel();
53
1/2
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 33 not taken.
2 llvm::ModulePassManager modulePassMgr = passBuilder->buildLTOPreLinkDefaultPipeline(llvmOptLevel);
54
55 // Run pipeline
56
1/2
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 29 not taken.
2 modulePassMgr.run(*sourceFile->llvmModule, moduleAnalysisMgr);
57
58 // Generate module summary index
59 llvm::ModuleSummaryIndexAnalysis moduleSummaryIndexAnalysis;
60
1/2
✓ Branch 19 → 20 taken 2 times.
✗ Branch 19 → 30 not taken.
2 moduleSummaryIndexAnalysis.run(*sourceFile->llvmModule, moduleAnalysisMgr);
61 2 }
62
63 1 void IROptimizer::optimizePostLink() {
64 if (cliOptions.printDebugOutput && cliOptions.dump.dumpIR && !cliOptions.dump.dumpToFiles) // GCOV_EXCL_LINE
65 std::cout << "\nOptimizing on level " + std::to_string(static_cast<uint8_t>(cliOptions.optLevel)) // GCOV_EXCL_LINE
66 << " (post-link) ...\n"; // GCOV_EXCL_LINE
67 1 llvm::Module &ltoModule = *resourceManager.ltoModule;
68
69 // Compute module summary index
70 llvm::ModuleSummaryIndexAnalysis moduleSummaryIndexAnalysis;
71
1/2
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 35 not taken.
1 llvm::ModuleSummaryIndex moduleSummaryIndex = moduleSummaryIndexAnalysis.run(ltoModule, moduleAnalysisMgr);
72 1 moduleSummaryIndex.setWithWholeProgramVisibility();
73
74 // Prepare pipeline
75 1 const llvm::OptimizationLevel llvmOptLevel = getLLVMOptLevelFromSpiceOptLevel();
76
1/2
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 33 not taken.
1 llvm::ModulePassManager modulePassMgr = passBuilder->buildLTODefaultPipeline(llvmOptLevel, &moduleSummaryIndex);
77
78 // Add optional passes
79
1/2
✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 31 not taken.
1 addInstrumentationPassToPipeline(modulePassMgr);
80
81 // Run pipeline
82
1/2
✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 30 not taken.
1 modulePassMgr.run(ltoModule, moduleAnalysisMgr);
83 1 }
84
85 892 void IROptimizer::addInstrumentationPassToPipeline(llvm::ModulePassManager &modulePassMgr) const {
86
5/6
✓ Branch 2 → 3 taken 877 times.
✓ Branch 2 → 4 taken 5 times.
✓ Branch 2 → 8 taken 6 times.
✓ Branch 2 → 13 taken 2 times.
✓ Branch 2 → 18 taken 2 times.
✗ Branch 2 → 20 not taken.
892 switch (cliOptions.instrumentation.sanitizer) {
87 877 case Sanitizer::NONE: {
88 877 return;
89 }
90 5 case Sanitizer::ADDRESS: {
91 5 llvm::AddressSanitizerOptions asanOptions;
92 5 asanOptions.UseAfterScope = true;
93
2/4
✓ Branch 4 → 5 taken 5 times.
✗ Branch 4 → 21 not taken.
✓ Branch 5 → 6 taken 5 times.
✗ Branch 5 → 21 not taken.
5 modulePassMgr.addPass(llvm::AddressSanitizerPass(asanOptions));
94 5 break;
95 }
96 6 case Sanitizer::THREAD: {
97
1/2
✓ Branch 8 → 9 taken 6 times.
✗ Branch 8 → 23 not taken.
6 modulePassMgr.addPass(llvm::ModuleThreadSanitizerPass());
98
2/4
✓ Branch 9 → 10 taken 6 times.
✗ Branch 9 → 26 not taken.
✓ Branch 10 → 11 taken 6 times.
✗ Branch 10 → 24 not taken.
6 modulePassMgr.addPass(llvm::createModuleToFunctionPassAdaptor(llvm::ThreadSanitizerPass()));
99 6 break;
100 }
101 2 case Sanitizer::MEMORY: {
102
1/2
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 29 not taken.
2 llvm::MemorySanitizerOptions msanOptions;
103 2 msanOptions.EagerChecks = true;
104
1/2
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 28 not taken.
2 modulePassMgr.addPass(llvm::MemorySanitizerPass(msanOptions));
105 2 break;
106 }
107 2 case Sanitizer::TYPE: {
108
1/2
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 30 not taken.
2 modulePassMgr.addPass(llvm::TypeSanitizerPass());
109 2 break;
110 }
111 }
112 }
113
114 894 llvm::OptimizationLevel IROptimizer::getLLVMOptLevelFromSpiceOptLevel() const {
115
6/6
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 23 times.
✓ Branch 2 → 5 taken 6 times.
✓ Branch 2 → 6 taken 1 time.
✓ Branch 2 → 7 taken 1 time.
✓ Branch 2 → 8 taken 862 times.
894 switch (cliOptions.optLevel) {
116 1 case OptLevel::O1:
117 1 return llvm::OptimizationLevel::O1;
118 23 case OptLevel::O2:
119 23 return llvm::OptimizationLevel::O2;
120 6 case OptLevel::O3:
121 6 return llvm::OptimizationLevel::O3;
122 1 case OptLevel::Os:
123 1 return llvm::OptimizationLevel::Os;
124 1 case OptLevel::Oz:
125 1 return llvm::OptimizationLevel::Oz;
126 862 default:
127 862 return llvm::OptimizationLevel::O0;
128 }
129 }
130
131 } // namespace spice::compiler
132