Loop invariant code motion initial implementation
[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   // Returns true if |this| is an instruction with an opcode safe to move
384   bool IsOpcodeCodeMotionSafe() const;
385
386   // Pretty-prints |inst|.
387   //
388   // Provides the disassembly of a specific instruction. Utilizes |inst|'s
389   // context to provide the correct interpretation of types, constants, etc.
390   //
391   // |options| are the disassembly options. SPV_BINARY_TO_TEXT_OPTION_NO_HEADER
392   // is always added to |options|.
393   std::string PrettyPrint(uint32_t options = 0u) const;
394
395  private:
396   // Returns the total count of result type id and result id.
397   uint32_t TypeResultIdCount() const {
398     return (type_id_ != 0) + (result_id_ != 0);
399   }
400
401   // Returns true if the instruction declares a variable that is read-only.  The
402   // first version assumes the module is a shader module.  The second assumes a
403   // kernel.
404   bool IsReadOnlyVariableShaders() const;
405   bool IsReadOnlyVariableKernel() const;
406
407   // Returns true if it is valid to use the result of |inst| as the base
408   // pointer for a load or store.  In this case, valid is defined by the relaxed
409   // logical addressing rules when using logical addressing.  Normal validation
410   // rules for physical addressing.
411   bool IsValidBasePointer() const;
412
413   // Returns true if the result of |inst| can be used as the base image for an
414   // instruction that samples a image, reads an image, or writes to an image.
415   bool IsValidBaseImage() const;
416
417   IRContext* context_;  // IR Context
418   SpvOp opcode_;        // Opcode
419   uint32_t type_id_;    // Result type id. A value of 0 means no result type id.
420   uint32_t result_id_;  // Result id. A value of 0 means no result id.
421   uint32_t unique_id_;  // Unique instruction id
422   // All logical operands, including result type id and result id.
423   std::vector<Operand> operands_;
424   // Opline and OpNoLine instructions preceding this instruction. Note that for
425   // Instructions representing OpLine or OpNonLine itself, this field should be
426   // empty.
427   std::vector<Instruction> dbg_line_insts_;
428
429   friend InstructionList;
430 };
431
432 // Pretty-prints |inst| to |str| and returns |str|.
433 //
434 // Provides the disassembly of a specific instruction. Utilizes |inst|'s context
435 // to provide the correct interpretation of types, constants, etc.
436 //
437 // Disassembly uses raw ids (not pretty printed names).
438 std::ostream& operator<<(std::ostream& str, const ir::Instruction& inst);
439
440 inline bool Instruction::operator==(const Instruction& other) const {
441   return unique_id() == other.unique_id();
442 }
443
444 inline bool Instruction::operator!=(const Instruction& other) const {
445   return !(*this == other);
446 }
447
448 inline bool Instruction::operator<(const Instruction& other) const {
449   return unique_id() < other.unique_id();
450 }
451
452 inline const Operand& Instruction::GetOperand(uint32_t index) const {
453   assert(index < operands_.size() && "operand index out of bound");
454   return operands_[index];
455 };
456
457 inline void Instruction::AddOperand(Operand&& operand) {
458   operands_.push_back(std::move(operand));
459 }
460
461 inline void Instruction::SetInOperand(uint32_t index,
462                                       std::vector<uint32_t>&& data) {
463   SetOperand(index + TypeResultIdCount(), std::move(data));
464 }
465
466 inline void Instruction::SetOperand(uint32_t index,
467                                     std::vector<uint32_t>&& data) {
468   assert(index < operands_.size() && "operand index out of bound");
469   assert(index >= TypeResultIdCount() && "operand is not a in-operand");
470   operands_[index].words = std::move(data);
471 }
472
473 inline void Instruction::SetInOperands(std::vector<Operand>&& new_operands) {
474   // Remove the old in operands.
475   operands_.erase(operands_.begin() + TypeResultIdCount(), operands_.end());
476   // Add the new in operands.
477   operands_.insert(operands_.end(), new_operands.begin(), new_operands.end());
478 }
479
480 inline void Instruction::SetResultId(uint32_t res_id) {
481   result_id_ = res_id;
482   auto ridx = (type_id_ != 0) ? 1 : 0;
483   assert(operands_[ridx].type == SPV_OPERAND_TYPE_RESULT_ID);
484   operands_[ridx].words = {res_id};
485 }
486
487 inline void Instruction::SetResultType(uint32_t ty_id) {
488   if (type_id_ != 0) {
489     type_id_ = ty_id;
490     assert(operands_.front().type == SPV_OPERAND_TYPE_TYPE_ID);
491     operands_.front().words = {ty_id};
492   }
493 }
494
495 inline bool Instruction::IsNop() const {
496   return opcode_ == SpvOpNop && type_id_ == 0 && result_id_ == 0 &&
497          operands_.empty();
498 }
499
500 inline void Instruction::ToNop() {
501   opcode_ = SpvOpNop;
502   type_id_ = result_id_ = 0;
503   operands_.clear();
504 }
505
506 inline bool Instruction::WhileEachInst(
507     const std::function<bool(Instruction*)>& f, bool run_on_debug_line_insts) {
508   if (run_on_debug_line_insts) {
509     for (auto& dbg_line : dbg_line_insts_) {
510       if (!f(&dbg_line)) return false;
511     }
512   }
513   return f(this);
514 }
515
516 inline bool Instruction::WhileEachInst(
517     const std::function<bool(const Instruction*)>& f,
518     bool run_on_debug_line_insts) const {
519   if (run_on_debug_line_insts) {
520     for (auto& dbg_line : dbg_line_insts_) {
521       if (!f(&dbg_line)) return false;
522     }
523   }
524   return f(this);
525 }
526
527 inline void Instruction::ForEachInst(const std::function<void(Instruction*)>& f,
528                                      bool run_on_debug_line_insts) {
529   WhileEachInst(
530       [&f](Instruction* inst) {
531         f(inst);
532         return true;
533       },
534       run_on_debug_line_insts);
535 }
536
537 inline void Instruction::ForEachInst(
538     const std::function<void(const Instruction*)>& f,
539     bool run_on_debug_line_insts) const {
540   WhileEachInst(
541       [&f](const Instruction* inst) {
542         f(inst);
543         return true;
544       },
545       run_on_debug_line_insts);
546 }
547
548 inline void Instruction::ForEachId(const std::function<void(uint32_t*)>& f) {
549   for (auto& opnd : operands_)
550     if (spvIsIdType(opnd.type)) f(&opnd.words[0]);
551   if (type_id_ != 0u) type_id_ = GetSingleWordOperand(0u);
552   if (result_id_ != 0u)
553     result_id_ = GetSingleWordOperand(type_id_ == 0u ? 0u : 1u);
554 }
555
556 inline void Instruction::ForEachId(
557     const std::function<void(const uint32_t*)>& f) const {
558   for (const auto& opnd : operands_)
559     if (spvIsIdType(opnd.type)) f(&opnd.words[0]);
560 }
561
562 inline bool Instruction::WhileEachInId(
563     const std::function<bool(uint32_t*)>& f) {
564   for (auto& opnd : operands_) {
565     switch (opnd.type) {
566       case SPV_OPERAND_TYPE_RESULT_ID:
567       case SPV_OPERAND_TYPE_TYPE_ID:
568         break;
569       default:
570         if (spvIsIdType(opnd.type)) {
571           if (!f(&opnd.words[0])) return false;
572         }
573         break;
574     }
575   }
576   return true;
577 }
578
579 inline bool Instruction::WhileEachInId(
580     const std::function<bool(const uint32_t*)>& f) const {
581   for (const auto& opnd : operands_) {
582     switch (opnd.type) {
583       case SPV_OPERAND_TYPE_RESULT_ID:
584       case SPV_OPERAND_TYPE_TYPE_ID:
585         break;
586       default:
587         if (spvIsIdType(opnd.type)) {
588           if (!f(&opnd.words[0])) return false;
589         }
590         break;
591     }
592   }
593   return true;
594 }
595
596 inline void Instruction::ForEachInId(const std::function<void(uint32_t*)>& f) {
597   WhileEachInId([&f](uint32_t* id) {
598     f(id);
599     return true;
600   });
601 }
602
603 inline void Instruction::ForEachInId(
604     const std::function<void(const uint32_t*)>& f) const {
605   WhileEachInId([&f](const uint32_t* id) {
606     f(id);
607     return true;
608   });
609 }
610
611 inline bool Instruction::WhileEachInOperand(
612     const std::function<bool(uint32_t*)>& f) {
613   for (auto& opnd : operands_) {
614     switch (opnd.type) {
615       case SPV_OPERAND_TYPE_RESULT_ID:
616       case SPV_OPERAND_TYPE_TYPE_ID:
617         break;
618       default:
619         if (!f(&opnd.words[0])) return false;
620         break;
621     }
622   }
623   return true;
624 }
625
626 inline bool Instruction::WhileEachInOperand(
627     const std::function<bool(const uint32_t*)>& f) const {
628   for (const auto& opnd : operands_) {
629     switch (opnd.type) {
630       case SPV_OPERAND_TYPE_RESULT_ID:
631       case SPV_OPERAND_TYPE_TYPE_ID:
632         break;
633       default:
634         if (!f(&opnd.words[0])) return false;
635         break;
636     }
637   }
638   return true;
639 }
640
641 inline void Instruction::ForEachInOperand(
642     const std::function<void(uint32_t*)>& f) {
643   WhileEachInOperand([&f](uint32_t* op) {
644     f(op);
645     return true;
646   });
647 }
648
649 inline void Instruction::ForEachInOperand(
650     const std::function<void(const uint32_t*)>& f) const {
651   WhileEachInOperand([&f](const uint32_t* op) {
652     f(op);
653     return true;
654   });
655 }
656
657 inline bool Instruction::HasLabels() const {
658   switch (opcode_) {
659     case SpvOpSelectionMerge:
660     case SpvOpBranch:
661     case SpvOpLoopMerge:
662     case SpvOpBranchConditional:
663     case SpvOpSwitch:
664     case SpvOpPhi:
665       return true;
666       break;
667     default:
668       break;
669   }
670   return false;
671 }
672
673 bool Instruction::IsDecoration() const {
674   return spvOpcodeIsDecoration(opcode());
675 }
676
677 bool Instruction::IsLoad() const { return spvOpcodeIsLoad(opcode()); }
678
679 bool Instruction::IsAtomicOp() const { return spvOpcodeIsAtomicOp(opcode()); }
680
681 bool Instruction::IsConstant() const {
682   return IsCompileTimeConstantInst(opcode());
683 }
684 }  // namespace ir
685 }  // namespace spvtools
686
687 #endif  // LIBSPIRV_OPT_INSTRUCTION_H_