1 //===- IRSimilarityIdentifier.cpp - Find similarity in a module -----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // \file 10 // Implementation file for the IRSimilarityIdentifier for identifying 11 // similarities in IR including the IRInstructionMapper. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Analysis/IRSimilarityIdentifier.h" 16 #include "llvm/ADT/DenseMap.h" 17 #include "llvm/IR/Intrinsics.h" 18 #include "llvm/IR/Operator.h" 19 #include "llvm/IR/User.h" 20 #include "llvm/InitializePasses.h" 21 #include "llvm/Support/SuffixTree.h" 22 23 using namespace llvm; 24 using namespace IRSimilarity; 25 26 namespace llvm { 27 cl::opt<bool> 28 DisableBranches("no-ir-sim-branch-matching", cl::init(false), 29 cl::ReallyHidden, 30 cl::desc("disable similarity matching, and outlining, " 31 "across branches for debugging purposes.")); 32 } // namespace llvm 33 34 cl::opt<bool> 35 DisableIndirectCalls("no-ir-sim-indirect-calls", cl::init(false), 36 cl::ReallyHidden, 37 cl::desc("disable outlining indirect calls.")); 38 39 cl::opt<bool> 40 MatchCallsByName("ir-sim-calls-by-name", cl::init(false), cl::ReallyHidden, 41 cl::desc("only allow matching call instructions if the " 42 "name and type signature match.")); 43 44 45 IRInstructionData::IRInstructionData(Instruction &I, bool Legality, 46 IRInstructionDataList &IDList) 47 : Inst(&I), Legal(Legality), IDL(&IDList) { 48 initializeInstruction(); 49 } 50 51 void IRInstructionData::initializeInstruction() { 52 // We check for whether we have a comparison instruction. If it is, we 53 // find the "less than" version of the predicate for consistency for 54 // comparison instructions throught the program. 55 if (CmpInst *C = dyn_cast<CmpInst>(Inst)) { 56 CmpInst::Predicate Predicate = predicateForConsistency(C); 57 if (Predicate != C->getPredicate()) 58 RevisedPredicate = Predicate; 59 } 60 61 // Here we collect the operands and their types for determining whether 62 // the structure of the operand use matches between two different candidates. 63 for (Use &OI : Inst->operands()) { 64 if (isa<CmpInst>(Inst) && RevisedPredicate.hasValue()) { 65 // If we have a CmpInst where the predicate is reversed, it means the 66 // operands must be reversed as well. 67 OperVals.insert(OperVals.begin(), OI.get()); 68 continue; 69 } 70 71 OperVals.push_back(OI.get()); 72 } 73 74 // We capture the incoming BasicBlocks as values as well as the incoming 75 // Values in order to check for structural similarity. 76 if (PHINode *PN = dyn_cast<PHINode>(Inst)) 77 for (BasicBlock *BB : PN->blocks()) 78 OperVals.push_back(BB); 79 } 80 81 IRInstructionData::IRInstructionData(IRInstructionDataList &IDList) 82 : IDL(&IDList) {} 83 84 void IRInstructionData::setBranchSuccessors( 85 DenseMap<BasicBlock *, unsigned> &BasicBlockToInteger) { 86 assert(isa<BranchInst>(Inst) && "Instruction must be branch"); 87 88 BranchInst *BI = cast<BranchInst>(Inst); 89 DenseMap<BasicBlock *, unsigned>::iterator BBNumIt; 90 91 BBNumIt = BasicBlockToInteger.find(BI->getParent()); 92 assert(BBNumIt != BasicBlockToInteger.end() && 93 "Could not find location for BasicBlock!"); 94 95 int CurrentBlockNumber = static_cast<int>(BBNumIt->second); 96 97 for (BasicBlock *Successor : BI->successors()) { 98 BBNumIt = BasicBlockToInteger.find(Successor); 99 assert(BBNumIt != BasicBlockToInteger.end() && 100 "Could not find number for BasicBlock!"); 101 int OtherBlockNumber = static_cast<int>(BBNumIt->second); 102 103 int Relative = OtherBlockNumber - CurrentBlockNumber; 104 RelativeBlockLocations.push_back(Relative); 105 } 106 } 107 108 void IRInstructionData::setCalleeName(bool MatchByName) { 109 CallInst *CI = dyn_cast<CallInst>(Inst); 110 assert(CI && "Instruction must be call"); 111 112 CalleeName = ""; 113 if (!CI->isIndirectCall() && MatchByName) 114 CalleeName = CI->getCalledFunction()->getName().str(); 115 } 116 117 void IRInstructionData::setPHIPredecessors( 118 DenseMap<BasicBlock *, unsigned> &BasicBlockToInteger) { 119 assert(isa<PHINode>(Inst) && "Instruction must be phi node"); 120 121 PHINode *PN = cast<PHINode>(Inst); 122 DenseMap<BasicBlock *, unsigned>::iterator BBNumIt; 123 124 BBNumIt = BasicBlockToInteger.find(PN->getParent()); 125 assert(BBNumIt != BasicBlockToInteger.end() && 126 "Could not find location for BasicBlock!"); 127 128 int CurrentBlockNumber = static_cast<int>(BBNumIt->second); 129 130 // Convert the incoming blocks of the PHINode to an integer value, based on 131 // the relative distances between the current block and the incoming block. 132 for (unsigned Idx = 0; Idx < PN->getNumIncomingValues(); Idx++) { 133 BasicBlock *Incoming = PN->getIncomingBlock(Idx); 134 BBNumIt = BasicBlockToInteger.find(Incoming); 135 assert(BBNumIt != BasicBlockToInteger.end() && 136 "Could not find number for BasicBlock!"); 137 int OtherBlockNumber = static_cast<int>(BBNumIt->second); 138 139 int Relative = OtherBlockNumber - CurrentBlockNumber; 140 RelativeBlockLocations.push_back(Relative); 141 RelativeBlockLocations.push_back(Relative); 142 } 143 } 144 145 CmpInst::Predicate IRInstructionData::predicateForConsistency(CmpInst *CI) { 146 switch (CI->getPredicate()) { 147 case CmpInst::FCMP_OGT: 148 case CmpInst::FCMP_UGT: 149 case CmpInst::FCMP_OGE: 150 case CmpInst::FCMP_UGE: 151 case CmpInst::ICMP_SGT: 152 case CmpInst::ICMP_UGT: 153 case CmpInst::ICMP_SGE: 154 case CmpInst::ICMP_UGE: 155 return CI->getSwappedPredicate(); 156 default: 157 return CI->getPredicate(); 158 } 159 } 160 161 CmpInst::Predicate IRInstructionData::getPredicate() const { 162 assert(isa<CmpInst>(Inst) && 163 "Can only get a predicate from a compare instruction"); 164 165 if (RevisedPredicate.hasValue()) 166 return RevisedPredicate.getValue(); 167 168 return cast<CmpInst>(Inst)->getPredicate(); 169 } 170 171 StringRef IRInstructionData::getCalleeName() const { 172 assert(isa<CallInst>(Inst) && 173 "Can only get a name from a call instruction"); 174 175 assert(CalleeName.hasValue() && "CalleeName has not been set"); 176 177 return *CalleeName; 178 } 179 180 bool IRSimilarity::isClose(const IRInstructionData &A, 181 const IRInstructionData &B) { 182 183 if (!A.Legal || !B.Legal) 184 return false; 185 186 // Check if we are performing the same sort of operation on the same types 187 // but not on the same values. 188 if (!A.Inst->isSameOperationAs(B.Inst)) { 189 // If there is a predicate, this means that either there is a swapped 190 // predicate, or that the types are different, we want to make sure that 191 // the predicates are equivalent via swapping. 192 if (isa<CmpInst>(A.Inst) && isa<CmpInst>(B.Inst)) { 193 194 if (A.getPredicate() != B.getPredicate()) 195 return false; 196 197 // If the predicates are the same via swap, make sure that the types are 198 // still the same. 199 auto ZippedTypes = zip(A.OperVals, B.OperVals); 200 201 return all_of( 202 ZippedTypes, [](std::tuple<llvm::Value *, llvm::Value *> R) { 203 return std::get<0>(R)->getType() == std::get<1>(R)->getType(); 204 }); 205 } 206 207 return false; 208 } 209 210 // Since any GEP Instruction operands after the first operand cannot be 211 // defined by a register, we must make sure that the operands after the first 212 // are the same in the two instructions 213 if (auto *GEP = dyn_cast<GetElementPtrInst>(A.Inst)) { 214 auto *OtherGEP = cast<GetElementPtrInst>(B.Inst); 215 216 // If the instructions do not have the same inbounds restrictions, we do 217 // not consider them the same. 218 if (GEP->isInBounds() != OtherGEP->isInBounds()) 219 return false; 220 221 auto ZippedOperands = zip(GEP->indices(), OtherGEP->indices()); 222 223 // We increment here since we do not care about the first instruction, 224 // we only care about the following operands since they must be the 225 // exact same to be considered similar. 226 return all_of(drop_begin(ZippedOperands), 227 [](std::tuple<llvm::Use &, llvm::Use &> R) { 228 return std::get<0>(R) == std::get<1>(R); 229 }); 230 } 231 232 // If the instructions are functions calls, we make sure that the function 233 // name is the same. We already know that the types are since is 234 // isSameOperationAs is true. 235 if (isa<CallInst>(A.Inst) && isa<CallInst>(B.Inst)) { 236 if (A.getCalleeName().str().compare(B.getCalleeName().str()) != 0) 237 return false; 238 } 239 240 if (isa<BranchInst>(A.Inst) && isa<BranchInst>(B.Inst) && 241 A.RelativeBlockLocations.size() != B.RelativeBlockLocations.size()) 242 return false; 243 244 return true; 245 } 246 247 // TODO: This is the same as the MachineOutliner, and should be consolidated 248 // into the same interface. 249 void IRInstructionMapper::convertToUnsignedVec( 250 BasicBlock &BB, std::vector<IRInstructionData *> &InstrList, 251 std::vector<unsigned> &IntegerMapping) { 252 BasicBlock::iterator It = BB.begin(); 253 254 std::vector<unsigned> IntegerMappingForBB; 255 std::vector<IRInstructionData *> InstrListForBB; 256 257 for (BasicBlock::iterator Et = BB.end(); It != Et; ++It) { 258 switch (InstClassifier.visit(*It)) { 259 case InstrType::Legal: 260 mapToLegalUnsigned(It, IntegerMappingForBB, InstrListForBB); 261 break; 262 case InstrType::Illegal: 263 mapToIllegalUnsigned(It, IntegerMappingForBB, InstrListForBB); 264 break; 265 case InstrType::Invisible: 266 AddedIllegalLastTime = false; 267 break; 268 } 269 } 270 271 if (HaveLegalRange) { 272 if (AddedIllegalLastTime) 273 mapToIllegalUnsigned(It, IntegerMappingForBB, InstrListForBB, true); 274 for (IRInstructionData *ID : InstrListForBB) 275 this->IDL->push_back(*ID); 276 llvm::append_range(InstrList, InstrListForBB); 277 llvm::append_range(IntegerMapping, IntegerMappingForBB); 278 } 279 } 280 281 // TODO: This is the same as the MachineOutliner, and should be consolidated 282 // into the same interface. 283 unsigned IRInstructionMapper::mapToLegalUnsigned( 284 BasicBlock::iterator &It, std::vector<unsigned> &IntegerMappingForBB, 285 std::vector<IRInstructionData *> &InstrListForBB) { 286 // We added something legal, so we should unset the AddedLegalLastTime 287 // flag. 288 AddedIllegalLastTime = false; 289 290 // If we have at least two adjacent legal instructions (which may have 291 // invisible instructions in between), remember that. 292 if (CanCombineWithPrevInstr) 293 HaveLegalRange = true; 294 CanCombineWithPrevInstr = true; 295 296 // Get the integer for this instruction or give it the current 297 // LegalInstrNumber. 298 IRInstructionData *ID = allocateIRInstructionData(*It, true, *IDL); 299 InstrListForBB.push_back(ID); 300 301 if (isa<BranchInst>(*It)) 302 ID->setBranchSuccessors(BasicBlockToInteger); 303 304 if (isa<CallInst>(*It)) 305 ID->setCalleeName(EnableMatchCallsByName); 306 307 if (isa<PHINode>(*It)) 308 ID->setPHIPredecessors(BasicBlockToInteger); 309 310 // Add to the instruction list 311 bool WasInserted; 312 DenseMap<IRInstructionData *, unsigned, IRInstructionDataTraits>::iterator 313 ResultIt; 314 std::tie(ResultIt, WasInserted) = 315 InstructionIntegerMap.insert(std::make_pair(ID, LegalInstrNumber)); 316 unsigned INumber = ResultIt->second; 317 318 // There was an insertion. 319 if (WasInserted) 320 LegalInstrNumber++; 321 322 IntegerMappingForBB.push_back(INumber); 323 324 // Make sure we don't overflow or use any integers reserved by the DenseMap. 325 assert(LegalInstrNumber < IllegalInstrNumber && 326 "Instruction mapping overflow!"); 327 328 assert(LegalInstrNumber != DenseMapInfo<unsigned>::getEmptyKey() && 329 "Tried to assign DenseMap tombstone or empty key to instruction."); 330 assert(LegalInstrNumber != DenseMapInfo<unsigned>::getTombstoneKey() && 331 "Tried to assign DenseMap tombstone or empty key to instruction."); 332 333 return INumber; 334 } 335 336 IRInstructionData * 337 IRInstructionMapper::allocateIRInstructionData(Instruction &I, bool Legality, 338 IRInstructionDataList &IDL) { 339 return new (InstDataAllocator->Allocate()) IRInstructionData(I, Legality, IDL); 340 } 341 342 IRInstructionData * 343 IRInstructionMapper::allocateIRInstructionData(IRInstructionDataList &IDL) { 344 return new (InstDataAllocator->Allocate()) IRInstructionData(IDL); 345 } 346 347 IRInstructionDataList * 348 IRInstructionMapper::allocateIRInstructionDataList() { 349 return new (IDLAllocator->Allocate()) IRInstructionDataList(); 350 } 351 352 // TODO: This is the same as the MachineOutliner, and should be consolidated 353 // into the same interface. 354 unsigned IRInstructionMapper::mapToIllegalUnsigned( 355 BasicBlock::iterator &It, std::vector<unsigned> &IntegerMappingForBB, 356 std::vector<IRInstructionData *> &InstrListForBB, bool End) { 357 // Can't combine an illegal instruction. Set the flag. 358 CanCombineWithPrevInstr = false; 359 360 // Only add one illegal number per range of legal numbers. 361 if (AddedIllegalLastTime) 362 return IllegalInstrNumber; 363 364 IRInstructionData *ID = nullptr; 365 if (!End) 366 ID = allocateIRInstructionData(*It, false, *IDL); 367 else 368 ID = allocateIRInstructionData(*IDL); 369 InstrListForBB.push_back(ID); 370 371 // Remember that we added an illegal number last time. 372 AddedIllegalLastTime = true; 373 unsigned INumber = IllegalInstrNumber; 374 IntegerMappingForBB.push_back(IllegalInstrNumber--); 375 376 assert(LegalInstrNumber < IllegalInstrNumber && 377 "Instruction mapping overflow!"); 378 379 assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getEmptyKey() && 380 "IllegalInstrNumber cannot be DenseMap tombstone or empty key!"); 381 382 assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getTombstoneKey() && 383 "IllegalInstrNumber cannot be DenseMap tombstone or empty key!"); 384 385 return INumber; 386 } 387 388 IRSimilarityCandidate::IRSimilarityCandidate(unsigned StartIdx, unsigned Len, 389 IRInstructionData *FirstInstIt, 390 IRInstructionData *LastInstIt) 391 : StartIdx(StartIdx), Len(Len) { 392 393 assert(FirstInstIt != nullptr && "Instruction is nullptr!"); 394 assert(LastInstIt != nullptr && "Instruction is nullptr!"); 395 assert(StartIdx + Len > StartIdx && 396 "Overflow for IRSimilarityCandidate range?"); 397 assert(Len - 1 == static_cast<unsigned>(std::distance( 398 iterator(FirstInstIt), iterator(LastInstIt))) && 399 "Length of the first and last IRInstructionData do not match the " 400 "given length"); 401 402 // We iterate over the given instructions, and map each unique value 403 // to a unique number in the IRSimilarityCandidate ValueToNumber and 404 // NumberToValue maps. A constant get its own value globally, the individual 405 // uses of the constants are not considered to be unique. 406 // 407 // IR: Mapping Added: 408 // %add1 = add i32 %a, c1 %add1 -> 3, %a -> 1, c1 -> 2 409 // %add2 = add i32 %a, %1 %add2 -> 4 410 // %add3 = add i32 c2, c1 %add3 -> 6, c2 -> 5 411 // 412 // when replace with global values, starting from 1, would be 413 // 414 // 3 = add i32 1, 2 415 // 4 = add i32 1, 3 416 // 6 = add i32 5, 2 417 unsigned LocalValNumber = 1; 418 IRInstructionDataList::iterator ID = iterator(*FirstInstIt); 419 for (unsigned Loc = StartIdx; Loc < StartIdx + Len; Loc++, ID++) { 420 // Map the operand values to an unsigned integer if it does not already 421 // have an unsigned integer assigned to it. 422 for (Value *Arg : ID->OperVals) 423 if (ValueToNumber.find(Arg) == ValueToNumber.end()) { 424 ValueToNumber.try_emplace(Arg, LocalValNumber); 425 NumberToValue.try_emplace(LocalValNumber, Arg); 426 LocalValNumber++; 427 } 428 429 // Mapping the instructions to an unsigned integer if it is not already 430 // exist in the mapping. 431 if (ValueToNumber.find(ID->Inst) == ValueToNumber.end()) { 432 ValueToNumber.try_emplace(ID->Inst, LocalValNumber); 433 NumberToValue.try_emplace(LocalValNumber, ID->Inst); 434 LocalValNumber++; 435 } 436 } 437 438 // Setting the first and last instruction data pointers for the candidate. If 439 // we got through the entire for loop without hitting an assert, we know 440 // that both of these instructions are not nullptrs. 441 FirstInst = FirstInstIt; 442 LastInst = LastInstIt; 443 } 444 445 bool IRSimilarityCandidate::isSimilar(const IRSimilarityCandidate &A, 446 const IRSimilarityCandidate &B) { 447 if (A.getLength() != B.getLength()) 448 return false; 449 450 auto InstrDataForBoth = 451 zip(make_range(A.begin(), A.end()), make_range(B.begin(), B.end())); 452 453 return all_of(InstrDataForBoth, 454 [](std::tuple<IRInstructionData &, IRInstructionData &> R) { 455 IRInstructionData &A = std::get<0>(R); 456 IRInstructionData &B = std::get<1>(R); 457 if (!A.Legal || !B.Legal) 458 return false; 459 return isClose(A, B); 460 }); 461 } 462 463 /// Determine if one or more of the assigned global value numbers for the 464 /// operands in \p TargetValueNumbers is in the current mapping set for operand 465 /// numbers in \p SourceOperands. The set of possible corresponding global 466 /// value numbers are replaced with the most recent version of compatible 467 /// values. 468 /// 469 /// \param [in] SourceValueToNumberMapping - The mapping of a Value to global 470 /// value number for the source IRInstructionCandidate. 471 /// \param [in, out] CurrentSrcTgtNumberMapping - The current mapping of source 472 /// IRSimilarityCandidate global value numbers to a set of possible numbers in 473 /// the target. 474 /// \param [in] SourceOperands - The operands in the original 475 /// IRSimilarityCandidate in the current instruction. 476 /// \param [in] TargetValueNumbers - The global value numbers of the operands in 477 /// the corresponding Instruction in the other IRSimilarityCandidate. 478 /// \returns true if there exists a possible mapping between the source 479 /// Instruction operands and the target Instruction operands, and false if not. 480 static bool checkNumberingAndReplaceCommutative( 481 const DenseMap<Value *, unsigned> &SourceValueToNumberMapping, 482 DenseMap<unsigned, DenseSet<unsigned>> &CurrentSrcTgtNumberMapping, 483 ArrayRef<Value *> &SourceOperands, 484 DenseSet<unsigned> &TargetValueNumbers){ 485 486 DenseMap<unsigned, DenseSet<unsigned>>::iterator ValueMappingIt; 487 488 unsigned ArgVal; 489 bool WasInserted; 490 491 // Iterate over the operands in the source IRSimilarityCandidate to determine 492 // whether there exists an operand in the other IRSimilarityCandidate that 493 // creates a valid mapping of Value to Value between the 494 // IRSimilarityCaniddates. 495 for (Value *V : SourceOperands) { 496 ArgVal = SourceValueToNumberMapping.find(V)->second; 497 498 std::tie(ValueMappingIt, WasInserted) = CurrentSrcTgtNumberMapping.insert( 499 std::make_pair(ArgVal, TargetValueNumbers)); 500 501 // Instead of finding a current mapping, we inserted a set. This means a 502 // mapping did not exist for the source Instruction operand, it has no 503 // current constraints we need to check. 504 if (WasInserted) 505 continue; 506 507 // If a mapping already exists for the source operand to the values in the 508 // other IRSimilarityCandidate we need to iterate over the items in other 509 // IRSimilarityCandidate's Instruction to determine whether there is a valid 510 // mapping of Value to Value. 511 DenseSet<unsigned> NewSet; 512 for (unsigned &Curr : ValueMappingIt->second) 513 // If we can find the value in the mapping, we add it to the new set. 514 if (TargetValueNumbers.contains(Curr)) 515 NewSet.insert(Curr); 516 517 // If we could not find a Value, return 0. 518 if (NewSet.empty()) 519 return false; 520 521 // Otherwise replace the old mapping with the newly constructed one. 522 if (NewSet.size() != ValueMappingIt->second.size()) 523 ValueMappingIt->second.swap(NewSet); 524 525 // We have reached no conclusions about the mapping, and cannot remove 526 // any items from the other operands, so we move to check the next operand. 527 if (ValueMappingIt->second.size() != 1) 528 continue; 529 530 531 unsigned ValToRemove = *ValueMappingIt->second.begin(); 532 // When there is only one item left in the mapping for and operand, remove 533 // the value from the other operands. If it results in there being no 534 // mapping, return false, it means the mapping is wrong 535 for (Value *InnerV : SourceOperands) { 536 if (V == InnerV) 537 continue; 538 539 unsigned InnerVal = SourceValueToNumberMapping.find(InnerV)->second; 540 ValueMappingIt = CurrentSrcTgtNumberMapping.find(InnerVal); 541 if (ValueMappingIt == CurrentSrcTgtNumberMapping.end()) 542 continue; 543 544 ValueMappingIt->second.erase(ValToRemove); 545 if (ValueMappingIt->second.empty()) 546 return false; 547 } 548 } 549 550 return true; 551 } 552 553 /// Determine if operand number \p TargetArgVal is in the current mapping set 554 /// for operand number \p SourceArgVal. 555 /// 556 /// \param [in, out] CurrentSrcTgtNumberMapping current mapping of global 557 /// value numbers from source IRSimilarityCandidate to target 558 /// IRSimilarityCandidate. 559 /// \param [in] SourceArgVal The global value number for an operand in the 560 /// in the original candidate. 561 /// \param [in] TargetArgVal The global value number for the corresponding 562 /// operand in the other candidate. 563 /// \returns True if there exists a mapping and false if not. 564 bool checkNumberingAndReplace( 565 DenseMap<unsigned, DenseSet<unsigned>> &CurrentSrcTgtNumberMapping, 566 unsigned SourceArgVal, unsigned TargetArgVal) { 567 // We are given two unsigned integers representing the global values of 568 // the operands in different IRSimilarityCandidates and a current mapping 569 // between the two. 570 // 571 // Source Operand GVN: 1 572 // Target Operand GVN: 2 573 // CurrentMapping: {1: {1, 2}} 574 // 575 // Since we have mapping, and the target operand is contained in the set, we 576 // update it to: 577 // CurrentMapping: {1: {2}} 578 // and can return true. But, if the mapping was 579 // CurrentMapping: {1: {3}} 580 // we would return false. 581 582 bool WasInserted; 583 DenseMap<unsigned, DenseSet<unsigned>>::iterator Val; 584 585 std::tie(Val, WasInserted) = CurrentSrcTgtNumberMapping.insert( 586 std::make_pair(SourceArgVal, DenseSet<unsigned>({TargetArgVal}))); 587 588 // If we created a new mapping, then we are done. 589 if (WasInserted) 590 return true; 591 592 // If there is more than one option in the mapping set, and the target value 593 // is included in the mapping set replace that set with one that only includes 594 // the target value, as it is the only valid mapping via the non commutative 595 // instruction. 596 597 DenseSet<unsigned> &TargetSet = Val->second; 598 if (TargetSet.size() > 1 && TargetSet.contains(TargetArgVal)) { 599 TargetSet.clear(); 600 TargetSet.insert(TargetArgVal); 601 return true; 602 } 603 604 // Return true if we can find the value in the set. 605 return TargetSet.contains(TargetArgVal); 606 } 607 608 bool IRSimilarityCandidate::compareNonCommutativeOperandMapping( 609 OperandMapping A, OperandMapping B) { 610 // Iterators to keep track of where we are in the operands for each 611 // Instruction. 612 ArrayRef<Value *>::iterator VItA = A.OperVals.begin(); 613 ArrayRef<Value *>::iterator VItB = B.OperVals.begin(); 614 unsigned OperandLength = A.OperVals.size(); 615 616 // For each operand, get the value numbering and ensure it is consistent. 617 for (unsigned Idx = 0; Idx < OperandLength; Idx++, VItA++, VItB++) { 618 unsigned OperValA = A.IRSC.ValueToNumber.find(*VItA)->second; 619 unsigned OperValB = B.IRSC.ValueToNumber.find(*VItB)->second; 620 621 // Attempt to add a set with only the target value. If there is no mapping 622 // we can create it here. 623 // 624 // For an instruction like a subtraction: 625 // IRSimilarityCandidateA: IRSimilarityCandidateB: 626 // %resultA = sub %a, %b %resultB = sub %d, %e 627 // 628 // We map %a -> %d and %b -> %e. 629 // 630 // And check to see whether their mapping is consistent in 631 // checkNumberingAndReplace. 632 633 if (!checkNumberingAndReplace(A.ValueNumberMapping, OperValA, OperValB)) 634 return false; 635 636 if (!checkNumberingAndReplace(B.ValueNumberMapping, OperValB, OperValA)) 637 return false; 638 } 639 return true; 640 } 641 642 bool IRSimilarityCandidate::compareCommutativeOperandMapping( 643 OperandMapping A, OperandMapping B) { 644 DenseSet<unsigned> ValueNumbersA; 645 DenseSet<unsigned> ValueNumbersB; 646 647 ArrayRef<Value *>::iterator VItA = A.OperVals.begin(); 648 ArrayRef<Value *>::iterator VItB = B.OperVals.begin(); 649 unsigned OperandLength = A.OperVals.size(); 650 651 // Find the value number sets for the operands. 652 for (unsigned Idx = 0; Idx < OperandLength; 653 Idx++, VItA++, VItB++) { 654 ValueNumbersA.insert(A.IRSC.ValueToNumber.find(*VItA)->second); 655 ValueNumbersB.insert(B.IRSC.ValueToNumber.find(*VItB)->second); 656 } 657 658 // Iterate over the operands in the first IRSimilarityCandidate and make sure 659 // there exists a possible mapping with the operands in the second 660 // IRSimilarityCandidate. 661 if (!checkNumberingAndReplaceCommutative(A.IRSC.ValueToNumber, 662 A.ValueNumberMapping, A.OperVals, 663 ValueNumbersB)) 664 return false; 665 666 // Iterate over the operands in the second IRSimilarityCandidate and make sure 667 // there exists a possible mapping with the operands in the first 668 // IRSimilarityCandidate. 669 if (!checkNumberingAndReplaceCommutative(B.IRSC.ValueToNumber, 670 B.ValueNumberMapping, B.OperVals, 671 ValueNumbersA)) 672 return false; 673 674 return true; 675 } 676 677 bool IRSimilarityCandidate::checkRelativeLocations(RelativeLocMapping A, 678 RelativeLocMapping B) { 679 // Get the basic blocks the label refers to. 680 BasicBlock *ABB = static_cast<BasicBlock *>(A.OperVal); 681 BasicBlock *BBB = static_cast<BasicBlock *>(B.OperVal); 682 683 // Get the basic blocks contained in each region. 684 DenseSet<BasicBlock *> BasicBlockA; 685 DenseSet<BasicBlock *> BasicBlockB; 686 A.IRSC.getBasicBlocks(BasicBlockA); 687 B.IRSC.getBasicBlocks(BasicBlockB); 688 689 // Determine if the block is contained in the region. 690 bool AContained = BasicBlockA.contains(ABB); 691 bool BContained = BasicBlockB.contains(BBB); 692 693 // Both blocks need to be contained in the region, or both need to be outside 694 // the reigon. 695 if (AContained != BContained) 696 return false; 697 698 // If both are contained, then we need to make sure that the relative 699 // distance to the target blocks are the same. 700 if (AContained) 701 return A.RelativeLocation == B.RelativeLocation; 702 return true; 703 } 704 705 bool IRSimilarityCandidate::compareStructure(const IRSimilarityCandidate &A, 706 const IRSimilarityCandidate &B) { 707 DenseMap<unsigned, DenseSet<unsigned>> MappingA; 708 DenseMap<unsigned, DenseSet<unsigned>> MappingB; 709 return IRSimilarityCandidate::compareStructure(A, B, MappingA, MappingB); 710 } 711 712 typedef detail::zippy<detail::zip_shortest, SmallVector<int, 4> &, 713 SmallVector<int, 4> &, ArrayRef<Value *> &, 714 ArrayRef<Value *> &> 715 ZippedRelativeLocationsT; 716 717 bool IRSimilarityCandidate::compareStructure( 718 const IRSimilarityCandidate &A, const IRSimilarityCandidate &B, 719 DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingA, 720 DenseMap<unsigned, DenseSet<unsigned>> &ValueNumberMappingB) { 721 if (A.getLength() != B.getLength()) 722 return false; 723 724 if (A.ValueToNumber.size() != B.ValueToNumber.size()) 725 return false; 726 727 iterator ItA = A.begin(); 728 iterator ItB = B.begin(); 729 730 // These ValueNumber Mapping sets create a create a mapping between the values 731 // in one candidate to values in the other candidate. If we create a set with 732 // one element, and that same element maps to the original element in the 733 // candidate we have a good mapping. 734 DenseMap<unsigned, DenseSet<unsigned>>::iterator ValueMappingIt; 735 736 737 // Iterate over the instructions contained in each candidate 738 unsigned SectionLength = A.getStartIdx() + A.getLength(); 739 for (unsigned Loc = A.getStartIdx(); Loc < SectionLength; 740 ItA++, ItB++, Loc++) { 741 // Make sure the instructions are similar to one another. 742 if (!isClose(*ItA, *ItB)) 743 return false; 744 745 Instruction *IA = ItA->Inst; 746 Instruction *IB = ItB->Inst; 747 748 if (!ItA->Legal || !ItB->Legal) 749 return false; 750 751 // Get the operand sets for the instructions. 752 ArrayRef<Value *> OperValsA = ItA->OperVals; 753 ArrayRef<Value *> OperValsB = ItB->OperVals; 754 755 unsigned InstValA = A.ValueToNumber.find(IA)->second; 756 unsigned InstValB = B.ValueToNumber.find(IB)->second; 757 758 bool WasInserted; 759 // Ensure that the mappings for the instructions exists. 760 std::tie(ValueMappingIt, WasInserted) = ValueNumberMappingA.insert( 761 std::make_pair(InstValA, DenseSet<unsigned>({InstValB}))); 762 if (!WasInserted && !ValueMappingIt->second.contains(InstValB)) 763 return false; 764 765 std::tie(ValueMappingIt, WasInserted) = ValueNumberMappingB.insert( 766 std::make_pair(InstValB, DenseSet<unsigned>({InstValA}))); 767 if (!WasInserted && !ValueMappingIt->second.contains(InstValA)) 768 return false; 769 770 // We have different paths for commutative instructions and non-commutative 771 // instructions since commutative instructions could allow multiple mappings 772 // to certain values. 773 if (IA->isCommutative() && !isa<FPMathOperator>(IA)) { 774 if (!compareCommutativeOperandMapping( 775 {A, OperValsA, ValueNumberMappingA}, 776 {B, OperValsB, ValueNumberMappingB})) 777 return false; 778 continue; 779 } 780 781 // Handle the non-commutative cases. 782 if (!compareNonCommutativeOperandMapping( 783 {A, OperValsA, ValueNumberMappingA}, 784 {B, OperValsB, ValueNumberMappingB})) 785 return false; 786 787 // Here we check that between two corresponding instructions, 788 // when referring to a basic block in the same region, the 789 // relative locations are the same. And, that the instructions refer to 790 // basic blocks outside the region in the same corresponding locations. 791 792 // We are able to make the assumption about blocks outside of the region 793 // since the target block labels are considered values and will follow the 794 // same number matching that we defined for the other instructions in the 795 // region. So, at this point, in each location we target a specific block 796 // outside the region, we are targeting a corresponding block in each 797 // analagous location in the region we are comparing to. 798 if (!(isa<BranchInst>(IA) && isa<BranchInst>(IB)) && 799 !(isa<PHINode>(IA) && isa<PHINode>(IB))) 800 continue; 801 802 SmallVector<int, 4> &RelBlockLocsA = ItA->RelativeBlockLocations; 803 SmallVector<int, 4> &RelBlockLocsB = ItB->RelativeBlockLocations; 804 if (RelBlockLocsA.size() != RelBlockLocsB.size() && 805 OperValsA.size() != OperValsB.size()) 806 return false; 807 808 ZippedRelativeLocationsT ZippedRelativeLocations = 809 zip(RelBlockLocsA, RelBlockLocsB, OperValsA, OperValsB); 810 if (any_of(ZippedRelativeLocations, 811 [&A, &B](std::tuple<int, int, Value *, Value *> R) { 812 return !checkRelativeLocations( 813 {A, std::get<0>(R), std::get<2>(R)}, 814 {B, std::get<1>(R), std::get<3>(R)}); 815 })) 816 return false; 817 } 818 return true; 819 } 820 821 bool IRSimilarityCandidate::overlap(const IRSimilarityCandidate &A, 822 const IRSimilarityCandidate &B) { 823 auto DoesOverlap = [](const IRSimilarityCandidate &X, 824 const IRSimilarityCandidate &Y) { 825 // Check: 826 // XXXXXX X starts before Y ends 827 // YYYYYYY Y starts after X starts 828 return X.StartIdx <= Y.getEndIdx() && Y.StartIdx >= X.StartIdx; 829 }; 830 831 return DoesOverlap(A, B) || DoesOverlap(B, A); 832 } 833 834 void IRSimilarityIdentifier::populateMapper( 835 Module &M, std::vector<IRInstructionData *> &InstrList, 836 std::vector<unsigned> &IntegerMapping) { 837 838 std::vector<IRInstructionData *> InstrListForModule; 839 std::vector<unsigned> IntegerMappingForModule; 840 // Iterate over the functions in the module to map each Instruction in each 841 // BasicBlock to an unsigned integer. 842 Mapper.initializeForBBs(M); 843 844 for (Function &F : M) { 845 846 if (F.empty()) 847 continue; 848 849 for (BasicBlock &BB : F) { 850 851 // BB has potential to have similarity since it has a size greater than 2 852 // and can therefore match other regions greater than 2. Map it to a list 853 // of unsigned integers. 854 Mapper.convertToUnsignedVec(BB, InstrListForModule, 855 IntegerMappingForModule); 856 } 857 858 BasicBlock::iterator It = F.begin()->end(); 859 Mapper.mapToIllegalUnsigned(It, IntegerMappingForModule, InstrListForModule, 860 true); 861 if (InstrListForModule.size() > 0) 862 Mapper.IDL->push_back(*InstrListForModule.back()); 863 } 864 865 // Insert the InstrListForModule at the end of the overall InstrList so that 866 // we can have a long InstrList for the entire set of Modules being analyzed. 867 llvm::append_range(InstrList, InstrListForModule); 868 // Do the same as above, but for IntegerMapping. 869 llvm::append_range(IntegerMapping, IntegerMappingForModule); 870 } 871 872 void IRSimilarityIdentifier::populateMapper( 873 ArrayRef<std::unique_ptr<Module>> &Modules, 874 std::vector<IRInstructionData *> &InstrList, 875 std::vector<unsigned> &IntegerMapping) { 876 877 // Iterate over, and map the instructions in each module. 878 for (const std::unique_ptr<Module> &M : Modules) 879 populateMapper(*M, InstrList, IntegerMapping); 880 } 881 882 /// From a repeated subsequence, find all the different instances of the 883 /// subsequence from the \p InstrList, and create an IRSimilarityCandidate from 884 /// the IRInstructionData in subsequence. 885 /// 886 /// \param [in] Mapper - The instruction mapper for basic correctness checks. 887 /// \param [in] InstrList - The vector that holds the instruction data. 888 /// \param [in] IntegerMapping - The vector that holds the mapped integers. 889 /// \param [out] CandsForRepSubstring - The vector to store the generated 890 /// IRSimilarityCandidates. 891 static void createCandidatesFromSuffixTree( 892 const IRInstructionMapper& Mapper, std::vector<IRInstructionData *> &InstrList, 893 std::vector<unsigned> &IntegerMapping, SuffixTree::RepeatedSubstring &RS, 894 std::vector<IRSimilarityCandidate> &CandsForRepSubstring) { 895 896 unsigned StringLen = RS.Length; 897 if (StringLen < 2) 898 return; 899 900 // Create an IRSimilarityCandidate for instance of this subsequence \p RS. 901 for (const unsigned &StartIdx : RS.StartIndices) { 902 unsigned EndIdx = StartIdx + StringLen - 1; 903 904 // Check that this subsequence does not contain an illegal instruction. 905 bool ContainsIllegal = false; 906 for (unsigned CurrIdx = StartIdx; CurrIdx <= EndIdx; CurrIdx++) { 907 unsigned Key = IntegerMapping[CurrIdx]; 908 if (Key > Mapper.IllegalInstrNumber) { 909 ContainsIllegal = true; 910 break; 911 } 912 } 913 914 // If we have an illegal instruction, we should not create an 915 // IRSimilarityCandidate for this region. 916 if (ContainsIllegal) 917 continue; 918 919 // We are getting iterators to the instructions in this region of code 920 // by advancing the start and end indices from the start of the 921 // InstrList. 922 std::vector<IRInstructionData *>::iterator StartIt = InstrList.begin(); 923 std::advance(StartIt, StartIdx); 924 std::vector<IRInstructionData *>::iterator EndIt = InstrList.begin(); 925 std::advance(EndIt, EndIdx); 926 927 CandsForRepSubstring.emplace_back(StartIdx, StringLen, *StartIt, *EndIt); 928 } 929 } 930 931 void IRSimilarityCandidate::createCanonicalRelationFrom( 932 IRSimilarityCandidate &SourceCand, 933 DenseMap<unsigned, DenseSet<unsigned>> &ToSourceMapping, 934 DenseMap<unsigned, DenseSet<unsigned>> &FromSourceMapping) { 935 assert(SourceCand.CanonNumToNumber.size() != 0 && 936 "Base canonical relationship is empty!"); 937 assert(SourceCand.NumberToCanonNum.size() != 0 && 938 "Base canonical relationship is empty!"); 939 940 assert(CanonNumToNumber.size() == 0 && "Canonical Relationship is non-empty"); 941 assert(NumberToCanonNum.size() == 0 && "Canonical Relationship is non-empty"); 942 943 DenseSet<unsigned> UsedGVNs; 944 // Iterate over the mappings provided from this candidate to SourceCand. We 945 // are then able to map the GVN in this candidate to the same canonical number 946 // given to the corresponding GVN in SourceCand. 947 for (std::pair<unsigned, DenseSet<unsigned>> &GVNMapping : ToSourceMapping) { 948 unsigned SourceGVN = GVNMapping.first; 949 950 assert(GVNMapping.second.size() != 0 && "Possible GVNs is 0!"); 951 952 unsigned ResultGVN; 953 // We need special handling if we have more than one potential value. This 954 // means that there are at least two GVNs that could correspond to this GVN. 955 // This could lead to potential swapping later on, so we make a decision 956 // here to ensure a one-to-one mapping. 957 if (GVNMapping.second.size() > 1) { 958 bool Found = false; 959 for (unsigned Val : GVNMapping.second) { 960 // We make sure the target value number hasn't already been reserved. 961 if (UsedGVNs.contains(Val)) 962 continue; 963 964 // We make sure that the opposite mapping is still consistent. 965 DenseMap<unsigned, DenseSet<unsigned>>::iterator It = 966 FromSourceMapping.find(Val); 967 968 if (!It->second.contains(SourceGVN)) 969 continue; 970 971 // We pick the first item that satisfies these conditions. 972 Found = true; 973 ResultGVN = Val; 974 break; 975 } 976 977 assert(Found && "Could not find matching value for source GVN"); 978 (void)Found; 979 980 } else 981 ResultGVN = *GVNMapping.second.begin(); 982 983 // Whatever GVN is found, we mark it as used. 984 UsedGVNs.insert(ResultGVN); 985 986 unsigned CanonNum = *SourceCand.getCanonicalNum(ResultGVN); 987 CanonNumToNumber.insert(std::make_pair(CanonNum, SourceGVN)); 988 NumberToCanonNum.insert(std::make_pair(SourceGVN, CanonNum)); 989 } 990 } 991 992 void IRSimilarityCandidate::createCanonicalMappingFor( 993 IRSimilarityCandidate &CurrCand) { 994 assert(CurrCand.CanonNumToNumber.size() == 0 && 995 "Canonical Relationship is non-empty"); 996 assert(CurrCand.NumberToCanonNum.size() == 0 && 997 "Canonical Relationship is non-empty"); 998 999 unsigned CanonNum = 0; 1000 // Iterate over the value numbers found, the order does not matter in this 1001 // case. 1002 for (std::pair<unsigned, Value *> &NumToVal : CurrCand.NumberToValue) { 1003 CurrCand.NumberToCanonNum.insert(std::make_pair(NumToVal.first, CanonNum)); 1004 CurrCand.CanonNumToNumber.insert(std::make_pair(CanonNum, NumToVal.first)); 1005 CanonNum++; 1006 } 1007 } 1008 1009 /// From the list of IRSimilarityCandidates, perform a comparison between each 1010 /// IRSimilarityCandidate to determine if there are overlapping 1011 /// IRInstructionData, or if they do not have the same structure. 1012 /// 1013 /// \param [in] CandsForRepSubstring - The vector containing the 1014 /// IRSimilarityCandidates. 1015 /// \param [out] StructuralGroups - the mapping of unsigned integers to vector 1016 /// of IRSimilarityCandidates where each of the IRSimilarityCandidates in the 1017 /// vector are structurally similar to one another. 1018 static void findCandidateStructures( 1019 std::vector<IRSimilarityCandidate> &CandsForRepSubstring, 1020 DenseMap<unsigned, SimilarityGroup> &StructuralGroups) { 1021 std::vector<IRSimilarityCandidate>::iterator CandIt, CandEndIt, InnerCandIt, 1022 InnerCandEndIt; 1023 1024 // IRSimilarityCandidates each have a structure for operand use. It is 1025 // possible that two instances of the same subsequences have different 1026 // structure. Each type of structure found is assigned a number. This 1027 // DenseMap maps an IRSimilarityCandidate to which type of similarity 1028 // discovered it fits within. 1029 DenseMap<IRSimilarityCandidate *, unsigned> CandToGroup; 1030 1031 // Find the compatibility from each candidate to the others to determine 1032 // which candidates overlap and which have the same structure by mapping 1033 // each structure to a different group. 1034 bool SameStructure; 1035 bool Inserted; 1036 unsigned CurrentGroupNum = 0; 1037 unsigned OuterGroupNum; 1038 DenseMap<IRSimilarityCandidate *, unsigned>::iterator CandToGroupIt; 1039 DenseMap<IRSimilarityCandidate *, unsigned>::iterator CandToGroupItInner; 1040 DenseMap<unsigned, SimilarityGroup>::iterator CurrentGroupPair; 1041 1042 // Iterate over the candidates to determine its structural and overlapping 1043 // compatibility with other instructions 1044 DenseMap<unsigned, DenseSet<unsigned>> ValueNumberMappingA; 1045 DenseMap<unsigned, DenseSet<unsigned>> ValueNumberMappingB; 1046 for (CandIt = CandsForRepSubstring.begin(), 1047 CandEndIt = CandsForRepSubstring.end(); 1048 CandIt != CandEndIt; CandIt++) { 1049 1050 // Determine if it has an assigned structural group already. 1051 CandToGroupIt = CandToGroup.find(&*CandIt); 1052 if (CandToGroupIt == CandToGroup.end()) { 1053 // If not, we assign it one, and add it to our mapping. 1054 std::tie(CandToGroupIt, Inserted) = 1055 CandToGroup.insert(std::make_pair(&*CandIt, CurrentGroupNum++)); 1056 } 1057 1058 // Get the structural group number from the iterator. 1059 OuterGroupNum = CandToGroupIt->second; 1060 1061 // Check if we already have a list of IRSimilarityCandidates for the current 1062 // structural group. Create one if one does not exist. 1063 CurrentGroupPair = StructuralGroups.find(OuterGroupNum); 1064 if (CurrentGroupPair == StructuralGroups.end()) { 1065 IRSimilarityCandidate::createCanonicalMappingFor(*CandIt); 1066 std::tie(CurrentGroupPair, Inserted) = StructuralGroups.insert( 1067 std::make_pair(OuterGroupNum, SimilarityGroup({*CandIt}))); 1068 } 1069 1070 // Iterate over the IRSimilarityCandidates following the current 1071 // IRSimilarityCandidate in the list to determine whether the two 1072 // IRSimilarityCandidates are compatible. This is so we do not repeat pairs 1073 // of IRSimilarityCandidates. 1074 for (InnerCandIt = std::next(CandIt), 1075 InnerCandEndIt = CandsForRepSubstring.end(); 1076 InnerCandIt != InnerCandEndIt; InnerCandIt++) { 1077 1078 // We check if the inner item has a group already, if it does, we skip it. 1079 CandToGroupItInner = CandToGroup.find(&*InnerCandIt); 1080 if (CandToGroupItInner != CandToGroup.end()) 1081 continue; 1082 1083 // Otherwise we determine if they have the same structure and add it to 1084 // vector if they match. 1085 ValueNumberMappingA.clear(); 1086 ValueNumberMappingB.clear(); 1087 SameStructure = IRSimilarityCandidate::compareStructure( 1088 *CandIt, *InnerCandIt, ValueNumberMappingA, ValueNumberMappingB); 1089 if (!SameStructure) 1090 continue; 1091 1092 InnerCandIt->createCanonicalRelationFrom(*CandIt, ValueNumberMappingA, 1093 ValueNumberMappingB); 1094 CandToGroup.insert(std::make_pair(&*InnerCandIt, OuterGroupNum)); 1095 CurrentGroupPair->second.push_back(*InnerCandIt); 1096 } 1097 } 1098 } 1099 1100 void IRSimilarityIdentifier::findCandidates( 1101 std::vector<IRInstructionData *> &InstrList, 1102 std::vector<unsigned> &IntegerMapping) { 1103 SuffixTree ST(IntegerMapping); 1104 1105 std::vector<IRSimilarityCandidate> CandsForRepSubstring; 1106 std::vector<SimilarityGroup> NewCandidateGroups; 1107 1108 DenseMap<unsigned, SimilarityGroup> StructuralGroups; 1109 1110 // Iterate over the subsequences found by the Suffix Tree to create 1111 // IRSimilarityCandidates for each repeated subsequence and determine which 1112 // instances are structurally similar to one another. 1113 for (SuffixTree::RepeatedSubstring &RS : ST) { 1114 createCandidatesFromSuffixTree(Mapper, InstrList, IntegerMapping, RS, 1115 CandsForRepSubstring); 1116 1117 if (CandsForRepSubstring.size() < 2) 1118 continue; 1119 1120 findCandidateStructures(CandsForRepSubstring, StructuralGroups); 1121 for (std::pair<unsigned, SimilarityGroup> &Group : StructuralGroups) 1122 // We only add the group if it contains more than one 1123 // IRSimilarityCandidate. If there is only one, that means there is no 1124 // other repeated subsequence with the same structure. 1125 if (Group.second.size() > 1) 1126 SimilarityCandidates->push_back(Group.second); 1127 1128 CandsForRepSubstring.clear(); 1129 StructuralGroups.clear(); 1130 NewCandidateGroups.clear(); 1131 } 1132 } 1133 1134 SimilarityGroupList &IRSimilarityIdentifier::findSimilarity( 1135 ArrayRef<std::unique_ptr<Module>> Modules) { 1136 resetSimilarityCandidates(); 1137 1138 std::vector<IRInstructionData *> InstrList; 1139 std::vector<unsigned> IntegerMapping; 1140 Mapper.InstClassifier.EnableBranches = this->EnableBranches; 1141 Mapper.InstClassifier.EnableIndirectCalls = EnableIndirectCalls; 1142 Mapper.EnableMatchCallsByName = EnableMatchingCallsByName; 1143 1144 populateMapper(Modules, InstrList, IntegerMapping); 1145 findCandidates(InstrList, IntegerMapping); 1146 1147 return SimilarityCandidates.getValue(); 1148 } 1149 1150 SimilarityGroupList &IRSimilarityIdentifier::findSimilarity(Module &M) { 1151 resetSimilarityCandidates(); 1152 Mapper.InstClassifier.EnableBranches = this->EnableBranches; 1153 Mapper.InstClassifier.EnableIndirectCalls = EnableIndirectCalls; 1154 Mapper.EnableMatchCallsByName = EnableMatchingCallsByName; 1155 1156 std::vector<IRInstructionData *> InstrList; 1157 std::vector<unsigned> IntegerMapping; 1158 1159 populateMapper(M, InstrList, IntegerMapping); 1160 findCandidates(InstrList, IntegerMapping); 1161 1162 return SimilarityCandidates.getValue(); 1163 } 1164 1165 INITIALIZE_PASS(IRSimilarityIdentifierWrapperPass, "ir-similarity-identifier", 1166 "ir-similarity-identifier", false, true) 1167 1168 IRSimilarityIdentifierWrapperPass::IRSimilarityIdentifierWrapperPass() 1169 : ModulePass(ID) { 1170 initializeIRSimilarityIdentifierWrapperPassPass( 1171 *PassRegistry::getPassRegistry()); 1172 } 1173 1174 bool IRSimilarityIdentifierWrapperPass::doInitialization(Module &M) { 1175 IRSI.reset(new IRSimilarityIdentifier(!DisableBranches, !DisableIndirectCalls, 1176 MatchCallsByName)); 1177 return false; 1178 } 1179 1180 bool IRSimilarityIdentifierWrapperPass::doFinalization(Module &M) { 1181 IRSI.reset(); 1182 return false; 1183 } 1184 1185 bool IRSimilarityIdentifierWrapperPass::runOnModule(Module &M) { 1186 IRSI->findSimilarity(M); 1187 return false; 1188 } 1189 1190 AnalysisKey IRSimilarityAnalysis::Key; 1191 IRSimilarityIdentifier IRSimilarityAnalysis::run(Module &M, 1192 ModuleAnalysisManager &) { 1193 1194 auto IRSI = IRSimilarityIdentifier(!DisableBranches, !DisableIndirectCalls, 1195 MatchCallsByName); 1196 IRSI.findSimilarity(M); 1197 return IRSI; 1198 } 1199 1200 PreservedAnalyses 1201 IRSimilarityAnalysisPrinterPass::run(Module &M, ModuleAnalysisManager &AM) { 1202 IRSimilarityIdentifier &IRSI = AM.getResult<IRSimilarityAnalysis>(M); 1203 Optional<SimilarityGroupList> &SimilarityCandidatesOpt = IRSI.getSimilarity(); 1204 1205 for (std::vector<IRSimilarityCandidate> &CandVec : *SimilarityCandidatesOpt) { 1206 OS << CandVec.size() << " candidates of length " 1207 << CandVec.begin()->getLength() << ". Found in: \n"; 1208 for (IRSimilarityCandidate &Cand : CandVec) { 1209 OS << " Function: " << Cand.front()->Inst->getFunction()->getName().str() 1210 << ", Basic Block: "; 1211 if (Cand.front()->Inst->getParent()->getName().str() == "") 1212 OS << "(unnamed)"; 1213 else 1214 OS << Cand.front()->Inst->getParent()->getName().str(); 1215 OS << "\n Start Instruction: "; 1216 Cand.frontInstruction()->print(OS); 1217 OS << "\n End Instruction: "; 1218 Cand.backInstruction()->print(OS); 1219 OS << "\n"; 1220 } 1221 } 1222 1223 return PreservedAnalyses::all(); 1224 } 1225 1226 char IRSimilarityIdentifierWrapperPass::ID = 0; 1227