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