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