| 158 | } |
| 159 | |
| 160 | Reducer::ReductionResultStatus Reducer::RunPasses( |
| 161 | std::vector<std::unique_ptr<ReductionPass>>* passes, |
| 162 | spv_const_reducer_options options, spv_validator_options validator_options, |
| 163 | const SpirvTools& tools, std::vector<uint32_t>* current_binary, |
| 164 | uint32_t* const reductions_applied) { |
| 165 | // Determines whether, on completing one round of reduction passes, it is |
| 166 | // worthwhile trying a further round. |
| 167 | bool another_round_worthwhile = true; |
| 168 | |
| 169 | // Apply round after round of reduction passes until we hit the reduction |
| 170 | // step limit, or deem that another round is not going to be worthwhile. |
| 171 | while (!ReachedStepLimit(*reductions_applied, options) && |
| 172 | another_round_worthwhile) { |
| 173 | // At the start of a round of reduction passes, assume another round will |
| 174 | // not be worthwhile unless we find evidence to the contrary. |
| 175 | another_round_worthwhile = false; |
| 176 | |
| 177 | // Iterate through the available passes. |
| 178 | for (auto& pass : *passes) { |
| 179 | // If this pass hasn't reached its minimum granularity then it's |
| 180 | // worth eventually doing another round of reductions, in order to |
| 181 | // try this pass at a finer granularity. |
| 182 | another_round_worthwhile |= !pass->ReachedMinimumGranularity(); |
| 183 | |
| 184 | // Keep applying this pass at its current granularity until it stops |
| 185 | // working or we hit the reduction step limit. |
| 186 | consumer_(SPV_MSG_INFO, nullptr, {}, |
| 187 | ("Trying pass " + pass->GetName() + ".").c_str()); |
| 188 | do { |
| 189 | auto maybe_result = |
| 190 | pass->TryApplyReduction(*current_binary, options->target_function); |
| 191 | if (maybe_result.empty()) { |
| 192 | // For this round, the pass has no more opportunities (chunks) to |
| 193 | // apply, so move on to the next pass. |
| 194 | consumer_( |
| 195 | SPV_MSG_INFO, nullptr, {}, |
| 196 | ("Pass " + pass->GetName() + " did not make a reduction step.") |
| 197 | .c_str()); |
| 198 | break; |
| 199 | } |
| 200 | bool interesting = false; |
| 201 | std::stringstream stringstream; |
| 202 | (*reductions_applied)++; |
| 203 | stringstream << "Pass " << pass->GetName() << " made reduction step " |
| 204 | << *reductions_applied << "."; |
| 205 | consumer_(SPV_MSG_INFO, nullptr, {}, (stringstream.str().c_str())); |
| 206 | if (!tools.Validate(&maybe_result[0], maybe_result.size(), |
| 207 | validator_options)) { |
| 208 | // The reduction step went wrong and an invalid binary was produced. |
| 209 | // By design, this shouldn't happen; this is a safeguard to stop an |
| 210 | // invalid binary from being regarded as interesting. |
| 211 | consumer_(SPV_MSG_INFO, nullptr, {}, |
| 212 | "Reduction step produced an invalid binary."); |
| 213 | if (options->fail_on_validation_error) { |
| 214 | // In this mode, we fail, so we update the current binary so it is |
| 215 | // output for debugging. |
| 216 | *current_binary = std::move(maybe_result); |
| 217 | return Reducer::ReductionResultStatus::kStateInvalid; |
nothing calls this directly
no test coverage detected