1e8d8bef9SDimitry Andric //===- IRSimilarityIdentifier.cpp - Find similarity in a module -----------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric // 9e8d8bef9SDimitry Andric // \file 10e8d8bef9SDimitry Andric // Implementation file for the IRSimilarityIdentifier for identifying 11e8d8bef9SDimitry Andric // similarities in IR including the IRInstructionMapper. 12e8d8bef9SDimitry Andric // 13e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 14e8d8bef9SDimitry Andric 15e8d8bef9SDimitry Andric #include "llvm/Analysis/IRSimilarityIdentifier.h" 16e8d8bef9SDimitry Andric #include "llvm/ADT/DenseMap.h" 17e8d8bef9SDimitry Andric #include "llvm/IR/Intrinsics.h" 18e8d8bef9SDimitry Andric #include "llvm/IR/Operator.h" 19e8d8bef9SDimitry Andric #include "llvm/IR/User.h" 20e8d8bef9SDimitry Andric #include "llvm/InitializePasses.h" 21e8d8bef9SDimitry Andric #include "llvm/Support/SuffixTree.h" 22e8d8bef9SDimitry Andric 23e8d8bef9SDimitry Andric using namespace llvm; 24e8d8bef9SDimitry Andric using namespace IRSimilarity; 25e8d8bef9SDimitry Andric 2604eeddc0SDimitry Andric namespace llvm { 27349cc55cSDimitry Andric cl::opt<bool> 28349cc55cSDimitry Andric DisableBranches("no-ir-sim-branch-matching", cl::init(false), 29349cc55cSDimitry Andric cl::ReallyHidden, 30349cc55cSDimitry Andric cl::desc("disable similarity matching, and outlining, " 31349cc55cSDimitry Andric "across branches for debugging purposes.")); 32349cc55cSDimitry Andric 3304eeddc0SDimitry Andric cl::opt<bool> 3404eeddc0SDimitry Andric DisableIndirectCalls("no-ir-sim-indirect-calls", cl::init(false), 3504eeddc0SDimitry Andric cl::ReallyHidden, 3604eeddc0SDimitry Andric cl::desc("disable outlining indirect calls.")); 3704eeddc0SDimitry Andric 3804eeddc0SDimitry Andric cl::opt<bool> 3904eeddc0SDimitry Andric MatchCallsByName("ir-sim-calls-by-name", cl::init(false), cl::ReallyHidden, 4004eeddc0SDimitry Andric cl::desc("only allow matching call instructions if the " 4104eeddc0SDimitry Andric "name and type signature match.")); 421fd87a68SDimitry Andric 431fd87a68SDimitry Andric cl::opt<bool> 441fd87a68SDimitry Andric DisableIntrinsics("no-ir-sim-intrinsics", cl::init(false), cl::ReallyHidden, 451fd87a68SDimitry Andric cl::desc("Don't match or outline intrinsics")); 4604eeddc0SDimitry Andric } // namespace llvm 4704eeddc0SDimitry Andric 48e8d8bef9SDimitry Andric IRInstructionData::IRInstructionData(Instruction &I, bool Legality, 49e8d8bef9SDimitry Andric IRInstructionDataList &IDList) 50e8d8bef9SDimitry Andric : Inst(&I), Legal(Legality), IDL(&IDList) { 51349cc55cSDimitry Andric initializeInstruction(); 52349cc55cSDimitry Andric } 53349cc55cSDimitry Andric 54349cc55cSDimitry Andric void IRInstructionData::initializeInstruction() { 55e8d8bef9SDimitry Andric // We check for whether we have a comparison instruction. If it is, we 56e8d8bef9SDimitry Andric // find the "less than" version of the predicate for consistency for 57e8d8bef9SDimitry Andric // comparison instructions throught the program. 58349cc55cSDimitry Andric if (CmpInst *C = dyn_cast<CmpInst>(Inst)) { 59e8d8bef9SDimitry Andric CmpInst::Predicate Predicate = predicateForConsistency(C); 60e8d8bef9SDimitry Andric if (Predicate != C->getPredicate()) 61e8d8bef9SDimitry Andric RevisedPredicate = Predicate; 62e8d8bef9SDimitry Andric } 63e8d8bef9SDimitry Andric 64e8d8bef9SDimitry Andric // Here we collect the operands and their types for determining whether 65e8d8bef9SDimitry Andric // the structure of the operand use matches between two different candidates. 66349cc55cSDimitry Andric for (Use &OI : Inst->operands()) { 67*81ad6265SDimitry Andric if (isa<CmpInst>(Inst) && RevisedPredicate) { 68e8d8bef9SDimitry Andric // If we have a CmpInst where the predicate is reversed, it means the 69e8d8bef9SDimitry Andric // operands must be reversed as well. 70e8d8bef9SDimitry Andric OperVals.insert(OperVals.begin(), OI.get()); 71e8d8bef9SDimitry Andric continue; 72e8d8bef9SDimitry Andric } 73e8d8bef9SDimitry Andric 74e8d8bef9SDimitry Andric OperVals.push_back(OI.get()); 75e8d8bef9SDimitry Andric } 7604eeddc0SDimitry Andric 7704eeddc0SDimitry Andric // We capture the incoming BasicBlocks as values as well as the incoming 7804eeddc0SDimitry Andric // Values in order to check for structural similarity. 7904eeddc0SDimitry Andric if (PHINode *PN = dyn_cast<PHINode>(Inst)) 8004eeddc0SDimitry Andric for (BasicBlock *BB : PN->blocks()) 8104eeddc0SDimitry Andric OperVals.push_back(BB); 82e8d8bef9SDimitry Andric } 83e8d8bef9SDimitry Andric 84349cc55cSDimitry Andric IRInstructionData::IRInstructionData(IRInstructionDataList &IDList) 8504eeddc0SDimitry Andric : IDL(&IDList) {} 86349cc55cSDimitry Andric 87349cc55cSDimitry Andric void IRInstructionData::setBranchSuccessors( 88349cc55cSDimitry Andric DenseMap<BasicBlock *, unsigned> &BasicBlockToInteger) { 89349cc55cSDimitry Andric assert(isa<BranchInst>(Inst) && "Instruction must be branch"); 90349cc55cSDimitry Andric 91349cc55cSDimitry Andric BranchInst *BI = cast<BranchInst>(Inst); 92349cc55cSDimitry Andric DenseMap<BasicBlock *, unsigned>::iterator BBNumIt; 93349cc55cSDimitry Andric 94349cc55cSDimitry Andric BBNumIt = BasicBlockToInteger.find(BI->getParent()); 95349cc55cSDimitry Andric assert(BBNumIt != BasicBlockToInteger.end() && 96349cc55cSDimitry Andric "Could not find location for BasicBlock!"); 97349cc55cSDimitry Andric 98349cc55cSDimitry Andric int CurrentBlockNumber = static_cast<int>(BBNumIt->second); 99349cc55cSDimitry Andric 100349cc55cSDimitry Andric for (BasicBlock *Successor : BI->successors()) { 101349cc55cSDimitry Andric BBNumIt = BasicBlockToInteger.find(Successor); 102349cc55cSDimitry Andric assert(BBNumIt != BasicBlockToInteger.end() && 103349cc55cSDimitry Andric "Could not find number for BasicBlock!"); 104349cc55cSDimitry Andric int OtherBlockNumber = static_cast<int>(BBNumIt->second); 105349cc55cSDimitry Andric 106349cc55cSDimitry Andric int Relative = OtherBlockNumber - CurrentBlockNumber; 107349cc55cSDimitry Andric RelativeBlockLocations.push_back(Relative); 108349cc55cSDimitry Andric } 109349cc55cSDimitry Andric } 110349cc55cSDimitry Andric 11104eeddc0SDimitry Andric void IRInstructionData::setCalleeName(bool MatchByName) { 11204eeddc0SDimitry Andric CallInst *CI = dyn_cast<CallInst>(Inst); 11304eeddc0SDimitry Andric assert(CI && "Instruction must be call"); 11404eeddc0SDimitry Andric 11504eeddc0SDimitry Andric CalleeName = ""; 1161fd87a68SDimitry Andric if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) { 1171fd87a68SDimitry Andric // To hash intrinsics, we use the opcode, and types like the other 1181fd87a68SDimitry Andric // instructions, but also, the Intrinsic ID, and the Name of the 1191fd87a68SDimitry Andric // intrinsic. 1201fd87a68SDimitry Andric Intrinsic::ID IntrinsicID = II->getIntrinsicID(); 1211fd87a68SDimitry Andric FunctionType *FT = II->getFunctionType(); 1221fd87a68SDimitry Andric // If there is an overloaded name, we have to use the complex version 1231fd87a68SDimitry Andric // of getName to get the entire string. 1241fd87a68SDimitry Andric if (Intrinsic::isOverloaded(IntrinsicID)) 1251fd87a68SDimitry Andric CalleeName = 1261fd87a68SDimitry Andric Intrinsic::getName(IntrinsicID, FT->params(), II->getModule(), FT); 1271fd87a68SDimitry Andric // If there is not an overloaded name, we only need to use this version. 1281fd87a68SDimitry Andric else 1291fd87a68SDimitry Andric CalleeName = Intrinsic::getName(IntrinsicID).str(); 1301fd87a68SDimitry Andric 1311fd87a68SDimitry Andric return; 1321fd87a68SDimitry Andric } 1331fd87a68SDimitry Andric 13404eeddc0SDimitry Andric if (!CI->isIndirectCall() && MatchByName) 13504eeddc0SDimitry Andric CalleeName = CI->getCalledFunction()->getName().str(); 13604eeddc0SDimitry Andric } 13704eeddc0SDimitry Andric 13804eeddc0SDimitry Andric void IRInstructionData::setPHIPredecessors( 13904eeddc0SDimitry Andric DenseMap<BasicBlock *, unsigned> &BasicBlockToInteger) { 14004eeddc0SDimitry Andric assert(isa<PHINode>(Inst) && "Instruction must be phi node"); 14104eeddc0SDimitry Andric 14204eeddc0SDimitry Andric PHINode *PN = cast<PHINode>(Inst); 14304eeddc0SDimitry Andric DenseMap<BasicBlock *, unsigned>::iterator BBNumIt; 14404eeddc0SDimitry Andric 14504eeddc0SDimitry Andric BBNumIt = BasicBlockToInteger.find(PN->getParent()); 14604eeddc0SDimitry Andric assert(BBNumIt != BasicBlockToInteger.end() && 14704eeddc0SDimitry Andric "Could not find location for BasicBlock!"); 14804eeddc0SDimitry Andric 14904eeddc0SDimitry Andric int CurrentBlockNumber = static_cast<int>(BBNumIt->second); 15004eeddc0SDimitry Andric 15104eeddc0SDimitry Andric // Convert the incoming blocks of the PHINode to an integer value, based on 15204eeddc0SDimitry Andric // the relative distances between the current block and the incoming block. 15304eeddc0SDimitry Andric for (unsigned Idx = 0; Idx < PN->getNumIncomingValues(); Idx++) { 15404eeddc0SDimitry Andric BasicBlock *Incoming = PN->getIncomingBlock(Idx); 15504eeddc0SDimitry Andric BBNumIt = BasicBlockToInteger.find(Incoming); 15604eeddc0SDimitry Andric assert(BBNumIt != BasicBlockToInteger.end() && 15704eeddc0SDimitry Andric "Could not find number for BasicBlock!"); 15804eeddc0SDimitry Andric int OtherBlockNumber = static_cast<int>(BBNumIt->second); 15904eeddc0SDimitry Andric 16004eeddc0SDimitry Andric int Relative = OtherBlockNumber - CurrentBlockNumber; 16104eeddc0SDimitry Andric RelativeBlockLocations.push_back(Relative); 16204eeddc0SDimitry Andric RelativeBlockLocations.push_back(Relative); 16304eeddc0SDimitry Andric } 16404eeddc0SDimitry Andric } 16504eeddc0SDimitry Andric 166e8d8bef9SDimitry Andric CmpInst::Predicate IRInstructionData::predicateForConsistency(CmpInst *CI) { 167e8d8bef9SDimitry Andric switch (CI->getPredicate()) { 168e8d8bef9SDimitry Andric case CmpInst::FCMP_OGT: 169e8d8bef9SDimitry Andric case CmpInst::FCMP_UGT: 170e8d8bef9SDimitry Andric case CmpInst::FCMP_OGE: 171e8d8bef9SDimitry Andric case CmpInst::FCMP_UGE: 172e8d8bef9SDimitry Andric case CmpInst::ICMP_SGT: 173e8d8bef9SDimitry Andric case CmpInst::ICMP_UGT: 174e8d8bef9SDimitry Andric case CmpInst::ICMP_SGE: 175e8d8bef9SDimitry Andric case CmpInst::ICMP_UGE: 176e8d8bef9SDimitry Andric return CI->getSwappedPredicate(); 177e8d8bef9SDimitry Andric default: 178e8d8bef9SDimitry Andric return CI->getPredicate(); 179e8d8bef9SDimitry Andric } 180e8d8bef9SDimitry Andric } 181e8d8bef9SDimitry Andric 182e8d8bef9SDimitry Andric CmpInst::Predicate IRInstructionData::getPredicate() const { 183e8d8bef9SDimitry Andric assert(isa<CmpInst>(Inst) && 184e8d8bef9SDimitry Andric "Can only get a predicate from a compare instruction"); 185e8d8bef9SDimitry Andric 186*81ad6265SDimitry Andric if (RevisedPredicate) 187e8d8bef9SDimitry Andric return RevisedPredicate.getValue(); 188e8d8bef9SDimitry Andric 189e8d8bef9SDimitry Andric return cast<CmpInst>(Inst)->getPredicate(); 190e8d8bef9SDimitry Andric } 191e8d8bef9SDimitry Andric 19204eeddc0SDimitry Andric StringRef IRInstructionData::getCalleeName() const { 19304eeddc0SDimitry Andric assert(isa<CallInst>(Inst) && 19404eeddc0SDimitry Andric "Can only get a name from a call instruction"); 195e8d8bef9SDimitry Andric 196*81ad6265SDimitry Andric assert(CalleeName && "CalleeName has not been set"); 19704eeddc0SDimitry Andric 19804eeddc0SDimitry Andric return *CalleeName; 199e8d8bef9SDimitry Andric } 200e8d8bef9SDimitry Andric 201e8d8bef9SDimitry Andric bool IRSimilarity::isClose(const IRInstructionData &A, 202e8d8bef9SDimitry Andric const IRInstructionData &B) { 203e8d8bef9SDimitry Andric 204e8d8bef9SDimitry Andric if (!A.Legal || !B.Legal) 205e8d8bef9SDimitry Andric return false; 206e8d8bef9SDimitry Andric 207e8d8bef9SDimitry Andric // Check if we are performing the same sort of operation on the same types 208e8d8bef9SDimitry Andric // but not on the same values. 209e8d8bef9SDimitry Andric if (!A.Inst->isSameOperationAs(B.Inst)) { 210e8d8bef9SDimitry Andric // If there is a predicate, this means that either there is a swapped 211e8d8bef9SDimitry Andric // predicate, or that the types are different, we want to make sure that 212e8d8bef9SDimitry Andric // the predicates are equivalent via swapping. 213e8d8bef9SDimitry Andric if (isa<CmpInst>(A.Inst) && isa<CmpInst>(B.Inst)) { 214e8d8bef9SDimitry Andric 215e8d8bef9SDimitry Andric if (A.getPredicate() != B.getPredicate()) 216e8d8bef9SDimitry Andric return false; 217e8d8bef9SDimitry Andric 218e8d8bef9SDimitry Andric // If the predicates are the same via swap, make sure that the types are 219e8d8bef9SDimitry Andric // still the same. 220e8d8bef9SDimitry Andric auto ZippedTypes = zip(A.OperVals, B.OperVals); 221e8d8bef9SDimitry Andric 222e8d8bef9SDimitry Andric return all_of( 223e8d8bef9SDimitry Andric ZippedTypes, [](std::tuple<llvm::Value *, llvm::Value *> R) { 224e8d8bef9SDimitry Andric return std::get<0>(R)->getType() == std::get<1>(R)->getType(); 225e8d8bef9SDimitry Andric }); 226e8d8bef9SDimitry Andric } 227e8d8bef9SDimitry Andric 228e8d8bef9SDimitry Andric return false; 229e8d8bef9SDimitry Andric } 230e8d8bef9SDimitry Andric 231e8d8bef9SDimitry Andric // Since any GEP Instruction operands after the first operand cannot be 232e8d8bef9SDimitry Andric // defined by a register, we must make sure that the operands after the first 233e8d8bef9SDimitry Andric // are the same in the two instructions 234e8d8bef9SDimitry Andric if (auto *GEP = dyn_cast<GetElementPtrInst>(A.Inst)) { 235e8d8bef9SDimitry Andric auto *OtherGEP = cast<GetElementPtrInst>(B.Inst); 236e8d8bef9SDimitry Andric 237e8d8bef9SDimitry Andric // If the instructions do not have the same inbounds restrictions, we do 238e8d8bef9SDimitry Andric // not consider them the same. 239e8d8bef9SDimitry Andric if (GEP->isInBounds() != OtherGEP->isInBounds()) 240e8d8bef9SDimitry Andric return false; 241e8d8bef9SDimitry Andric 242e8d8bef9SDimitry Andric auto ZippedOperands = zip(GEP->indices(), OtherGEP->indices()); 243e8d8bef9SDimitry Andric 244e8d8bef9SDimitry Andric // We increment here since we do not care about the first instruction, 245e8d8bef9SDimitry Andric // we only care about the following operands since they must be the 246e8d8bef9SDimitry Andric // exact same to be considered similar. 247e8d8bef9SDimitry Andric return all_of(drop_begin(ZippedOperands), 248e8d8bef9SDimitry Andric [](std::tuple<llvm::Use &, llvm::Use &> R) { 249e8d8bef9SDimitry Andric return std::get<0>(R) == std::get<1>(R); 250e8d8bef9SDimitry Andric }); 251e8d8bef9SDimitry Andric } 252e8d8bef9SDimitry Andric 25304eeddc0SDimitry Andric // If the instructions are functions calls, we make sure that the function 25404eeddc0SDimitry Andric // name is the same. We already know that the types are since is 25504eeddc0SDimitry Andric // isSameOperationAs is true. 256e8d8bef9SDimitry Andric if (isa<CallInst>(A.Inst) && isa<CallInst>(B.Inst)) { 2571fd87a68SDimitry Andric if (A.getCalleeName().str() != B.getCalleeName().str()) 258e8d8bef9SDimitry Andric return false; 259e8d8bef9SDimitry Andric } 260e8d8bef9SDimitry Andric 261349cc55cSDimitry Andric if (isa<BranchInst>(A.Inst) && isa<BranchInst>(B.Inst) && 262349cc55cSDimitry Andric A.RelativeBlockLocations.size() != B.RelativeBlockLocations.size()) 263349cc55cSDimitry Andric return false; 264349cc55cSDimitry Andric 265e8d8bef9SDimitry Andric return true; 266e8d8bef9SDimitry Andric } 267e8d8bef9SDimitry Andric 268e8d8bef9SDimitry Andric // TODO: This is the same as the MachineOutliner, and should be consolidated 269e8d8bef9SDimitry Andric // into the same interface. 270e8d8bef9SDimitry Andric void IRInstructionMapper::convertToUnsignedVec( 271e8d8bef9SDimitry Andric BasicBlock &BB, std::vector<IRInstructionData *> &InstrList, 272e8d8bef9SDimitry Andric std::vector<unsigned> &IntegerMapping) { 273e8d8bef9SDimitry Andric BasicBlock::iterator It = BB.begin(); 274e8d8bef9SDimitry Andric 275e8d8bef9SDimitry Andric std::vector<unsigned> IntegerMappingForBB; 276e8d8bef9SDimitry Andric std::vector<IRInstructionData *> InstrListForBB; 277e8d8bef9SDimitry Andric 278e8d8bef9SDimitry Andric for (BasicBlock::iterator Et = BB.end(); It != Et; ++It) { 279e8d8bef9SDimitry Andric switch (InstClassifier.visit(*It)) { 280e8d8bef9SDimitry Andric case InstrType::Legal: 281e8d8bef9SDimitry Andric mapToLegalUnsigned(It, IntegerMappingForBB, InstrListForBB); 282e8d8bef9SDimitry Andric break; 283e8d8bef9SDimitry Andric case InstrType::Illegal: 284e8d8bef9SDimitry Andric mapToIllegalUnsigned(It, IntegerMappingForBB, InstrListForBB); 285e8d8bef9SDimitry Andric break; 286e8d8bef9SDimitry Andric case InstrType::Invisible: 287e8d8bef9SDimitry Andric AddedIllegalLastTime = false; 288e8d8bef9SDimitry Andric break; 289e8d8bef9SDimitry Andric } 290e8d8bef9SDimitry Andric } 291e8d8bef9SDimitry Andric 292349cc55cSDimitry Andric if (AddedIllegalLastTime) 293e8d8bef9SDimitry Andric mapToIllegalUnsigned(It, IntegerMappingForBB, InstrListForBB, true); 294fe6060f1SDimitry Andric for (IRInstructionData *ID : InstrListForBB) 295fe6060f1SDimitry Andric this->IDL->push_back(*ID); 296e8d8bef9SDimitry Andric llvm::append_range(InstrList, InstrListForBB); 297e8d8bef9SDimitry Andric llvm::append_range(IntegerMapping, IntegerMappingForBB); 298e8d8bef9SDimitry Andric } 299e8d8bef9SDimitry Andric 300e8d8bef9SDimitry Andric // TODO: This is the same as the MachineOutliner, and should be consolidated 301e8d8bef9SDimitry Andric // into the same interface. 302e8d8bef9SDimitry Andric unsigned IRInstructionMapper::mapToLegalUnsigned( 303e8d8bef9SDimitry Andric BasicBlock::iterator &It, std::vector<unsigned> &IntegerMappingForBB, 304e8d8bef9SDimitry Andric std::vector<IRInstructionData *> &InstrListForBB) { 305e8d8bef9SDimitry Andric // We added something legal, so we should unset the AddedLegalLastTime 306e8d8bef9SDimitry Andric // flag. 307e8d8bef9SDimitry Andric AddedIllegalLastTime = false; 308e8d8bef9SDimitry Andric 309e8d8bef9SDimitry Andric // If we have at least two adjacent legal instructions (which may have 310e8d8bef9SDimitry Andric // invisible instructions in between), remember that. 311e8d8bef9SDimitry Andric if (CanCombineWithPrevInstr) 312e8d8bef9SDimitry Andric HaveLegalRange = true; 313e8d8bef9SDimitry Andric CanCombineWithPrevInstr = true; 314e8d8bef9SDimitry Andric 315e8d8bef9SDimitry Andric // Get the integer for this instruction or give it the current 316e8d8bef9SDimitry Andric // LegalInstrNumber. 317e8d8bef9SDimitry Andric IRInstructionData *ID = allocateIRInstructionData(*It, true, *IDL); 318e8d8bef9SDimitry Andric InstrListForBB.push_back(ID); 319e8d8bef9SDimitry Andric 320349cc55cSDimitry Andric if (isa<BranchInst>(*It)) 321349cc55cSDimitry Andric ID->setBranchSuccessors(BasicBlockToInteger); 322349cc55cSDimitry Andric 32304eeddc0SDimitry Andric if (isa<CallInst>(*It)) 32404eeddc0SDimitry Andric ID->setCalleeName(EnableMatchCallsByName); 32504eeddc0SDimitry Andric 32604eeddc0SDimitry Andric if (isa<PHINode>(*It)) 32704eeddc0SDimitry Andric ID->setPHIPredecessors(BasicBlockToInteger); 32804eeddc0SDimitry Andric 329e8d8bef9SDimitry Andric // Add to the instruction list 330e8d8bef9SDimitry Andric bool WasInserted; 331e8d8bef9SDimitry Andric DenseMap<IRInstructionData *, unsigned, IRInstructionDataTraits>::iterator 332e8d8bef9SDimitry Andric ResultIt; 333e8d8bef9SDimitry Andric std::tie(ResultIt, WasInserted) = 334e8d8bef9SDimitry Andric InstructionIntegerMap.insert(std::make_pair(ID, LegalInstrNumber)); 335e8d8bef9SDimitry Andric unsigned INumber = ResultIt->second; 336e8d8bef9SDimitry Andric 337e8d8bef9SDimitry Andric // There was an insertion. 338e8d8bef9SDimitry Andric if (WasInserted) 339e8d8bef9SDimitry Andric LegalInstrNumber++; 340e8d8bef9SDimitry Andric 341e8d8bef9SDimitry Andric IntegerMappingForBB.push_back(INumber); 342e8d8bef9SDimitry Andric 343e8d8bef9SDimitry Andric // Make sure we don't overflow or use any integers reserved by the DenseMap. 344e8d8bef9SDimitry Andric assert(LegalInstrNumber < IllegalInstrNumber && 345e8d8bef9SDimitry Andric "Instruction mapping overflow!"); 346e8d8bef9SDimitry Andric 347e8d8bef9SDimitry Andric assert(LegalInstrNumber != DenseMapInfo<unsigned>::getEmptyKey() && 348e8d8bef9SDimitry Andric "Tried to assign DenseMap tombstone or empty key to instruction."); 349e8d8bef9SDimitry Andric assert(LegalInstrNumber != DenseMapInfo<unsigned>::getTombstoneKey() && 350e8d8bef9SDimitry Andric "Tried to assign DenseMap tombstone or empty key to instruction."); 351e8d8bef9SDimitry Andric 352e8d8bef9SDimitry Andric return INumber; 353e8d8bef9SDimitry Andric } 354e8d8bef9SDimitry Andric 355e8d8bef9SDimitry Andric IRInstructionData * 356e8d8bef9SDimitry Andric IRInstructionMapper::allocateIRInstructionData(Instruction &I, bool Legality, 357e8d8bef9SDimitry Andric IRInstructionDataList &IDL) { 358e8d8bef9SDimitry Andric return new (InstDataAllocator->Allocate()) IRInstructionData(I, Legality, IDL); 359e8d8bef9SDimitry Andric } 360e8d8bef9SDimitry Andric 361349cc55cSDimitry Andric IRInstructionData * 362349cc55cSDimitry Andric IRInstructionMapper::allocateIRInstructionData(IRInstructionDataList &IDL) { 363349cc55cSDimitry Andric return new (InstDataAllocator->Allocate()) IRInstructionData(IDL); 364349cc55cSDimitry Andric } 365349cc55cSDimitry Andric 366e8d8bef9SDimitry Andric IRInstructionDataList * 367e8d8bef9SDimitry Andric IRInstructionMapper::allocateIRInstructionDataList() { 368e8d8bef9SDimitry Andric return new (IDLAllocator->Allocate()) IRInstructionDataList(); 369e8d8bef9SDimitry Andric } 370e8d8bef9SDimitry Andric 371e8d8bef9SDimitry Andric // TODO: This is the same as the MachineOutliner, and should be consolidated 372e8d8bef9SDimitry Andric // into the same interface. 373e8d8bef9SDimitry Andric unsigned IRInstructionMapper::mapToIllegalUnsigned( 374e8d8bef9SDimitry Andric BasicBlock::iterator &It, std::vector<unsigned> &IntegerMappingForBB, 375e8d8bef9SDimitry Andric std::vector<IRInstructionData *> &InstrListForBB, bool End) { 376e8d8bef9SDimitry Andric // Can't combine an illegal instruction. Set the flag. 377e8d8bef9SDimitry Andric CanCombineWithPrevInstr = false; 378e8d8bef9SDimitry Andric 379e8d8bef9SDimitry Andric // Only add one illegal number per range of legal numbers. 380e8d8bef9SDimitry Andric if (AddedIllegalLastTime) 381e8d8bef9SDimitry Andric return IllegalInstrNumber; 382e8d8bef9SDimitry Andric 383e8d8bef9SDimitry Andric IRInstructionData *ID = nullptr; 384e8d8bef9SDimitry Andric if (!End) 385e8d8bef9SDimitry Andric ID = allocateIRInstructionData(*It, false, *IDL); 386349cc55cSDimitry Andric else 387349cc55cSDimitry Andric ID = allocateIRInstructionData(*IDL); 388e8d8bef9SDimitry Andric InstrListForBB.push_back(ID); 389e8d8bef9SDimitry Andric 390e8d8bef9SDimitry Andric // Remember that we added an illegal number last time. 391e8d8bef9SDimitry Andric AddedIllegalLastTime = true; 392e8d8bef9SDimitry Andric unsigned INumber = IllegalInstrNumber; 393e8d8bef9SDimitry Andric IntegerMappingForBB.push_back(IllegalInstrNumber--); 394e8d8bef9SDimitry Andric 395e8d8bef9SDimitry Andric assert(LegalInstrNumber < IllegalInstrNumber && 396e8d8bef9SDimitry Andric "Instruction mapping overflow!"); 397e8d8bef9SDimitry Andric 398e8d8bef9SDimitry Andric assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getEmptyKey() && 399e8d8bef9SDimitry Andric "IllegalInstrNumber cannot be DenseMap tombstone or empty key!"); 400e8d8bef9SDimitry Andric 401e8d8bef9SDimitry Andric assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getTombstoneKey() && 402e8d8bef9SDimitry Andric "IllegalInstrNumber cannot be DenseMap tombstone or empty key!"); 403e8d8bef9SDimitry Andric 404e8d8bef9SDimitry Andric return INumber; 405e8d8bef9SDimitry Andric } 406e8d8bef9SDimitry Andric 407e8d8bef9SDimitry Andric IRSimilarityCandidate::IRSimilarityCandidate(unsigned StartIdx, unsigned Len, 408e8d8bef9SDimitry Andric IRInstructionData *FirstInstIt, 409e8d8bef9SDimitry Andric IRInstructionData *LastInstIt) 410e8d8bef9SDimitry Andric : StartIdx(StartIdx), Len(Len) { 411e8d8bef9SDimitry Andric 412e8d8bef9SDimitry Andric assert(FirstInstIt != nullptr && "Instruction is nullptr!"); 413e8d8bef9SDimitry Andric assert(LastInstIt != nullptr && "Instruction is nullptr!"); 414e8d8bef9SDimitry Andric assert(StartIdx + Len > StartIdx && 415e8d8bef9SDimitry Andric "Overflow for IRSimilarityCandidate range?"); 416e8d8bef9SDimitry Andric assert(Len - 1 == static_cast<unsigned>(std::distance( 417e8d8bef9SDimitry Andric iterator(FirstInstIt), iterator(LastInstIt))) && 418e8d8bef9SDimitry Andric "Length of the first and last IRInstructionData do not match the " 419e8d8bef9SDimitry Andric "given length"); 420e8d8bef9SDimitry Andric 421e8d8bef9SDimitry Andric // We iterate over the given instructions, and map each unique value 422e8d8bef9SDimitry Andric // to a unique number in the IRSimilarityCandidate ValueToNumber and 423e8d8bef9SDimitry Andric // NumberToValue maps. A constant get its own value globally, the individual 424e8d8bef9SDimitry Andric // uses of the constants are not considered to be unique. 425e8d8bef9SDimitry Andric // 426e8d8bef9SDimitry Andric // IR: Mapping Added: 427e8d8bef9SDimitry Andric // %add1 = add i32 %a, c1 %add1 -> 3, %a -> 1, c1 -> 2 428e8d8bef9SDimitry Andric // %add2 = add i32 %a, %1 %add2 -> 4 429e8d8bef9SDimitry Andric // %add3 = add i32 c2, c1 %add3 -> 6, c2 -> 5 430e8d8bef9SDimitry Andric // 431e8d8bef9SDimitry Andric // when replace with global values, starting from 1, would be 432e8d8bef9SDimitry Andric // 433e8d8bef9SDimitry Andric // 3 = add i32 1, 2 434e8d8bef9SDimitry Andric // 4 = add i32 1, 3 435e8d8bef9SDimitry Andric // 6 = add i32 5, 2 436e8d8bef9SDimitry Andric unsigned LocalValNumber = 1; 437e8d8bef9SDimitry Andric IRInstructionDataList::iterator ID = iterator(*FirstInstIt); 438e8d8bef9SDimitry Andric for (unsigned Loc = StartIdx; Loc < StartIdx + Len; Loc++, ID++) { 439e8d8bef9SDimitry Andric // Map the operand values to an unsigned integer if it does not already 440e8d8bef9SDimitry Andric // have an unsigned integer assigned to it. 441e8d8bef9SDimitry Andric for (Value *Arg : ID->OperVals) 442e8d8bef9SDimitry Andric if (ValueToNumber.find(Arg) == ValueToNumber.end()) { 443e8d8bef9SDimitry Andric ValueToNumber.try_emplace(Arg, LocalValNumber); 444e8d8bef9SDimitry Andric NumberToValue.try_emplace(LocalValNumber, Arg); 445e8d8bef9SDimitry Andric LocalValNumber++; 446e8d8bef9SDimitry Andric } 447e8d8bef9SDimitry Andric 448e8d8bef9SDimitry Andric // Mapping the instructions to an unsigned integer if it is not already 449e8d8bef9SDimitry Andric // exist in the mapping. 450e8d8bef9SDimitry Andric if (ValueToNumber.find(ID->Inst) == ValueToNumber.end()) { 451e8d8bef9SDimitry Andric ValueToNumber.try_emplace(ID->Inst, LocalValNumber); 452e8d8bef9SDimitry Andric NumberToValue.try_emplace(LocalValNumber, ID->Inst); 453e8d8bef9SDimitry Andric LocalValNumber++; 454e8d8bef9SDimitry Andric } 455e8d8bef9SDimitry Andric } 456e8d8bef9SDimitry Andric 457e8d8bef9SDimitry Andric // Setting the first and last instruction data pointers for the candidate. If 458e8d8bef9SDimitry Andric // we got through the entire for loop without hitting an assert, we know 459e8d8bef9SDimitry Andric // that both of these instructions are not nullptrs. 460e8d8bef9SDimitry Andric FirstInst = FirstInstIt; 461e8d8bef9SDimitry Andric LastInst = LastInstIt; 462*81ad6265SDimitry Andric 463*81ad6265SDimitry Andric // Add the basic blocks contained in the set into the global value numbering. 464*81ad6265SDimitry Andric DenseSet<BasicBlock *> BBSet; 465*81ad6265SDimitry Andric getBasicBlocks(BBSet); 466*81ad6265SDimitry Andric for (BasicBlock *BB : BBSet) { 467*81ad6265SDimitry Andric if (ValueToNumber.find(BB) != ValueToNumber.end()) 468*81ad6265SDimitry Andric continue; 469*81ad6265SDimitry Andric 470*81ad6265SDimitry Andric ValueToNumber.try_emplace(BB, LocalValNumber); 471*81ad6265SDimitry Andric NumberToValue.try_emplace(LocalValNumber, BB); 472*81ad6265SDimitry Andric LocalValNumber++; 473*81ad6265SDimitry Andric } 474e8d8bef9SDimitry Andric } 475e8d8bef9SDimitry Andric 476e8d8bef9SDimitry Andric bool IRSimilarityCandidate::isSimilar(const IRSimilarityCandidate &A, 477e8d8bef9SDimitry Andric const IRSimilarityCandidate &B) { 478e8d8bef9SDimitry Andric if (A.getLength() != B.getLength()) 479e8d8bef9SDimitry Andric return false; 480e8d8bef9SDimitry Andric 481e8d8bef9SDimitry Andric auto InstrDataForBoth = 482e8d8bef9SDimitry Andric zip(make_range(A.begin(), A.end()), make_range(B.begin(), B.end())); 483e8d8bef9SDimitry Andric 484e8d8bef9SDimitry Andric return all_of(InstrDataForBoth, 485e8d8bef9SDimitry Andric [](std::tuple<IRInstructionData &, IRInstructionData &> R) { 486e8d8bef9SDimitry Andric IRInstructionData &A = std::get<0>(R); 487e8d8bef9SDimitry Andric IRInstructionData &B = std::get<1>(R); 488e8d8bef9SDimitry Andric if (!A.Legal || !B.Legal) 489e8d8bef9SDimitry Andric return false; 490e8d8bef9SDimitry Andric return isClose(A, B); 491e8d8bef9SDimitry Andric }); 492e8d8bef9SDimitry Andric } 493e8d8bef9SDimitry Andric 494e8d8bef9SDimitry Andric /// Determine if one or more of the assigned global value numbers for the 495e8d8bef9SDimitry Andric /// operands in \p TargetValueNumbers is in the current mapping set for operand 496e8d8bef9SDimitry Andric /// numbers in \p SourceOperands. The set of possible corresponding global 497e8d8bef9SDimitry Andric /// value numbers are replaced with the most recent version of compatible 498e8d8bef9SDimitry Andric /// values. 499e8d8bef9SDimitry Andric /// 500e8d8bef9SDimitry Andric /// \param [in] SourceValueToNumberMapping - The mapping of a Value to global 501e8d8bef9SDimitry Andric /// value number for the source IRInstructionCandidate. 502e8d8bef9SDimitry Andric /// \param [in, out] CurrentSrcTgtNumberMapping - The current mapping of source 503e8d8bef9SDimitry Andric /// IRSimilarityCandidate global value numbers to a set of possible numbers in 504e8d8bef9SDimitry Andric /// the target. 505e8d8bef9SDimitry Andric /// \param [in] SourceOperands - The operands in the original 506e8d8bef9SDimitry Andric /// IRSimilarityCandidate in the current instruction. 507e8d8bef9SDimitry Andric /// \param [in] TargetValueNumbers - The global value numbers of the operands in 508e8d8bef9SDimitry Andric /// the corresponding Instruction in the other IRSimilarityCandidate. 509e8d8bef9SDimitry Andric /// \returns true if there exists a possible mapping between the source 510e8d8bef9SDimitry Andric /// Instruction operands and the target Instruction operands, and false if not. 511e8d8bef9SDimitry Andric static bool checkNumberingAndReplaceCommutative( 512e8d8bef9SDimitry Andric const DenseMap<Value *, unsigned> &SourceValueToNumberMapping, 513e8d8bef9SDimitry Andric DenseMap<unsigned, DenseSet<unsigned>> &CurrentSrcTgtNumberMapping, 514e8d8bef9SDimitry Andric ArrayRef<Value *> &SourceOperands, 515e8d8bef9SDimitry Andric DenseSet<unsigned> &TargetValueNumbers){ 516e8d8bef9SDimitry Andric 517e8d8bef9SDimitry Andric DenseMap<unsigned, DenseSet<unsigned>>::iterator ValueMappingIt; 518e8d8bef9SDimitry Andric 519e8d8bef9SDimitry Andric unsigned ArgVal; 520e8d8bef9SDimitry Andric bool WasInserted; 521e8d8bef9SDimitry Andric 522e8d8bef9SDimitry Andric // Iterate over the operands in the source IRSimilarityCandidate to determine 523e8d8bef9SDimitry Andric // whether there exists an operand in the other IRSimilarityCandidate that 524e8d8bef9SDimitry Andric // creates a valid mapping of Value to Value between the 525e8d8bef9SDimitry Andric // IRSimilarityCaniddates. 526e8d8bef9SDimitry Andric for (Value *V : SourceOperands) { 527e8d8bef9SDimitry Andric ArgVal = SourceValueToNumberMapping.find(V)->second; 528e8d8bef9SDimitry Andric 529*81ad6265SDimitry Andric // Instead of finding a current mapping, we attempt to insert a set. 530e8d8bef9SDimitry Andric std::tie(ValueMappingIt, WasInserted) = CurrentSrcTgtNumberMapping.insert( 531e8d8bef9SDimitry Andric std::make_pair(ArgVal, TargetValueNumbers)); 532e8d8bef9SDimitry Andric 533*81ad6265SDimitry Andric // We need to iterate over the items in other IRSimilarityCandidate's 534*81ad6265SDimitry Andric // Instruction to determine whether there is a valid mapping of 535*81ad6265SDimitry Andric // Value to Value. 536e8d8bef9SDimitry Andric DenseSet<unsigned> NewSet; 537e8d8bef9SDimitry Andric for (unsigned &Curr : ValueMappingIt->second) 538e8d8bef9SDimitry Andric // If we can find the value in the mapping, we add it to the new set. 539e8d8bef9SDimitry Andric if (TargetValueNumbers.contains(Curr)) 540e8d8bef9SDimitry Andric NewSet.insert(Curr); 541e8d8bef9SDimitry Andric 542e8d8bef9SDimitry Andric // If we could not find a Value, return 0. 543e8d8bef9SDimitry Andric if (NewSet.empty()) 544e8d8bef9SDimitry Andric return false; 545e8d8bef9SDimitry Andric 546e8d8bef9SDimitry Andric // Otherwise replace the old mapping with the newly constructed one. 547e8d8bef9SDimitry Andric if (NewSet.size() != ValueMappingIt->second.size()) 548e8d8bef9SDimitry Andric ValueMappingIt->second.swap(NewSet); 549e8d8bef9SDimitry Andric 550e8d8bef9SDimitry Andric // We have reached no conclusions about the mapping, and cannot remove 551e8d8bef9SDimitry Andric // any items from the other operands, so we move to check the next operand. 552e8d8bef9SDimitry Andric if (ValueMappingIt->second.size() != 1) 553e8d8bef9SDimitry Andric continue; 554e8d8bef9SDimitry Andric 555e8d8bef9SDimitry Andric unsigned ValToRemove = *ValueMappingIt->second.begin(); 556e8d8bef9SDimitry Andric // When there is only one item left in the mapping for and operand, remove 557e8d8bef9SDimitry Andric // the value from the other operands. If it results in there being no 558e8d8bef9SDimitry Andric // mapping, return false, it means the mapping is wrong 559e8d8bef9SDimitry Andric for (Value *InnerV : SourceOperands) { 560e8d8bef9SDimitry Andric if (V == InnerV) 561e8d8bef9SDimitry Andric continue; 562e8d8bef9SDimitry Andric 563e8d8bef9SDimitry Andric unsigned InnerVal = SourceValueToNumberMapping.find(InnerV)->second; 564e8d8bef9SDimitry Andric ValueMappingIt = CurrentSrcTgtNumberMapping.find(InnerVal); 565e8d8bef9SDimitry Andric if (ValueMappingIt == CurrentSrcTgtNumberMapping.end()) 566e8d8bef9SDimitry Andric continue; 567e8d8bef9SDimitry Andric 568e8d8bef9SDimitry Andric ValueMappingIt->second.erase(ValToRemove); 569e8d8bef9SDimitry Andric if (ValueMappingIt->second.empty()) 570e8d8bef9SDimitry Andric return false; 571e8d8bef9SDimitry Andric } 572e8d8bef9SDimitry Andric } 573e8d8bef9SDimitry Andric 574e8d8bef9SDimitry Andric return true; 575e8d8bef9SDimitry Andric } 576e8d8bef9SDimitry Andric 577e8d8bef9SDimitry Andric /// Determine if operand number \p TargetArgVal is in the current mapping set 578e8d8bef9SDimitry Andric /// for operand number \p SourceArgVal. 579e8d8bef9SDimitry Andric /// 580e8d8bef9SDimitry Andric /// \param [in, out] CurrentSrcTgtNumberMapping current mapping of global 581e8d8bef9SDimitry Andric /// value numbers from source IRSimilarityCandidate to target 582e8d8bef9SDimitry Andric /// IRSimilarityCandidate. 583e8d8bef9SDimitry Andric /// \param [in] SourceArgVal The global value number for an operand in the 584e8d8bef9SDimitry Andric /// in the original candidate. 585e8d8bef9SDimitry Andric /// \param [in] TargetArgVal The global value number for the corresponding 586e8d8bef9SDimitry Andric /// operand in the other candidate. 587e8d8bef9SDimitry Andric /// \returns True if there exists a mapping and false if not. 588e8d8bef9SDimitry Andric bool checkNumberingAndReplace( 589e8d8bef9SDimitry Andric DenseMap<unsigned, DenseSet<unsigned>> &CurrentSrcTgtNumberMapping, 590e8d8bef9SDimitry Andric unsigned SourceArgVal, unsigned TargetArgVal) { 591e8d8bef9SDimitry Andric // We are given two unsigned integers representing the global values of 592e8d8bef9SDimitry Andric // the operands in different IRSimilarityCandidates and a current mapping 593e8d8bef9SDimitry Andric // between the two. 594e8d8bef9SDimitry Andric // 595e8d8bef9SDimitry Andric // Source Operand GVN: 1 596e8d8bef9SDimitry Andric // Target Operand GVN: 2 597e8d8bef9SDimitry Andric // CurrentMapping: {1: {1, 2}} 598e8d8bef9SDimitry Andric // 599e8d8bef9SDimitry Andric // Since we have mapping, and the target operand is contained in the set, we 600e8d8bef9SDimitry Andric // update it to: 601e8d8bef9SDimitry Andric // CurrentMapping: {1: {2}} 602e8d8bef9SDimitry Andric // and can return true. But, if the mapping was 603e8d8bef9SDimitry Andric // CurrentMapping: {1: {3}} 604e8d8bef9SDimitry Andric // we would return false. 605e8d8bef9SDimitry Andric 606e8d8bef9SDimitry Andric bool WasInserted; 607e8d8bef9SDimitry Andric DenseMap<unsigned, DenseSet<unsigned>>::iterator Val; 608e8d8bef9SDimitry Andric 609e8d8bef9SDimitry Andric std::tie(Val, WasInserted) = CurrentSrcTgtNumberMapping.insert( 610e8d8bef9SDimitry Andric std::make_pair(SourceArgVal, DenseSet<unsigned>({TargetArgVal}))); 611e8d8bef9SDimitry Andric 612e8d8bef9SDimitry Andric // If we created a new mapping, then we are done. 613e8d8bef9SDimitry Andric if (WasInserted) 614e8d8bef9SDimitry Andric return true; 615e8d8bef9SDimitry Andric 616e8d8bef9SDimitry Andric // If there is more than one option in the mapping set, and the target value 617e8d8bef9SDimitry Andric // is included in the mapping set replace that set with one that only includes 618e8d8bef9SDimitry Andric // the target value, as it is the only valid mapping via the non commutative 619e8d8bef9SDimitry Andric // instruction. 620e8d8bef9SDimitry Andric 621e8d8bef9SDimitry Andric DenseSet<unsigned> &TargetSet = Val->second; 622e8d8bef9SDimitry Andric if (TargetSet.size() > 1 && TargetSet.contains(TargetArgVal)) { 623e8d8bef9SDimitry Andric TargetSet.clear(); 624e8d8bef9SDimitry Andric TargetSet.insert(TargetArgVal); 625e8d8bef9SDimitry Andric return true; 626e8d8bef9SDimitry Andric } 627e8d8bef9SDimitry Andric 628e8d8bef9SDimitry Andric // Return true if we can find the value in the set. 629e8d8bef9SDimitry Andric return TargetSet.contains(TargetArgVal); 630e8d8bef9SDimitry Andric } 631e8d8bef9SDimitry Andric 632e8d8bef9SDimitry Andric bool IRSimilarityCandidate::compareNonCommutativeOperandMapping( 633e8d8bef9SDimitry Andric OperandMapping A, OperandMapping B) { 634e8d8bef9SDimitry Andric // Iterators to keep track of where we are in the operands for each 635e8d8bef9SDimitry Andric // Instruction. 636e8d8bef9SDimitry Andric ArrayRef<Value *>::iterator VItA = A.OperVals.begin(); 637e8d8bef9SDimitry Andric ArrayRef<Value *>::iterator VItB = B.OperVals.begin(); 638e8d8bef9SDimitry Andric unsigned OperandLength = A.OperVals.size(); 639e8d8bef9SDimitry Andric 640e8d8bef9SDimitry Andric // For each operand, get the value numbering and ensure it is consistent. 641e8d8bef9SDimitry Andric for (unsigned Idx = 0; Idx < OperandLength; Idx++, VItA++, VItB++) { 642e8d8bef9SDimitry Andric unsigned OperValA = A.IRSC.ValueToNumber.find(*VItA)->second; 643e8d8bef9SDimitry Andric unsigned OperValB = B.IRSC.ValueToNumber.find(*VItB)->second; 644e8d8bef9SDimitry Andric 645e8d8bef9SDimitry Andric // Attempt to add a set with only the target value. If there is no mapping 646e8d8bef9SDimitry Andric // we can create it here. 647e8d8bef9SDimitry Andric // 648e8d8bef9SDimitry Andric // For an instruction like a subtraction: 649e8d8bef9SDimitry Andric // IRSimilarityCandidateA: IRSimilarityCandidateB: 650e8d8bef9SDimitry Andric // %resultA = sub %a, %b %resultB = sub %d, %e 651e8d8bef9SDimitry Andric // 652e8d8bef9SDimitry Andric // We map %a -> %d and %b -> %e. 653e8d8bef9SDimitry Andric // 654e8d8bef9SDimitry Andric // And check to see whether their mapping is consistent in 655e8d8bef9SDimitry Andric // checkNumberingAndReplace. 656e8d8bef9SDimitry Andric 657e8d8bef9SDimitry Andric if (!checkNumberingAndReplace(A.ValueNumberMapping, OperValA, OperValB)) 658e8d8bef9SDimitry Andric return false; 659e8d8bef9SDimitry Andric 660e8d8bef9SDimitry Andric if (!checkNumberingAndReplace(B.ValueNumberMapping, OperValB, OperValA)) 661e8d8bef9SDimitry Andric return false; 662e8d8bef9SDimitry Andric } 663e8d8bef9SDimitry Andric return true; 664e8d8bef9SDimitry Andric } 665e8d8bef9SDimitry Andric 666e8d8bef9SDimitry Andric bool IRSimilarityCandidate::compareCommutativeOperandMapping( 667e8d8bef9SDimitry Andric OperandMapping A, OperandMapping B) { 668e8d8bef9SDimitry Andric DenseSet<unsigned> ValueNumbersA; 669e8d8bef9SDimitry Andric DenseSet<unsigned> ValueNumbersB; 670e8d8bef9SDimitry Andric 671e8d8bef9SDimitry Andric ArrayRef<Value *>::iterator VItA = A.OperVals.begin(); 672e8d8bef9SDimitry Andric ArrayRef<Value *>::iterator VItB = B.OperVals.begin(); 673e8d8bef9SDimitry Andric unsigned OperandLength = A.OperVals.size(); 674e8d8bef9SDimitry Andric 675e8d8bef9SDimitry Andric // Find the value number sets for the operands. 676e8d8bef9SDimitry Andric for (unsigned Idx = 0; Idx < OperandLength; 677e8d8bef9SDimitry Andric Idx++, VItA++, VItB++) { 678e8d8bef9SDimitry Andric ValueNumbersA.insert(A.IRSC.ValueToNumber.find(*VItA)->second); 679e8d8bef9SDimitry Andric ValueNumbersB.insert(B.IRSC.ValueToNumber.find(*VItB)->second); 680e8d8bef9SDimitry Andric } 681e8d8bef9SDimitry Andric 682e8d8bef9SDimitry Andric // Iterate over the operands in the first IRSimilarityCandidate and make sure 683e8d8bef9SDimitry Andric // there exists a possible mapping with the operands in the second 684e8d8bef9SDimitry Andric // IRSimilarityCandidate. 685e8d8bef9SDimitry Andric if (!checkNumberingAndReplaceCommutative(A.IRSC.ValueToNumber, 686e8d8bef9SDimitry Andric A.ValueNumberMapping, A.OperVals, 687e8d8bef9SDimitry Andric ValueNumbersB)) 688e8d8bef9SDimitry Andric return false; 689e8d8bef9SDimitry Andric 690e8d8bef9SDimitry Andric // Iterate over the operands in the second IRSimilarityCandidate and make sure 691e8d8bef9SDimitry Andric // there exists a possible mapping with the operands in the first 692e8d8bef9SDimitry Andric // IRSimilarityCandidate. 693e8d8bef9SDimitry Andric if (!checkNumberingAndReplaceCommutative(B.IRSC.ValueToNumber, 694e8d8bef9SDimitry Andric B.ValueNumberMapping, B.OperVals, 695e8d8bef9SDimitry Andric ValueNumbersA)) 696e8d8bef9SDimitry Andric return false; 697e8d8bef9SDimitry Andric 698e8d8bef9SDimitry Andric return true; 699e8d8bef9SDimitry Andric } 700e8d8bef9SDimitry Andric 701349cc55cSDimitry Andric bool IRSimilarityCandidate::checkRelativeLocations(RelativeLocMapping A, 702349cc55cSDimitry Andric RelativeLocMapping B) { 703349cc55cSDimitry Andric // Get the basic blocks the label refers to. 704349cc55cSDimitry Andric BasicBlock *ABB = static_cast<BasicBlock *>(A.OperVal); 705349cc55cSDimitry Andric BasicBlock *BBB = static_cast<BasicBlock *>(B.OperVal); 706349cc55cSDimitry Andric 707349cc55cSDimitry Andric // Get the basic blocks contained in each region. 708349cc55cSDimitry Andric DenseSet<BasicBlock *> BasicBlockA; 709349cc55cSDimitry Andric DenseSet<BasicBlock *> BasicBlockB; 710349cc55cSDimitry Andric A.IRSC.getBasicBlocks(BasicBlockA); 711349cc55cSDimitry Andric B.IRSC.getBasicBlocks(BasicBlockB); 712349cc55cSDimitry Andric 713349cc55cSDimitry Andric // Determine if the block is contained in the region. 714349cc55cSDimitry Andric bool AContained = BasicBlockA.contains(ABB); 715349cc55cSDimitry Andric bool BContained = BasicBlockB.contains(BBB); 716349cc55cSDimitry Andric 717349cc55cSDimitry Andric // Both blocks need to be contained in the region, or both need to be outside 718349cc55cSDimitry Andric // the reigon. 719349cc55cSDimitry Andric if (AContained != BContained) 720349cc55cSDimitry Andric return false; 721349cc55cSDimitry Andric 722349cc55cSDimitry Andric // If both are contained, then we need to make sure that the relative 723349cc55cSDimitry Andric // distance to the target blocks are the same. 724349cc55cSDimitry Andric if (AContained) 725349cc55cSDimitry Andric return A.RelativeLocation == B.RelativeLocation; 726349cc55cSDimitry Andric return true; 727349cc55cSDimitry Andric } 728349cc55cSDimitry Andric 729e8d8bef9SDimitry Andric bool IRSimilarityCandidate::compareStructure(const IRSimilarityCandidate &A, 730e8d8bef9SDimitry Andric const IRSimilarityCandidate &B) { 731349cc55cSDimitry Andric DenseMap<unsigned, DenseSet<unsigned>> MappingA; 732349cc55cSDimitry Andric DenseMap<unsigned, DenseSet<unsigned>> MappingB; 733349cc55cSDimitry Andric return IRSimilarityCandidate::compareStructure(A, B, MappingA, MappingB); 734349cc55cSDimitry Andric } 735349cc55cSDimitry Andric 736349cc55cSDimitry Andric typedef detail::zippy<detail::zip_shortest, SmallVector<int, 4> &, 737349cc55cSDimitry Andric SmallVector<int, 4> &, ArrayRef<Value *> &, 738349cc55cSDimitry Andric ArrayRef<Value *> &> 739349cc55cSDimitry Andric ZippedRelativeLocationsT; 740349cc55cSDimitry Andric 741349cc55cSDimitry Andric bool IRSimilarityCandidate::compareStructure( 742349cc55cSDimitry Andric const IRSimilarityCandidate &A, const IRSimilarityCandidate &B, 743349cc55cSDimitry Andric DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingA, 744349cc55cSDimitry Andric DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingB) { 745e8d8bef9SDimitry Andric if (A.getLength() != B.getLength()) 746e8d8bef9SDimitry Andric return false; 747e8d8bef9SDimitry Andric 748e8d8bef9SDimitry Andric if (A.ValueToNumber.size() != B.ValueToNumber.size()) 749e8d8bef9SDimitry Andric return false; 750e8d8bef9SDimitry Andric 751e8d8bef9SDimitry Andric iterator ItA = A.begin(); 752e8d8bef9SDimitry Andric iterator ItB = B.begin(); 753e8d8bef9SDimitry Andric 754349cc55cSDimitry Andric // These ValueNumber Mapping sets create a create a mapping between the values 755349cc55cSDimitry Andric // in one candidate to values in the other candidate. If we create a set with 756349cc55cSDimitry Andric // one element, and that same element maps to the original element in the 757349cc55cSDimitry Andric // candidate we have a good mapping. 758e8d8bef9SDimitry Andric DenseMap<unsigned, DenseSet<unsigned>>::iterator ValueMappingIt; 759e8d8bef9SDimitry Andric 760e8d8bef9SDimitry Andric 761e8d8bef9SDimitry Andric // Iterate over the instructions contained in each candidate 762e8d8bef9SDimitry Andric unsigned SectionLength = A.getStartIdx() + A.getLength(); 763e8d8bef9SDimitry Andric for (unsigned Loc = A.getStartIdx(); Loc < SectionLength; 764e8d8bef9SDimitry Andric ItA++, ItB++, Loc++) { 765e8d8bef9SDimitry Andric // Make sure the instructions are similar to one another. 766e8d8bef9SDimitry Andric if (!isClose(*ItA, *ItB)) 767e8d8bef9SDimitry Andric return false; 768e8d8bef9SDimitry Andric 769e8d8bef9SDimitry Andric Instruction *IA = ItA->Inst; 770e8d8bef9SDimitry Andric Instruction *IB = ItB->Inst; 771e8d8bef9SDimitry Andric 772e8d8bef9SDimitry Andric if (!ItA->Legal || !ItB->Legal) 773e8d8bef9SDimitry Andric return false; 774e8d8bef9SDimitry Andric 775e8d8bef9SDimitry Andric // Get the operand sets for the instructions. 776e8d8bef9SDimitry Andric ArrayRef<Value *> OperValsA = ItA->OperVals; 777e8d8bef9SDimitry Andric ArrayRef<Value *> OperValsB = ItB->OperVals; 778e8d8bef9SDimitry Andric 779e8d8bef9SDimitry Andric unsigned InstValA = A.ValueToNumber.find(IA)->second; 780e8d8bef9SDimitry Andric unsigned InstValB = B.ValueToNumber.find(IB)->second; 781e8d8bef9SDimitry Andric 782349cc55cSDimitry Andric bool WasInserted; 783e8d8bef9SDimitry Andric // Ensure that the mappings for the instructions exists. 784e8d8bef9SDimitry Andric std::tie(ValueMappingIt, WasInserted) = ValueNumberMappingA.insert( 785e8d8bef9SDimitry Andric std::make_pair(InstValA, DenseSet<unsigned>({InstValB}))); 786e8d8bef9SDimitry Andric if (!WasInserted && !ValueMappingIt->second.contains(InstValB)) 787e8d8bef9SDimitry Andric return false; 788e8d8bef9SDimitry Andric 789e8d8bef9SDimitry Andric std::tie(ValueMappingIt, WasInserted) = ValueNumberMappingB.insert( 790e8d8bef9SDimitry Andric std::make_pair(InstValB, DenseSet<unsigned>({InstValA}))); 791e8d8bef9SDimitry Andric if (!WasInserted && !ValueMappingIt->second.contains(InstValA)) 792e8d8bef9SDimitry Andric return false; 793e8d8bef9SDimitry Andric 794e8d8bef9SDimitry Andric // We have different paths for commutative instructions and non-commutative 795e8d8bef9SDimitry Andric // instructions since commutative instructions could allow multiple mappings 796e8d8bef9SDimitry Andric // to certain values. 797*81ad6265SDimitry Andric if (IA->isCommutative() && !isa<FPMathOperator>(IA) && 798*81ad6265SDimitry Andric !isa<IntrinsicInst>(IA)) { 799e8d8bef9SDimitry Andric if (!compareCommutativeOperandMapping( 800e8d8bef9SDimitry Andric {A, OperValsA, ValueNumberMappingA}, 801e8d8bef9SDimitry Andric {B, OperValsB, ValueNumberMappingB})) 802e8d8bef9SDimitry Andric return false; 803e8d8bef9SDimitry Andric continue; 804e8d8bef9SDimitry Andric } 805e8d8bef9SDimitry Andric 806e8d8bef9SDimitry Andric // Handle the non-commutative cases. 807e8d8bef9SDimitry Andric if (!compareNonCommutativeOperandMapping( 808e8d8bef9SDimitry Andric {A, OperValsA, ValueNumberMappingA}, 809e8d8bef9SDimitry Andric {B, OperValsB, ValueNumberMappingB})) 810e8d8bef9SDimitry Andric return false; 811349cc55cSDimitry Andric 812349cc55cSDimitry Andric // Here we check that between two corresponding instructions, 813349cc55cSDimitry Andric // when referring to a basic block in the same region, the 814349cc55cSDimitry Andric // relative locations are the same. And, that the instructions refer to 815349cc55cSDimitry Andric // basic blocks outside the region in the same corresponding locations. 816349cc55cSDimitry Andric 817349cc55cSDimitry Andric // We are able to make the assumption about blocks outside of the region 818349cc55cSDimitry Andric // since the target block labels are considered values and will follow the 819349cc55cSDimitry Andric // same number matching that we defined for the other instructions in the 820349cc55cSDimitry Andric // region. So, at this point, in each location we target a specific block 821349cc55cSDimitry Andric // outside the region, we are targeting a corresponding block in each 822349cc55cSDimitry Andric // analagous location in the region we are comparing to. 823349cc55cSDimitry Andric if (!(isa<BranchInst>(IA) && isa<BranchInst>(IB)) && 824349cc55cSDimitry Andric !(isa<PHINode>(IA) && isa<PHINode>(IB))) 825349cc55cSDimitry Andric continue; 826349cc55cSDimitry Andric 827349cc55cSDimitry Andric SmallVector<int, 4> &RelBlockLocsA = ItA->RelativeBlockLocations; 828349cc55cSDimitry Andric SmallVector<int, 4> &RelBlockLocsB = ItB->RelativeBlockLocations; 829349cc55cSDimitry Andric if (RelBlockLocsA.size() != RelBlockLocsB.size() && 830349cc55cSDimitry Andric OperValsA.size() != OperValsB.size()) 831349cc55cSDimitry Andric return false; 832349cc55cSDimitry Andric 833349cc55cSDimitry Andric ZippedRelativeLocationsT ZippedRelativeLocations = 834349cc55cSDimitry Andric zip(RelBlockLocsA, RelBlockLocsB, OperValsA, OperValsB); 835349cc55cSDimitry Andric if (any_of(ZippedRelativeLocations, 836349cc55cSDimitry Andric [&A, &B](std::tuple<int, int, Value *, Value *> R) { 837349cc55cSDimitry Andric return !checkRelativeLocations( 838349cc55cSDimitry Andric {A, std::get<0>(R), std::get<2>(R)}, 839349cc55cSDimitry Andric {B, std::get<1>(R), std::get<3>(R)}); 840349cc55cSDimitry Andric })) 841349cc55cSDimitry Andric return false; 842e8d8bef9SDimitry Andric } 843e8d8bef9SDimitry Andric return true; 844e8d8bef9SDimitry Andric } 845e8d8bef9SDimitry Andric 846e8d8bef9SDimitry Andric bool IRSimilarityCandidate::overlap(const IRSimilarityCandidate &A, 847e8d8bef9SDimitry Andric const IRSimilarityCandidate &B) { 848e8d8bef9SDimitry Andric auto DoesOverlap = [](const IRSimilarityCandidate &X, 849e8d8bef9SDimitry Andric const IRSimilarityCandidate &Y) { 850e8d8bef9SDimitry Andric // Check: 851e8d8bef9SDimitry Andric // XXXXXX X starts before Y ends 852e8d8bef9SDimitry Andric // YYYYYYY Y starts after X starts 853e8d8bef9SDimitry Andric return X.StartIdx <= Y.getEndIdx() && Y.StartIdx >= X.StartIdx; 854e8d8bef9SDimitry Andric }; 855e8d8bef9SDimitry Andric 856e8d8bef9SDimitry Andric return DoesOverlap(A, B) || DoesOverlap(B, A); 857e8d8bef9SDimitry Andric } 858e8d8bef9SDimitry Andric 859e8d8bef9SDimitry Andric void IRSimilarityIdentifier::populateMapper( 860e8d8bef9SDimitry Andric Module &M, std::vector<IRInstructionData *> &InstrList, 861e8d8bef9SDimitry Andric std::vector<unsigned> &IntegerMapping) { 862e8d8bef9SDimitry Andric 863e8d8bef9SDimitry Andric std::vector<IRInstructionData *> InstrListForModule; 864e8d8bef9SDimitry Andric std::vector<unsigned> IntegerMappingForModule; 865e8d8bef9SDimitry Andric // Iterate over the functions in the module to map each Instruction in each 866e8d8bef9SDimitry Andric // BasicBlock to an unsigned integer. 867349cc55cSDimitry Andric Mapper.initializeForBBs(M); 868349cc55cSDimitry Andric 869e8d8bef9SDimitry Andric for (Function &F : M) { 870e8d8bef9SDimitry Andric 871e8d8bef9SDimitry Andric if (F.empty()) 872e8d8bef9SDimitry Andric continue; 873e8d8bef9SDimitry Andric 874e8d8bef9SDimitry Andric for (BasicBlock &BB : F) { 875e8d8bef9SDimitry Andric 876e8d8bef9SDimitry Andric // BB has potential to have similarity since it has a size greater than 2 877e8d8bef9SDimitry Andric // and can therefore match other regions greater than 2. Map it to a list 878e8d8bef9SDimitry Andric // of unsigned integers. 879e8d8bef9SDimitry Andric Mapper.convertToUnsignedVec(BB, InstrListForModule, 880e8d8bef9SDimitry Andric IntegerMappingForModule); 881e8d8bef9SDimitry Andric } 882349cc55cSDimitry Andric 883349cc55cSDimitry Andric BasicBlock::iterator It = F.begin()->end(); 884349cc55cSDimitry Andric Mapper.mapToIllegalUnsigned(It, IntegerMappingForModule, InstrListForModule, 885349cc55cSDimitry Andric true); 886349cc55cSDimitry Andric if (InstrListForModule.size() > 0) 887349cc55cSDimitry Andric Mapper.IDL->push_back(*InstrListForModule.back()); 888e8d8bef9SDimitry Andric } 889e8d8bef9SDimitry Andric 890e8d8bef9SDimitry Andric // Insert the InstrListForModule at the end of the overall InstrList so that 891e8d8bef9SDimitry Andric // we can have a long InstrList for the entire set of Modules being analyzed. 892e8d8bef9SDimitry Andric llvm::append_range(InstrList, InstrListForModule); 893e8d8bef9SDimitry Andric // Do the same as above, but for IntegerMapping. 894e8d8bef9SDimitry Andric llvm::append_range(IntegerMapping, IntegerMappingForModule); 895e8d8bef9SDimitry Andric } 896e8d8bef9SDimitry Andric 897e8d8bef9SDimitry Andric void IRSimilarityIdentifier::populateMapper( 898e8d8bef9SDimitry Andric ArrayRef<std::unique_ptr<Module>> &Modules, 899e8d8bef9SDimitry Andric std::vector<IRInstructionData *> &InstrList, 900e8d8bef9SDimitry Andric std::vector<unsigned> &IntegerMapping) { 901e8d8bef9SDimitry Andric 902e8d8bef9SDimitry Andric // Iterate over, and map the instructions in each module. 903e8d8bef9SDimitry Andric for (const std::unique_ptr<Module> &M : Modules) 904e8d8bef9SDimitry Andric populateMapper(*M, InstrList, IntegerMapping); 905e8d8bef9SDimitry Andric } 906e8d8bef9SDimitry Andric 907e8d8bef9SDimitry Andric /// From a repeated subsequence, find all the different instances of the 908e8d8bef9SDimitry Andric /// subsequence from the \p InstrList, and create an IRSimilarityCandidate from 909e8d8bef9SDimitry Andric /// the IRInstructionData in subsequence. 910e8d8bef9SDimitry Andric /// 9114824e7fdSDimitry Andric /// \param [in] Mapper - The instruction mapper for basic correctness checks. 912e8d8bef9SDimitry Andric /// \param [in] InstrList - The vector that holds the instruction data. 913e8d8bef9SDimitry Andric /// \param [in] IntegerMapping - The vector that holds the mapped integers. 914e8d8bef9SDimitry Andric /// \param [out] CandsForRepSubstring - The vector to store the generated 915e8d8bef9SDimitry Andric /// IRSimilarityCandidates. 916e8d8bef9SDimitry Andric static void createCandidatesFromSuffixTree( 917fe6060f1SDimitry Andric const IRInstructionMapper& Mapper, std::vector<IRInstructionData *> &InstrList, 918e8d8bef9SDimitry Andric std::vector<unsigned> &IntegerMapping, SuffixTree::RepeatedSubstring &RS, 919e8d8bef9SDimitry Andric std::vector<IRSimilarityCandidate> &CandsForRepSubstring) { 920e8d8bef9SDimitry Andric 921e8d8bef9SDimitry Andric unsigned StringLen = RS.Length; 922349cc55cSDimitry Andric if (StringLen < 2) 923349cc55cSDimitry Andric return; 924e8d8bef9SDimitry Andric 925e8d8bef9SDimitry Andric // Create an IRSimilarityCandidate for instance of this subsequence \p RS. 926e8d8bef9SDimitry Andric for (const unsigned &StartIdx : RS.StartIndices) { 927e8d8bef9SDimitry Andric unsigned EndIdx = StartIdx + StringLen - 1; 928e8d8bef9SDimitry Andric 929e8d8bef9SDimitry Andric // Check that this subsequence does not contain an illegal instruction. 930e8d8bef9SDimitry Andric bool ContainsIllegal = false; 931e8d8bef9SDimitry Andric for (unsigned CurrIdx = StartIdx; CurrIdx <= EndIdx; CurrIdx++) { 932e8d8bef9SDimitry Andric unsigned Key = IntegerMapping[CurrIdx]; 933e8d8bef9SDimitry Andric if (Key > Mapper.IllegalInstrNumber) { 934e8d8bef9SDimitry Andric ContainsIllegal = true; 935e8d8bef9SDimitry Andric break; 936e8d8bef9SDimitry Andric } 937e8d8bef9SDimitry Andric } 938e8d8bef9SDimitry Andric 939e8d8bef9SDimitry Andric // If we have an illegal instruction, we should not create an 940e8d8bef9SDimitry Andric // IRSimilarityCandidate for this region. 941e8d8bef9SDimitry Andric if (ContainsIllegal) 942e8d8bef9SDimitry Andric continue; 943e8d8bef9SDimitry Andric 944e8d8bef9SDimitry Andric // We are getting iterators to the instructions in this region of code 945e8d8bef9SDimitry Andric // by advancing the start and end indices from the start of the 946e8d8bef9SDimitry Andric // InstrList. 947e8d8bef9SDimitry Andric std::vector<IRInstructionData *>::iterator StartIt = InstrList.begin(); 948e8d8bef9SDimitry Andric std::advance(StartIt, StartIdx); 949e8d8bef9SDimitry Andric std::vector<IRInstructionData *>::iterator EndIt = InstrList.begin(); 950e8d8bef9SDimitry Andric std::advance(EndIt, EndIdx); 951e8d8bef9SDimitry Andric 952e8d8bef9SDimitry Andric CandsForRepSubstring.emplace_back(StartIdx, StringLen, *StartIt, *EndIt); 953e8d8bef9SDimitry Andric } 954e8d8bef9SDimitry Andric } 955e8d8bef9SDimitry Andric 956349cc55cSDimitry Andric void IRSimilarityCandidate::createCanonicalRelationFrom( 957349cc55cSDimitry Andric IRSimilarityCandidate &SourceCand, 958349cc55cSDimitry Andric DenseMap<unsigned, DenseSet<unsigned>> &ToSourceMapping, 959349cc55cSDimitry Andric DenseMap<unsigned, DenseSet<unsigned>> &FromSourceMapping) { 960349cc55cSDimitry Andric assert(SourceCand.CanonNumToNumber.size() != 0 && 961349cc55cSDimitry Andric "Base canonical relationship is empty!"); 962349cc55cSDimitry Andric assert(SourceCand.NumberToCanonNum.size() != 0 && 963349cc55cSDimitry Andric "Base canonical relationship is empty!"); 964349cc55cSDimitry Andric 965349cc55cSDimitry Andric assert(CanonNumToNumber.size() == 0 && "Canonical Relationship is non-empty"); 966349cc55cSDimitry Andric assert(NumberToCanonNum.size() == 0 && "Canonical Relationship is non-empty"); 967349cc55cSDimitry Andric 968349cc55cSDimitry Andric DenseSet<unsigned> UsedGVNs; 969349cc55cSDimitry Andric // Iterate over the mappings provided from this candidate to SourceCand. We 970349cc55cSDimitry Andric // are then able to map the GVN in this candidate to the same canonical number 971349cc55cSDimitry Andric // given to the corresponding GVN in SourceCand. 972349cc55cSDimitry Andric for (std::pair<unsigned, DenseSet<unsigned>> &GVNMapping : ToSourceMapping) { 973349cc55cSDimitry Andric unsigned SourceGVN = GVNMapping.first; 974349cc55cSDimitry Andric 975349cc55cSDimitry Andric assert(GVNMapping.second.size() != 0 && "Possible GVNs is 0!"); 976349cc55cSDimitry Andric 977349cc55cSDimitry Andric unsigned ResultGVN; 978349cc55cSDimitry Andric // We need special handling if we have more than one potential value. This 979349cc55cSDimitry Andric // means that there are at least two GVNs that could correspond to this GVN. 980349cc55cSDimitry Andric // This could lead to potential swapping later on, so we make a decision 981349cc55cSDimitry Andric // here to ensure a one-to-one mapping. 982349cc55cSDimitry Andric if (GVNMapping.second.size() > 1) { 983349cc55cSDimitry Andric bool Found = false; 984349cc55cSDimitry Andric for (unsigned Val : GVNMapping.second) { 985349cc55cSDimitry Andric // We make sure the target value number hasn't already been reserved. 986349cc55cSDimitry Andric if (UsedGVNs.contains(Val)) 987349cc55cSDimitry Andric continue; 988349cc55cSDimitry Andric 989349cc55cSDimitry Andric // We make sure that the opposite mapping is still consistent. 990349cc55cSDimitry Andric DenseMap<unsigned, DenseSet<unsigned>>::iterator It = 991349cc55cSDimitry Andric FromSourceMapping.find(Val); 992349cc55cSDimitry Andric 993349cc55cSDimitry Andric if (!It->second.contains(SourceGVN)) 994349cc55cSDimitry Andric continue; 995349cc55cSDimitry Andric 996349cc55cSDimitry Andric // We pick the first item that satisfies these conditions. 997349cc55cSDimitry Andric Found = true; 998349cc55cSDimitry Andric ResultGVN = Val; 999349cc55cSDimitry Andric break; 1000349cc55cSDimitry Andric } 1001349cc55cSDimitry Andric 1002349cc55cSDimitry Andric assert(Found && "Could not find matching value for source GVN"); 1003349cc55cSDimitry Andric (void)Found; 1004349cc55cSDimitry Andric 1005349cc55cSDimitry Andric } else 1006349cc55cSDimitry Andric ResultGVN = *GVNMapping.second.begin(); 1007349cc55cSDimitry Andric 1008349cc55cSDimitry Andric // Whatever GVN is found, we mark it as used. 1009349cc55cSDimitry Andric UsedGVNs.insert(ResultGVN); 1010349cc55cSDimitry Andric 1011349cc55cSDimitry Andric unsigned CanonNum = *SourceCand.getCanonicalNum(ResultGVN); 1012349cc55cSDimitry Andric CanonNumToNumber.insert(std::make_pair(CanonNum, SourceGVN)); 1013349cc55cSDimitry Andric NumberToCanonNum.insert(std::make_pair(SourceGVN, CanonNum)); 1014349cc55cSDimitry Andric } 1015*81ad6265SDimitry Andric 1016*81ad6265SDimitry Andric DenseSet<BasicBlock *> BBSet; 1017*81ad6265SDimitry Andric getBasicBlocks(BBSet); 1018*81ad6265SDimitry Andric // Find canonical numbers for the BasicBlocks in the current candidate. 1019*81ad6265SDimitry Andric // This is done by finding the corresponding value for the first instruction 1020*81ad6265SDimitry Andric // in the block in the current candidate, finding the matching value in the 1021*81ad6265SDimitry Andric // source candidate. Then by finding the parent of this value, use the 1022*81ad6265SDimitry Andric // canonical number of the block in the source candidate for the canonical 1023*81ad6265SDimitry Andric // number in the current candidate. 1024*81ad6265SDimitry Andric for (BasicBlock *BB : BBSet) { 1025*81ad6265SDimitry Andric unsigned BBGVNForCurrCand = ValueToNumber.find(BB)->second; 1026*81ad6265SDimitry Andric 1027*81ad6265SDimitry Andric // We can skip the BasicBlock if the canonical numbering has already been 1028*81ad6265SDimitry Andric // found in a separate instruction. 1029*81ad6265SDimitry Andric if (NumberToCanonNum.find(BBGVNForCurrCand) != NumberToCanonNum.end()) 1030*81ad6265SDimitry Andric continue; 1031*81ad6265SDimitry Andric 1032*81ad6265SDimitry Andric // If the basic block is the starting block, then the shared instruction may 1033*81ad6265SDimitry Andric // not be the first instruction in the block, it will be the first 1034*81ad6265SDimitry Andric // instruction in the similarity region. 1035*81ad6265SDimitry Andric Value *FirstOutlineInst = BB == getStartBB() 1036*81ad6265SDimitry Andric ? frontInstruction() 1037*81ad6265SDimitry Andric : &*BB->instructionsWithoutDebug().begin(); 1038*81ad6265SDimitry Andric 1039*81ad6265SDimitry Andric unsigned FirstInstGVN = *getGVN(FirstOutlineInst); 1040*81ad6265SDimitry Andric unsigned FirstInstCanonNum = *getCanonicalNum(FirstInstGVN); 1041*81ad6265SDimitry Andric unsigned SourceGVN = *SourceCand.fromCanonicalNum(FirstInstCanonNum); 1042*81ad6265SDimitry Andric Value *SourceV = *SourceCand.fromGVN(SourceGVN); 1043*81ad6265SDimitry Andric BasicBlock *SourceBB = cast<Instruction>(SourceV)->getParent(); 1044*81ad6265SDimitry Andric unsigned SourceBBGVN = *SourceCand.getGVN(SourceBB); 1045*81ad6265SDimitry Andric unsigned SourceCanonBBGVN = *SourceCand.getCanonicalNum(SourceBBGVN); 1046*81ad6265SDimitry Andric CanonNumToNumber.insert(std::make_pair(SourceCanonBBGVN, BBGVNForCurrCand)); 1047*81ad6265SDimitry Andric NumberToCanonNum.insert(std::make_pair(BBGVNForCurrCand, SourceCanonBBGVN)); 1048*81ad6265SDimitry Andric } 1049349cc55cSDimitry Andric } 1050349cc55cSDimitry Andric 1051349cc55cSDimitry Andric void IRSimilarityCandidate::createCanonicalMappingFor( 1052349cc55cSDimitry Andric IRSimilarityCandidate &CurrCand) { 1053349cc55cSDimitry Andric assert(CurrCand.CanonNumToNumber.size() == 0 && 1054349cc55cSDimitry Andric "Canonical Relationship is non-empty"); 1055349cc55cSDimitry Andric assert(CurrCand.NumberToCanonNum.size() == 0 && 1056349cc55cSDimitry Andric "Canonical Relationship is non-empty"); 1057349cc55cSDimitry Andric 1058349cc55cSDimitry Andric unsigned CanonNum = 0; 1059349cc55cSDimitry Andric // Iterate over the value numbers found, the order does not matter in this 1060349cc55cSDimitry Andric // case. 1061349cc55cSDimitry Andric for (std::pair<unsigned, Value *> &NumToVal : CurrCand.NumberToValue) { 1062349cc55cSDimitry Andric CurrCand.NumberToCanonNum.insert(std::make_pair(NumToVal.first, CanonNum)); 1063349cc55cSDimitry Andric CurrCand.CanonNumToNumber.insert(std::make_pair(CanonNum, NumToVal.first)); 1064349cc55cSDimitry Andric CanonNum++; 1065349cc55cSDimitry Andric } 1066349cc55cSDimitry Andric } 1067349cc55cSDimitry Andric 1068e8d8bef9SDimitry Andric /// From the list of IRSimilarityCandidates, perform a comparison between each 1069e8d8bef9SDimitry Andric /// IRSimilarityCandidate to determine if there are overlapping 1070e8d8bef9SDimitry Andric /// IRInstructionData, or if they do not have the same structure. 1071e8d8bef9SDimitry Andric /// 1072e8d8bef9SDimitry Andric /// \param [in] CandsForRepSubstring - The vector containing the 1073e8d8bef9SDimitry Andric /// IRSimilarityCandidates. 1074e8d8bef9SDimitry Andric /// \param [out] StructuralGroups - the mapping of unsigned integers to vector 1075e8d8bef9SDimitry Andric /// of IRSimilarityCandidates where each of the IRSimilarityCandidates in the 1076e8d8bef9SDimitry Andric /// vector are structurally similar to one another. 1077e8d8bef9SDimitry Andric static void findCandidateStructures( 1078e8d8bef9SDimitry Andric std::vector<IRSimilarityCandidate> &CandsForRepSubstring, 1079e8d8bef9SDimitry Andric DenseMap<unsigned, SimilarityGroup> &StructuralGroups) { 1080e8d8bef9SDimitry Andric std::vector<IRSimilarityCandidate>::iterator CandIt, CandEndIt, InnerCandIt, 1081e8d8bef9SDimitry Andric InnerCandEndIt; 1082e8d8bef9SDimitry Andric 1083e8d8bef9SDimitry Andric // IRSimilarityCandidates each have a structure for operand use. It is 1084e8d8bef9SDimitry Andric // possible that two instances of the same subsequences have different 1085e8d8bef9SDimitry Andric // structure. Each type of structure found is assigned a number. This 1086e8d8bef9SDimitry Andric // DenseMap maps an IRSimilarityCandidate to which type of similarity 1087e8d8bef9SDimitry Andric // discovered it fits within. 1088e8d8bef9SDimitry Andric DenseMap<IRSimilarityCandidate *, unsigned> CandToGroup; 1089e8d8bef9SDimitry Andric 1090e8d8bef9SDimitry Andric // Find the compatibility from each candidate to the others to determine 1091e8d8bef9SDimitry Andric // which candidates overlap and which have the same structure by mapping 1092e8d8bef9SDimitry Andric // each structure to a different group. 1093e8d8bef9SDimitry Andric bool SameStructure; 1094e8d8bef9SDimitry Andric bool Inserted; 1095e8d8bef9SDimitry Andric unsigned CurrentGroupNum = 0; 1096e8d8bef9SDimitry Andric unsigned OuterGroupNum; 1097e8d8bef9SDimitry Andric DenseMap<IRSimilarityCandidate *, unsigned>::iterator CandToGroupIt; 1098e8d8bef9SDimitry Andric DenseMap<IRSimilarityCandidate *, unsigned>::iterator CandToGroupItInner; 1099e8d8bef9SDimitry Andric DenseMap<unsigned, SimilarityGroup>::iterator CurrentGroupPair; 1100e8d8bef9SDimitry Andric 1101e8d8bef9SDimitry Andric // Iterate over the candidates to determine its structural and overlapping 1102e8d8bef9SDimitry Andric // compatibility with other instructions 1103349cc55cSDimitry Andric DenseMap<unsigned, DenseSet<unsigned>> ValueNumberMappingA; 1104349cc55cSDimitry Andric DenseMap<unsigned, DenseSet<unsigned>> ValueNumberMappingB; 1105e8d8bef9SDimitry Andric for (CandIt = CandsForRepSubstring.begin(), 1106e8d8bef9SDimitry Andric CandEndIt = CandsForRepSubstring.end(); 1107e8d8bef9SDimitry Andric CandIt != CandEndIt; CandIt++) { 1108e8d8bef9SDimitry Andric 1109e8d8bef9SDimitry Andric // Determine if it has an assigned structural group already. 1110e8d8bef9SDimitry Andric CandToGroupIt = CandToGroup.find(&*CandIt); 1111e8d8bef9SDimitry Andric if (CandToGroupIt == CandToGroup.end()) { 1112e8d8bef9SDimitry Andric // If not, we assign it one, and add it to our mapping. 1113e8d8bef9SDimitry Andric std::tie(CandToGroupIt, Inserted) = 1114e8d8bef9SDimitry Andric CandToGroup.insert(std::make_pair(&*CandIt, CurrentGroupNum++)); 1115e8d8bef9SDimitry Andric } 1116e8d8bef9SDimitry Andric 1117e8d8bef9SDimitry Andric // Get the structural group number from the iterator. 1118e8d8bef9SDimitry Andric OuterGroupNum = CandToGroupIt->second; 1119e8d8bef9SDimitry Andric 1120e8d8bef9SDimitry Andric // Check if we already have a list of IRSimilarityCandidates for the current 1121e8d8bef9SDimitry Andric // structural group. Create one if one does not exist. 1122e8d8bef9SDimitry Andric CurrentGroupPair = StructuralGroups.find(OuterGroupNum); 1123349cc55cSDimitry Andric if (CurrentGroupPair == StructuralGroups.end()) { 1124349cc55cSDimitry Andric IRSimilarityCandidate::createCanonicalMappingFor(*CandIt); 1125e8d8bef9SDimitry Andric std::tie(CurrentGroupPair, Inserted) = StructuralGroups.insert( 1126e8d8bef9SDimitry Andric std::make_pair(OuterGroupNum, SimilarityGroup({*CandIt}))); 1127349cc55cSDimitry Andric } 1128e8d8bef9SDimitry Andric 1129e8d8bef9SDimitry Andric // Iterate over the IRSimilarityCandidates following the current 1130e8d8bef9SDimitry Andric // IRSimilarityCandidate in the list to determine whether the two 1131e8d8bef9SDimitry Andric // IRSimilarityCandidates are compatible. This is so we do not repeat pairs 1132e8d8bef9SDimitry Andric // of IRSimilarityCandidates. 1133e8d8bef9SDimitry Andric for (InnerCandIt = std::next(CandIt), 1134e8d8bef9SDimitry Andric InnerCandEndIt = CandsForRepSubstring.end(); 1135e8d8bef9SDimitry Andric InnerCandIt != InnerCandEndIt; InnerCandIt++) { 1136e8d8bef9SDimitry Andric 1137e8d8bef9SDimitry Andric // We check if the inner item has a group already, if it does, we skip it. 1138e8d8bef9SDimitry Andric CandToGroupItInner = CandToGroup.find(&*InnerCandIt); 1139e8d8bef9SDimitry Andric if (CandToGroupItInner != CandToGroup.end()) 1140e8d8bef9SDimitry Andric continue; 1141e8d8bef9SDimitry Andric 1142e8d8bef9SDimitry Andric // Otherwise we determine if they have the same structure and add it to 1143e8d8bef9SDimitry Andric // vector if they match. 1144349cc55cSDimitry Andric ValueNumberMappingA.clear(); 1145349cc55cSDimitry Andric ValueNumberMappingB.clear(); 1146349cc55cSDimitry Andric SameStructure = IRSimilarityCandidate::compareStructure( 1147349cc55cSDimitry Andric *CandIt, *InnerCandIt, ValueNumberMappingA, ValueNumberMappingB); 1148e8d8bef9SDimitry Andric if (!SameStructure) 1149e8d8bef9SDimitry Andric continue; 1150e8d8bef9SDimitry Andric 1151349cc55cSDimitry Andric InnerCandIt->createCanonicalRelationFrom(*CandIt, ValueNumberMappingA, 1152349cc55cSDimitry Andric ValueNumberMappingB); 1153e8d8bef9SDimitry Andric CandToGroup.insert(std::make_pair(&*InnerCandIt, OuterGroupNum)); 1154e8d8bef9SDimitry Andric CurrentGroupPair->second.push_back(*InnerCandIt); 1155e8d8bef9SDimitry Andric } 1156e8d8bef9SDimitry Andric } 1157e8d8bef9SDimitry Andric } 1158e8d8bef9SDimitry Andric 1159e8d8bef9SDimitry Andric void IRSimilarityIdentifier::findCandidates( 1160e8d8bef9SDimitry Andric std::vector<IRInstructionData *> &InstrList, 1161e8d8bef9SDimitry Andric std::vector<unsigned> &IntegerMapping) { 1162e8d8bef9SDimitry Andric SuffixTree ST(IntegerMapping); 1163e8d8bef9SDimitry Andric 1164e8d8bef9SDimitry Andric std::vector<IRSimilarityCandidate> CandsForRepSubstring; 1165e8d8bef9SDimitry Andric std::vector<SimilarityGroup> NewCandidateGroups; 1166e8d8bef9SDimitry Andric 1167e8d8bef9SDimitry Andric DenseMap<unsigned, SimilarityGroup> StructuralGroups; 1168e8d8bef9SDimitry Andric 1169e8d8bef9SDimitry Andric // Iterate over the subsequences found by the Suffix Tree to create 1170e8d8bef9SDimitry Andric // IRSimilarityCandidates for each repeated subsequence and determine which 1171e8d8bef9SDimitry Andric // instances are structurally similar to one another. 1172fe6060f1SDimitry Andric for (SuffixTree::RepeatedSubstring &RS : ST) { 1173fe6060f1SDimitry Andric createCandidatesFromSuffixTree(Mapper, InstrList, IntegerMapping, RS, 1174e8d8bef9SDimitry Andric CandsForRepSubstring); 1175e8d8bef9SDimitry Andric 1176e8d8bef9SDimitry Andric if (CandsForRepSubstring.size() < 2) 1177e8d8bef9SDimitry Andric continue; 1178e8d8bef9SDimitry Andric 1179e8d8bef9SDimitry Andric findCandidateStructures(CandsForRepSubstring, StructuralGroups); 1180e8d8bef9SDimitry Andric for (std::pair<unsigned, SimilarityGroup> &Group : StructuralGroups) 1181e8d8bef9SDimitry Andric // We only add the group if it contains more than one 1182e8d8bef9SDimitry Andric // IRSimilarityCandidate. If there is only one, that means there is no 1183e8d8bef9SDimitry Andric // other repeated subsequence with the same structure. 1184e8d8bef9SDimitry Andric if (Group.second.size() > 1) 1185e8d8bef9SDimitry Andric SimilarityCandidates->push_back(Group.second); 1186e8d8bef9SDimitry Andric 1187e8d8bef9SDimitry Andric CandsForRepSubstring.clear(); 1188e8d8bef9SDimitry Andric StructuralGroups.clear(); 1189e8d8bef9SDimitry Andric NewCandidateGroups.clear(); 1190e8d8bef9SDimitry Andric } 1191e8d8bef9SDimitry Andric } 1192e8d8bef9SDimitry Andric 1193e8d8bef9SDimitry Andric SimilarityGroupList &IRSimilarityIdentifier::findSimilarity( 1194e8d8bef9SDimitry Andric ArrayRef<std::unique_ptr<Module>> Modules) { 1195e8d8bef9SDimitry Andric resetSimilarityCandidates(); 1196e8d8bef9SDimitry Andric 1197e8d8bef9SDimitry Andric std::vector<IRInstructionData *> InstrList; 1198e8d8bef9SDimitry Andric std::vector<unsigned> IntegerMapping; 1199349cc55cSDimitry Andric Mapper.InstClassifier.EnableBranches = this->EnableBranches; 120004eeddc0SDimitry Andric Mapper.InstClassifier.EnableIndirectCalls = EnableIndirectCalls; 120104eeddc0SDimitry Andric Mapper.EnableMatchCallsByName = EnableMatchingCallsByName; 12021fd87a68SDimitry Andric Mapper.InstClassifier.EnableIntrinsics = EnableIntrinsics; 1203*81ad6265SDimitry Andric Mapper.InstClassifier.EnableMustTailCalls = EnableMustTailCalls; 1204e8d8bef9SDimitry Andric 1205e8d8bef9SDimitry Andric populateMapper(Modules, InstrList, IntegerMapping); 1206e8d8bef9SDimitry Andric findCandidates(InstrList, IntegerMapping); 1207e8d8bef9SDimitry Andric 1208*81ad6265SDimitry Andric return *SimilarityCandidates; 1209e8d8bef9SDimitry Andric } 1210e8d8bef9SDimitry Andric 1211e8d8bef9SDimitry Andric SimilarityGroupList &IRSimilarityIdentifier::findSimilarity(Module &M) { 1212e8d8bef9SDimitry Andric resetSimilarityCandidates(); 1213349cc55cSDimitry Andric Mapper.InstClassifier.EnableBranches = this->EnableBranches; 121404eeddc0SDimitry Andric Mapper.InstClassifier.EnableIndirectCalls = EnableIndirectCalls; 121504eeddc0SDimitry Andric Mapper.EnableMatchCallsByName = EnableMatchingCallsByName; 12161fd87a68SDimitry Andric Mapper.InstClassifier.EnableIntrinsics = EnableIntrinsics; 1217*81ad6265SDimitry Andric Mapper.InstClassifier.EnableMustTailCalls = EnableMustTailCalls; 1218e8d8bef9SDimitry Andric 1219e8d8bef9SDimitry Andric std::vector<IRInstructionData *> InstrList; 1220e8d8bef9SDimitry Andric std::vector<unsigned> IntegerMapping; 1221e8d8bef9SDimitry Andric 1222e8d8bef9SDimitry Andric populateMapper(M, InstrList, IntegerMapping); 1223e8d8bef9SDimitry Andric findCandidates(InstrList, IntegerMapping); 1224e8d8bef9SDimitry Andric 1225*81ad6265SDimitry Andric return *SimilarityCandidates; 1226e8d8bef9SDimitry Andric } 1227e8d8bef9SDimitry Andric 1228e8d8bef9SDimitry Andric INITIALIZE_PASS(IRSimilarityIdentifierWrapperPass, "ir-similarity-identifier", 1229e8d8bef9SDimitry Andric "ir-similarity-identifier", false, true) 1230e8d8bef9SDimitry Andric 1231e8d8bef9SDimitry Andric IRSimilarityIdentifierWrapperPass::IRSimilarityIdentifierWrapperPass() 1232e8d8bef9SDimitry Andric : ModulePass(ID) { 1233e8d8bef9SDimitry Andric initializeIRSimilarityIdentifierWrapperPassPass( 1234e8d8bef9SDimitry Andric *PassRegistry::getPassRegistry()); 1235e8d8bef9SDimitry Andric } 1236e8d8bef9SDimitry Andric 1237e8d8bef9SDimitry Andric bool IRSimilarityIdentifierWrapperPass::doInitialization(Module &M) { 123804eeddc0SDimitry Andric IRSI.reset(new IRSimilarityIdentifier(!DisableBranches, !DisableIndirectCalls, 1239*81ad6265SDimitry Andric MatchCallsByName, !DisableIntrinsics, 1240*81ad6265SDimitry Andric false)); 1241e8d8bef9SDimitry Andric return false; 1242e8d8bef9SDimitry Andric } 1243e8d8bef9SDimitry Andric 1244e8d8bef9SDimitry Andric bool IRSimilarityIdentifierWrapperPass::doFinalization(Module &M) { 1245e8d8bef9SDimitry Andric IRSI.reset(); 1246e8d8bef9SDimitry Andric return false; 1247e8d8bef9SDimitry Andric } 1248e8d8bef9SDimitry Andric 1249e8d8bef9SDimitry Andric bool IRSimilarityIdentifierWrapperPass::runOnModule(Module &M) { 1250fe6060f1SDimitry Andric IRSI->findSimilarity(M); 1251e8d8bef9SDimitry Andric return false; 1252e8d8bef9SDimitry Andric } 1253e8d8bef9SDimitry Andric 1254e8d8bef9SDimitry Andric AnalysisKey IRSimilarityAnalysis::Key; 1255e8d8bef9SDimitry Andric IRSimilarityIdentifier IRSimilarityAnalysis::run(Module &M, 1256e8d8bef9SDimitry Andric ModuleAnalysisManager &) { 125704eeddc0SDimitry Andric auto IRSI = IRSimilarityIdentifier(!DisableBranches, !DisableIndirectCalls, 1258*81ad6265SDimitry Andric MatchCallsByName, !DisableIntrinsics, 1259*81ad6265SDimitry Andric false); 1260fe6060f1SDimitry Andric IRSI.findSimilarity(M); 1261fe6060f1SDimitry Andric return IRSI; 1262e8d8bef9SDimitry Andric } 1263e8d8bef9SDimitry Andric 1264e8d8bef9SDimitry Andric PreservedAnalyses 1265e8d8bef9SDimitry Andric IRSimilarityAnalysisPrinterPass::run(Module &M, ModuleAnalysisManager &AM) { 1266e8d8bef9SDimitry Andric IRSimilarityIdentifier &IRSI = AM.getResult<IRSimilarityAnalysis>(M); 1267e8d8bef9SDimitry Andric Optional<SimilarityGroupList> &SimilarityCandidatesOpt = IRSI.getSimilarity(); 1268e8d8bef9SDimitry Andric 1269e8d8bef9SDimitry Andric for (std::vector<IRSimilarityCandidate> &CandVec : *SimilarityCandidatesOpt) { 1270e8d8bef9SDimitry Andric OS << CandVec.size() << " candidates of length " 1271e8d8bef9SDimitry Andric << CandVec.begin()->getLength() << ". Found in: \n"; 1272e8d8bef9SDimitry Andric for (IRSimilarityCandidate &Cand : CandVec) { 1273e8d8bef9SDimitry Andric OS << " Function: " << Cand.front()->Inst->getFunction()->getName().str() 1274e8d8bef9SDimitry Andric << ", Basic Block: "; 1275e8d8bef9SDimitry Andric if (Cand.front()->Inst->getParent()->getName().str() == "") 1276fe6060f1SDimitry Andric OS << "(unnamed)"; 1277e8d8bef9SDimitry Andric else 1278fe6060f1SDimitry Andric OS << Cand.front()->Inst->getParent()->getName().str(); 1279fe6060f1SDimitry Andric OS << "\n Start Instruction: "; 1280fe6060f1SDimitry Andric Cand.frontInstruction()->print(OS); 1281fe6060f1SDimitry Andric OS << "\n End Instruction: "; 1282fe6060f1SDimitry Andric Cand.backInstruction()->print(OS); 1283fe6060f1SDimitry Andric OS << "\n"; 1284e8d8bef9SDimitry Andric } 1285e8d8bef9SDimitry Andric } 1286e8d8bef9SDimitry Andric 1287e8d8bef9SDimitry Andric return PreservedAnalyses::all(); 1288e8d8bef9SDimitry Andric } 1289e8d8bef9SDimitry Andric 1290e8d8bef9SDimitry Andric char IRSimilarityIdentifierWrapperPass::ID = 0; 1291