diff --git a/llvm/include/llvm/Analysis/IRSimilarityIdentifier.h b/llvm/include/llvm/Analysis/IRSimilarityIdentifier.h --- a/llvm/include/llvm/Analysis/IRSimilarityIdentifier.h +++ b/llvm/include/llvm/Analysis/IRSimilarityIdentifier.h @@ -226,6 +226,11 @@ void setPHIPredecessors(DenseMap &BasicBlockToInteger); + /// Get the BasicBlock based operands for PHINodes and BranchInsts. + /// + /// \returns A list of relevant BasicBlocks. + ArrayRef getBlockOperVals(); + /// Hashes \p Value based on its opcode, types, and operand types. /// Two IRInstructionData instances produce the same hash when they perform /// the same operation. diff --git a/llvm/lib/Analysis/IRSimilarityIdentifier.cpp b/llvm/lib/Analysis/IRSimilarityIdentifier.cpp --- a/llvm/lib/Analysis/IRSimilarityIdentifier.cpp +++ b/llvm/lib/Analysis/IRSimilarityIdentifier.cpp @@ -14,6 +14,7 @@ #include "llvm/Analysis/IRSimilarityIdentifier.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetOperations.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Operator.h" #include "llvm/IR/User.h" @@ -97,7 +98,8 @@ int CurrentBlockNumber = static_cast(BBNumIt->second); - for (BasicBlock *Successor : BI->successors()) { + for (Value *V : getBlockOperVals()) { + BasicBlock *Successor = cast(V); BBNumIt = BasicBlockToInteger.find(Successor); assert(BBNumIt != BasicBlockToInteger.end() && "Could not find number for BasicBlock!"); @@ -108,6 +110,25 @@ } } +ArrayRef IRInstructionData::getBlockOperVals() { + assert((isa(Inst) || + isa(Inst)) && "Instruction must be branch or PHINode"); + + if (BranchInst *BI = dyn_cast(Inst)) + return ArrayRef( + std::next(OperVals.begin(), BI->isConditional() ? 1 : 0), + OperVals.end() + ); + + if (PHINode *PN = dyn_cast(Inst)) + return ArrayRef( + std::next(OperVals.begin(), PN->getNumIncomingValues()), + OperVals.end() + ); + + return ArrayRef(); +} + void IRInstructionData::setCalleeName(bool MatchByName) { CallInst *CI = dyn_cast(Inst); assert(CI && "Instruction must be call"); @@ -159,7 +180,6 @@ int Relative = OtherBlockNumber - CurrentBlockNumber; RelativeBlockLocations.push_back(Relative); - RelativeBlockLocations.push_back(Relative); } } @@ -701,8 +721,8 @@ bool IRSimilarityCandidate::checkRelativeLocations(RelativeLocMapping A, RelativeLocMapping B) { // Get the basic blocks the label refers to. - BasicBlock *ABB = static_cast(A.OperVal); - BasicBlock *BBB = static_cast(B.OperVal); + BasicBlock *ABB = cast(A.OperVal); + BasicBlock *BBB = cast(B.OperVal); // Get the basic blocks contained in each region. DenseSet BasicBlockA; @@ -715,7 +735,7 @@ bool BContained = BasicBlockB.contains(BBB); // Both blocks need to be contained in the region, or both need to be outside - // the reigon. + // the region. if (AContained != BContained) return false; @@ -826,12 +846,22 @@ SmallVector &RelBlockLocsA = ItA->RelativeBlockLocations; SmallVector &RelBlockLocsB = ItB->RelativeBlockLocations; + ArrayRef ABL = ItA->getBlockOperVals(); + ArrayRef BBL = ItB->getBlockOperVals(); + + // Check to make sure that the number of operands, and branching locations + // between BranchInsts is the same. if (RelBlockLocsA.size() != RelBlockLocsB.size() && - OperValsA.size() != OperValsB.size()) + ABL.size() != BBL.size()) return false; + assert(RelBlockLocsA.size() == ABL.size() && + "Block information vectors not the same size."); + assert(RelBlockLocsB.size() == BBL.size() && + "Block information vectors not the same size."); + ZippedRelativeLocationsT ZippedRelativeLocations = - zip(RelBlockLocsA, RelBlockLocsB, OperValsA, OperValsB); + zip(RelBlockLocsA, RelBlockLocsB, ABL, BBL); if (any_of(ZippedRelativeLocations, [&A, &B](std::tuple R) { return !checkRelativeLocations(