xref: /freebsd/contrib/llvm-project/llvm/include/llvm/SandboxIR/SandboxIR.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===- SandboxIR.h ----------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Sandbox IR is a lightweight overlay transactional IR on top of LLVM IR.
10 // Features:
11 // - You can save/rollback the state of the IR at any time.
12 // - Any changes made to Sandbox IR will automatically update the underlying
13 //   LLVM IR so both IRs are always in sync.
14 // - Feels like LLVM IR, similar API.
15 //
16 // SandboxIR forms a class hierarchy that resembles that of LLVM IR
17 // but is in the `sandboxir` namespace:
18 //
19 // namespace sandboxir {
20 //
21 //        +- Argument                   +- BinaryOperator
22 //        |                             |
23 // Value -+- BasicBlock                 +- BranchInst
24 //        |                             |
25 //        +- Function   +- Constant     +- CastInst
26 //        |             |               |
27 //        +- User ------+- Instruction -+- CallInst
28 //                                      |
29 //                                      +- CmpInst
30 //                                      |
31 //                                      +- ExtractElementInst
32 //                                      |
33 //                                      +- GetElementPtrInst
34 //                                      |
35 //                                      +- InsertElementInst
36 //                                      |
37 //                                      +- LoadInst
38 //                                      |
39 //                                      +- OpaqueInst
40 //                                      |
41 //                                      +- PHINode
42 //                                      |
43 //                                      +- ReturnInst
44 //                                      |
45 //                                      +- SelectInst
46 //                                      |
47 //                                      +- ShuffleVectorInst
48 //                                      |
49 //                                      +- StoreInst
50 //                                      |
51 //                                      +- UnaryOperator
52 //
53 // Use
54 //
55 // } // namespace sandboxir
56 //
57 
58 #ifndef LLVM_SANDBOXIR_SANDBOXIR_H
59 #define LLVM_SANDBOXIR_SANDBOXIR_H
60 
61 #include "llvm/IR/Function.h"
62 #include "llvm/IR/IRBuilder.h"
63 #include "llvm/IR/User.h"
64 #include "llvm/IR/Value.h"
65 #include "llvm/SandboxIR/Tracker.h"
66 #include "llvm/SandboxIR/Use.h"
67 #include "llvm/Support/raw_ostream.h"
68 #include <iterator>
69 
70 namespace llvm {
71 
72 namespace sandboxir {
73 
74 class BasicBlock;
75 class Context;
76 class Function;
77 class Instruction;
78 class SelectInst;
79 class LoadInst;
80 class ReturnInst;
81 class StoreInst;
82 class User;
83 class Value;
84 
85 /// Iterator for the `Use` edges of a User's operands.
86 /// \Returns the operand `Use` when dereferenced.
87 class OperandUseIterator {
88   sandboxir::Use Use;
89   /// Don't let the user create a non-empty OperandUseIterator.
OperandUseIterator(const class Use & Use)90   OperandUseIterator(const class Use &Use) : Use(Use) {}
91   friend class User;                                  // For constructor
92 #define DEF_INSTR(ID, OPC, CLASS) friend class CLASS; // For constructor
93 #include "llvm/SandboxIR/SandboxIRValues.def"
94 
95 public:
96   using difference_type = std::ptrdiff_t;
97   using value_type = sandboxir::Use;
98   using pointer = value_type *;
99   using reference = value_type &;
100   using iterator_category = std::input_iterator_tag;
101 
102   OperandUseIterator() = default;
103   value_type operator*() const;
104   OperandUseIterator &operator++();
105   bool operator==(const OperandUseIterator &Other) const {
106     return Use == Other.Use;
107   }
108   bool operator!=(const OperandUseIterator &Other) const {
109     return !(*this == Other);
110   }
111 };
112 
113 /// Iterator for the `Use` edges of a Value's users.
114 /// \Returns a `Use` when dereferenced.
115 class UserUseIterator {
116   sandboxir::Use Use;
117   /// Don't let the user create a non-empty UserUseIterator.
UserUseIterator(const class Use & Use)118   UserUseIterator(const class Use &Use) : Use(Use) {}
119   friend class Value; // For constructor
120 
121 public:
122   using difference_type = std::ptrdiff_t;
123   using value_type = sandboxir::Use;
124   using pointer = value_type *;
125   using reference = value_type &;
126   using iterator_category = std::input_iterator_tag;
127 
128   UserUseIterator() = default;
129   value_type operator*() const { return Use; }
130   UserUseIterator &operator++();
131   bool operator==(const UserUseIterator &Other) const {
132     return Use == Other.Use;
133   }
134   bool operator!=(const UserUseIterator &Other) const {
135     return !(*this == Other);
136   }
137 };
138 
139 /// A SandboxIR Value has users. This is the base class.
140 class Value {
141 public:
142   enum class ClassID : unsigned {
143 #define DEF_VALUE(ID, CLASS) ID,
144 #define DEF_USER(ID, CLASS) ID,
145 #define DEF_INSTR(ID, OPC, CLASS) ID,
146 #include "llvm/SandboxIR/SandboxIRValues.def"
147   };
148 
149 protected:
getSubclassIDStr(ClassID ID)150   static const char *getSubclassIDStr(ClassID ID) {
151     switch (ID) {
152 #define DEF_VALUE(ID, CLASS)                                                   \
153   case ClassID::ID:                                                            \
154     return #ID;
155 #define DEF_USER(ID, CLASS)                                                    \
156   case ClassID::ID:                                                            \
157     return #ID;
158 #define DEF_INSTR(ID, OPC, CLASS)                                              \
159   case ClassID::ID:                                                            \
160     return #ID;
161 #include "llvm/SandboxIR/SandboxIRValues.def"
162     }
163     llvm_unreachable("Unimplemented ID");
164   }
165 
166   /// For isa/dyn_cast.
167   ClassID SubclassID;
168 #ifndef NDEBUG
169   /// A unique ID used for forming the name (used for debugging).
170   unsigned UID;
171 #endif
172   /// The LLVM Value that corresponds to this SandboxIR Value.
173   /// NOTE: Some sandboxir Instructions, like Packs, may include more than one
174   /// value and in these cases `Val` points to the last instruction in program
175   /// order.
176   llvm::Value *Val = nullptr;
177 
178   friend class Context;    // For getting `Val`.
179   friend class User;       // For getting `Val`.
180   friend class Use;        // For getting `Val`.
181   friend class SelectInst; // For getting `Val`.
182   friend class LoadInst;   // For getting `Val`.
183   friend class StoreInst;  // For getting `Val`.
184   friend class ReturnInst; // For getting `Val`.
185 
186   /// All values point to the context.
187   Context &Ctx;
188   // This is used by eraseFromParent().
clearValue()189   void clearValue() { Val = nullptr; }
190   template <typename ItTy, typename SBTy> friend class LLVMOpUserItToSBTy;
191 
192   Value(ClassID SubclassID, llvm::Value *Val, Context &Ctx);
193 
194 public:
195   virtual ~Value() = default;
getSubclassID()196   ClassID getSubclassID() const { return SubclassID; }
197 
198   using use_iterator = UserUseIterator;
199   using const_use_iterator = UserUseIterator;
200 
201   use_iterator use_begin();
use_begin()202   const_use_iterator use_begin() const {
203     return const_cast<Value *>(this)->use_begin();
204   }
use_end()205   use_iterator use_end() { return use_iterator(Use(nullptr, nullptr, Ctx)); }
use_end()206   const_use_iterator use_end() const {
207     return const_cast<Value *>(this)->use_end();
208   }
209 
uses()210   iterator_range<use_iterator> uses() {
211     return make_range<use_iterator>(use_begin(), use_end());
212   }
uses()213   iterator_range<const_use_iterator> uses() const {
214     return make_range<const_use_iterator>(use_begin(), use_end());
215   }
216 
217   /// Helper for mapped_iterator.
218   struct UseToUser {
operatorUseToUser219     User *operator()(const Use &Use) const { return &*Use.getUser(); }
220   };
221 
222   using user_iterator = mapped_iterator<sandboxir::UserUseIterator, UseToUser>;
223   using const_user_iterator = user_iterator;
224 
225   user_iterator user_begin();
user_end()226   user_iterator user_end() {
227     return user_iterator(Use(nullptr, nullptr, Ctx), UseToUser());
228   }
user_begin()229   const_user_iterator user_begin() const {
230     return const_cast<Value *>(this)->user_begin();
231   }
user_end()232   const_user_iterator user_end() const {
233     return const_cast<Value *>(this)->user_end();
234   }
235 
users()236   iterator_range<user_iterator> users() {
237     return make_range<user_iterator>(user_begin(), user_end());
238   }
users()239   iterator_range<const_user_iterator> users() const {
240     return make_range<const_user_iterator>(user_begin(), user_end());
241   }
242   /// \Returns the number of user edges (not necessarily to unique users).
243   /// WARNING: This is a linear-time operation.
244   unsigned getNumUses() const;
245   /// Return true if this value has N uses or more.
246   /// This is logically equivalent to getNumUses() >= N.
247   /// WARNING: This can be expensive, as it is linear to the number of users.
hasNUsesOrMore(unsigned Num)248   bool hasNUsesOrMore(unsigned Num) const {
249     unsigned Cnt = 0;
250     for (auto It = use_begin(), ItE = use_end(); It != ItE; ++It) {
251       if (++Cnt >= Num)
252         return true;
253     }
254     return false;
255   }
256   /// Return true if this Value has exactly N uses.
hasNUses(unsigned Num)257   bool hasNUses(unsigned Num) const {
258     unsigned Cnt = 0;
259     for (auto It = use_begin(), ItE = use_end(); It != ItE; ++It) {
260       if (++Cnt > Num)
261         return false;
262     }
263     return Cnt == Num;
264   }
265 
getType()266   Type *getType() const { return Val->getType(); }
267 
getContext()268   Context &getContext() const { return Ctx; }
269 
270   void replaceUsesWithIf(Value *OtherV,
271                          llvm::function_ref<bool(const Use &)> ShouldReplace);
272   void replaceAllUsesWith(Value *Other);
273 
274   /// \Returns the LLVM IR name of the bottom-most LLVM value.
getName()275   StringRef getName() const { return Val->getName(); }
276 
277 #ifndef NDEBUG
278   /// Should crash if there is something wrong with the instruction.
279   virtual void verify() const = 0;
280   /// Returns the unique id in the form 'SB<number>.' like 'SB1.'
281   std::string getUid() const;
282   virtual void dumpCommonHeader(raw_ostream &OS) const;
283   void dumpCommonFooter(raw_ostream &OS) const;
284   void dumpCommonPrefix(raw_ostream &OS) const;
285   void dumpCommonSuffix(raw_ostream &OS) const;
286   void printAsOperandCommon(raw_ostream &OS) const;
287   friend raw_ostream &operator<<(raw_ostream &OS, const sandboxir::Value &V) {
288     V.dump(OS);
289     return OS;
290   }
291   virtual void dump(raw_ostream &OS) const = 0;
292   LLVM_DUMP_METHOD virtual void dump() const = 0;
293 #endif
294 };
295 
296 /// Argument of a sandboxir::Function.
297 class Argument : public sandboxir::Value {
Argument(llvm::Argument * Arg,sandboxir::Context & Ctx)298   Argument(llvm::Argument *Arg, sandboxir::Context &Ctx)
299       : sandboxir::Value(ClassID::Argument, Arg, Ctx) {}
300   friend class Context; // For constructor.
301 
302 public:
classof(const sandboxir::Value * From)303   static bool classof(const sandboxir::Value *From) {
304     return From->getSubclassID() == ClassID::Argument;
305   }
306 #ifndef NDEBUG
verify()307   void verify() const final {
308     assert(isa<llvm::Argument>(Val) && "Expected Argument!");
309   }
310   friend raw_ostream &operator<<(raw_ostream &OS,
311                                  const sandboxir::Argument &TArg) {
312     TArg.dump(OS);
313     return OS;
314   }
315   void printAsOperand(raw_ostream &OS) const;
316   void dump(raw_ostream &OS) const final;
317   LLVM_DUMP_METHOD void dump() const final;
318 #endif
319 };
320 
321 /// A sandboxir::User has operands.
322 class User : public Value {
323 protected:
User(ClassID ID,llvm::Value * V,Context & Ctx)324   User(ClassID ID, llvm::Value *V, Context &Ctx) : Value(ID, V, Ctx) {}
325 
326   /// \Returns the Use edge that corresponds to \p OpIdx.
327   /// Note: This is the default implementation that works for instructions that
328   /// match the underlying LLVM instruction. All others should use a different
329   /// implementation.
330   Use getOperandUseDefault(unsigned OpIdx, bool Verify) const;
331   /// \Returns the Use for the \p OpIdx'th operand. This is virtual to allow
332   /// instructions to deviate from the LLVM IR operands, which is a requirement
333   /// for sandboxir Instructions that consist of more than one LLVM Instruction.
334   virtual Use getOperandUseInternal(unsigned OpIdx, bool Verify) const = 0;
335   friend class OperandUseIterator; // for getOperandUseInternal()
336 
337   /// The default implementation works only for single-LLVMIR-instruction
338   /// Users and only if they match exactly the LLVM instruction.
getUseOperandNoDefault(const Use & Use)339   unsigned getUseOperandNoDefault(const Use &Use) const {
340     return Use.LLVMUse->getOperandNo();
341   }
342   /// \Returns the operand index of \p Use.
343   virtual unsigned getUseOperandNo(const Use &Use) const = 0;
344   friend unsigned Use::getOperandNo() const; // For getUseOperandNo()
345 
346 #ifndef NDEBUG
347   void verifyUserOfLLVMUse(const llvm::Use &Use) const;
348 #endif // NDEBUG
349 
350 public:
351   /// For isa/dyn_cast.
352   static bool classof(const Value *From);
353   using op_iterator = OperandUseIterator;
354   using const_op_iterator = OperandUseIterator;
355   using op_range = iterator_range<op_iterator>;
356   using const_op_range = iterator_range<const_op_iterator>;
357 
op_begin()358   virtual op_iterator op_begin() {
359     assert(isa<llvm::User>(Val) && "Expect User value!");
360     return op_iterator(getOperandUseInternal(0, /*Verify=*/false));
361   }
op_end()362   virtual op_iterator op_end() {
363     assert(isa<llvm::User>(Val) && "Expect User value!");
364     return op_iterator(
365         getOperandUseInternal(getNumOperands(), /*Verify=*/false));
366   }
op_begin()367   virtual const_op_iterator op_begin() const {
368     return const_cast<User *>(this)->op_begin();
369   }
op_end()370   virtual const_op_iterator op_end() const {
371     return const_cast<User *>(this)->op_end();
372   }
373 
operands()374   op_range operands() { return make_range<op_iterator>(op_begin(), op_end()); }
operands()375   const_op_range operands() const {
376     return make_range<const_op_iterator>(op_begin(), op_end());
377   }
getOperand(unsigned OpIdx)378   Value *getOperand(unsigned OpIdx) const { return getOperandUse(OpIdx).get(); }
379   /// \Returns the operand edge for \p OpIdx. NOTE: This should also work for
380   /// OpIdx == getNumOperands(), which is used for op_end().
getOperandUse(unsigned OpIdx)381   Use getOperandUse(unsigned OpIdx) const {
382     return getOperandUseInternal(OpIdx, /*Verify=*/true);
383   }
getNumOperands()384   virtual unsigned getNumOperands() const {
385     return isa<llvm::User>(Val) ? cast<llvm::User>(Val)->getNumOperands() : 0;
386   }
387 
388   virtual void setOperand(unsigned OperandIdx, Value *Operand);
389   /// Replaces any operands that match \p FromV with \p ToV. Returns whether any
390   /// operands were replaced.
391   bool replaceUsesOfWith(Value *FromV, Value *ToV);
392 
393 #ifndef NDEBUG
verify()394   void verify() const override {
395     assert(isa<llvm::User>(Val) && "Expected User!");
396   }
397   void dumpCommonHeader(raw_ostream &OS) const final;
dump(raw_ostream & OS)398   void dump(raw_ostream &OS) const override {
399     // TODO: Remove this tmp implementation once we get the Instruction classes.
400   }
dump()401   LLVM_DUMP_METHOD void dump() const override {
402     // TODO: Remove this tmp implementation once we get the Instruction classes.
403   }
404 #endif
405 };
406 
407 class Constant : public sandboxir::User {
Constant(llvm::Constant * C,sandboxir::Context & SBCtx)408   Constant(llvm::Constant *C, sandboxir::Context &SBCtx)
409       : sandboxir::User(ClassID::Constant, C, SBCtx) {}
410   friend class Context; // For constructor.
getOperandUseInternal(unsigned OpIdx,bool Verify)411   Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
412     return getOperandUseDefault(OpIdx, Verify);
413   }
414 
415 public:
416   static Constant *createInt(Type *Ty, uint64_t V, Context &Ctx,
417                              bool IsSigned = false);
418   /// For isa/dyn_cast.
classof(const sandboxir::Value * From)419   static bool classof(const sandboxir::Value *From) {
420     return From->getSubclassID() == ClassID::Constant ||
421            From->getSubclassID() == ClassID::Function;
422   }
getParent()423   sandboxir::Context &getParent() const { return getContext(); }
getUseOperandNo(const Use & Use)424   unsigned getUseOperandNo(const Use &Use) const final {
425     return getUseOperandNoDefault(Use);
426   }
427 #ifndef NDEBUG
verify()428   void verify() const final {
429     assert(isa<llvm::Constant>(Val) && "Expected Constant!");
430   }
431   friend raw_ostream &operator<<(raw_ostream &OS,
432                                  const sandboxir::Constant &SBC) {
433     SBC.dump(OS);
434     return OS;
435   }
436   void dump(raw_ostream &OS) const override;
437   LLVM_DUMP_METHOD void dump() const override;
438 #endif
439 };
440 
441 /// Iterator for `Instruction`s in a `BasicBlock.
442 /// \Returns an sandboxir::Instruction & when derereferenced.
443 class BBIterator {
444 public:
445   using difference_type = std::ptrdiff_t;
446   using value_type = Instruction;
447   using pointer = value_type *;
448   using reference = value_type &;
449   using iterator_category = std::bidirectional_iterator_tag;
450 
451 private:
452   llvm::BasicBlock *BB;
453   llvm::BasicBlock::iterator It;
454   Context *Ctx;
455   pointer getInstr(llvm::BasicBlock::iterator It) const;
456 
457 public:
BBIterator()458   BBIterator() : BB(nullptr), Ctx(nullptr) {}
BBIterator(llvm::BasicBlock * BB,llvm::BasicBlock::iterator It,Context * Ctx)459   BBIterator(llvm::BasicBlock *BB, llvm::BasicBlock::iterator It, Context *Ctx)
460       : BB(BB), It(It), Ctx(Ctx) {}
461   reference operator*() const { return *getInstr(It); }
462   BBIterator &operator++();
463   BBIterator operator++(int) {
464     auto Copy = *this;
465     ++*this;
466     return Copy;
467   }
468   BBIterator &operator--();
469   BBIterator operator--(int) {
470     auto Copy = *this;
471     --*this;
472     return Copy;
473   }
474   bool operator==(const BBIterator &Other) const {
475     assert(Ctx == Other.Ctx && "BBIterators in different context!");
476     return It == Other.It;
477   }
478   bool operator!=(const BBIterator &Other) const { return !(*this == Other); }
479   /// \Returns the SBInstruction that corresponds to this iterator, or null if
480   /// the instruction is not found in the IR-to-SandboxIR tables.
get()481   pointer get() const { return getInstr(It); }
482 };
483 
484 /// A sandboxir::User with operands, opcode and linked with previous/next
485 /// instructions in an instruction list.
486 class Instruction : public sandboxir::User {
487 public:
488   enum class Opcode {
489 #define DEF_VALUE(ID, CLASS)
490 #define DEF_USER(ID, CLASS)
491 #define OP(OPC) OPC,
492 #define DEF_INSTR(ID, OPC, CLASS) OPC
493 #include "llvm/SandboxIR/SandboxIRValues.def"
494   };
495 
496 protected:
Instruction(ClassID ID,Opcode Opc,llvm::Instruction * I,sandboxir::Context & SBCtx)497   Instruction(ClassID ID, Opcode Opc, llvm::Instruction *I,
498               sandboxir::Context &SBCtx)
499       : sandboxir::User(ID, I, SBCtx), Opc(Opc) {}
500 
501   Opcode Opc;
502 
503   /// A SandboxIR Instruction may map to multiple LLVM IR Instruction. This
504   /// returns its topmost LLVM IR instruction.
505   llvm::Instruction *getTopmostLLVMInstruction() const;
506   friend class SelectInst; // For getTopmostLLVMInstruction().
507   friend class LoadInst;   // For getTopmostLLVMInstruction().
508   friend class StoreInst;  // For getTopmostLLVMInstruction().
509   friend class ReturnInst; // For getTopmostLLVMInstruction().
510 
511   /// \Returns the LLVM IR Instructions that this SandboxIR maps to in program
512   /// order.
513   virtual SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const = 0;
514   friend class EraseFromParent; // For getLLVMInstrs().
515 
516 public:
517   static const char *getOpcodeName(Opcode Opc);
518 #ifndef NDEBUG
519   friend raw_ostream &operator<<(raw_ostream &OS, Opcode Opc) {
520     OS << getOpcodeName(Opc);
521     return OS;
522   }
523 #endif
524   /// This is used by BasicBlock::iterator.
525   virtual unsigned getNumOfIRInstrs() const = 0;
526   /// \Returns a BasicBlock::iterator for this Instruction.
527   BBIterator getIterator() const;
528   /// \Returns the next sandboxir::Instruction in the block, or nullptr if at
529   /// the end of the block.
530   Instruction *getNextNode() const;
531   /// \Returns the previous sandboxir::Instruction in the block, or nullptr if
532   /// at the beginning of the block.
533   Instruction *getPrevNode() const;
534   /// \Returns this Instruction's opcode. Note that SandboxIR has its own opcode
535   /// state to allow for new SandboxIR-specific instructions.
getOpcode()536   Opcode getOpcode() const { return Opc; }
537   /// Detach this from its parent BasicBlock without deleting it.
538   void removeFromParent();
539   /// Detach this Value from its parent and delete it.
540   void eraseFromParent();
541   /// Insert this detached instruction before \p BeforeI.
542   void insertBefore(Instruction *BeforeI);
543   /// Insert this detached instruction after \p AfterI.
544   void insertAfter(Instruction *AfterI);
545   /// Insert this detached instruction into \p BB at \p WhereIt.
546   void insertInto(BasicBlock *BB, const BBIterator &WhereIt);
547   /// Move this instruction to \p WhereIt.
548   void moveBefore(BasicBlock &BB, const BBIterator &WhereIt);
549   /// Move this instruction before \p Before.
moveBefore(Instruction * Before)550   void moveBefore(Instruction *Before) {
551     moveBefore(*Before->getParent(), Before->getIterator());
552   }
553   /// Move this instruction after \p After.
moveAfter(Instruction * After)554   void moveAfter(Instruction *After) {
555     moveBefore(*After->getParent(), std::next(After->getIterator()));
556   }
557   /// \Returns the BasicBlock containing this Instruction, or null if it is
558   /// detached.
559   BasicBlock *getParent() const;
560   /// For isa/dyn_cast.
561   static bool classof(const sandboxir::Value *From);
562 
563 #ifndef NDEBUG
564   friend raw_ostream &operator<<(raw_ostream &OS,
565                                  const sandboxir::Instruction &SBI) {
566     SBI.dump(OS);
567     return OS;
568   }
569   void dump(raw_ostream &OS) const override;
570   LLVM_DUMP_METHOD void dump() const override;
571 #endif
572 };
573 
574 class SelectInst : public Instruction {
575   /// Use Context::createSelectInst(). Don't call the
576   /// constructor directly.
SelectInst(llvm::SelectInst * CI,Context & Ctx)577   SelectInst(llvm::SelectInst *CI, Context &Ctx)
578       : Instruction(ClassID::Select, Opcode::Select, CI, Ctx) {}
579   friend Context; // for SelectInst()
getOperandUseInternal(unsigned OpIdx,bool Verify)580   Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
581     return getOperandUseDefault(OpIdx, Verify);
582   }
getLLVMInstrs()583   SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
584     return {cast<llvm::Instruction>(Val)};
585   }
586   static Value *createCommon(Value *Cond, Value *True, Value *False,
587                              const Twine &Name, IRBuilder<> &Builder,
588                              Context &Ctx);
589 
590 public:
getUseOperandNo(const Use & Use)591   unsigned getUseOperandNo(const Use &Use) const final {
592     return getUseOperandNoDefault(Use);
593   }
getNumOfIRInstrs()594   unsigned getNumOfIRInstrs() const final { return 1u; }
595   static Value *create(Value *Cond, Value *True, Value *False,
596                        Instruction *InsertBefore, Context &Ctx,
597                        const Twine &Name = "");
598   static Value *create(Value *Cond, Value *True, Value *False,
599                        BasicBlock *InsertAtEnd, Context &Ctx,
600                        const Twine &Name = "");
getCondition()601   Value *getCondition() { return getOperand(0); }
getTrueValue()602   Value *getTrueValue() { return getOperand(1); }
getFalseValue()603   Value *getFalseValue() { return getOperand(2); }
604 
setCondition(Value * New)605   void setCondition(Value *New) { setOperand(0, New); }
setTrueValue(Value * New)606   void setTrueValue(Value *New) { setOperand(1, New); }
setFalseValue(Value * New)607   void setFalseValue(Value *New) { setOperand(2, New); }
swapValues()608   void swapValues() { cast<llvm::SelectInst>(Val)->swapValues(); }
609   /// For isa/dyn_cast.
610   static bool classof(const Value *From);
611 #ifndef NDEBUG
verify()612   void verify() const final {
613     assert(isa<llvm::SelectInst>(Val) && "Expected SelectInst!");
614   }
615   void dump(raw_ostream &OS) const override;
616   LLVM_DUMP_METHOD void dump() const override;
617 #endif
618 };
619 
620 class LoadInst final : public Instruction {
621   /// Use LoadInst::create() instead of calling the constructor.
LoadInst(llvm::LoadInst * LI,Context & Ctx)622   LoadInst(llvm::LoadInst *LI, Context &Ctx)
623       : Instruction(ClassID::Load, Opcode::Load, LI, Ctx) {}
624   friend Context; // for LoadInst()
getOperandUseInternal(unsigned OpIdx,bool Verify)625   Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
626     return getOperandUseDefault(OpIdx, Verify);
627   }
getLLVMInstrs()628   SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
629     return {cast<llvm::Instruction>(Val)};
630   }
631 
632 public:
getUseOperandNo(const Use & Use)633   unsigned getUseOperandNo(const Use &Use) const final {
634     return getUseOperandNoDefault(Use);
635   }
636 
getNumOfIRInstrs()637   unsigned getNumOfIRInstrs() const final { return 1u; }
638   static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
639                           Instruction *InsertBefore, Context &Ctx,
640                           const Twine &Name = "");
641   static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
642                           BasicBlock *InsertAtEnd, Context &Ctx,
643                           const Twine &Name = "");
644   /// For isa/dyn_cast.
645   static bool classof(const Value *From);
646   Value *getPointerOperand() const;
getAlign()647   Align getAlign() const { return cast<llvm::LoadInst>(Val)->getAlign(); }
isUnordered()648   bool isUnordered() const { return cast<llvm::LoadInst>(Val)->isUnordered(); }
isSimple()649   bool isSimple() const { return cast<llvm::LoadInst>(Val)->isSimple(); }
650 #ifndef NDEBUG
verify()651   void verify() const final {
652     assert(isa<llvm::LoadInst>(Val) && "Expected LoadInst!");
653   }
654   void dump(raw_ostream &OS) const override;
655   LLVM_DUMP_METHOD void dump() const override;
656 #endif
657 };
658 
659 class StoreInst final : public Instruction {
660   /// Use StoreInst::create().
StoreInst(llvm::StoreInst * SI,Context & Ctx)661   StoreInst(llvm::StoreInst *SI, Context &Ctx)
662       : Instruction(ClassID::Store, Opcode::Store, SI, Ctx) {}
663   friend Context; // for StoreInst()
getOperandUseInternal(unsigned OpIdx,bool Verify)664   Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
665     return getOperandUseDefault(OpIdx, Verify);
666   }
getLLVMInstrs()667   SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
668     return {cast<llvm::Instruction>(Val)};
669   }
670 
671 public:
getUseOperandNo(const Use & Use)672   unsigned getUseOperandNo(const Use &Use) const final {
673     return getUseOperandNoDefault(Use);
674   }
getNumOfIRInstrs()675   unsigned getNumOfIRInstrs() const final { return 1u; }
676   static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
677                            Instruction *InsertBefore, Context &Ctx);
678   static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
679                            BasicBlock *InsertAtEnd, Context &Ctx);
680   /// For isa/dyn_cast.
681   static bool classof(const Value *From);
682   Value *getValueOperand() const;
683   Value *getPointerOperand() const;
getAlign()684   Align getAlign() const { return cast<llvm::StoreInst>(Val)->getAlign(); }
isSimple()685   bool isSimple() const { return cast<llvm::StoreInst>(Val)->isSimple(); }
isUnordered()686   bool isUnordered() const { return cast<llvm::StoreInst>(Val)->isUnordered(); }
687 #ifndef NDEBUG
verify()688   void verify() const final {
689     assert(isa<llvm::StoreInst>(Val) && "Expected StoreInst!");
690   }
691   void dump(raw_ostream &OS) const override;
692   LLVM_DUMP_METHOD void dump() const override;
693 #endif
694 };
695 
696 class ReturnInst final : public Instruction {
697   /// Use ReturnInst::create() instead of calling the constructor.
ReturnInst(llvm::Instruction * I,Context & Ctx)698   ReturnInst(llvm::Instruction *I, Context &Ctx)
699       : Instruction(ClassID::Ret, Opcode::Ret, I, Ctx) {}
ReturnInst(ClassID SubclassID,llvm::Instruction * I,Context & Ctx)700   ReturnInst(ClassID SubclassID, llvm::Instruction *I, Context &Ctx)
701       : Instruction(SubclassID, Opcode::Ret, I, Ctx) {}
702   friend class Context; // For accessing the constructor in create*()
getOperandUseInternal(unsigned OpIdx,bool Verify)703   Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
704     return getOperandUseDefault(OpIdx, Verify);
705   }
getLLVMInstrs()706   SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
707     return {cast<llvm::Instruction>(Val)};
708   }
709   static ReturnInst *createCommon(Value *RetVal, IRBuilder<> &Builder,
710                                   Context &Ctx);
711 
712 public:
713   static ReturnInst *create(Value *RetVal, Instruction *InsertBefore,
714                             Context &Ctx);
715   static ReturnInst *create(Value *RetVal, BasicBlock *InsertAtEnd,
716                             Context &Ctx);
classof(const Value * From)717   static bool classof(const Value *From) {
718     return From->getSubclassID() == ClassID::Ret;
719   }
getUseOperandNo(const Use & Use)720   unsigned getUseOperandNo(const Use &Use) const final {
721     return getUseOperandNoDefault(Use);
722   }
getNumOfIRInstrs()723   unsigned getNumOfIRInstrs() const final { return 1u; }
724   /// \Returns null if there is no return value.
725   Value *getReturnValue() const;
726 #ifndef NDEBUG
verify()727   void verify() const final {}
728   void dump(raw_ostream &OS) const override;
729   LLVM_DUMP_METHOD void dump() const override;
730 #endif
731 };
732 
733 /// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to
734 /// an OpaqueInstr.
735 class OpaqueInst : public sandboxir::Instruction {
OpaqueInst(llvm::Instruction * I,sandboxir::Context & Ctx)736   OpaqueInst(llvm::Instruction *I, sandboxir::Context &Ctx)
737       : sandboxir::Instruction(ClassID::Opaque, Opcode::Opaque, I, Ctx) {}
OpaqueInst(ClassID SubclassID,llvm::Instruction * I,sandboxir::Context & Ctx)738   OpaqueInst(ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx)
739       : sandboxir::Instruction(SubclassID, Opcode::Opaque, I, Ctx) {}
740   friend class Context; // For constructor.
getOperandUseInternal(unsigned OpIdx,bool Verify)741   Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
742     return getOperandUseDefault(OpIdx, Verify);
743   }
getLLVMInstrs()744   SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
745     return {cast<llvm::Instruction>(Val)};
746   }
747 
748 public:
classof(const sandboxir::Value * From)749   static bool classof(const sandboxir::Value *From) {
750     return From->getSubclassID() == ClassID::Opaque;
751   }
getUseOperandNo(const Use & Use)752   unsigned getUseOperandNo(const Use &Use) const final {
753     return getUseOperandNoDefault(Use);
754   }
getNumOfIRInstrs()755   unsigned getNumOfIRInstrs() const final { return 1u; }
756 #ifndef NDEBUG
verify()757   void verify() const final {
758     // Nothing to do
759   }
760   friend raw_ostream &operator<<(raw_ostream &OS,
761                                  const sandboxir::OpaqueInst &OI) {
762     OI.dump(OS);
763     return OS;
764   }
765   void dump(raw_ostream &OS) const override;
766   LLVM_DUMP_METHOD void dump() const override;
767 #endif
768 };
769 
770 /// Contains a list of sandboxir::Instruction's.
771 class BasicBlock : public Value {
772   /// Builds a graph that contains all values in \p BB in their original form
773   /// i.e., no vectorization is taking place here.
774   void buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB);
775   friend class Context;     // For `buildBasicBlockFromIR`
776   friend class Instruction; // For LLVM Val.
777 
BasicBlock(llvm::BasicBlock * BB,Context & SBCtx)778   BasicBlock(llvm::BasicBlock *BB, Context &SBCtx)
779       : Value(ClassID::Block, BB, SBCtx) {
780     buildBasicBlockFromLLVMIR(BB);
781   }
782 
783 public:
784   ~BasicBlock() = default;
785   /// For isa/dyn_cast.
classof(const Value * From)786   static bool classof(const Value *From) {
787     return From->getSubclassID() == Value::ClassID::Block;
788   }
789   Function *getParent() const;
790   using iterator = BBIterator;
791   iterator begin() const;
end()792   iterator end() const {
793     auto *BB = cast<llvm::BasicBlock>(Val);
794     return iterator(BB, BB->end(), &Ctx);
795   }
rbegin()796   std::reverse_iterator<iterator> rbegin() const {
797     return std::make_reverse_iterator(end());
798   }
rend()799   std::reverse_iterator<iterator> rend() const {
800     return std::make_reverse_iterator(begin());
801   }
getContext()802   Context &getContext() const { return Ctx; }
803   Instruction *getTerminator() const;
empty()804   bool empty() const { return begin() == end(); }
805   Instruction &front() const;
806   Instruction &back() const;
807 
808 #ifndef NDEBUG
verify()809   void verify() const final {
810     assert(isa<llvm::BasicBlock>(Val) && "Expected BasicBlock!");
811   }
812   friend raw_ostream &operator<<(raw_ostream &OS, const BasicBlock &SBBB) {
813     SBBB.dump(OS);
814     return OS;
815   }
816   void dump(raw_ostream &OS) const final;
817   LLVM_DUMP_METHOD void dump() const final;
818 #endif
819 };
820 
821 class Context {
822 protected:
823   LLVMContext &LLVMCtx;
824   Tracker IRTracker;
825 
826   /// Maps LLVM Value to the corresponding sandboxir::Value. Owns all
827   /// SandboxIR objects.
828   DenseMap<llvm::Value *, std::unique_ptr<sandboxir::Value>>
829       LLVMValueToValueMap;
830 
831   /// Remove \p V from the maps and returns the unique_ptr.
832   std::unique_ptr<Value> detachLLVMValue(llvm::Value *V);
833   /// Remove \p SBV from all SandboxIR maps and stop owning it. This effectively
834   /// detaches \p V from the underlying IR.
835   std::unique_ptr<Value> detach(Value *V);
836   friend void Instruction::eraseFromParent(); // For detach().
837   /// Take ownership of VPtr and store it in `LLVMValueToValueMap`.
838   Value *registerValue(std::unique_ptr<Value> &&VPtr);
839   friend class EraseFromParent; // For registerValue().
840   /// This is the actual function that creates sandboxir values for \p V,
841   /// and among others handles all instruction types.
842   Value *getOrCreateValueInternal(llvm::Value *V, llvm::User *U = nullptr);
843   /// Get or create a sandboxir::Argument for an existing LLVM IR \p LLVMArg.
getOrCreateArgument(llvm::Argument * LLVMArg)844   Argument *getOrCreateArgument(llvm::Argument *LLVMArg) {
845     auto Pair = LLVMValueToValueMap.insert({LLVMArg, nullptr});
846     auto It = Pair.first;
847     if (Pair.second) {
848       It->second = std::unique_ptr<Argument>(new Argument(LLVMArg, *this));
849       return cast<Argument>(It->second.get());
850     }
851     return cast<Argument>(It->second.get());
852   }
853   /// Get or create a sandboxir::Value for an existing LLVM IR \p LLVMV.
getOrCreateValue(llvm::Value * LLVMV)854   Value *getOrCreateValue(llvm::Value *LLVMV) {
855     return getOrCreateValueInternal(LLVMV, 0);
856   }
857   /// Get or create a sandboxir::Constant from an existing LLVM IR \p LLVMC.
getOrCreateConstant(llvm::Constant * LLVMC)858   Constant *getOrCreateConstant(llvm::Constant *LLVMC) {
859     return cast<Constant>(getOrCreateValueInternal(LLVMC, 0));
860   }
861   friend class Constant; // For getOrCreateConstant().
862   /// Create a sandboxir::BasicBlock for an existing LLVM IR \p BB. This will
863   /// also create all contents of the block.
864   BasicBlock *createBasicBlock(llvm::BasicBlock *BB);
865 
866   friend class BasicBlock; // For getOrCreateValue().
867 
868   IRBuilder<ConstantFolder> LLVMIRBuilder;
getLLVMIRBuilder()869   auto &getLLVMIRBuilder() { return LLVMIRBuilder; }
870 
871   SelectInst *createSelectInst(llvm::SelectInst *SI);
872   friend SelectInst; // For createSelectInst()
873   LoadInst *createLoadInst(llvm::LoadInst *LI);
874   friend LoadInst; // For createLoadInst()
875   StoreInst *createStoreInst(llvm::StoreInst *SI);
876   friend StoreInst; // For createStoreInst()
877   ReturnInst *createReturnInst(llvm::ReturnInst *I);
878   friend ReturnInst; // For createReturnInst()
879 
880 public:
Context(LLVMContext & LLVMCtx)881   Context(LLVMContext &LLVMCtx)
882       : LLVMCtx(LLVMCtx), IRTracker(*this),
883         LLVMIRBuilder(LLVMCtx, ConstantFolder()) {}
884 
getTracker()885   Tracker &getTracker() { return IRTracker; }
886   /// Convenience function for `getTracker().save()`
save()887   void save() { IRTracker.save(); }
888   /// Convenience function for `getTracker().revert()`
revert()889   void revert() { IRTracker.revert(); }
890   /// Convenience function for `getTracker().accept()`
accept()891   void accept() { IRTracker.accept(); }
892 
893   sandboxir::Value *getValue(llvm::Value *V) const;
getValue(const llvm::Value * V)894   const sandboxir::Value *getValue(const llvm::Value *V) const {
895     return getValue(const_cast<llvm::Value *>(V));
896   }
897   /// Create a sandboxir::Function for an existing LLVM IR \p F, including all
898   /// blocks and instructions.
899   /// This is the main API function for creating Sandbox IR.
900   Function *createFunction(llvm::Function *F);
901 
902   /// \Returns the number of values registered with Context.
getNumValues()903   size_t getNumValues() const { return LLVMValueToValueMap.size(); }
904 };
905 
906 class Function : public sandboxir::Value {
907   /// Helper for mapped_iterator.
908   struct LLVMBBToBB {
909     Context &Ctx;
LLVMBBToBBLLVMBBToBB910     LLVMBBToBB(Context &Ctx) : Ctx(Ctx) {}
operatorLLVMBBToBB911     BasicBlock &operator()(llvm::BasicBlock &LLVMBB) const {
912       return *cast<BasicBlock>(Ctx.getValue(&LLVMBB));
913     }
914   };
915   /// Use Context::createFunction() instead.
Function(llvm::Function * F,sandboxir::Context & Ctx)916   Function(llvm::Function *F, sandboxir::Context &Ctx)
917       : sandboxir::Value(ClassID::Function, F, Ctx) {}
918   friend class Context; // For constructor.
919 
920 public:
921   /// For isa/dyn_cast.
classof(const sandboxir::Value * From)922   static bool classof(const sandboxir::Value *From) {
923     return From->getSubclassID() == ClassID::Function;
924   }
925 
getArg(unsigned Idx)926   Argument *getArg(unsigned Idx) const {
927     llvm::Argument *Arg = cast<llvm::Function>(Val)->getArg(Idx);
928     return cast<Argument>(Ctx.getValue(Arg));
929   }
930 
arg_size()931   size_t arg_size() const { return cast<llvm::Function>(Val)->arg_size(); }
arg_empty()932   bool arg_empty() const { return cast<llvm::Function>(Val)->arg_empty(); }
933 
934   using iterator = mapped_iterator<llvm::Function::iterator, LLVMBBToBB>;
begin()935   iterator begin() const {
936     LLVMBBToBB BBGetter(Ctx);
937     return iterator(cast<llvm::Function>(Val)->begin(), BBGetter);
938   }
end()939   iterator end() const {
940     LLVMBBToBB BBGetter(Ctx);
941     return iterator(cast<llvm::Function>(Val)->end(), BBGetter);
942   }
943 
944 #ifndef NDEBUG
verify()945   void verify() const final {
946     assert(isa<llvm::Function>(Val) && "Expected Function!");
947   }
948   void dumpNameAndArgs(raw_ostream &OS) const;
949   void dump(raw_ostream &OS) const final;
950   LLVM_DUMP_METHOD void dump() const final;
951 #endif
952 };
953 
954 } // namespace sandboxir
955 } // namespace llvm
956 
957 #endif // LLVM_SANDBOXIR_SANDBOXIR_H
958