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