• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "source/reduce/operand_to_undef_reduction_opportunity_finder.h"
16 
17 #include "source/opt/instruction.h"
18 #include "source/reduce/change_operand_to_undef_reduction_opportunity.h"
19 
20 namespace spvtools {
21 namespace reduce {
22 
23 std::vector<std::unique_ptr<ReductionOpportunity>>
GetAvailableOpportunities(opt::IRContext * context,uint32_t target_function) const24 OperandToUndefReductionOpportunityFinder::GetAvailableOpportunities(
25     opt::IRContext* context, uint32_t target_function) const {
26   std::vector<std::unique_ptr<ReductionOpportunity>> result;
27 
28   for (auto* function : GetTargetFunctions(context, target_function)) {
29     for (auto& block : *function) {
30       for (auto& inst : block) {
31         // Skip instructions that result in a pointer type.
32         auto type_id = inst.type_id();
33         if (type_id) {
34           auto type_id_def = context->get_def_use_mgr()->GetDef(type_id);
35           if (type_id_def->opcode() == SpvOpTypePointer) {
36             continue;
37           }
38         }
39 
40         // We iterate through the operands using an explicit index (rather
41         // than using a lambda) so that we use said index in the construction
42         // of a ChangeOperandToUndefReductionOpportunity
43         for (uint32_t index = 0; index < inst.NumOperands(); index++) {
44           const auto& operand = inst.GetOperand(index);
45 
46           if (spvIsInIdType(operand.type)) {
47             const auto operand_id = operand.words[0];
48             auto operand_id_def =
49                 context->get_def_use_mgr()->GetDef(operand_id);
50 
51             // Skip constant and undef operands.
52             // We always want the reducer to make the module "smaller", which
53             // ensures termination.
54             // Therefore, we assume: id > undef id > constant id.
55             if (spvOpcodeIsConstantOrUndef(operand_id_def->opcode())) {
56               continue;
57             }
58 
59             // Don't replace function operands with undef.
60             if (operand_id_def->opcode() == SpvOpFunction) {
61               continue;
62             }
63 
64             // Only consider operands that have a type.
65             auto operand_type_id = operand_id_def->type_id();
66             if (operand_type_id) {
67               auto operand_type_id_def =
68                   context->get_def_use_mgr()->GetDef(operand_type_id);
69 
70               // Skip pointer operands.
71               if (operand_type_id_def->opcode() == SpvOpTypePointer) {
72                 continue;
73               }
74 
75               result.push_back(
76                   MakeUnique<ChangeOperandToUndefReductionOpportunity>(
77                       context, &inst, index));
78             }
79           }
80         }
81       }
82     }
83   }
84   return result;
85 }
86 
GetName() const87 std::string OperandToUndefReductionOpportunityFinder::GetName() const {
88   return "OperandToUndefReductionOpportunityFinder";
89 }
90 
91 }  // namespace reduce
92 }  // namespace spvtools
93