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