| 50 | AddedFunctionReducer::~AddedFunctionReducer() = default; |
| 51 | |
| 52 | AddedFunctionReducer::AddedFunctionReducerResult AddedFunctionReducer::Run() { |
| 53 | // Replay all transformations before the AddFunction transformation, then |
| 54 | // add the raw function associated with the AddFunction transformation. |
| 55 | std::vector<uint32_t> binary_to_reduce; |
| 56 | std::unordered_set<uint32_t> irrelevant_pointee_global_variables; |
| 57 | ReplayPrefixAndAddFunction(&binary_to_reduce, |
| 58 | &irrelevant_pointee_global_variables); |
| 59 | |
| 60 | // Set up spirv-reduce to use our very specific interestingness function. |
| 61 | reduce::Reducer reducer(target_env_); |
| 62 | reducer.SetMessageConsumer(consumer_); |
| 63 | reducer.AddDefaultReductionPasses(); |
| 64 | reducer.SetInterestingnessFunction( |
| 65 | [this, &irrelevant_pointee_global_variables]( |
| 66 | const std::vector<uint32_t>& binary_under_reduction, |
| 67 | uint32_t /*unused*/) { |
| 68 | return InterestingnessFunctionForReducingAddedFunction( |
| 69 | binary_under_reduction, irrelevant_pointee_global_variables); |
| 70 | }); |
| 71 | |
| 72 | // Instruct spirv-reduce to only target the function with the id associated |
| 73 | // with the AddFunction transformation that we care about. |
| 74 | spvtools::ReducerOptions reducer_options; |
| 75 | reducer_options.set_target_function(GetAddedFunctionId()); |
| 76 | // Bound the number of reduction steps that spirv-reduce can make according |
| 77 | // to the overall shrinker step limit and the number of shrink attempts that |
| 78 | // have already been tried. |
| 79 | assert(shrinker_step_limit_ > num_existing_shrink_attempts_ && |
| 80 | "The added function reducer should not have been invoked."); |
| 81 | reducer_options.set_step_limit(shrinker_step_limit_ - |
| 82 | num_existing_shrink_attempts_); |
| 83 | |
| 84 | // Run spirv-reduce. |
| 85 | std::vector<uint32_t> reduced_binary; |
| 86 | auto reducer_result = |
| 87 | reducer.Run(std::move(binary_to_reduce), &reduced_binary, reducer_options, |
| 88 | validator_options_); |
| 89 | if (reducer_result != reduce::Reducer::kComplete && |
| 90 | reducer_result != reduce::Reducer::kReachedStepLimit) { |
| 91 | return {AddedFunctionReducerResultStatus::kReductionFailed, |
| 92 | std::vector<uint32_t>(), protobufs::TransformationSequence(), 0}; |
| 93 | } |
| 94 | |
| 95 | // Provide the outer shrinker with an adapted sequence of transformations in |
| 96 | // which the AddFunction transformation of interest has been simplified to use |
| 97 | // the version of the added function that appears in |reduced_binary|. |
| 98 | std::vector<uint32_t> binary_out; |
| 99 | protobufs::TransformationSequence transformation_sequence_out; |
| 100 | ReplayAdaptedTransformations(reduced_binary, &binary_out, |
| 101 | &transformation_sequence_out); |
| 102 | // We subtract 1 from |num_reducer_interestingness_function_invocations_| to |
| 103 | // account for the fact that spirv-reduce invokes its interestingness test |
| 104 | // once before reduction commences in order to check that the initial module |
| 105 | // is interesting. |
| 106 | assert(num_reducer_interestingness_function_invocations_ > 0 && |
| 107 | "At a minimum spirv-reduce should have invoked its interestingness " |
| 108 | "test once."); |
| 109 | return {AddedFunctionReducerResultStatus::kComplete, std::move(binary_out), |
no test coverage detected