VapourSynth-llvmexpr
Loading...
Searching...
No Matches
analysis::DynamicArrayAllocOptPass Class Reference

#include <llvmexpr/analysis/passes/DynamicArrayAllocOptPass.hpp>

Inheritance diagram for analysis::DynamicArrayAllocOptPass:
Collaboration diagram for analysis::DynamicArrayAllocOptPass:

Public Member Functions

const char * getName () const override
PreservedAnalyses run (std::vector< Token > &tokens, AnalysisManager &am) override
Public Member Functions inherited from analysis::Pass
 Pass ()=default
virtual ~Pass ()=default
 Pass (const Pass &)=delete
Passoperator= (const Pass &)=delete
 Pass (Pass &&)=delete
Passoperator= (Pass &&)=delete

Detailed Description

Eliminates redundant dynamic array allocations. If between two allocations of the same array, there are no reads or writes to that array on all possible control flow paths, the first allocation is replaced with a DROP instruction to maintain stack effects.

Depends on: BlockAnalysisPass, BuildCFGPass

Definition at line 36 of file DynamicArrayAllocOptPass.hpp.

Member Function Documentation

◆ getName()

const char * analysis::DynamicArrayAllocOptPass::getName ( ) const
inlinenodiscardoverridevirtual

Implements analysis::Pass.

Definition at line 38 of file DynamicArrayAllocOptPass.hpp.

38 {
39 return "Dynamic Array Allocation Optimization Pass";
40 }

◆ run()

PreservedAnalyses analysis::DynamicArrayAllocOptPass::run ( std::vector< Token > & tokens,
AnalysisManager & am )
overridevirtual

Implements analysis::TransformationPass.

Definition at line 123 of file DynamicArrayAllocOptPass.cpp.

124 {
125 const auto& block_result = am.getResult<BlockAnalysisPass>();
126 const auto& cfg_blocks = block_result.cfg_blocks;
127
128 std::set<int> allocations_to_remove;
129
130 std::map<std::string, std::vector<int>> dynamic_allocations;
131
132 for (size_t i = 0; i < tokens.size(); ++i) {
133 const auto& token = tokens[i];
134 if (token.type == TokenType::ArrayAllocDyn) {
135 const auto& payload = std::get<TokenPayloadArrayOp>(token.payload);
136 dynamic_allocations[payload.name].push_back(static_cast<int>(i));
137 }
138 }
139
140 for (const auto& [array_name, alloc_indices] : dynamic_allocations) {
141 if (alloc_indices.size() < 2) {
142 continue;
143 }
144
145 for (size_t i = 0; i < alloc_indices.size() - 1; ++i) {
146 int first_alloc = alloc_indices[i];
147 int second_alloc = alloc_indices[i + 1];
148
149 bool used = is_array_used_between(array_name, tokens, cfg_blocks,
150 first_alloc, second_alloc);
151
152 if (!used) {
153 allocations_to_remove.insert(first_alloc);
154 }
155 }
156 }
157
158 if (allocations_to_remove.empty()) {
159 return PreservedAnalyses::all();
160 }
161
162 for (int token_idx : allocations_to_remove) {
163 auto& token = tokens[token_idx];
164 token.type = TokenType::Drop;
165 token.text = "drop1";
166 token.payload = TokenPayloadStackOp{.n = 1};
167 }
168
170}
static PreservedAnalyses all()
static PreservedAnalyses none()

References analysis::PreservedAnalyses::all(), ArrayAllocDyn, Drop, analysis::AnalysisManager::getResult(), and analysis::PreservedAnalyses::none().


The documentation for this class was generated from the following files: