MCPcopy Create free account
hub / github.com/KhronosGroup/SPIRV-Tools / Process

Method Process

source/opt/unify_const_pass.cpp:106–172  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

104} // namespace
105
106Pass::Status UnifyConstantPass::Process() {
107 bool modified = false;
108 ResultIdTrie defined_constants;
109
110 for (Instruction *next_instruction,
111 *inst = &*(context()->types_values_begin());
112 inst; inst = next_instruction) {
113 next_instruction = inst->NextNode();
114
115 // Do not handle the instruction when there are decorations upon the result
116 // id.
117 if (get_def_use_mgr()->GetAnnotations(inst->result_id()).size() != 0) {
118 continue;
119 }
120
121 // The overall algorithm is to store the result ids of all the eligible
122 // constants encountered so far in a trie. For a constant defining
123 // instruction under consideration, use its opcode, result type id and
124 // words in operands as an array of keys to lookup the trie. If a result id
125 // can be found for that array of keys, a constant with exactly the same
126 // value must has been defined before, the constant under processing
127 // should be replaced by the constant previously defined. If no such result
128 // id can be found for that array of keys, this must be the first time a
129 // constant with its value be defined, we then create a new trie node to
130 // store the result id with the keys. When replacing a duplicated constant
131 // with a previously defined constant, all the uses of the duplicated
132 // constant, which must be placed after the duplicated constant defining
133 // instruction, will be updated. This way, the descendants of the
134 // previously defined constant and the duplicated constant will both refer
135 // to the previously defined constant. So that the operand ids which are
136 // used in key arrays will be the ids of the unified constants, when
137 // processing is up to a descendant. This makes comparing the key array
138 // always valid for judging duplication.
139 switch (inst->opcode()) {
140 case spv::Op::OpConstantTrue:
141 case spv::Op::OpConstantFalse:
142 case spv::Op::OpConstant:
143 case spv::Op::OpConstantNull:
144 case spv::Op::OpConstantSampler:
145 case spv::Op::OpConstantComposite:
146 // Only spec constants defined with OpSpecConstantOp and
147 // OpSpecConstantComposite should be processed in this pass. Spec
148 // constants defined with OpSpecConstant{|True|False} are decorated with
149 // 'SpecId' decoration and all of them should be treated as unique.
150 // 'SpecId' is not applicable to SpecConstants defined with
151 // OpSpecConstant{Op|Composite}, their values are not necessary to be
152 // unique. When all the operands/components are the same between two
153 // OpSpecConstant{Op|Composite} results, their result values must be the
154 // same so are unifiable.
155 case spv::Op::OpSpecConstantOp:
156 case spv::Op::OpSpecConstantComposite: {
157 uint32_t id = defined_constants.LookupEquivalentResultFor(*inst);
158 if (id != inst->result_id()) {
159 // The constant is a duplicated one, use the cached constant to
160 // replace the uses of this duplicated one, then turn it to nop.
161 context()->ReplaceAllUsesWith(inst->result_id(), id);
162 context()->KillInst(inst);
163 modified = true;

Callers

nothing calls this directly

Calls 9

NextNodeMethod · 0.80
GetAnnotationsMethod · 0.80
ReplaceAllUsesWithMethod · 0.80
types_values_beginMethod · 0.45
sizeMethod · 0.45
result_idMethod · 0.45
opcodeMethod · 0.45
KillInstMethod · 0.45

Tested by

no test coverage detected