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