SROA: Do replacement on structs with no partial references.
[platform/upstream/SPIRV-Tools.git] / source / opt / instruction.h
1 // Copyright (c) 2016 Google Inc.
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 #ifndef LIBSPIRV_OPT_INSTRUCTION_H_
16 #define LIBSPIRV_OPT_INSTRUCTION_H_
17
18 #include <cassert>
19 #include <functional>
20 #include <utility>
21 #include <vector>
22
23 #include "opcode.h"
24 #include "operand.h"
25 #include "util/ilist_node.h"
26
27 #include "latest_version_spirv_header.h"
28 #include "reflect.h"
29 #include "spirv-tools/libspirv.h"
30
31 namespace spvtools {
32 namespace ir {
33
34 class Function;
35 class IRContext;
36 class Module;
37 class InstructionList;
38
39 // Relaxed logcial addressing:
40 //
41 // In the logical addressing model, pointers cannot be stored or loaded.  This
42 // is a useful assumption because it simplifies the aliasing significantly.
43 // However, for the purpose of legalizing code generated from HLSL, we will have
44 // to allow storing and loading of pointers to opaque objects and runtime
45 // arrays.  This relaxation of the rule still implies that function and private
46 // scope variables do not have any aliasing, so we can treat them as before.
47 // This will be call the relaxed logical addressing model.
48 //
49 // This relaxation of the rule will be allowed by |GetBaseAddress|, but it will
50 // enforce that no other pointers are stored or loaded.
51
52 // About operand:
53 //
54 // In the SPIR-V specification, the term "operand" is used to mean any single
55 // SPIR-V word following the leading wordcount-opcode word. Here, the term
56 // "operand" is used to mean a *logical* operand. A logical operand may consist
57 // of multiple SPIR-V words, which together make up the same component. For
58 // example, a logical operand of a 64-bit integer needs two words to express.
59 //
60 // Further, we categorize logical operands into *in* and *out* operands.
61 // In operands are operands actually serve as input to operations, while out
62 // operands are operands that represent ids generated from operations (result
63 // type id or result id). For example, for "OpIAdd %rtype %rid %inop1 %inop2",
64 // "%inop1" and "%inop2" are in operands, while "%rtype" and "%rid" are out
65 // operands.
66
67 // A *logical* operand to a SPIR-V instruction. It can be the type id, result
68 // id, or other additional operands carried in an instruction.
69 struct Operand {
70   Operand(spv_operand_type_t t, std::vector<uint32_t>&& w)
71       : type(t), words(std::move(w)) {}
72
73   Operand(spv_operand_type_t t, const std::vector<uint32_t>& w)
74       : type(t), words(w) {}
75
76   spv_operand_type_t type;      // Type of this logical operand.
77   std::vector<uint32_t> words;  // Binary segments of this logical operand.
78
79   friend bool operator==(const Operand& o1, const Operand& o2) {
80     return o1.type == o2.type && o1.words == o2.words;
81   }
82
83   // TODO(antiagainst): create fields for literal number kind, width, etc.
84 };
85
86 inline bool operator!=(const Operand& o1, const Operand& o2) {
87   return !(o1 == o2);
88 }
89
90 // A SPIR-V instruction. It contains the opcode and any additional logical
91 // operand, including the result id (if any) and result type id (if any). It
92 // may also contain line-related debug instruction (OpLine, OpNoLine) directly
93 // appearing before this instruction. Note that the result id of an instruction
94 // should never change after the instruction being built. If the result id
95 // needs to change, the user should create a new instruction instead.
96 class Instruction : public utils::IntrusiveNodeBase<Instruction> {
97  public:
98   using iterator = std::vector<Operand>::iterator;
99   using const_iterator = std::vector<Operand>::const_iterator;
100
101   // Creates a default OpNop instruction.
102   // This exists solely for containers that can't do without. Should be removed.
103   Instruction()
104       : utils::IntrusiveNodeBase<Instruction>(),
105         context_(nullptr),
106         opcode_(SpvOpNop),
107         type_id_(0),
108         result_id_(0),
109         unique_id_(0) {}
110
111   // Creates a default OpNop instruction.
112   Instruction(IRContext*);
113   // Creates an instruction with the given opcode |op| and no additional logical
114   // operands.
115   Instruction(IRContext*, SpvOp);
116   // Creates an instruction using the given spv_parsed_instruction_t |inst|. All
117   // the data inside |inst| will be copied and owned in this instance. And keep
118   // record of line-related debug instructions |dbg_line| ahead of this
119   // instruction, if any.
120   Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
121               std::vector<Instruction>&& dbg_line = {});
122
123   // Creates an instruction with the given opcode |op|, type id: |ty_id|,
124   // result id: |res_id| and input operands: |in_operands|.
125   Instruction(IRContext* c, SpvOp op, uint32_t ty_id, uint32_t res_id,
126               const std::vector<Operand>& in_operands);
127
128   // TODO: I will want to remove these, but will first have to remove the use of
129   // std::vector<Instruction>.
130   Instruction(const Instruction&) = default;
131   Instruction& operator=(const Instruction&) = default;
132
133   Instruction(Instruction&&);
134   Instruction& operator=(Instruction&&);
135
136   virtual ~Instruction() = default;
137
138   // Returns a newly allocated instruction that has the same operands, result,
139   // and type as |this|.  The new instruction is not linked into any list.
140   // It is the responsibility of the caller to make sure that the storage is
141   // removed. It is the caller's responsibility to make sure that there is only
142   // one instruction for each result id.
143   Instruction* Clone(IRContext* c) const;
144
145   IRContext* context() const { return context_; }
146
147   SpvOp opcode() const { return opcode_; }
148   // Sets the opcode of this instruction to a specific opcode. Note this may
149   // invalidate the instruction.
150   // TODO(qining): Remove this function when instruction building and insertion
151   // is well implemented.
152   void SetOpcode(SpvOp op) { opcode_ = op; }
153   uint32_t type_id() const { return type_id_; }
154   uint32_t result_id() const { return result_id_; }
155   uint32_t unique_id() const {
156     assert(unique_id_ != 0);
157     return unique_id_;
158   }
159   // Returns the vector of line-related debug instructions attached to this
160   // instruction and the caller can directly modify them.
161   std::vector<Instruction>& dbg_line_insts() { return dbg_line_insts_; }
162   const std::vector<Instruction>& dbg_line_insts() const {
163     return dbg_line_insts_;
164   }
165
166   // Same semantics as in the base class except the list the InstructionList
167   // containing |pos| will now assume ownership of |this|.
168   // inline void MoveBefore(Instruction* pos);
169   // inline void InsertAfter(Instruction* pos);
170
171   // Begin and end iterators for operands.
172   iterator begin() { return operands_.begin(); }
173   iterator end() { return operands_.end(); }
174   const_iterator begin() const { return operands_.cbegin(); }
175   const_iterator end() const { return operands_.cend(); }
176   // Const begin and end iterators for operands.
177   const_iterator cbegin() const { return operands_.cbegin(); }
178   const_iterator cend() const { return operands_.cend(); }
179
180   // Gets the number of logical operands.
181   uint32_t NumOperands() const {
182     return static_cast<uint32_t>(operands_.size());
183   }
184   // Gets the number of SPIR-V words occupied by all logical operands.
185   uint32_t NumOperandWords() const {
186     return NumInOperandWords() + TypeResultIdCount();
187   }
188   // Gets the |index|-th logical operand.
189   inline const Operand& GetOperand(uint32_t index) const;
190   // Adds |operand| to the list of operands of this instruction.
191   // It is the responsibility of the caller to make sure
192   // that the instruction remains valid.
193   inline void AddOperand(Operand&& operand);
194   // Gets the |index|-th logical operand as a single SPIR-V word. This method is
195   // not expected to be used with logical operands consisting of multiple SPIR-V
196   // words.
197   uint32_t GetSingleWordOperand(uint32_t index) const;
198   // Sets the |index|-th in-operand's data to the given |data|.
199   inline void SetInOperand(uint32_t index, std::vector<uint32_t>&& data);
200   // Sets the |index|-th operand's data to the given |data|.
201   // This is for in-operands modification only, but with |index| expressed in
202   // terms of operand index rather than in-operand index.
203   inline void SetOperand(uint32_t index, std::vector<uint32_t>&& data);
204   // Replace all of the in operands with those in |new_operands|.
205   inline void SetInOperands(std::vector<Operand>&& new_operands);
206   // Sets the result type id.
207   inline void SetResultType(uint32_t ty_id);
208   // Sets the result id
209   inline void SetResultId(uint32_t res_id);
210   inline bool HasResultId() const { return result_id_ != 0; }
211   // Remove the |index|-th operand
212   void RemoveOperand(uint32_t index) {
213     operands_.erase(operands_.begin() + index);
214   }
215
216   // The following methods are similar to the above, but are for in operands.
217   uint32_t NumInOperands() const {
218     return static_cast<uint32_t>(operands_.size() - TypeResultIdCount());
219   }
220   uint32_t NumInOperandWords() const;
221   const Operand& GetInOperand(uint32_t index) const {
222     return GetOperand(index + TypeResultIdCount());
223   }
224   uint32_t GetSingleWordInOperand(uint32_t index) const {
225     return GetSingleWordOperand(index + TypeResultIdCount());
226   }
227   void RemoveInOperand(uint32_t index) {
228     operands_.erase(operands_.begin() + index + TypeResultIdCount());
229   }
230
231   // Returns true if this instruction is OpNop.
232   inline bool IsNop() const;
233   // Turns this instruction to OpNop. This does not clear out all preceding
234   // line-related debug instructions.
235   inline void ToNop();
236
237   // Runs the given function |f| on this instruction and optionally on the
238   // preceding debug line instructions.  The function will always be run
239   // if this is itself a debug line instruction.
240   inline void ForEachInst(const std::function<void(Instruction*)>& f,
241                           bool run_on_debug_line_insts = false);
242   inline void ForEachInst(const std::function<void(const Instruction*)>& f,
243                           bool run_on_debug_line_insts = false) const;
244
245   // Runs the given function |f| on this instruction and optionally on the
246   // preceding debug line instructions.  The function will always be run
247   // if this is itself a debug line instruction. If |f| returns false,
248   // iteration is terminated and this function returns false.
249   inline bool WhileEachInst(const std::function<bool(Instruction*)>& f,
250                             bool run_on_debug_line_insts = false);
251   inline bool WhileEachInst(const std::function<bool(const Instruction*)>& f,
252                             bool run_on_debug_line_insts = false) const;
253
254   // Runs the given function |f| on all operand ids.
255   //
256   // |f| should not transform an ID into 0, as 0 is an invalid ID.
257   inline void ForEachId(const std::function<void(uint32_t*)>& f);
258   inline void ForEachId(const std::function<void(const uint32_t*)>& f) const;
259
260   // Runs the given function |f| on all "in" operand ids.
261   inline void ForEachInId(const std::function<void(uint32_t*)>& f);
262   inline void ForEachInId(const std::function<void(const uint32_t*)>& f) const;
263
264   // Runs the given function |f| on all "in" operand ids. If |f| returns false,
265   // iteration is terminated and this function returns false.
266   inline bool WhileEachInId(const std::function<bool(uint32_t*)>& f);
267   inline bool WhileEachInId(
268       const std::function<bool(const uint32_t*)>& f) const;
269
270   // Runs the given function |f| on all "in" operands.
271   inline void ForEachInOperand(const std::function<void(uint32_t*)>& f);
272   inline void ForEachInOperand(
273       const std::function<void(const uint32_t*)>& f) const;
274
275   // Runs the given function |f| on all "in" operands. If |f| returns false,
276   // iteration is terminated and this function return false.
277   inline bool WhileEachInOperand(const std::function<bool(uint32_t*)>& f);
278   inline bool WhileEachInOperand(
279       const std::function<bool(const uint32_t*)>& f) const;
280
281   // Returns true if any operands can be labels
282   inline bool HasLabels() const;
283
284   // Pushes the binary segments for this instruction into the back of *|binary|.
285   void ToBinaryWithoutAttachedDebugInsts(std::vector<uint32_t>* binary) const;
286
287   // Replaces the operands to the instruction with |new_operands|. The caller
288   // is responsible for building a complete and valid list of operands for
289   // this instruction.
290   void ReplaceOperands(const std::vector<Operand>& new_operands);
291
292   // Returns true if the instruction annotates an id with a decoration.
293   inline bool IsDecoration() const;
294
295   // Returns true if the instruction is known to be a load from read-only
296   // memory.
297   bool IsReadOnlyLoad() const;
298
299   // Returns the instruction that gives the base address of an address
300   // calculation.  The instruction must be a load, as defined by |IsLoad|,
301   // store, copy, or access chain instruction.  In logical addressing mode, will
302   // return an OpVariable or OpFunctionParameter instruction. For relaxed
303   // logical addressing, it would also return a load of a pointer to an opaque
304   // object.  For physical addressing mode, could return other types of
305   // instructions.
306   Instruction* GetBaseAddress() const;
307
308   // Returns true if the instruction loads from memory or samples an image, and
309   // stores the result into an id. It considers only core instructions.
310   // Memory-to-memory instructions are not considered loads.
311   inline bool IsLoad() const;
312
313   // Returns true if the instruction declares a variable that is read-only.
314   bool IsReadOnlyVariable() const;
315
316   // The following functions check for the various descriptor types defined in
317   // the Vulkan specification section 13.1.
318
319   // Returns true if the instruction defines a pointer type that points to a
320   // storage image.
321   bool IsVulkanStorageImage() const;
322
323   // Returns true if the instruction defines a pointer type that points to a
324   // sampled image.
325   bool IsVulkanSampledImage() const;
326
327   // Returns true if the instruction defines a pointer type that points to a
328   // storage texel buffer.
329   bool IsVulkanStorageTexelBuffer() const;
330
331   // Returns true if the instruction defines a pointer type that points to a
332   // storage buffer.
333   bool IsVulkanStorageBuffer() const;
334
335   // Returns true if the instruction defines a pointer type that points to a
336   // uniform buffer.
337   bool IsVulkanUniformBuffer() const;
338
339   // Returns true if the instruction is an atom operation.
340   inline bool IsAtomicOp() const;
341
342   // Returns true if this instruction is a branch or switch instruction (either
343   // conditional or not).
344   bool IsBranch() const { return spvOpcodeIsBranch(opcode()); }
345
346   // Returns true if this instruction causes the function to finish execution
347   // and return to its caller
348   bool IsReturn() const { return spvOpcodeIsReturn(opcode()); }
349
350   // Returns true if this instruction exits this function or aborts execution.
351   bool IsReturnOrAbort() const { return spvOpcodeIsReturnOrAbort(opcode()); }
352
353   // Returns the id for the |element|'th subtype. If the |this| is not a
354   // composite type, this function returns 0.
355   uint32_t GetTypeComponent(uint32_t element) const;
356
357   // Returns true if this instruction is a basic block terminator.
358   bool IsBlockTerminator() const {
359     return spvOpcodeIsBlockTerminator(opcode());
360   }
361
362   // Returns true if |this| is an instruction that define an opaque type.  Since
363   // runtime array have similar characteristics they are included as opaque
364   // types.
365   bool IsOpaqueType() const;
366
367   // Returns true if |this| is an instruction which could be folded into a
368   // constant value.
369   bool IsFoldable() const;
370
371   inline bool operator==(const Instruction&) const;
372   inline bool operator!=(const Instruction&) const;
373   inline bool operator<(const Instruction&) const;
374
375   Instruction* InsertBefore(std::vector<std::unique_ptr<Instruction>>&& list);
376   Instruction* InsertBefore(std::unique_ptr<Instruction>&& i);
377   using utils::IntrusiveNodeBase<Instruction>::InsertBefore;
378
379   // Returns true if |this| is an instruction defining a constant, but not a
380   // Spec constant.
381   inline bool IsConstant() const;
382
383   // Pretty-prints |inst|.
384   //
385   // Provides the disassembly of a specific instruction. Utilizes |inst|'s
386   // context to provide the correct interpretation of types, constants, etc.
387   //
388   // |options| are the disassembly options. SPV_BINARY_TO_TEXT_OPTION_NO_HEADER
389   // is always added to |options|.
390   std::string PrettyPrint(uint32_t options = 0u) const;
391
392  private:
393   // Returns the total count of result type id and result id.
394   uint32_t TypeResultIdCount() const {
395     return (type_id_ != 0) + (result_id_ != 0);
396   }
397
398   // Returns true if the instruction declares a variable that is read-only.  The
399   // first version assumes the module is a shader module.  The second assumes a
400   // kernel.
401   bool IsReadOnlyVariableShaders() const;
402   bool IsReadOnlyVariableKernel() const;
403
404   // Returns true if it is valid to use the result of |inst| as the base
405   // pointer for a load or store.  In this case, valid is defined by the relaxed
406   // logical addressing rules when using logical addressing.  Normal validation
407   // rules for physical addressing.
408   bool IsValidBasePointer() const;
409
410   // Returns true if the result of |inst| can be used as the base image for an
411   // instruction that samples a image, reads an image, or writes to an image.
412   bool IsValidBaseImage() const;
413
414   IRContext* context_;  // IR Context
415   SpvOp opcode_;        // Opcode
416   uint32_t type_id_;    // Result type id. A value of 0 means no result type id.
417   uint32_t result_id_;  // Result id. A value of 0 means no result id.
418   uint32_t unique_id_;  // Unique instruction id
419   // All logical operands, including result type id and result id.
420   std::vector<Operand> operands_;
421   // Opline and OpNoLine instructions preceding this instruction. Note that for
422   // Instructions representing OpLine or OpNonLine itself, this field should be
423   // empty.
424   std::vector<Instruction> dbg_line_insts_;
425
426   friend InstructionList;
427 };
428
429 // Pretty-prints |inst| to |str| and returns |str|.
430 //
431 // Provides the disassembly of a specific instruction. Utilizes |inst|'s context
432 // to provide the correct interpretation of types, constants, etc.
433 //
434 // Disassembly uses raw ids (not pretty printed names).
435 std::ostream& operator<<(std::ostream& str, const ir::Instruction& inst);
436
437 inline bool Instruction::operator==(const Instruction& other) const {
438   return unique_id() == other.unique_id();
439 }
440
441 inline bool Instruction::operator!=(const Instruction& other) const {
442   return !(*this == other);
443 }
444
445 inline bool Instruction::operator<(const Instruction& other) const {
446   return unique_id() < other.unique_id();
447 }
448
449 inline const Operand& Instruction::GetOperand(uint32_t index) const {
450   assert(index < operands_.size() && "operand index out of bound");
451   return operands_[index];
452 };
453
454 inline void Instruction::AddOperand(Operand&& operand) {
455   operands_.push_back(std::move(operand));
456 }
457
458 inline void Instruction::SetInOperand(uint32_t index,
459                                       std::vector<uint32_t>&& data) {
460   SetOperand(index + TypeResultIdCount(), std::move(data));
461 }
462
463 inline void Instruction::SetOperand(uint32_t index,
464                                     std::vector<uint32_t>&& data) {
465   assert(index < operands_.size() && "operand index out of bound");
466   assert(index >= TypeResultIdCount() && "operand is not a in-operand");
467   operands_[index].words = std::move(data);
468 }
469
470 inline void Instruction::SetInOperands(std::vector<Operand>&& new_operands) {
471   // Remove the old in operands.
472   operands_.erase(operands_.begin() + TypeResultIdCount(), operands_.end());
473   // Add the new in operands.
474   operands_.insert(operands_.end(), new_operands.begin(), new_operands.end());
475 }
476
477 inline void Instruction::SetResultId(uint32_t res_id) {
478   result_id_ = res_id;
479   auto ridx = (type_id_ != 0) ? 1 : 0;
480   assert(operands_[ridx].type == SPV_OPERAND_TYPE_RESULT_ID);
481   operands_[ridx].words = {res_id};
482 }
483
484 inline void Instruction::SetResultType(uint32_t ty_id) {
485   if (type_id_ != 0) {
486     type_id_ = ty_id;
487     assert(operands_.front().type == SPV_OPERAND_TYPE_TYPE_ID);
488     operands_.front().words = {ty_id};
489   }
490 }
491
492 inline bool Instruction::IsNop() const {
493   return opcode_ == SpvOpNop && type_id_ == 0 && result_id_ == 0 &&
494          operands_.empty();
495 }
496
497 inline void Instruction::ToNop() {
498   opcode_ = SpvOpNop;
499   type_id_ = result_id_ = 0;
500   operands_.clear();
501 }
502
503 inline bool Instruction::WhileEachInst(
504     const std::function<bool(Instruction*)>& f, bool run_on_debug_line_insts) {
505   if (run_on_debug_line_insts) {
506     for (auto& dbg_line : dbg_line_insts_) {
507       if (!f(&dbg_line)) return false;
508     }
509   }
510   return f(this);
511 }
512
513 inline bool Instruction::WhileEachInst(
514     const std::function<bool(const Instruction*)>& f,
515     bool run_on_debug_line_insts) const {
516   if (run_on_debug_line_insts) {
517     for (auto& dbg_line : dbg_line_insts_) {
518       if (!f(&dbg_line)) return false;
519     }
520   }
521   return f(this);
522 }
523
524 inline void Instruction::ForEachInst(const std::function<void(Instruction*)>& f,
525                                      bool run_on_debug_line_insts) {
526   WhileEachInst(
527       [&f](Instruction* inst) {
528         f(inst);
529         return true;
530       },
531       run_on_debug_line_insts);
532 }
533
534 inline void Instruction::ForEachInst(
535     const std::function<void(const Instruction*)>& f,
536     bool run_on_debug_line_insts) const {
537   WhileEachInst(
538       [&f](const Instruction* inst) {
539         f(inst);
540         return true;
541       },
542       run_on_debug_line_insts);
543 }
544
545 inline void Instruction::ForEachId(const std::function<void(uint32_t*)>& f) {
546   for (auto& opnd : operands_)
547     if (spvIsIdType(opnd.type)) f(&opnd.words[0]);
548   if (type_id_ != 0u) type_id_ = GetSingleWordOperand(0u);
549   if (result_id_ != 0u)
550     result_id_ = GetSingleWordOperand(type_id_ == 0u ? 0u : 1u);
551 }
552
553 inline void Instruction::ForEachId(
554     const std::function<void(const uint32_t*)>& f) const {
555   for (const auto& opnd : operands_)
556     if (spvIsIdType(opnd.type)) f(&opnd.words[0]);
557 }
558
559 inline bool Instruction::WhileEachInId(
560     const std::function<bool(uint32_t*)>& f) {
561   for (auto& opnd : operands_) {
562     switch (opnd.type) {
563       case SPV_OPERAND_TYPE_RESULT_ID:
564       case SPV_OPERAND_TYPE_TYPE_ID:
565         break;
566       default:
567         if (spvIsIdType(opnd.type)) {
568           if (!f(&opnd.words[0])) return false;
569         }
570         break;
571     }
572   }
573   return true;
574 }
575
576 inline bool Instruction::WhileEachInId(
577     const std::function<bool(const uint32_t*)>& f) const {
578   for (const auto& opnd : operands_) {
579     switch (opnd.type) {
580       case SPV_OPERAND_TYPE_RESULT_ID:
581       case SPV_OPERAND_TYPE_TYPE_ID:
582         break;
583       default:
584         if (spvIsIdType(opnd.type)) {
585           if (!f(&opnd.words[0])) return false;
586         }
587         break;
588     }
589   }
590   return true;
591 }
592
593 inline void Instruction::ForEachInId(const std::function<void(uint32_t*)>& f) {
594   WhileEachInId([&f](uint32_t* id) {
595     f(id);
596     return true;
597   });
598 }
599
600 inline void Instruction::ForEachInId(
601     const std::function<void(const uint32_t*)>& f) const {
602   WhileEachInId([&f](const uint32_t* id) {
603     f(id);
604     return true;
605   });
606 }
607
608 inline bool Instruction::WhileEachInOperand(
609     const std::function<bool(uint32_t*)>& f) {
610   for (auto& opnd : operands_) {
611     switch (opnd.type) {
612       case SPV_OPERAND_TYPE_RESULT_ID:
613       case SPV_OPERAND_TYPE_TYPE_ID:
614         break;
615       default:
616         if (!f(&opnd.words[0])) return false;
617         break;
618     }
619   }
620   return true;
621 }
622
623 inline bool Instruction::WhileEachInOperand(
624     const std::function<bool(const uint32_t*)>& f) const {
625   for (const auto& opnd : operands_) {
626     switch (opnd.type) {
627       case SPV_OPERAND_TYPE_RESULT_ID:
628       case SPV_OPERAND_TYPE_TYPE_ID:
629         break;
630       default:
631         if (!f(&opnd.words[0])) return false;
632         break;
633     }
634   }
635   return true;
636 }
637
638 inline void Instruction::ForEachInOperand(
639     const std::function<void(uint32_t*)>& f) {
640   WhileEachInOperand([&f](uint32_t* op) {
641     f(op);
642     return true;
643   });
644 }
645
646 inline void Instruction::ForEachInOperand(
647     const std::function<void(const uint32_t*)>& f) const {
648   WhileEachInOperand([&f](const uint32_t* op) {
649     f(op);
650     return true;
651   });
652 }
653
654 inline bool Instruction::HasLabels() const {
655   switch (opcode_) {
656     case SpvOpSelectionMerge:
657     case SpvOpBranch:
658     case SpvOpLoopMerge:
659     case SpvOpBranchConditional:
660     case SpvOpSwitch:
661     case SpvOpPhi:
662       return true;
663       break;
664     default:
665       break;
666   }
667   return false;
668 }
669
670 bool Instruction::IsDecoration() const {
671   return spvOpcodeIsDecoration(opcode());
672 }
673
674 bool Instruction::IsLoad() const { return spvOpcodeIsLoad(opcode()); }
675
676 bool Instruction::IsAtomicOp() const { return spvOpcodeIsAtomicOp(opcode()); }
677
678 bool Instruction::IsConstant() const {
679   return IsCompileTimeConstantInst(opcode());
680 }
681 }  // namespace ir
682 }  // namespace spvtools
683
684 #endif  // LIBSPIRV_OPT_INSTRUCTION_H_