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_pass.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 using namespace opt; 24 25 std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(IRContext * context) const26OperandToUndefReductionPass::GetAvailableOpportunities( 27 IRContext* context) const { 28 std::vector<std::unique_ptr<ReductionOpportunity>> result; 29 30 for (auto& function : *context->module()) { 31 for (auto& block : function) { 32 for (auto& inst : block) { 33 // Skip instructions that result in a pointer type. 34 auto type_id = inst.type_id(); 35 if (type_id) { 36 auto type_id_def = context->get_def_use_mgr()->GetDef(type_id); 37 if (type_id_def->opcode() == SpvOpTypePointer) { 38 continue; 39 } 40 } 41 42 // We iterate through the operands using an explicit index (rather 43 // than using a lambda) so that we use said index in the construction 44 // of a ChangeOperandToUndefReductionOpportunity 45 for (uint32_t index = 0; index < inst.NumOperands(); index++) { 46 const auto& operand = inst.GetOperand(index); 47 48 if (spvIsInIdType(operand.type)) { 49 const auto operand_id = operand.words[0]; 50 auto operand_id_def = 51 context->get_def_use_mgr()->GetDef(operand_id); 52 53 // Skip constant and undef operands. 54 // We always want the reducer to make the module "smaller", which 55 // ensures termination. 56 // Therefore, we assume: id > undef id > constant id. 57 if (spvOpcodeIsConstantOrUndef(operand_id_def->opcode())) { 58 continue; 59 } 60 61 // Don't replace function operands with undef. 62 if (operand_id_def->opcode() == SpvOpFunction) { 63 continue; 64 } 65 66 // Only consider operands that have a type. 67 auto operand_type_id = operand_id_def->type_id(); 68 if (operand_type_id) { 69 auto operand_type_id_def = 70 context->get_def_use_mgr()->GetDef(operand_type_id); 71 72 // Skip pointer operands. 73 if (operand_type_id_def->opcode() == SpvOpTypePointer) { 74 continue; 75 } 76 77 result.push_back( 78 MakeUnique<ChangeOperandToUndefReductionOpportunity>( 79 context, &inst, index)); 80 } 81 } 82 } 83 } 84 } 85 } 86 return result; 87 } 88 GetName() const89std::string OperandToUndefReductionPass::GetName() const { 90 return "OperandToUndefReductionPass"; 91 } 92 93 } // namespace reduce 94 } // namespace spvtools 95