| 118 | } |
| 119 | |
| 120 | std::map<FunctionHandle, SideEffects> SideEffectsPropagator::sideEffects( |
| 121 | Dialect const& _dialect, |
| 122 | CallGraph const& _directCallGraph |
| 123 | ) |
| 124 | { |
| 125 | // Any loop currently makes a function non-movable, because |
| 126 | // it could be a non-terminating loop. |
| 127 | // The same is true for any function part of a call cycle. |
| 128 | // In the future, we should refine that, because the property |
| 129 | // is actually a bit different from "not movable". |
| 130 | |
| 131 | std::map<FunctionHandle, SideEffects> ret; |
| 132 | for (auto const& function: _directCallGraph.functionsWithLoops) |
| 133 | { |
| 134 | ret[function].movable = false; |
| 135 | ret[function].canBeRemoved = false; |
| 136 | ret[function].canBeRemovedIfNoMSize = false; |
| 137 | ret[function].cannotLoop = false; |
| 138 | } |
| 139 | |
| 140 | for (auto const& function: _directCallGraph.recursiveFunctions()) |
| 141 | { |
| 142 | ret[function].movable = false; |
| 143 | ret[function].canBeRemoved = false; |
| 144 | ret[function].canBeRemovedIfNoMSize = false; |
| 145 | ret[function].cannotLoop = false; |
| 146 | } |
| 147 | |
| 148 | for (auto const& call: _directCallGraph.functionCalls) |
| 149 | { |
| 150 | FunctionHandle funName = call.first; |
| 151 | SideEffects sideEffects; |
| 152 | auto _visit = [&, visited = std::set<FunctionHandle>{}](FunctionHandle _function, auto&& _recurse) mutable { |
| 153 | if (!visited.insert(_function).second) |
| 154 | return; |
| 155 | if (sideEffects == SideEffects::worst()) |
| 156 | return; |
| 157 | if (BuiltinHandle const* builtinHandle = std::get_if<BuiltinHandle>(&_function)) |
| 158 | sideEffects += _dialect.builtin(*builtinHandle).sideEffects; |
| 159 | else |
| 160 | { |
| 161 | if (ret.count(_function)) |
| 162 | sideEffects += ret[_function]; |
| 163 | for (FunctionHandle const& callee: _directCallGraph.functionCalls.at(_function)) |
| 164 | _recurse(callee, _recurse); |
| 165 | } |
| 166 | }; |
| 167 | for (auto const& _v: call.second) |
| 168 | _visit(_v, _visit); |
| 169 | ret[funName] += sideEffects; |
| 170 | } |
| 171 | return ret; |
| 172 | } |
| 173 | |
| 174 | MovableChecker::MovableChecker(Dialect const& _dialect, Expression const& _expression): |
| 175 | MovableChecker(_dialect) |
no test coverage detected