• 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/opt/strip_nonsemantic_info_pass.h"
16 
17 #include <cstring>
18 #include <vector>
19 
20 #include "source/opt/instruction.h"
21 #include "source/opt/ir_context.h"
22 #include "source/util/string_utils.h"
23 
24 namespace spvtools {
25 namespace opt {
26 
Process()27 Pass::Status StripNonSemanticInfoPass::Process() {
28   bool modified = false;
29 
30   std::vector<Instruction*> to_remove;
31 
32   bool other_uses_for_decorate_string = false;
33   for (auto& inst : context()->module()->annotations()) {
34     switch (inst.opcode()) {
35       case SpvOpDecorateStringGOOGLE:
36         if (inst.GetSingleWordInOperand(1) == SpvDecorationHlslSemanticGOOGLE ||
37             inst.GetSingleWordInOperand(1) == SpvDecorationUserTypeGOOGLE) {
38           to_remove.push_back(&inst);
39         } else {
40           other_uses_for_decorate_string = true;
41         }
42         break;
43 
44       case SpvOpMemberDecorateStringGOOGLE:
45         if (inst.GetSingleWordInOperand(2) == SpvDecorationHlslSemanticGOOGLE ||
46             inst.GetSingleWordInOperand(2) == SpvDecorationUserTypeGOOGLE) {
47           to_remove.push_back(&inst);
48         } else {
49           other_uses_for_decorate_string = true;
50         }
51         break;
52 
53       case SpvOpDecorateId:
54         if (inst.GetSingleWordInOperand(1) ==
55             SpvDecorationHlslCounterBufferGOOGLE) {
56           to_remove.push_back(&inst);
57         }
58         break;
59 
60       default:
61         break;
62     }
63   }
64 
65   for (auto& inst : context()->module()->extensions()) {
66     const std::string ext_name = inst.GetInOperand(0).AsString();
67     if (ext_name == "SPV_GOOGLE_hlsl_functionality1") {
68       to_remove.push_back(&inst);
69     } else if (ext_name == "SPV_GOOGLE_user_type") {
70       to_remove.push_back(&inst);
71     } else if (!other_uses_for_decorate_string &&
72                ext_name == "SPV_GOOGLE_decorate_string") {
73       to_remove.push_back(&inst);
74     } else if (ext_name == "SPV_KHR_non_semantic_info") {
75       to_remove.push_back(&inst);
76     }
77   }
78 
79   // remove any extended inst imports that are non semantic
80   std::unordered_set<uint32_t> non_semantic_sets;
81   for (auto& inst : context()->module()->ext_inst_imports()) {
82     assert(inst.opcode() == SpvOpExtInstImport &&
83            "Expecting an import of an extension's instruction set.");
84     const std::string extension_name = inst.GetInOperand(0).AsString();
85     if (spvtools::utils::starts_with(extension_name, "NonSemantic.")) {
86       non_semantic_sets.insert(inst.result_id());
87       to_remove.push_back(&inst);
88     }
89   }
90 
91   // if we removed some non-semantic sets, then iterate over the instructions in
92   // the module to remove any OpExtInst that referenced those sets
93   if (!non_semantic_sets.empty()) {
94     context()->module()->ForEachInst(
95         [&non_semantic_sets, &to_remove](Instruction* inst) {
96           if (inst->opcode() == SpvOpExtInst) {
97             if (non_semantic_sets.find(inst->GetSingleWordInOperand(0)) !=
98                 non_semantic_sets.end()) {
99               to_remove.push_back(inst);
100             }
101           }
102         },
103         true);
104   }
105 
106   for (auto* inst : to_remove) {
107     modified = true;
108     context()->KillInst(inst);
109   }
110 
111   return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
112 }
113 
114 }  // namespace opt
115 }  // namespace spvtools
116