xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Utils/IRNormalizer.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
1 //===--------------- IRNormalizer.cpp - IR Normalizer ---------------===//
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 /// \file
9 /// This file implements the IRNormalizer class which aims to transform LLVM
10 /// Modules into a normal form by reordering and renaming instructions while
11 /// preserving the same semantics. The normalizer makes it easier to spot
12 /// semantic differences while diffing two modules which have undergone
13 /// different passes.
14 ///
15 //===----------------------------------------------------------------------===//
16 
17 #include "llvm/Transforms/Utils/IRNormalizer.h"
18 #include "llvm/ADT/SetVector.h"
19 #include "llvm/ADT/SmallPtrSet.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/IR/BasicBlock.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/IRBuilder.h"
25 #include "llvm/IR/InstIterator.h"
26 #include "llvm/Pass.h"
27 #include <stack>
28 
29 #define DEBUG_TYPE "normalize"
30 
31 using namespace llvm;
32 
33 namespace {
34 /// IRNormalizer aims to transform LLVM IR into normal form.
35 class IRNormalizer {
36 public:
37   bool runOnFunction(Function &F);
38 
39   IRNormalizer(IRNormalizerOptions Options) : Options(Options) {}
40 
41 private:
42   const IRNormalizerOptions Options;
43 
44   // Random constant for hashing, so the state isn't zero.
45   const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
46   DenseSet<const Instruction *> NamedInstructions;
47 
48   SmallVector<Instruction *, 16> Outputs;
49 
50   /// \name Naming.
51   /// @{
52   void nameFunctionArguments(Function &F) const;
53   void nameBasicBlocks(Function &F) const;
54   void nameInstruction(Instruction *I);
55   void nameAsInitialInstruction(Instruction *I) const;
56   void nameAsRegularInstruction(Instruction *I);
57   void foldInstructionName(Instruction *I) const;
58   /// @}
59 
60   /// \name Reordering.
61   /// @{
62   void reorderInstructions(Function &F) const;
63   void reorderDefinition(Instruction *Definition,
64                          std::stack<Instruction *> &TopologicalSort,
65                          SmallPtrSet<const Instruction *, 32> &Visited) const;
66   void reorderInstructionOperandsByNames(Instruction *I) const;
67   void reorderPHIIncomingValues(PHINode *Phi) const;
68   /// @}
69 
70   /// \name Utility methods.
71   /// @{
72   template <typename T>
73   void sortCommutativeOperands(Instruction *I, T &Operands) const;
74   SmallVector<Instruction *, 16> collectOutputInstructions(Function &F) const;
75   bool isOutput(const Instruction *I) const;
76   bool isInitialInstruction(const Instruction *I) const;
77   bool hasOnlyImmediateOperands(const Instruction *I) const;
78   SetVector<int>
79   getOutputFootprint(Instruction *I,
80                      SmallPtrSet<const Instruction *, 32> &Visited) const;
81   /// @}
82 };
83 } // namespace
84 
85 /// Entry method to the IRNormalizer.
86 ///
87 /// \param F Function to normalize.
88 bool IRNormalizer::runOnFunction(Function &F) {
89   nameFunctionArguments(F);
90   nameBasicBlocks(F);
91 
92   Outputs = collectOutputInstructions(F);
93 
94   if (!Options.PreserveOrder)
95     reorderInstructions(F);
96 
97   // TODO: Reorder basic blocks via a topological sort.
98 
99   for (auto &I : Outputs)
100     nameInstruction(I);
101 
102   for (auto &I : instructions(F)) {
103     if (!Options.PreserveOrder) {
104       if (Options.ReorderOperands)
105         reorderInstructionOperandsByNames(&I);
106 
107       if (auto *Phi = dyn_cast<PHINode>(&I))
108         reorderPHIIncomingValues(Phi);
109     }
110     foldInstructionName(&I);
111   }
112 
113   return true;
114 }
115 
116 /// Numbers arguments.
117 ///
118 /// \param F Function whose arguments will be renamed.
119 void IRNormalizer::nameFunctionArguments(Function &F) const {
120   int ArgumentCounter = 0;
121   for (auto &A : F.args()) {
122     if (Options.RenameAll || A.getName().empty()) {
123       A.setName("a" + Twine(ArgumentCounter));
124       ArgumentCounter += 1;
125     }
126   }
127 }
128 
129 /// Names basic blocks using a generated hash for each basic block in
130 /// a function considering the opcode and the order of output instructions.
131 ///
132 /// \param F Function containing basic blocks to rename.
133 void IRNormalizer::nameBasicBlocks(Function &F) const {
134   for (auto &B : F) {
135     // Initialize to a magic constant, so the state isn't zero.
136     uint64_t Hash = MagicHashConstant;
137 
138     // Hash considering output instruction opcodes.
139     for (auto &I : B)
140       if (isOutput(&I))
141         Hash = hashing::detail::hash_16_bytes(Hash, I.getOpcode());
142 
143     if (Options.RenameAll || B.getName().empty()) {
144       // Name basic block. Substring hash to make diffs more readable.
145       B.setName("bb" + std::to_string(Hash).substr(0, 5));
146     }
147   }
148 }
149 
150 /// Names instructions graphically (recursive) in accordance with the
151 /// def-use tree, starting from the initial instructions (defs), finishing at
152 /// the output (top-most user) instructions (depth-first).
153 ///
154 /// \param I Instruction to be renamed.
155 void IRNormalizer::nameInstruction(Instruction *I) {
156   // Ensure instructions are not renamed. This is done
157   // to prevent situation where instructions are used
158   // before their definition (in phi nodes)
159   if (NamedInstructions.contains(I))
160     return;
161   NamedInstructions.insert(I);
162   if (isInitialInstruction(I)) {
163     nameAsInitialInstruction(I);
164   } else {
165     // This must be a regular instruction.
166     nameAsRegularInstruction(I);
167   }
168 }
169 
170 template <typename T>
171 void IRNormalizer::sortCommutativeOperands(Instruction *I, T &Operands) const {
172   if (!(I->isCommutative() && Operands.size() >= 2))
173     return;
174   auto CommutativeEnd = Operands.begin();
175   std::advance(CommutativeEnd, 2);
176   llvm::sort(Operands.begin(), CommutativeEnd);
177 }
178 
179 /// Names instruction following the scheme:
180 /// vl00000Callee(Operands)
181 ///
182 /// Where 00000 is a hash calculated considering instruction's opcode and output
183 /// footprint. Callee's name is only included when instruction's type is
184 /// CallInst. In cases where instruction is commutative, operands list is also
185 /// sorted.
186 ///
187 /// Renames instruction only when RenameAll flag is raised or instruction is
188 /// unnamed.
189 ///
190 /// \see getOutputFootprint()
191 /// \param I Instruction to be renamed.
192 void IRNormalizer::nameAsInitialInstruction(Instruction *I) const {
193   if (I->getType()->isVoidTy())
194     return;
195   if (!(I->getName().empty() || Options.RenameAll))
196     return;
197   LLVM_DEBUG(dbgs() << "Naming initial instruction: " << *I << "\n");
198 
199   // Instruction operands for further sorting.
200   SmallVector<SmallString<64>, 4> Operands;
201 
202   // Collect operands.
203   for (auto &Op : I->operands()) {
204     if (!isa<Function>(Op)) {
205       std::string TextRepresentation;
206       raw_string_ostream Stream(TextRepresentation);
207       Op->printAsOperand(Stream, false);
208       Operands.push_back(StringRef(Stream.str()));
209     }
210   }
211 
212   sortCommutativeOperands(I, Operands);
213 
214   // Initialize to a magic constant, so the state isn't zero.
215   uint64_t Hash = MagicHashConstant;
216 
217   // Consider instruction's opcode in the hash.
218   Hash = hashing::detail::hash_16_bytes(Hash, I->getOpcode());
219 
220   SmallPtrSet<const Instruction *, 32> Visited;
221   // Get output footprint for I.
222   SetVector<int> OutputFootprint = getOutputFootprint(I, Visited);
223 
224   // Consider output footprint in the hash.
225   for (const int &Output : OutputFootprint)
226     Hash = hashing::detail::hash_16_bytes(Hash, Output);
227 
228   // Base instruction name.
229   SmallString<256> Name;
230   Name.append("vl" + std::to_string(Hash).substr(0, 5));
231 
232   // In case of CallInst, consider callee in the instruction name.
233   if (const auto *CI = dyn_cast<CallInst>(I)) {
234     Function *F = CI->getCalledFunction();
235 
236     if (F != nullptr)
237       Name.append(F->getName());
238   }
239 
240   Name.append("(");
241   for (size_t i = 0; i < Operands.size(); ++i) {
242     Name.append(Operands[i]);
243 
244     if (i < Operands.size() - 1)
245       Name.append(", ");
246   }
247   Name.append(")");
248 
249   I->setName(Name);
250 }
251 
252 /// Names instruction following the scheme:
253 /// op00000Callee(Operands)
254 ///
255 /// Where 00000 is a hash calculated considering instruction's opcode, its
256 /// operands' opcodes and order. Callee's name is only included when
257 /// instruction's type is CallInst. In cases where instruction is commutative,
258 /// operand list is also sorted.
259 ///
260 /// Names instructions recursively in accordance with the def-use tree,
261 /// starting from the initial instructions (defs), finishing at
262 /// the output (top-most user) instructions (depth-first).
263 ///
264 /// Renames instruction only when RenameAll flag is raised or instruction is
265 /// unnamed.
266 ///
267 /// \see getOutputFootprint()
268 /// \param I Instruction to be renamed.
269 void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
270   LLVM_DEBUG(dbgs() << "Naming regular instruction: " << *I << "\n");
271 
272   // Instruction operands for further sorting.
273   SmallVector<SmallString<128>, 4> Operands;
274 
275   // The name of a regular instruction depends
276   // on the names of its operands. Hence, all
277   // operands must be named first in the use-def
278   // walk.
279 
280   // Collect operands.
281   for (auto &Op : I->operands()) {
282     if (auto *I = dyn_cast<Instruction>(Op)) {
283       // Walk down the use-def chain.
284       nameInstruction(I);
285       Operands.push_back(I->getName());
286     } else if (!isa<Function>(Op)) {
287       // This must be an immediate value.
288       std::string TextRepresentation;
289       raw_string_ostream Stream(TextRepresentation);
290       Op->printAsOperand(Stream, false);
291       Operands.push_back(StringRef(Stream.str()));
292     }
293   }
294 
295   sortCommutativeOperands(I, Operands);
296 
297   // Initialize to a magic constant, so the state isn't zero.
298   uint64_t Hash = MagicHashConstant;
299 
300   // Consider instruction opcode in the hash.
301   Hash = hashing::detail::hash_16_bytes(Hash, I->getOpcode());
302 
303   // Operand opcodes for further sorting (commutative).
304   SmallVector<int, 4> OperandsOpcodes;
305 
306   // Collect operand opcodes for hashing.
307   for (auto &Op : I->operands())
308     if (auto *I = dyn_cast<Instruction>(Op))
309       OperandsOpcodes.push_back(I->getOpcode());
310 
311   sortCommutativeOperands(I, OperandsOpcodes);
312 
313   // Consider operand opcodes in the hash.
314   for (const int Code : OperandsOpcodes)
315     Hash = hashing::detail::hash_16_bytes(Hash, Code);
316 
317   // Base instruction name.
318   SmallString<512> Name;
319   Name.append("op" + std::to_string(Hash).substr(0, 5));
320 
321   // In case of CallInst, consider callee in the instruction name.
322   if (const auto *CI = dyn_cast<CallInst>(I))
323     if (const Function *F = CI->getCalledFunction())
324       Name.append(F->getName());
325 
326   Name.append("(");
327   for (size_t i = 0; i < Operands.size(); ++i) {
328     Name.append(Operands[i]);
329 
330     if (i < Operands.size() - 1)
331       Name.append(", ");
332   }
333   Name.append(")");
334 
335   if ((I->getName().empty() || Options.RenameAll) && !I->getType()->isVoidTy())
336     I->setName(Name);
337 }
338 
339 /// Shortens instruction's name. This method removes called function name from
340 /// the instruction name and substitutes the call chain with a corresponding
341 /// list of operands.
342 ///
343 /// Examples:
344 /// op00000Callee(op00001Callee(...), vl00000Callee(1, 2), ...)  ->
345 /// op00000(op00001, vl00000, ...) vl00000Callee(1, 2)  ->  vl00000(1, 2)
346 ///
347 /// This method omits output instructions and pre-output (instructions directly
348 /// used by an output instruction) instructions (by default). By default it also
349 /// does not affect user named instructions.
350 ///
351 /// \param I Instruction whose name will be folded.
352 void IRNormalizer::foldInstructionName(Instruction *I) const {
353   // If this flag is raised, fold all regular
354   // instructions (including pre-outputs).
355   if (!Options.FoldPreOutputs) {
356     // Don't fold if one of the users is an output instruction.
357     for (auto *U : I->users())
358       if (auto *IU = dyn_cast<Instruction>(U))
359         if (isOutput(IU))
360           return;
361   }
362 
363   // Don't fold if it is an output instruction or has no op prefix.
364   if (isOutput(I) || !I->getName().starts_with("op"))
365     return;
366 
367   // Instruction operands.
368   SmallVector<SmallString<64>, 4> Operands;
369 
370   for (auto &Op : I->operands()) {
371     if (const auto *I = dyn_cast<Instruction>(Op)) {
372       bool HasNormalName =
373           I->getName().starts_with("op") || I->getName().starts_with("vl");
374 
375       Operands.push_back(HasNormalName ? I->getName().substr(0, 7)
376                                        : I->getName());
377     }
378   }
379 
380   sortCommutativeOperands(I, Operands);
381 
382   SmallString<256> Name;
383   Name.append(I->getName().substr(0, 7));
384 
385   Name.append("(");
386   for (size_t i = 0; i < Operands.size(); ++i) {
387     Name.append(Operands[i]);
388 
389     if (i < Operands.size() - 1)
390       Name.append(", ");
391   }
392   Name.append(")");
393 
394   I->setName(Name);
395 }
396 
397 /// Reorders instructions by walking up the tree from each operand of an output
398 /// instruction and reducing the def-use distance.
399 /// This method assumes that output instructions were collected top-down,
400 /// otherwise the def-use chain may be broken.
401 /// This method is a wrapper for recursive reorderInstruction().
402 ///
403 /// \see reorderInstruction()
404 void IRNormalizer::reorderInstructions(Function &F) const {
405   for (auto &BB : F) {
406     LLVM_DEBUG(dbgs() << "Reordering instructions in basic block: "
407                       << BB.getName() << "\n");
408     // Find the source nodes of the DAG of instructions in this basic block.
409     // Source nodes are instructions that have side effects, are terminators, or
410     // don't have a parent in the DAG of instructions.
411     //
412     // We must iterate from the first to the last instruction otherwise side
413     // effecting instructions could be reordered.
414 
415     std::stack<Instruction *> TopologicalSort;
416     SmallPtrSet<const Instruction *, 32> Visited;
417     for (auto &I : BB) {
418       // First process side effecting and terminating instructions.
419       if (!(isOutput(&I) || I.isTerminator()))
420         continue;
421       LLVM_DEBUG(dbgs() << "\tReordering from source effecting instruction: ";
422                  I.dump());
423       reorderDefinition(&I, TopologicalSort, Visited);
424     }
425 
426     for (auto &I : BB) {
427       // Process the remaining instructions.
428       //
429       // TODO: Do more a intelligent sorting of these instructions. For example,
430       // seperate between dead instructinos and instructions used in another
431       // block. Use properties of the CFG the order instructions that are used
432       // in another block.
433       if (Visited.contains(&I))
434         continue;
435       LLVM_DEBUG(dbgs() << "\tReordering from source instruction: "; I.dump());
436       reorderDefinition(&I, TopologicalSort, Visited);
437     }
438 
439     LLVM_DEBUG(dbgs() << "Inserting instructions into: " << BB.getName()
440                       << "\n");
441     // Reorder based on the topological sort.
442     while (!TopologicalSort.empty()) {
443       auto *Instruction = TopologicalSort.top();
444       auto FirstNonPHIOrDbgOrAlloca = BB.getFirstNonPHIOrDbgOrAlloca();
445       if (auto *Call = dyn_cast<CallInst>(&*FirstNonPHIOrDbgOrAlloca)) {
446         if (Call->getIntrinsicID() ==
447                 Intrinsic::experimental_convergence_entry ||
448             Call->getIntrinsicID() == Intrinsic::experimental_convergence_loop)
449           FirstNonPHIOrDbgOrAlloca++;
450       }
451       Instruction->moveBefore(FirstNonPHIOrDbgOrAlloca);
452       TopologicalSort.pop();
453     }
454   }
455 }
456 
457 void IRNormalizer::reorderDefinition(
458     Instruction *Definition, std::stack<Instruction *> &TopologicalSort,
459     SmallPtrSet<const Instruction *, 32> &Visited) const {
460   if (Visited.contains(Definition))
461     return;
462   Visited.insert(Definition);
463 
464   {
465     const auto *BasicBlock = Definition->getParent();
466     const auto FirstNonPHIOrDbgOrAlloca =
467         BasicBlock->getFirstNonPHIOrDbgOrAlloca();
468     if (FirstNonPHIOrDbgOrAlloca == BasicBlock->end())
469       return; // TODO: Is this necessary?
470     if (Definition->comesBefore(&*FirstNonPHIOrDbgOrAlloca))
471       return; // TODO: Do some kind of ordering for these instructions.
472   }
473 
474   for (auto &Operand : Definition->operands()) {
475     if (auto *Op = dyn_cast<Instruction>(Operand)) {
476       if (Op->getParent() != Definition->getParent())
477         continue; // Only reorder instruction within the same basic block
478       reorderDefinition(Op, TopologicalSort, Visited);
479     }
480   }
481 
482   LLVM_DEBUG(dbgs() << "\t\tNext in topological sort: "; Definition->dump());
483   if (Definition->isTerminator())
484     return;
485   if (auto *Call = dyn_cast<CallInst>(Definition)) {
486     if (Call->isMustTailCall())
487       return;
488     if (Call->getIntrinsicID() == Intrinsic::experimental_deoptimize)
489       return;
490     if (Call->getIntrinsicID() == Intrinsic::experimental_convergence_entry)
491       return;
492     if (Call->getIntrinsicID() == Intrinsic::experimental_convergence_loop)
493       return;
494   }
495   if (auto *BitCast = dyn_cast<BitCastInst>(Definition)) {
496     if (auto *Call = dyn_cast<CallInst>(BitCast->getOperand(0))) {
497       if (Call->isMustTailCall())
498         return;
499     }
500   }
501 
502   TopologicalSort.emplace(Definition);
503 }
504 
505 /// Reorders instruction's operands alphabetically. This method assumes
506 /// that passed instruction is commutative. Changing the operand order
507 /// in other instructions may change the semantics.
508 ///
509 /// \param I Instruction whose operands will be reordered.
510 void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) const {
511   // This method assumes that passed I is commutative,
512   // changing the order of operands in other instructions
513   // may change the semantics.
514 
515   // Instruction operands for further sorting.
516   SmallVector<std::pair<std::string, Value *>, 4> Operands;
517 
518   // Collect operands.
519   for (auto &Op : I->operands()) {
520     if (auto *V = dyn_cast<Value>(Op)) {
521       if (isa<Instruction>(V)) {
522         // This is an an instruction.
523         Operands.push_back(std::pair<std::string, Value *>(V->getName(), V));
524       } else {
525         std::string TextRepresentation;
526         raw_string_ostream Stream(TextRepresentation);
527         Op->printAsOperand(Stream, false);
528         Operands.push_back(std::pair<std::string, Value *>(Stream.str(), V));
529       }
530     }
531   }
532 
533   // Sort operands.
534   sortCommutativeOperands(I, Operands);
535 
536   // Reorder operands.
537   unsigned Position = 0;
538   for (auto &Op : I->operands()) {
539     Op.set(Operands[Position].second);
540     Position += 1;
541   }
542 }
543 
544 /// Reorders PHI node's values according to the names of corresponding basic
545 /// blocks.
546 ///
547 /// \param Phi PHI node to normalize.
548 void IRNormalizer::reorderPHIIncomingValues(PHINode *Phi) const {
549   // Values for further sorting.
550   SmallVector<std::pair<Value *, BasicBlock *>, 2> Values;
551 
552   // Collect blocks and corresponding values.
553   for (auto &BB : Phi->blocks()) {
554     Value *V = Phi->getIncomingValueForBlock(BB);
555     Values.push_back(std::pair<Value *, BasicBlock *>(V, BB));
556   }
557 
558   // Sort values according to the name of a basic block.
559   llvm::sort(Values, [](const std::pair<Value *, BasicBlock *> &LHS,
560                         const std::pair<Value *, BasicBlock *> &RHS) {
561     return LHS.second->getName() < RHS.second->getName();
562   });
563 
564   // Swap.
565   for (unsigned i = 0; i < Values.size(); ++i) {
566     Phi->setIncomingBlock(i, Values[i].second);
567     Phi->setIncomingValue(i, Values[i].first);
568   }
569 }
570 
571 /// Returns a vector of output instructions. An output is an instruction which
572 /// has side-effects or is ReturnInst. Uses isOutput().
573 ///
574 /// \see isOutput()
575 /// \param F Function to collect outputs from.
576 SmallVector<Instruction *, 16>
577 IRNormalizer::collectOutputInstructions(Function &F) const {
578   // Output instructions are collected top-down in each function,
579   // any change may break the def-use chain in reordering methods.
580   SmallVector<Instruction *, 16> Outputs;
581   for (auto &I : instructions(F))
582     if (isOutput(&I))
583       Outputs.push_back(&I);
584   return Outputs;
585 }
586 
587 /// Helper method checking whether the instruction may have side effects or is
588 /// ReturnInst.
589 ///
590 /// \param I Considered instruction.
591 bool IRNormalizer::isOutput(const Instruction *I) const {
592   // Outputs are such instructions which may have side effects or is ReturnInst.
593   return I->mayHaveSideEffects() || isa<ReturnInst>(I);
594 }
595 
596 /// Helper method checking whether the instruction has users and only
597 /// immediate operands.
598 ///
599 /// \param I Considered instruction.
600 bool IRNormalizer::isInitialInstruction(const Instruction *I) const {
601   // Initial instructions are such instructions whose values are used by
602   // other instructions, yet they only depend on immediate values.
603   return !I->user_empty() && hasOnlyImmediateOperands(I);
604 }
605 
606 /// Helper method checking whether the instruction has only immediate operands.
607 ///
608 /// \param I Considered instruction.
609 bool IRNormalizer::hasOnlyImmediateOperands(const Instruction *I) const {
610   for (const auto &Op : I->operands())
611     if (isa<Instruction>(Op))
612       return false; // Found non-immediate operand (instruction).
613   return true;
614 }
615 
616 /// Helper method returning indices (distance from the beginning of the basic
617 /// block) of outputs using the \p I (eliminates repetitions). Walks down the
618 /// def-use tree recursively.
619 ///
620 /// \param I Considered instruction.
621 /// \param Visited Set of visited instructions.
622 SetVector<int> IRNormalizer::getOutputFootprint(
623     Instruction *I, SmallPtrSet<const Instruction *, 32> &Visited) const {
624 
625   // Vector containing indexes of outputs (no repetitions),
626   // which use I in the order of walking down the def-use tree.
627   SetVector<int> Outputs;
628 
629   if (!Visited.count(I)) {
630     Visited.insert(I);
631 
632     if (isOutput(I)) {
633       // Gets output instruction's parent function.
634       Function *Func = I->getParent()->getParent();
635 
636       // Finds and inserts the index of the output to the vector.
637       unsigned Count = 0;
638       for (const auto &B : *Func) {
639         for (const auto &E : B) {
640           if (&E == I)
641             Outputs.insert(Count);
642           Count += 1;
643         }
644       }
645 
646       // Returns to the used instruction.
647       return Outputs;
648     }
649 
650     for (auto *U : I->users()) {
651       if (auto *UI = dyn_cast<Instruction>(U)) {
652         // Vector for outputs which use UI.
653         SetVector<int> OutputsUsingUI = getOutputFootprint(UI, Visited);
654         // Insert the indexes of outputs using UI.
655         Outputs.insert_range(OutputsUsingUI);
656       }
657     }
658   }
659 
660   // Return to the used instruction.
661   return Outputs;
662 }
663 
664 PreservedAnalyses IRNormalizerPass::run(Function &F,
665                                         FunctionAnalysisManager &AM) const {
666   IRNormalizer(Options).runOnFunction(F);
667   PreservedAnalyses PA;
668   PA.preserveSet<CFGAnalyses>();
669   return PA;
670 }
671