xref: /freebsd/contrib/llvm-project/llvm/lib/Analysis/IRSimilarityIdentifier.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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