xref: /llvm-project/llvm/lib/Transforms/Utils/IRNormalizer.cpp (revision 81d18ad86419fc612c7071e888d11aa923eaeb8a)
12e9f8696SJustin Fargnoli //===--------------- IRNormalizer.cpp - IR Normalizer ---------------===//
22e9f8696SJustin Fargnoli //
32e9f8696SJustin Fargnoli // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42e9f8696SJustin Fargnoli // See https://llvm.org/LICENSE.txt for license information.
52e9f8696SJustin Fargnoli // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62e9f8696SJustin Fargnoli //
72e9f8696SJustin Fargnoli //===----------------------------------------------------------------------===//
82e9f8696SJustin Fargnoli /// \file
92e9f8696SJustin Fargnoli /// This file implements the IRNormalizer class which aims to transform LLVM
102e9f8696SJustin Fargnoli /// Modules into a normal form by reordering and renaming instructions while
112e9f8696SJustin Fargnoli /// preserving the same semantics. The normalizer makes it easier to spot
122e9f8696SJustin Fargnoli /// semantic differences while diffing two modules which have undergone
132e9f8696SJustin Fargnoli /// different passes.
142e9f8696SJustin Fargnoli ///
152e9f8696SJustin Fargnoli //===----------------------------------------------------------------------===//
162e9f8696SJustin Fargnoli 
172e9f8696SJustin Fargnoli #include "llvm/Transforms/Utils/IRNormalizer.h"
182e9f8696SJustin Fargnoli #include "llvm/ADT/SetVector.h"
192e9f8696SJustin Fargnoli #include "llvm/ADT/SmallPtrSet.h"
202e9f8696SJustin Fargnoli #include "llvm/ADT/SmallString.h"
212e9f8696SJustin Fargnoli #include "llvm/ADT/SmallVector.h"
222e9f8696SJustin Fargnoli #include "llvm/IR/BasicBlock.h"
232e9f8696SJustin Fargnoli #include "llvm/IR/Function.h"
242e9f8696SJustin Fargnoli #include "llvm/IR/IRBuilder.h"
252e9f8696SJustin Fargnoli #include "llvm/IR/InstIterator.h"
262e9f8696SJustin Fargnoli #include "llvm/IR/Module.h"
272e9f8696SJustin Fargnoli #include "llvm/InitializePasses.h"
282e9f8696SJustin Fargnoli #include "llvm/Pass.h"
292e9f8696SJustin Fargnoli #include "llvm/PassRegistry.h"
302e9f8696SJustin Fargnoli #include "llvm/Support/CommandLine.h"
312e9f8696SJustin Fargnoli #include "llvm/Transforms/Utils.h"
322e9f8696SJustin Fargnoli #include <algorithm>
332e9f8696SJustin Fargnoli #include <stack>
342e9f8696SJustin Fargnoli 
352e9f8696SJustin Fargnoli #define DEBUG_TYPE "normalize"
362e9f8696SJustin Fargnoli 
372e9f8696SJustin Fargnoli using namespace llvm;
382e9f8696SJustin Fargnoli 
392e9f8696SJustin Fargnoli namespace {
402e9f8696SJustin Fargnoli /// IRNormalizer aims to transform LLVM IR into normal form.
412e9f8696SJustin Fargnoli class IRNormalizer {
422e9f8696SJustin Fargnoli public:
432e9f8696SJustin Fargnoli   /// \name Normalizer flags.
442e9f8696SJustin Fargnoli   /// @{
452e9f8696SJustin Fargnoli   /// Preserves original order of instructions.
462e9f8696SJustin Fargnoli   static cl::opt<bool> PreserveOrder;
472e9f8696SJustin Fargnoli   /// Renames all instructions (including user-named).
482e9f8696SJustin Fargnoli   static cl::opt<bool> RenameAll; // TODO: Don't rename on empty name
492e9f8696SJustin Fargnoli   /// Folds all regular instructions (including pre-outputs).
502e9f8696SJustin Fargnoli   static cl::opt<bool> FoldPreOutputs;
512e9f8696SJustin Fargnoli   /// Sorts and reorders operands in commutative instructions.
522e9f8696SJustin Fargnoli   static cl::opt<bool> ReorderOperands;
532e9f8696SJustin Fargnoli   /// @}
542e9f8696SJustin Fargnoli 
552e9f8696SJustin Fargnoli   bool runOnFunction(Function &F);
562e9f8696SJustin Fargnoli 
572e9f8696SJustin Fargnoli private:
582e9f8696SJustin Fargnoli   // Random constant for hashing, so the state isn't zero.
592e9f8696SJustin Fargnoli   const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
602e9f8696SJustin Fargnoli   DenseSet<const Instruction *> NamedInstructions;
612e9f8696SJustin Fargnoli 
622e9f8696SJustin Fargnoli   SmallVector<Instruction *, 16> Outputs;
632e9f8696SJustin Fargnoli 
642e9f8696SJustin Fargnoli   /// \name Naming.
652e9f8696SJustin Fargnoli   /// @{
662e9f8696SJustin Fargnoli   void nameFunctionArguments(Function &F) const;
672e9f8696SJustin Fargnoli   void nameBasicBlocks(Function &F) const;
682e9f8696SJustin Fargnoli   void nameInstruction(Instruction *I);
692e9f8696SJustin Fargnoli   void nameAsInitialInstruction(Instruction *I) const;
702e9f8696SJustin Fargnoli   void nameAsRegularInstruction(Instruction *I);
712e9f8696SJustin Fargnoli   void foldInstructionName(Instruction *I) const;
722e9f8696SJustin Fargnoli   /// @}
732e9f8696SJustin Fargnoli 
742e9f8696SJustin Fargnoli   /// \name Reordering.
752e9f8696SJustin Fargnoli   /// @{
762e9f8696SJustin Fargnoli   void reorderInstructions(Function &F) const;
772e9f8696SJustin Fargnoli   void reorderDefinition(Instruction *Definition,
782e9f8696SJustin Fargnoli                          std::stack<Instruction *> &TopologicalSort,
792e9f8696SJustin Fargnoli                          SmallPtrSet<const Instruction *, 32> &Visited) const;
802e9f8696SJustin Fargnoli   void reorderInstructionOperandsByNames(Instruction *I) const;
812e9f8696SJustin Fargnoli   void reorderPHIIncomingValues(PHINode *Phi) const;
822e9f8696SJustin Fargnoli   /// @}
832e9f8696SJustin Fargnoli 
842e9f8696SJustin Fargnoli   /// \name Utility methods.
852e9f8696SJustin Fargnoli   /// @{
862e9f8696SJustin Fargnoli   template <typename T>
872e9f8696SJustin Fargnoli   void sortCommutativeOperands(Instruction *I, T &Operands) const;
882e9f8696SJustin Fargnoli   SmallVector<Instruction *, 16> collectOutputInstructions(Function &F) const;
892e9f8696SJustin Fargnoli   bool isOutput(const Instruction *I) const;
902e9f8696SJustin Fargnoli   bool isInitialInstruction(const Instruction *I) const;
912e9f8696SJustin Fargnoli   bool hasOnlyImmediateOperands(const Instruction *I) const;
922e9f8696SJustin Fargnoli   SetVector<int>
932e9f8696SJustin Fargnoli   getOutputFootprint(Instruction *I,
942e9f8696SJustin Fargnoli                      SmallPtrSet<const Instruction *, 32> &Visited) const;
952e9f8696SJustin Fargnoli   /// @}
962e9f8696SJustin Fargnoli };
972e9f8696SJustin Fargnoli } // namespace
982e9f8696SJustin Fargnoli 
992e9f8696SJustin Fargnoli cl::opt<bool> IRNormalizer::PreserveOrder(
1002e9f8696SJustin Fargnoli     "norm-preserve-order", cl::Hidden, cl::init(false),
1012e9f8696SJustin Fargnoli     cl::desc("Preserves original instruction order"));
1022e9f8696SJustin Fargnoli cl::opt<bool> IRNormalizer::RenameAll(
1032e9f8696SJustin Fargnoli     "norm-rename-all", cl::Hidden, cl::init(true),
1042e9f8696SJustin Fargnoli     cl::desc("Renames all instructions (including user-named)"));
1052e9f8696SJustin Fargnoli cl::opt<bool> IRNormalizer::FoldPreOutputs(
1062e9f8696SJustin Fargnoli     "norm-fold-all", cl::Hidden, cl::init(true),
1072e9f8696SJustin Fargnoli     cl::desc("Folds all regular instructions (including pre-outputs)"));
1082e9f8696SJustin Fargnoli cl::opt<bool> IRNormalizer::ReorderOperands(
1092e9f8696SJustin Fargnoli     "norm-reorder-operands", cl::Hidden, cl::init(true),
1102e9f8696SJustin Fargnoli     cl::desc("Sorts and reorders operands in commutative instructions"));
1112e9f8696SJustin Fargnoli 
1122e9f8696SJustin Fargnoli /// Entry method to the IRNormalizer.
1132e9f8696SJustin Fargnoli ///
1142e9f8696SJustin Fargnoli /// \param F Function to normalize.
1152e9f8696SJustin Fargnoli bool IRNormalizer::runOnFunction(Function &F) {
1162e9f8696SJustin Fargnoli   nameFunctionArguments(F);
1172e9f8696SJustin Fargnoli   nameBasicBlocks(F);
1182e9f8696SJustin Fargnoli 
1192e9f8696SJustin Fargnoli   Outputs = collectOutputInstructions(F);
1202e9f8696SJustin Fargnoli 
1212e9f8696SJustin Fargnoli   if (!PreserveOrder)
1222e9f8696SJustin Fargnoli     reorderInstructions(F);
1232e9f8696SJustin Fargnoli 
1242e9f8696SJustin Fargnoli   // TODO: Reorder basic blocks via a topological sort.
1252e9f8696SJustin Fargnoli 
1262e9f8696SJustin Fargnoli   for (auto &I : Outputs)
1272e9f8696SJustin Fargnoli     nameInstruction(I);
1282e9f8696SJustin Fargnoli 
1292e9f8696SJustin Fargnoli   for (auto &I : instructions(F)) {
1302e9f8696SJustin Fargnoli     if (!PreserveOrder) {
1312e9f8696SJustin Fargnoli       if (ReorderOperands)
1322e9f8696SJustin Fargnoli         reorderInstructionOperandsByNames(&I);
1332e9f8696SJustin Fargnoli 
1342e9f8696SJustin Fargnoli       if (auto *Phi = dyn_cast<PHINode>(&I))
1352e9f8696SJustin Fargnoli         reorderPHIIncomingValues(Phi);
1362e9f8696SJustin Fargnoli     }
1372e9f8696SJustin Fargnoli     foldInstructionName(&I);
1382e9f8696SJustin Fargnoli   }
1392e9f8696SJustin Fargnoli 
1402e9f8696SJustin Fargnoli   return true;
1412e9f8696SJustin Fargnoli }
1422e9f8696SJustin Fargnoli 
1432e9f8696SJustin Fargnoli /// Numbers arguments.
1442e9f8696SJustin Fargnoli ///
1452e9f8696SJustin Fargnoli /// \param F Function whose arguments will be renamed.
1462e9f8696SJustin Fargnoli void IRNormalizer::nameFunctionArguments(Function &F) const {
1472e9f8696SJustin Fargnoli   int ArgumentCounter = 0;
1482e9f8696SJustin Fargnoli   for (auto &A : F.args()) {
1492e9f8696SJustin Fargnoli     if (RenameAll || A.getName().empty()) {
1502e9f8696SJustin Fargnoli       A.setName("a" + Twine(ArgumentCounter));
1512e9f8696SJustin Fargnoli       ArgumentCounter += 1;
1522e9f8696SJustin Fargnoli     }
1532e9f8696SJustin Fargnoli   }
1542e9f8696SJustin Fargnoli }
1552e9f8696SJustin Fargnoli 
1562e9f8696SJustin Fargnoli /// Names basic blocks using a generated hash for each basic block in
1572e9f8696SJustin Fargnoli /// a function considering the opcode and the order of output instructions.
1582e9f8696SJustin Fargnoli ///
1592e9f8696SJustin Fargnoli /// \param F Function containing basic blocks to rename.
1602e9f8696SJustin Fargnoli void IRNormalizer::nameBasicBlocks(Function &F) const {
1612e9f8696SJustin Fargnoli   for (auto &B : F) {
1622e9f8696SJustin Fargnoli     // Initialize to a magic constant, so the state isn't zero.
1632e9f8696SJustin Fargnoli     uint64_t Hash = MagicHashConstant;
1642e9f8696SJustin Fargnoli 
1652e9f8696SJustin Fargnoli     // Hash considering output instruction opcodes.
1662e9f8696SJustin Fargnoli     for (auto &I : B)
1672e9f8696SJustin Fargnoli       if (isOutput(&I))
1682e9f8696SJustin Fargnoli         Hash = hashing::detail::hash_16_bytes(Hash, I.getOpcode());
1692e9f8696SJustin Fargnoli 
1702e9f8696SJustin Fargnoli     if (RenameAll || B.getName().empty()) {
1712e9f8696SJustin Fargnoli       // Name basic block. Substring hash to make diffs more readable.
1722e9f8696SJustin Fargnoli       B.setName("bb" + std::to_string(Hash).substr(0, 5));
1732e9f8696SJustin Fargnoli     }
1742e9f8696SJustin Fargnoli   }
1752e9f8696SJustin Fargnoli }
1762e9f8696SJustin Fargnoli 
1772e9f8696SJustin Fargnoli /// Names instructions graphically (recursive) in accordance with the
1782e9f8696SJustin Fargnoli /// def-use tree, starting from the initial instructions (defs), finishing at
1792e9f8696SJustin Fargnoli /// the output (top-most user) instructions (depth-first).
1802e9f8696SJustin Fargnoli ///
1812e9f8696SJustin Fargnoli /// \param I Instruction to be renamed.
1822e9f8696SJustin Fargnoli void IRNormalizer::nameInstruction(Instruction *I) {
1832e9f8696SJustin Fargnoli   // Ensure instructions are not renamed. This is done
1842e9f8696SJustin Fargnoli   // to prevent situation where instructions are used
1852e9f8696SJustin Fargnoli   // before their definition (in phi nodes)
1862e9f8696SJustin Fargnoli   if (NamedInstructions.contains(I))
1872e9f8696SJustin Fargnoli     return;
1882e9f8696SJustin Fargnoli   NamedInstructions.insert(I);
1892e9f8696SJustin Fargnoli   if (isInitialInstruction(I)) {
1902e9f8696SJustin Fargnoli     nameAsInitialInstruction(I);
1912e9f8696SJustin Fargnoli   } else {
1922e9f8696SJustin Fargnoli     // This must be a regular instruction.
1932e9f8696SJustin Fargnoli     nameAsRegularInstruction(I);
1942e9f8696SJustin Fargnoli   }
1952e9f8696SJustin Fargnoli }
1962e9f8696SJustin Fargnoli 
1972e9f8696SJustin Fargnoli template <typename T>
1982e9f8696SJustin Fargnoli void IRNormalizer::sortCommutativeOperands(Instruction *I, T &Operands) const {
1992e9f8696SJustin Fargnoli   if (!(I->isCommutative() && Operands.size() >= 2))
2002e9f8696SJustin Fargnoli     return;
2012e9f8696SJustin Fargnoli   auto CommutativeEnd = Operands.begin();
2022e9f8696SJustin Fargnoli   std::advance(CommutativeEnd, 2);
2032e9f8696SJustin Fargnoli   llvm::sort(Operands.begin(), CommutativeEnd);
2042e9f8696SJustin Fargnoli }
2052e9f8696SJustin Fargnoli 
2062e9f8696SJustin Fargnoli /// Names instruction following the scheme:
2072e9f8696SJustin Fargnoli /// vl00000Callee(Operands)
2082e9f8696SJustin Fargnoli ///
2092e9f8696SJustin Fargnoli /// Where 00000 is a hash calculated considering instruction's opcode and output
2102e9f8696SJustin Fargnoli /// footprint. Callee's name is only included when instruction's type is
2112e9f8696SJustin Fargnoli /// CallInst. In cases where instruction is commutative, operands list is also
2122e9f8696SJustin Fargnoli /// sorted.
2132e9f8696SJustin Fargnoli ///
2142e9f8696SJustin Fargnoli /// Renames instruction only when RenameAll flag is raised or instruction is
2152e9f8696SJustin Fargnoli /// unnamed.
2162e9f8696SJustin Fargnoli ///
2172e9f8696SJustin Fargnoli /// \see getOutputFootprint()
2182e9f8696SJustin Fargnoli /// \param I Instruction to be renamed.
2192e9f8696SJustin Fargnoli void IRNormalizer::nameAsInitialInstruction(Instruction *I) const {
2202e9f8696SJustin Fargnoli   if (I->getType()->isVoidTy())
2212e9f8696SJustin Fargnoli     return;
2222e9f8696SJustin Fargnoli   if (!(I->getName().empty() || RenameAll))
2232e9f8696SJustin Fargnoli     return;
2242e9f8696SJustin Fargnoli   LLVM_DEBUG(dbgs() << "Naming initial instruction: " << *I << "\n");
2252e9f8696SJustin Fargnoli 
2262e9f8696SJustin Fargnoli   // Instruction operands for further sorting.
2272e9f8696SJustin Fargnoli   SmallVector<SmallString<64>, 4> Operands;
2282e9f8696SJustin Fargnoli 
2292e9f8696SJustin Fargnoli   // Collect operands.
2302e9f8696SJustin Fargnoli   for (auto &Op : I->operands()) {
2312e9f8696SJustin Fargnoli     if (!isa<Function>(Op)) {
2322e9f8696SJustin Fargnoli       std::string TextRepresentation;
2332e9f8696SJustin Fargnoli       raw_string_ostream Stream(TextRepresentation);
2342e9f8696SJustin Fargnoli       Op->printAsOperand(Stream, false);
2352e9f8696SJustin Fargnoli       Operands.push_back(StringRef(Stream.str()));
2362e9f8696SJustin Fargnoli     }
2372e9f8696SJustin Fargnoli   }
2382e9f8696SJustin Fargnoli 
2392e9f8696SJustin Fargnoli   sortCommutativeOperands(I, Operands);
2402e9f8696SJustin Fargnoli 
2412e9f8696SJustin Fargnoli   // Initialize to a magic constant, so the state isn't zero.
2422e9f8696SJustin Fargnoli   uint64_t Hash = MagicHashConstant;
2432e9f8696SJustin Fargnoli 
2442e9f8696SJustin Fargnoli   // Consider instruction's opcode in the hash.
2452e9f8696SJustin Fargnoli   Hash = hashing::detail::hash_16_bytes(Hash, I->getOpcode());
2462e9f8696SJustin Fargnoli 
2472e9f8696SJustin Fargnoli   SmallPtrSet<const Instruction *, 32> Visited;
2482e9f8696SJustin Fargnoli   // Get output footprint for I.
2492e9f8696SJustin Fargnoli   SetVector<int> OutputFootprint = getOutputFootprint(I, Visited);
2502e9f8696SJustin Fargnoli 
2512e9f8696SJustin Fargnoli   // Consider output footprint in the hash.
2522e9f8696SJustin Fargnoli   for (const int &Output : OutputFootprint)
2532e9f8696SJustin Fargnoli     Hash = hashing::detail::hash_16_bytes(Hash, Output);
2542e9f8696SJustin Fargnoli 
2552e9f8696SJustin Fargnoli   // Base instruction name.
2562e9f8696SJustin Fargnoli   SmallString<256> Name;
2572e9f8696SJustin Fargnoli   Name.append("vl" + std::to_string(Hash).substr(0, 5));
2582e9f8696SJustin Fargnoli 
2592e9f8696SJustin Fargnoli   // In case of CallInst, consider callee in the instruction name.
2602e9f8696SJustin Fargnoli   if (const auto *CI = dyn_cast<CallInst>(I)) {
2612e9f8696SJustin Fargnoli     Function *F = CI->getCalledFunction();
2622e9f8696SJustin Fargnoli 
2632e9f8696SJustin Fargnoli     if (F != nullptr)
2642e9f8696SJustin Fargnoli       Name.append(F->getName());
2652e9f8696SJustin Fargnoli   }
2662e9f8696SJustin Fargnoli 
2672e9f8696SJustin Fargnoli   Name.append("(");
2682e9f8696SJustin Fargnoli   for (size_t i = 0; i < Operands.size(); ++i) {
2692e9f8696SJustin Fargnoli     Name.append(Operands[i]);
2702e9f8696SJustin Fargnoli 
2712e9f8696SJustin Fargnoli     if (i < Operands.size() - 1)
2722e9f8696SJustin Fargnoli       Name.append(", ");
2732e9f8696SJustin Fargnoli   }
2742e9f8696SJustin Fargnoli   Name.append(")");
2752e9f8696SJustin Fargnoli 
2762e9f8696SJustin Fargnoli   I->setName(Name);
2772e9f8696SJustin Fargnoli }
2782e9f8696SJustin Fargnoli 
2792e9f8696SJustin Fargnoli /// Names instruction following the scheme:
2802e9f8696SJustin Fargnoli /// op00000Callee(Operands)
2812e9f8696SJustin Fargnoli ///
2822e9f8696SJustin Fargnoli /// Where 00000 is a hash calculated considering instruction's opcode, its
2832e9f8696SJustin Fargnoli /// operands' opcodes and order. Callee's name is only included when
2842e9f8696SJustin Fargnoli /// instruction's type is CallInst. In cases where instruction is commutative,
2852e9f8696SJustin Fargnoli /// operand list is also sorted.
2862e9f8696SJustin Fargnoli ///
2872e9f8696SJustin Fargnoli /// Names instructions recursively in accordance with the def-use tree,
2882e9f8696SJustin Fargnoli /// starting from the initial instructions (defs), finishing at
2892e9f8696SJustin Fargnoli /// the output (top-most user) instructions (depth-first).
2902e9f8696SJustin Fargnoli ///
2912e9f8696SJustin Fargnoli /// Renames instruction only when RenameAll flag is raised or instruction is
2922e9f8696SJustin Fargnoli /// unnamed.
2932e9f8696SJustin Fargnoli ///
2942e9f8696SJustin Fargnoli /// \see getOutputFootprint()
2952e9f8696SJustin Fargnoli /// \param I Instruction to be renamed.
2962e9f8696SJustin Fargnoli void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
2972e9f8696SJustin Fargnoli   LLVM_DEBUG(dbgs() << "Naming regular instruction: " << *I << "\n");
2982e9f8696SJustin Fargnoli 
2992e9f8696SJustin Fargnoli   // Instruction operands for further sorting.
3002e9f8696SJustin Fargnoli   SmallVector<SmallString<128>, 4> Operands;
3012e9f8696SJustin Fargnoli 
3022e9f8696SJustin Fargnoli   // The name of a regular instruction depends
3032e9f8696SJustin Fargnoli   // on the names of its operands. Hence, all
3042e9f8696SJustin Fargnoli   // operands must be named first in the use-def
3052e9f8696SJustin Fargnoli   // walk.
3062e9f8696SJustin Fargnoli 
3072e9f8696SJustin Fargnoli   // Collect operands.
3082e9f8696SJustin Fargnoli   for (auto &Op : I->operands()) {
3092e9f8696SJustin Fargnoli     if (auto *I = dyn_cast<Instruction>(Op)) {
3102e9f8696SJustin Fargnoli       // Walk down the use-def chain.
3112e9f8696SJustin Fargnoli       nameInstruction(I);
3122e9f8696SJustin Fargnoli       Operands.push_back(I->getName());
3132e9f8696SJustin Fargnoli     } else if (!isa<Function>(Op)) {
3142e9f8696SJustin Fargnoli       // This must be an immediate value.
3152e9f8696SJustin Fargnoli       std::string TextRepresentation;
3162e9f8696SJustin Fargnoli       raw_string_ostream Stream(TextRepresentation);
3172e9f8696SJustin Fargnoli       Op->printAsOperand(Stream, false);
3182e9f8696SJustin Fargnoli       Operands.push_back(StringRef(Stream.str()));
3192e9f8696SJustin Fargnoli     }
3202e9f8696SJustin Fargnoli   }
3212e9f8696SJustin Fargnoli 
3222e9f8696SJustin Fargnoli   sortCommutativeOperands(I, Operands);
3232e9f8696SJustin Fargnoli 
3242e9f8696SJustin Fargnoli   // Initialize to a magic constant, so the state isn't zero.
3252e9f8696SJustin Fargnoli   uint64_t Hash = MagicHashConstant;
3262e9f8696SJustin Fargnoli 
3272e9f8696SJustin Fargnoli   // Consider instruction opcode in the hash.
3282e9f8696SJustin Fargnoli   Hash = hashing::detail::hash_16_bytes(Hash, I->getOpcode());
3292e9f8696SJustin Fargnoli 
3302e9f8696SJustin Fargnoli   // Operand opcodes for further sorting (commutative).
3312e9f8696SJustin Fargnoli   SmallVector<int, 4> OperandsOpcodes;
3322e9f8696SJustin Fargnoli 
3332e9f8696SJustin Fargnoli   // Collect operand opcodes for hashing.
3342e9f8696SJustin Fargnoli   for (auto &Op : I->operands())
3352e9f8696SJustin Fargnoli     if (auto *I = dyn_cast<Instruction>(Op))
3362e9f8696SJustin Fargnoli       OperandsOpcodes.push_back(I->getOpcode());
3372e9f8696SJustin Fargnoli 
3382e9f8696SJustin Fargnoli   sortCommutativeOperands(I, OperandsOpcodes);
3392e9f8696SJustin Fargnoli 
3402e9f8696SJustin Fargnoli   // Consider operand opcodes in the hash.
3412e9f8696SJustin Fargnoli   for (const int Code : OperandsOpcodes)
3422e9f8696SJustin Fargnoli     Hash = hashing::detail::hash_16_bytes(Hash, Code);
3432e9f8696SJustin Fargnoli 
3442e9f8696SJustin Fargnoli   // Base instruction name.
3452e9f8696SJustin Fargnoli   SmallString<512> Name;
3462e9f8696SJustin Fargnoli   Name.append("op" + std::to_string(Hash).substr(0, 5));
3472e9f8696SJustin Fargnoli 
3482e9f8696SJustin Fargnoli   // In case of CallInst, consider callee in the instruction name.
3492e9f8696SJustin Fargnoli   if (const auto *CI = dyn_cast<CallInst>(I))
3502e9f8696SJustin Fargnoli     if (const Function *F = CI->getCalledFunction())
3512e9f8696SJustin Fargnoli       Name.append(F->getName());
3522e9f8696SJustin Fargnoli 
3532e9f8696SJustin Fargnoli   Name.append("(");
3542e9f8696SJustin Fargnoli   for (size_t i = 0; i < Operands.size(); ++i) {
3552e9f8696SJustin Fargnoli     Name.append(Operands[i]);
3562e9f8696SJustin Fargnoli 
3572e9f8696SJustin Fargnoli     if (i < Operands.size() - 1)
3582e9f8696SJustin Fargnoli       Name.append(", ");
3592e9f8696SJustin Fargnoli   }
3602e9f8696SJustin Fargnoli   Name.append(")");
3612e9f8696SJustin Fargnoli 
3622e9f8696SJustin Fargnoli   if ((I->getName().empty() || RenameAll) && !I->getType()->isVoidTy())
3632e9f8696SJustin Fargnoli     I->setName(Name);
3642e9f8696SJustin Fargnoli }
3652e9f8696SJustin Fargnoli 
3662e9f8696SJustin Fargnoli /// Shortens instruction's name. This method removes called function name from
3672e9f8696SJustin Fargnoli /// the instruction name and substitutes the call chain with a corresponding
3682e9f8696SJustin Fargnoli /// list of operands.
3692e9f8696SJustin Fargnoli ///
3702e9f8696SJustin Fargnoli /// Examples:
3712e9f8696SJustin Fargnoli /// op00000Callee(op00001Callee(...), vl00000Callee(1, 2), ...)  ->
3722e9f8696SJustin Fargnoli /// op00000(op00001, vl00000, ...) vl00000Callee(1, 2)  ->  vl00000(1, 2)
3732e9f8696SJustin Fargnoli ///
3742e9f8696SJustin Fargnoli /// This method omits output instructions and pre-output (instructions directly
3752e9f8696SJustin Fargnoli /// used by an output instruction) instructions (by default). By default it also
3762e9f8696SJustin Fargnoli /// does not affect user named instructions.
3772e9f8696SJustin Fargnoli ///
3782e9f8696SJustin Fargnoli /// \param I Instruction whose name will be folded.
3792e9f8696SJustin Fargnoli void IRNormalizer::foldInstructionName(Instruction *I) const {
3802e9f8696SJustin Fargnoli   // If this flag is raised, fold all regular
3812e9f8696SJustin Fargnoli   // instructions (including pre-outputs).
3822e9f8696SJustin Fargnoli   if (!FoldPreOutputs) {
3832e9f8696SJustin Fargnoli     // Don't fold if one of the users is an output instruction.
3842e9f8696SJustin Fargnoli     for (auto *U : I->users())
3852e9f8696SJustin Fargnoli       if (auto *IU = dyn_cast<Instruction>(U))
3862e9f8696SJustin Fargnoli         if (isOutput(IU))
3872e9f8696SJustin Fargnoli           return;
3882e9f8696SJustin Fargnoli   }
3892e9f8696SJustin Fargnoli 
3902e9f8696SJustin Fargnoli   // Don't fold if it is an output instruction or has no op prefix.
3912e9f8696SJustin Fargnoli   if (isOutput(I) || I->getName().substr(0, 2) != "op")
3922e9f8696SJustin Fargnoli     return;
3932e9f8696SJustin Fargnoli 
3942e9f8696SJustin Fargnoli   // Instruction operands.
3952e9f8696SJustin Fargnoli   SmallVector<SmallString<64>, 4> Operands;
3962e9f8696SJustin Fargnoli 
3972e9f8696SJustin Fargnoli   for (auto &Op : I->operands()) {
3982e9f8696SJustin Fargnoli     if (const auto *I = dyn_cast<Instruction>(Op)) {
3992e9f8696SJustin Fargnoli       bool HasNormalName = I->getName().substr(0, 2) == "op" ||
4002e9f8696SJustin Fargnoli                            I->getName().substr(0, 2) == "vl";
4012e9f8696SJustin Fargnoli 
4022e9f8696SJustin Fargnoli       Operands.push_back(HasNormalName ? I->getName().substr(0, 7)
4032e9f8696SJustin Fargnoli                                        : I->getName());
4042e9f8696SJustin Fargnoli     }
4052e9f8696SJustin Fargnoli   }
4062e9f8696SJustin Fargnoli 
4072e9f8696SJustin Fargnoli   sortCommutativeOperands(I, Operands);
4082e9f8696SJustin Fargnoli 
4092e9f8696SJustin Fargnoli   SmallString<256> Name;
4102e9f8696SJustin Fargnoli   Name.append(I->getName().substr(0, 7));
4112e9f8696SJustin Fargnoli 
4122e9f8696SJustin Fargnoli   Name.append("(");
4132e9f8696SJustin Fargnoli   for (size_t i = 0; i < Operands.size(); ++i) {
4142e9f8696SJustin Fargnoli     Name.append(Operands[i]);
4152e9f8696SJustin Fargnoli 
4162e9f8696SJustin Fargnoli     if (i < Operands.size() - 1)
4172e9f8696SJustin Fargnoli       Name.append(", ");
4182e9f8696SJustin Fargnoli   }
4192e9f8696SJustin Fargnoli   Name.append(")");
4202e9f8696SJustin Fargnoli 
4212e9f8696SJustin Fargnoli   I->setName(Name);
4222e9f8696SJustin Fargnoli }
4232e9f8696SJustin Fargnoli 
4242e9f8696SJustin Fargnoli /// Reorders instructions by walking up the tree from each operand of an output
4252e9f8696SJustin Fargnoli /// instruction and reducing the def-use distance.
4262e9f8696SJustin Fargnoli /// This method assumes that output instructions were collected top-down,
4272e9f8696SJustin Fargnoli /// otherwise the def-use chain may be broken.
4282e9f8696SJustin Fargnoli /// This method is a wrapper for recursive reorderInstruction().
4292e9f8696SJustin Fargnoli ///
4302e9f8696SJustin Fargnoli /// \see reorderInstruction()
4312e9f8696SJustin Fargnoli void IRNormalizer::reorderInstructions(Function &F) const {
4322e9f8696SJustin Fargnoli   for (auto &BB : F) {
4332e9f8696SJustin Fargnoli     LLVM_DEBUG(dbgs() << "Reordering instructions in basic block: "
4342e9f8696SJustin Fargnoli                       << BB.getName() << "\n");
4352e9f8696SJustin Fargnoli     // Find the source nodes of the DAG of instructions in this basic block.
4362e9f8696SJustin Fargnoli     // Source nodes are instructions that have side effects, are terminators, or
4372e9f8696SJustin Fargnoli     // don't have a parent in the DAG of instructions.
4382e9f8696SJustin Fargnoli     //
4392e9f8696SJustin Fargnoli     // We must iterate from the first to the last instruction otherwise side
4402e9f8696SJustin Fargnoli     // effecting instructions could be reordered.
4412e9f8696SJustin Fargnoli 
4422e9f8696SJustin Fargnoli     std::stack<Instruction *> TopologicalSort;
4432e9f8696SJustin Fargnoli     SmallPtrSet<const Instruction *, 32> Visited;
4442e9f8696SJustin Fargnoli     for (auto &I : BB) {
4452e9f8696SJustin Fargnoli       // First process side effecting and terminating instructions.
4462e9f8696SJustin Fargnoli       if (!(isOutput(&I) || I.isTerminator()))
4472e9f8696SJustin Fargnoli         continue;
4482e9f8696SJustin Fargnoli       LLVM_DEBUG(dbgs() << "\tReordering from source effecting instruction: ";
4492e9f8696SJustin Fargnoli                  I.dump());
4502e9f8696SJustin Fargnoli       reorderDefinition(&I, TopologicalSort, Visited);
4512e9f8696SJustin Fargnoli     }
4522e9f8696SJustin Fargnoli 
4532e9f8696SJustin Fargnoli     for (auto &I : BB) {
4542e9f8696SJustin Fargnoli       // Process the remaining instructions.
4552e9f8696SJustin Fargnoli       //
4562e9f8696SJustin Fargnoli       // TODO: Do more a intelligent sorting of these instructions. For example,
4572e9f8696SJustin Fargnoli       // seperate between dead instructinos and instructions used in another
4582e9f8696SJustin Fargnoli       // block. Use properties of the CFG the order instructions that are used
4592e9f8696SJustin Fargnoli       // in another block.
4602e9f8696SJustin Fargnoli       if (Visited.contains(&I))
4612e9f8696SJustin Fargnoli         continue;
4622e9f8696SJustin Fargnoli       LLVM_DEBUG(dbgs() << "\tReordering from source instruction: "; I.dump());
4632e9f8696SJustin Fargnoli       reorderDefinition(&I, TopologicalSort, Visited);
4642e9f8696SJustin Fargnoli     }
4652e9f8696SJustin Fargnoli 
4662e9f8696SJustin Fargnoli     LLVM_DEBUG(dbgs() << "Inserting instructions into: " << BB.getName()
4672e9f8696SJustin Fargnoli                       << "\n");
4682e9f8696SJustin Fargnoli     // Reorder based on the topological sort.
4692e9f8696SJustin Fargnoli     while (!TopologicalSort.empty()) {
4702e9f8696SJustin Fargnoli       auto *Instruction = TopologicalSort.top();
4712e9f8696SJustin Fargnoli       auto FirstNonPHIOrDbgOrAlloca = BB.getFirstNonPHIOrDbgOrAlloca();
4722e9f8696SJustin Fargnoli       if (auto *Call = dyn_cast<CallInst>(&*FirstNonPHIOrDbgOrAlloca)) {
4732e9f8696SJustin Fargnoli         if (Call->getIntrinsicID() ==
4742e9f8696SJustin Fargnoli                 Intrinsic::experimental_convergence_entry ||
4752e9f8696SJustin Fargnoli             Call->getIntrinsicID() == Intrinsic::experimental_convergence_loop)
4762e9f8696SJustin Fargnoli           FirstNonPHIOrDbgOrAlloca++;
4772e9f8696SJustin Fargnoli       }
478*81d18ad8SJeremy Morse       Instruction->moveBefore(FirstNonPHIOrDbgOrAlloca);
4792e9f8696SJustin Fargnoli       TopologicalSort.pop();
4802e9f8696SJustin Fargnoli     }
4812e9f8696SJustin Fargnoli   }
4822e9f8696SJustin Fargnoli }
4832e9f8696SJustin Fargnoli 
4842e9f8696SJustin Fargnoli void IRNormalizer::reorderDefinition(
4852e9f8696SJustin Fargnoli     Instruction *Definition, std::stack<Instruction *> &TopologicalSort,
4862e9f8696SJustin Fargnoli     SmallPtrSet<const Instruction *, 32> &Visited) const {
4872e9f8696SJustin Fargnoli   if (Visited.contains(Definition))
4882e9f8696SJustin Fargnoli     return;
4892e9f8696SJustin Fargnoli   Visited.insert(Definition);
4902e9f8696SJustin Fargnoli 
4912e9f8696SJustin Fargnoli   {
4922e9f8696SJustin Fargnoli     const auto *BasicBlock = Definition->getParent();
4932e9f8696SJustin Fargnoli     const auto FirstNonPHIOrDbgOrAlloca =
4942e9f8696SJustin Fargnoli         BasicBlock->getFirstNonPHIOrDbgOrAlloca();
4952e9f8696SJustin Fargnoli     if (FirstNonPHIOrDbgOrAlloca == BasicBlock->end())
4962e9f8696SJustin Fargnoli       return; // TODO: Is this necessary?
4972e9f8696SJustin Fargnoli     if (Definition->comesBefore(&*FirstNonPHIOrDbgOrAlloca))
4982e9f8696SJustin Fargnoli       return; // TODO: Do some kind of ordering for these instructions.
4992e9f8696SJustin Fargnoli   }
5002e9f8696SJustin Fargnoli 
5012e9f8696SJustin Fargnoli   for (auto &Operand : Definition->operands()) {
5022e9f8696SJustin Fargnoli     if (auto *Op = dyn_cast<Instruction>(Operand)) {
5032e9f8696SJustin Fargnoli       if (Op->getParent() != Definition->getParent())
5042e9f8696SJustin Fargnoli         continue; // Only reorder instruction within the same basic block
5052e9f8696SJustin Fargnoli       reorderDefinition(Op, TopologicalSort, Visited);
5062e9f8696SJustin Fargnoli     }
5072e9f8696SJustin Fargnoli   }
5082e9f8696SJustin Fargnoli 
5092e9f8696SJustin Fargnoli   LLVM_DEBUG(dbgs() << "\t\tNext in topological sort: "; Definition->dump());
5102e9f8696SJustin Fargnoli   if (Definition->isTerminator())
5112e9f8696SJustin Fargnoli     return;
5122e9f8696SJustin Fargnoli   if (auto *Call = dyn_cast<CallInst>(Definition)) {
5132e9f8696SJustin Fargnoli     if (Call->isMustTailCall())
5142e9f8696SJustin Fargnoli       return;
5152e9f8696SJustin Fargnoli     if (Call->getIntrinsicID() == Intrinsic::experimental_deoptimize)
5162e9f8696SJustin Fargnoli       return;
5172e9f8696SJustin Fargnoli     if (Call->getIntrinsicID() == Intrinsic::experimental_convergence_entry)
5182e9f8696SJustin Fargnoli       return;
5192e9f8696SJustin Fargnoli     if (Call->getIntrinsicID() == Intrinsic::experimental_convergence_loop)
5202e9f8696SJustin Fargnoli       return;
5212e9f8696SJustin Fargnoli   }
5222e9f8696SJustin Fargnoli   if (auto *BitCast = dyn_cast<BitCastInst>(Definition)) {
5232e9f8696SJustin Fargnoli     if (auto *Call = dyn_cast<CallInst>(BitCast->getOperand(0))) {
5242e9f8696SJustin Fargnoli       if (Call->isMustTailCall())
5252e9f8696SJustin Fargnoli         return;
5262e9f8696SJustin Fargnoli     }
5272e9f8696SJustin Fargnoli   }
5282e9f8696SJustin Fargnoli 
5292e9f8696SJustin Fargnoli   TopologicalSort.emplace(Definition);
5302e9f8696SJustin Fargnoli }
5312e9f8696SJustin Fargnoli 
5322e9f8696SJustin Fargnoli /// Reorders instruction's operands alphabetically. This method assumes
5332e9f8696SJustin Fargnoli /// that passed instruction is commutative. Changing the operand order
5342e9f8696SJustin Fargnoli /// in other instructions may change the semantics.
5352e9f8696SJustin Fargnoli ///
5362e9f8696SJustin Fargnoli /// \param I Instruction whose operands will be reordered.
5372e9f8696SJustin Fargnoli void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) const {
5382e9f8696SJustin Fargnoli   // This method assumes that passed I is commutative,
5392e9f8696SJustin Fargnoli   // changing the order of operands in other instructions
5402e9f8696SJustin Fargnoli   // may change the semantics.
5412e9f8696SJustin Fargnoli 
5422e9f8696SJustin Fargnoli   // Instruction operands for further sorting.
5432e9f8696SJustin Fargnoli   SmallVector<std::pair<std::string, Value *>, 4> Operands;
5442e9f8696SJustin Fargnoli 
5452e9f8696SJustin Fargnoli   // Collect operands.
5462e9f8696SJustin Fargnoli   for (auto &Op : I->operands()) {
5472e9f8696SJustin Fargnoli     if (auto *V = dyn_cast<Value>(Op)) {
5482e9f8696SJustin Fargnoli       if (isa<Instruction>(V)) {
5492e9f8696SJustin Fargnoli         // This is an an instruction.
5502e9f8696SJustin Fargnoli         Operands.push_back(std::pair<std::string, Value *>(V->getName(), V));
5512e9f8696SJustin Fargnoli       } else {
5522e9f8696SJustin Fargnoli         std::string TextRepresentation;
5532e9f8696SJustin Fargnoli         raw_string_ostream Stream(TextRepresentation);
5542e9f8696SJustin Fargnoli         Op->printAsOperand(Stream, false);
5552e9f8696SJustin Fargnoli         Operands.push_back(std::pair<std::string, Value *>(Stream.str(), V));
5562e9f8696SJustin Fargnoli       }
5572e9f8696SJustin Fargnoli     }
5582e9f8696SJustin Fargnoli   }
5592e9f8696SJustin Fargnoli 
5602e9f8696SJustin Fargnoli   // Sort operands.
5612e9f8696SJustin Fargnoli   sortCommutativeOperands(I, Operands);
5622e9f8696SJustin Fargnoli 
5632e9f8696SJustin Fargnoli   // Reorder operands.
5642e9f8696SJustin Fargnoli   unsigned Position = 0;
5652e9f8696SJustin Fargnoli   for (auto &Op : I->operands()) {
5662e9f8696SJustin Fargnoli     Op.set(Operands[Position].second);
5672e9f8696SJustin Fargnoli     Position += 1;
5682e9f8696SJustin Fargnoli   }
5692e9f8696SJustin Fargnoli }
5702e9f8696SJustin Fargnoli 
5712e9f8696SJustin Fargnoli /// Reorders PHI node's values according to the names of corresponding basic
5722e9f8696SJustin Fargnoli /// blocks.
5732e9f8696SJustin Fargnoli ///
5742e9f8696SJustin Fargnoli /// \param Phi PHI node to normalize.
5752e9f8696SJustin Fargnoli void IRNormalizer::reorderPHIIncomingValues(PHINode *Phi) const {
5762e9f8696SJustin Fargnoli   // Values for further sorting.
5772e9f8696SJustin Fargnoli   SmallVector<std::pair<Value *, BasicBlock *>, 2> Values;
5782e9f8696SJustin Fargnoli 
5792e9f8696SJustin Fargnoli   // Collect blocks and corresponding values.
5802e9f8696SJustin Fargnoli   for (auto &BB : Phi->blocks()) {
5812e9f8696SJustin Fargnoli     Value *V = Phi->getIncomingValueForBlock(BB);
5822e9f8696SJustin Fargnoli     Values.push_back(std::pair<Value *, BasicBlock *>(V, BB));
5832e9f8696SJustin Fargnoli   }
5842e9f8696SJustin Fargnoli 
5852e9f8696SJustin Fargnoli   // Sort values according to the name of a basic block.
5862e9f8696SJustin Fargnoli   llvm::sort(Values, [](const std::pair<Value *, BasicBlock *> &LHS,
5872e9f8696SJustin Fargnoli                         const std::pair<Value *, BasicBlock *> &RHS) {
5882e9f8696SJustin Fargnoli     return LHS.second->getName() < RHS.second->getName();
5892e9f8696SJustin Fargnoli   });
5902e9f8696SJustin Fargnoli 
5912e9f8696SJustin Fargnoli   // Swap.
5922e9f8696SJustin Fargnoli   for (unsigned i = 0; i < Values.size(); ++i) {
5932e9f8696SJustin Fargnoli     Phi->setIncomingBlock(i, Values[i].second);
5942e9f8696SJustin Fargnoli     Phi->setIncomingValue(i, Values[i].first);
5952e9f8696SJustin Fargnoli   }
5962e9f8696SJustin Fargnoli }
5972e9f8696SJustin Fargnoli 
5982e9f8696SJustin Fargnoli /// Returns a vector of output instructions. An output is an instruction which
5992e9f8696SJustin Fargnoli /// has side-effects or is ReturnInst. Uses isOutput().
6002e9f8696SJustin Fargnoli ///
6012e9f8696SJustin Fargnoli /// \see isOutput()
6022e9f8696SJustin Fargnoli /// \param F Function to collect outputs from.
6032e9f8696SJustin Fargnoli SmallVector<Instruction *, 16>
6042e9f8696SJustin Fargnoli IRNormalizer::collectOutputInstructions(Function &F) const {
6052e9f8696SJustin Fargnoli   // Output instructions are collected top-down in each function,
6062e9f8696SJustin Fargnoli   // any change may break the def-use chain in reordering methods.
6072e9f8696SJustin Fargnoli   SmallVector<Instruction *, 16> Outputs;
6082e9f8696SJustin Fargnoli   for (auto &I : instructions(F))
6092e9f8696SJustin Fargnoli     if (isOutput(&I))
6102e9f8696SJustin Fargnoli       Outputs.push_back(&I);
6112e9f8696SJustin Fargnoli   return Outputs;
6122e9f8696SJustin Fargnoli }
6132e9f8696SJustin Fargnoli 
6142e9f8696SJustin Fargnoli /// Helper method checking whether the instruction may have side effects or is
6152e9f8696SJustin Fargnoli /// ReturnInst.
6162e9f8696SJustin Fargnoli ///
6172e9f8696SJustin Fargnoli /// \param I Considered instruction.
6182e9f8696SJustin Fargnoli bool IRNormalizer::isOutput(const Instruction *I) const {
6192e9f8696SJustin Fargnoli   // Outputs are such instructions which may have side effects or is ReturnInst.
6202e9f8696SJustin Fargnoli   return I->mayHaveSideEffects() || isa<ReturnInst>(I);
6212e9f8696SJustin Fargnoli }
6222e9f8696SJustin Fargnoli 
6232e9f8696SJustin Fargnoli /// Helper method checking whether the instruction has users and only
6242e9f8696SJustin Fargnoli /// immediate operands.
6252e9f8696SJustin Fargnoli ///
6262e9f8696SJustin Fargnoli /// \param I Considered instruction.
6272e9f8696SJustin Fargnoli bool IRNormalizer::isInitialInstruction(const Instruction *I) const {
6282e9f8696SJustin Fargnoli   // Initial instructions are such instructions whose values are used by
6292e9f8696SJustin Fargnoli   // other instructions, yet they only depend on immediate values.
6302e9f8696SJustin Fargnoli   return !I->user_empty() && hasOnlyImmediateOperands(I);
6312e9f8696SJustin Fargnoli }
6322e9f8696SJustin Fargnoli 
6332e9f8696SJustin Fargnoli /// Helper method checking whether the instruction has only immediate operands.
6342e9f8696SJustin Fargnoli ///
6352e9f8696SJustin Fargnoli /// \param I Considered instruction.
6362e9f8696SJustin Fargnoli bool IRNormalizer::hasOnlyImmediateOperands(const Instruction *I) const {
6372e9f8696SJustin Fargnoli   for (const auto &Op : I->operands())
6382e9f8696SJustin Fargnoli     if (isa<Instruction>(Op))
6392e9f8696SJustin Fargnoli       return false; // Found non-immediate operand (instruction).
6402e9f8696SJustin Fargnoli   return true;
6412e9f8696SJustin Fargnoli }
6422e9f8696SJustin Fargnoli 
6432e9f8696SJustin Fargnoli /// Helper method returning indices (distance from the beginning of the basic
6442e9f8696SJustin Fargnoli /// block) of outputs using the \p I (eliminates repetitions). Walks down the
6452e9f8696SJustin Fargnoli /// def-use tree recursively.
6462e9f8696SJustin Fargnoli ///
6472e9f8696SJustin Fargnoli /// \param I Considered instruction.
6482e9f8696SJustin Fargnoli /// \param Visited Set of visited instructions.
6492e9f8696SJustin Fargnoli SetVector<int> IRNormalizer::getOutputFootprint(
6502e9f8696SJustin Fargnoli     Instruction *I, SmallPtrSet<const Instruction *, 32> &Visited) const {
6512e9f8696SJustin Fargnoli 
6522e9f8696SJustin Fargnoli   // Vector containing indexes of outputs (no repetitions),
6532e9f8696SJustin Fargnoli   // which use I in the order of walking down the def-use tree.
6542e9f8696SJustin Fargnoli   SetVector<int> Outputs;
6552e9f8696SJustin Fargnoli 
6562e9f8696SJustin Fargnoli   if (!Visited.count(I)) {
6572e9f8696SJustin Fargnoli     Visited.insert(I);
6582e9f8696SJustin Fargnoli 
6592e9f8696SJustin Fargnoli     if (isOutput(I)) {
6602e9f8696SJustin Fargnoli       // Gets output instruction's parent function.
6612e9f8696SJustin Fargnoli       Function *Func = I->getParent()->getParent();
6622e9f8696SJustin Fargnoli 
6632e9f8696SJustin Fargnoli       // Finds and inserts the index of the output to the vector.
6642e9f8696SJustin Fargnoli       unsigned Count = 0;
6652e9f8696SJustin Fargnoli       for (const auto &B : *Func) {
6662e9f8696SJustin Fargnoli         for (const auto &E : B) {
6672e9f8696SJustin Fargnoli           if (&E == I)
6682e9f8696SJustin Fargnoli             Outputs.insert(Count);
6692e9f8696SJustin Fargnoli           Count += 1;
6702e9f8696SJustin Fargnoli         }
6712e9f8696SJustin Fargnoli       }
6722e9f8696SJustin Fargnoli 
6732e9f8696SJustin Fargnoli       // Returns to the used instruction.
6742e9f8696SJustin Fargnoli       return Outputs;
6752e9f8696SJustin Fargnoli     }
6762e9f8696SJustin Fargnoli 
6772e9f8696SJustin Fargnoli     for (auto *U : I->users()) {
6782e9f8696SJustin Fargnoli       if (auto *UI = dyn_cast<Instruction>(U)) {
6792e9f8696SJustin Fargnoli         // Vector for outputs which use UI.
6802e9f8696SJustin Fargnoli         SetVector<int> OutputsUsingUI = getOutputFootprint(UI, Visited);
6812e9f8696SJustin Fargnoli         // Insert the indexes of outputs using UI.
6822e9f8696SJustin Fargnoli         Outputs.insert(OutputsUsingUI.begin(), OutputsUsingUI.end());
6832e9f8696SJustin Fargnoli       }
6842e9f8696SJustin Fargnoli     }
6852e9f8696SJustin Fargnoli   }
6862e9f8696SJustin Fargnoli 
6872e9f8696SJustin Fargnoli   // Return to the used instruction.
6882e9f8696SJustin Fargnoli   return Outputs;
6892e9f8696SJustin Fargnoli }
6902e9f8696SJustin Fargnoli 
6912e9f8696SJustin Fargnoli PreservedAnalyses IRNormalizerPass::run(Function &F,
6922e9f8696SJustin Fargnoli                                         FunctionAnalysisManager &AM) const {
6932e9f8696SJustin Fargnoli   IRNormalizer{}.runOnFunction(F);
6942e9f8696SJustin Fargnoli   PreservedAnalyses PA;
6952e9f8696SJustin Fargnoli   PA.preserveSet<CFGAnalyses>();
6962e9f8696SJustin Fargnoli   return PA;
6972e9f8696SJustin Fargnoli }
698