31 cl::desc(
"disable similarity matching, and outlining, "
32 "across branches for debugging purposes."));
37 cl::desc(
"disable outlining indirect calls."));
41 cl::desc(
"only allow matching call instructions if the "
42 "name and type signature match."));
46 cl::desc(
"Don't match or outline intrinsics"));
61 if (Predicate !=
C->getPredicate())
67 for (
Use &OI :
Inst->operands()) {
93 BBNumIt = BasicBlockToInteger.
find(
Inst->getParent());
94 assert(BBNumIt != BasicBlockToInteger.
end() &&
95 "Could not find location for BasicBlock!");
97 int CurrentBlockNumber =
static_cast<int>(BBNumIt->second);
102 assert(BBNumIt != BasicBlockToInteger.
end() &&
103 "Could not find number for BasicBlock!");
104 int OtherBlockNumber =
static_cast<int>(BBNumIt->second);
106 int Relative = OtherBlockNumber - CurrentBlockNumber;
119 std::next(
OperVals.begin(), PN->getNumIncomingValues()),
128 assert(CI &&
"Instruction must be call");
161 assert(BBNumIt != BasicBlockToInteger.
end() &&
162 "Could not find location for BasicBlock!");
164 int CurrentBlockNumber =
static_cast<int>(BBNumIt->second);
170 BBNumIt = BasicBlockToInteger.
find(Incoming);
171 assert(BBNumIt != BasicBlockToInteger.
end() &&
172 "Could not find number for BasicBlock!");
173 int OtherBlockNumber =
static_cast<int>(BBNumIt->second);
175 int Relative = OtherBlockNumber - CurrentBlockNumber;
198 "Can only get a predicate from a compare instruction");
208 "Can only get a name from a call instruction");
218 if (!
A.Legal || !
B.Legal)
223 if (!
A.Inst->isSameOperationAs(
B.Inst)) {
229 if (
A.getPredicate() !=
B.getPredicate())
234 auto ZippedTypes =
zip(
A.OperVals,
B.OperVals);
237 ZippedTypes, [](std::tuple<llvm::Value *, llvm::Value *> R) {
238 return std::get<0>(R)->getType() == std::get<1>(R)->getType();
253 if (
GEP->isInBounds() != OtherGEP->isInBounds())
256 auto ZippedOperands =
zip(
GEP->indices(), OtherGEP->indices());
262 [](std::tuple<llvm::Use &, llvm::Use &> R) {
263 return std::get<0>(R) == std::get<1>(R);
271 if (
A.getCalleeName() !=
B.getCalleeName())
277 A.RelativeBlockLocations.size() !=
B.RelativeBlockLocations.size())
286 BasicBlock &BB, std::vector<IRInstructionData *> &InstrList,
287 std::vector<unsigned> &IntegerMapping) {
290 std::vector<unsigned> IntegerMappingForBB;
291 std::vector<IRInstructionData *> InstrListForBB;
310 this->
IDL->push_back(*
ID);
319 std::vector<IRInstructionData *> &InstrListForBB) {
333 InstrListForBB.push_back(
ID);
348 std::tie(ResultIt, WasInserted) =
350 unsigned INumber = ResultIt->second;
356 IntegerMappingForBB.push_back(INumber);
360 "Instruction mapping overflow!");
385 std::vector<IRInstructionData *> &InstrListForBB,
bool End) {
398 InstrListForBB.push_back(
ID);
406 "Instruction mapping overflow!");
414 : StartIdx(StartIdx), Len(Len) {
416 assert(FirstInstIt !=
nullptr &&
"Instruction is nullptr!");
417 assert(LastInstIt !=
nullptr &&
"Instruction is nullptr!");
418 assert(StartIdx + Len > StartIdx &&
419 "Overflow for IRSimilarityCandidate range?");
420 assert(Len - 1 ==
static_cast<unsigned>(std::distance(
422 "Length of the first and last IRInstructionData do not match the "
440 unsigned LocalValNumber = 1;
442 for (
unsigned Loc = StartIdx;
Loc < StartIdx + Len;
Loc++,
ID++) {
445 for (
Value *Arg :
ID->OperVals)
446 if (ValueToNumber.try_emplace(Arg, LocalValNumber).second) {
447 NumberToValue.try_emplace(LocalValNumber, Arg);
453 if (ValueToNumber.try_emplace(
ID->Inst, LocalValNumber).second) {
454 NumberToValue.try_emplace(LocalValNumber,
ID->Inst);
462 FirstInst = FirstInstIt;
463 LastInst = LastInstIt;
469 if (ValueToNumber.try_emplace(BB, LocalValNumber).second) {
470 NumberToValue.try_emplace(LocalValNumber, BB);
478 if (
A.getLength() !=
B.getLength())
481 auto InstrDataForBoth =
484 return all_of(InstrDataForBoth,
485 [](std::tuple<IRInstructionData &, IRInstructionData &> R) {
488 if (!
A.Legal || !
B.Legal)
526 for (
Value *V : SourceOperands) {
527 ArgVal = SourceValueToNumberMapping.
find(V)->second;
530 std::tie(ValueMappingIt, WasInserted) = CurrentSrcTgtNumberMapping.insert(
531 std::make_pair(ArgVal, TargetValueNumbers));
537 for (
unsigned &Curr : ValueMappingIt->second)
539 if (TargetValueNumbers.
contains(Curr))
547 if (NewSet.
size() != ValueMappingIt->second.
size())
548 ValueMappingIt->second.
swap(NewSet);
552 if (ValueMappingIt->second.
size() != 1)
555 unsigned ValToRemove = *ValueMappingIt->second.
begin();
559 for (
Value *InnerV : SourceOperands) {
563 unsigned InnerVal = SourceValueToNumberMapping.
find(InnerV)->second;
564 ValueMappingIt = CurrentSrcTgtNumberMapping.
find(InnerVal);
565 if (ValueMappingIt == CurrentSrcTgtNumberMapping.
end())
568 ValueMappingIt->second.
erase(ValToRemove);
569 if (ValueMappingIt->second.
empty())
590 unsigned SourceArgVal,
unsigned TargetArgVal) {
609 std::tie(Val, WasInserted) = CurrentSrcTgtNumberMapping.insert(
622 if (TargetSet.
size() > 1 && TargetSet.
contains(TargetArgVal)) {
624 TargetSet.
insert(TargetArgVal);
629 return TargetSet.
contains(TargetArgVal);
638 unsigned OperandLength =
A.OperVals.size();
641 for (
unsigned Idx = 0; Idx < OperandLength; Idx++, VItA++, VItB++) {
642 unsigned OperValA =
A.IRSC.ValueToNumber.find(*VItA)->second;
643 unsigned OperValB =
B.IRSC.ValueToNumber.find(*VItB)->second;
673 unsigned OperandLength =
A.OperVals.size();
676 for (
unsigned Idx = 0; Idx < OperandLength;
677 Idx++, VItA++, VItB++) {
678 ValueNumbersA.
insert(
A.IRSC.ValueToNumber.find(*VItA)->second);
679 ValueNumbersB.
insert(
B.IRSC.ValueToNumber.find(*VItB)->second);
686 A.ValueNumberMapping,
A.OperVals,
694 B.ValueNumberMapping,
B.OperVals,
702 const unsigned InstValA,
const unsigned &InstValB,
707 std::tie(ValueMappingIt, WasInserted) = ValueNumberMappingA.insert(
709 if (!WasInserted && !ValueMappingIt->second.
contains(InstValB))
711 else if (ValueMappingIt->second.
size() != 1) {
716 ValueMappingIt->second.
end());
717 for (
unsigned OtherVal : OtherVals) {
718 if (OtherVal == InstValB)
720 auto OtherValIt = ValueNumberMappingA.find(OtherVal);
721 if (OtherValIt == ValueNumberMappingA.end())
723 OtherValIt->second.erase(InstValA);
725 ValueNumberMappingA.erase(ValueMappingIt);
726 std::tie(ValueMappingIt, WasInserted) = ValueNumberMappingA.insert(
742 A.IRSC.getBasicBlocks(BasicBlockA);
743 B.IRSC.getBasicBlocks(BasicBlockB);
746 bool AContained = BasicBlockA.
contains(ABB);
747 bool BContained = BasicBlockB.
contains(BBB);
751 if (AContained != BContained)
757 return A.RelativeLocation ==
B.RelativeLocation;
777 if (
A.getLength() !=
B.getLength())
780 if (
A.ValueToNumber.size() !=
B.ValueToNumber.size())
792 unsigned SectionLength =
A.getStartIdx() +
A.getLength();
793 for (
unsigned Loc =
A.getStartIdx();
Loc < SectionLength;
794 ItA++, ItB++,
Loc++) {
802 if (!ItA->Legal || !ItB->Legal)
809 unsigned InstValA =
A.ValueToNumber.find(IA)->second;
810 unsigned InstValB =
B.ValueToNumber.find(IB)->second;
814 ValueNumberMappingB))
818 ValueNumberMappingA))
827 {
A, OperValsA, ValueNumberMappingA},
828 {
B, OperValsB, ValueNumberMappingB}))
835 {
A, OperValsA, ValueNumberMappingA},
836 {
B, OperValsB, ValueNumberMappingB}))
851 IA->getOpcode() != IB->getOpcode())
861 if (RelBlockLocsA.
size() != RelBlockLocsB.
size() &&
866 "Block information vectors not the same size.");
868 "Block information vectors not the same size.");
871 zip(RelBlockLocsA, RelBlockLocsB, ABL, BBL);
872 if (
any_of(ZippedRelativeLocations,
873 [&
A, &
B](std::tuple<int, int, Value *, Value *> R) {
875 {
A, std::get<0>(R), std::get<2>(R)},
876 {
B, std::get<1>(R), std::get<3>(R)});
890 return X.StartIdx <=
Y.getEndIdx() &&
Y.StartIdx >=
X.StartIdx;
893 return DoesOverlap(
A,
B) || DoesOverlap(
B,
A);
896void IRSimilarityIdentifier::populateMapper(
897 Module &M, std::vector<IRInstructionData *> &InstrList,
898 std::vector<unsigned> &IntegerMapping) {
900 std::vector<IRInstructionData *> InstrListForModule;
901 std::vector<unsigned> IntegerMappingForModule;
904 Mapper.initializeForBBs(M);
916 Mapper.convertToUnsignedVec(BB, InstrListForModule,
917 IntegerMappingForModule);
921 Mapper.mapToIllegalUnsigned(It, IntegerMappingForModule, InstrListForModule,
923 if (InstrListForModule.size() > 0)
924 Mapper.IDL->push_back(*InstrListForModule.back());
934void IRSimilarityIdentifier::populateMapper(
935 ArrayRef<std::unique_ptr<Module>> &Modules,
936 std::vector<IRInstructionData *> &InstrList,
937 std::vector<unsigned> &IntegerMapping) {
940 for (
const std::unique_ptr<Module> &M : Modules)
941 populateMapper(*M, InstrList, IntegerMapping);
956 std::vector<IRSimilarityCandidate> &CandsForRepSubstring) {
958 unsigned StringLen = RS.Length;
963 for (
const unsigned &StartIdx : RS.StartIndices) {
964 unsigned EndIdx = StartIdx + StringLen - 1;
967 bool ContainsIllegal =
false;
968 for (
unsigned CurrIdx = StartIdx; CurrIdx <= EndIdx; CurrIdx++) {
969 unsigned Key = IntegerMapping[CurrIdx];
970 if (
Key > Mapper.IllegalInstrNumber) {
971 ContainsIllegal =
true;
984 std::vector<IRInstructionData *>::iterator StartIt = InstrList.
begin();
985 std::advance(StartIt, StartIdx);
986 std::vector<IRInstructionData *>::iterator EndIt = InstrList.
begin();
987 std::advance(EndIt, EndIdx);
989 CandsForRepSubstring.emplace_back(StartIdx, StringLen, *StartIt, *EndIt);
997 assert(SourceCand.CanonNumToNumber.
size() != 0 &&
998 "Base canonical relationship is empty!");
999 assert(SourceCand.NumberToCanonNum.
size() != 0 &&
1000 "Base canonical relationship is empty!");
1002 assert(CanonNumToNumber.size() == 0 &&
"Canonical Relationship is non-empty");
1003 assert(NumberToCanonNum.size() == 0 &&
"Canonical Relationship is non-empty");
1010 unsigned SourceGVN = GVNMapping.first;
1012 assert(GVNMapping.second.size() != 0 &&
"Possible GVNs is 0!");
1019 if (GVNMapping.second.size() > 1) {
1021 for (
unsigned Val : GVNMapping.second) {
1028 FromSourceMapping.find(Val);
1030 if (!It->second.
contains(SourceGVN))
1039 assert(Found &&
"Could not find matching value for source GVN");
1043 ResultGVN = *GVNMapping.second.begin();
1046 UsedGVNs.
insert(ResultGVN);
1049 CanonNumToNumber.insert(std::make_pair(CanonNum, SourceGVN));
1050 NumberToCanonNum.insert(std::make_pair(SourceGVN, CanonNum));
1062 unsigned BBGVNForCurrCand = ValueToNumber.find(BB)->second;
1066 if (NumberToCanonNum.contains(BBGVNForCurrCand))
1072 Value *FirstOutlineInst =
1075 unsigned FirstInstGVN = *
getGVN(FirstOutlineInst);
1080 unsigned SourceBBGVN = *SourceCand.
getGVN(SourceBB);
1082 CanonNumToNumber.insert(std::make_pair(SourceCanonBBGVN, BBGVNForCurrCand));
1083 NumberToCanonNum.insert(std::make_pair(BBGVNForCurrCand, SourceCanonBBGVN));
1091 "Canonical Relationship is non-empty");
1093 "Canonical Relationship is non-empty");
1095 assert(!SourceCandLarge.CanonNumToNumber.
empty() &&
1096 "Canonical Relationship is non-empty");
1097 assert(!SourceCandLarge.NumberToCanonNum.
empty() &&
1098 "Canonical Relationship is non-empty");
1100 assert(!TargetCandLarge.CanonNumToNumber.
empty() &&
1101 "Canonical Relationship is non-empty");
1102 assert(!TargetCandLarge.NumberToCanonNum.
empty() &&
1103 "Canonical Relationship is non-empty");
1105 assert(CanonNumToNumber.empty() &&
"Canonical Relationship is non-empty");
1106 assert(NumberToCanonNum.empty() &&
"Canonical Relationship is non-empty");
1112 for (std::pair<Value *, unsigned> &ValueNumPair : ValueToNumber) {
1113 Value *CurrVal = ValueNumPair.first;
1114 unsigned TargetCandGVN = ValueNumPair.second;
1118 std::optional<unsigned> OLargeTargetGVN = TargetCandLarge.
getGVN(CurrVal);
1119 assert(OLargeTargetGVN.has_value() &&
"GVN not found for Value");
1122 std::optional<unsigned> OTargetCandCanon =
1124 assert(OTargetCandCanon.has_value() &&
1125 "Canononical Number not found for GVN");
1128 std::optional<unsigned> OLargeSourceGVN =
1130 assert(OLargeSourceGVN.has_value() &&
1131 "GVN Number not found for Canonical Number");
1134 std::optional<Value *> OLargeSourceV =
1135 SourceCandLarge.
fromGVN(OLargeSourceGVN.value());
1136 assert(OLargeSourceV.has_value() &&
"Value not found for GVN");
1139 std::optional<unsigned> OSourceGVN =
1140 SourceCand.
getGVN(OLargeSourceV.value());
1141 assert(OSourceGVN.has_value() &&
"GVN Number not found for Value");
1144 std::optional<unsigned> OSourceCanon =
1146 assert(OSourceCanon.has_value() &&
"Canon Number not found for GVN");
1150 CanonNumToNumber.insert(
1151 std::make_pair(OSourceCanon.value(), TargetCandGVN));
1152 NumberToCanonNum.insert(
1153 std::make_pair(TargetCandGVN, OSourceCanon.value()));
1159 assert(CurrCand.CanonNumToNumber.
size() == 0 &&
1160 "Canonical Relationship is non-empty");
1161 assert(CurrCand.NumberToCanonNum.
size() == 0 &&
1162 "Canonical Relationship is non-empty");
1164 unsigned CanonNum = 0;
1167 for (std::pair<unsigned, Value *> &NumToVal : CurrCand.NumberToValue) {
1168 CurrCand.NumberToCanonNum.
insert(std::make_pair(NumToVal.first, CanonNum));
1169 CurrCand.CanonNumToNumber.
insert(std::make_pair(CanonNum, NumToVal.first));
1187static std::optional<
1188 std::pair<IRSimilarityCandidate *, IRSimilarityCandidate *>>
1200 auto IdxToCandidateIt = IndexToIncludedCand.
find(CandA.
getStartIdx());
1201 std::optional<std::pair<IRSimilarityCandidate *, IRSimilarityCandidate *>>
1208 if (IdxToCandidateIt == IndexToIncludedCand.end())
1214 unsigned GroupNum = CandToGroup.
find(MatchedCand)->second;
1215 IncludedGroupAndCandA.
insert(std::make_pair(GroupNum, MatchedCand));
1216 IncludedGroupsA.
insert(GroupNum);
1221 IdxToCandidateIt = IndexToIncludedCand.find(CandBStart);
1222 if (IdxToCandidateIt == IndexToIncludedCand.end())
1228 unsigned GroupNum = CandToGroup.
find(MatchedCand)->second;
1229 IncludedGroupAndCandB.
insert(std::make_pair(GroupNum, MatchedCand));
1230 IncludedGroupsB.
insert(GroupNum);
1239 if (IncludedGroupsA.
empty())
1243 auto ItA = IncludedGroupAndCandA.
find(*IncludedGroupsA.
begin());
1244 auto ItB = IncludedGroupAndCandB.
find(*IncludedGroupsA.
begin());
1245 Result = std::make_pair(ItA->second, ItB->second);
1263 std::vector<IRSimilarityCandidate> &CandsForRepSubstring,
1268 std::vector<IRSimilarityCandidate>::iterator CandIt, CandEndIt, InnerCandIt,
1283 unsigned CurrentGroupNum = 0;
1284 unsigned OuterGroupNum;
1293 for (CandIt = CandsForRepSubstring.begin(),
1294 CandEndIt = CandsForRepSubstring.end();
1295 CandIt != CandEndIt; CandIt++) {
1299 std::tie(CandToGroupIt, Inserted) =
1300 CandToGroup.
try_emplace(&*CandIt, CurrentGroupNum);
1305 OuterGroupNum = CandToGroupIt->second;
1309 CurrentGroupPair = StructuralGroups.
find(OuterGroupNum);
1310 if (CurrentGroupPair == StructuralGroups.
end()) {
1312 std::tie(CurrentGroupPair, Inserted) = StructuralGroups.
insert(
1320 for (InnerCandIt = std::next(CandIt),
1321 InnerCandEndIt = CandsForRepSubstring.end();
1322 InnerCandIt != InnerCandEndIt; InnerCandIt++) {
1325 CandToGroupItInner = CandToGroup.
find(&*InnerCandIt);
1326 if (CandToGroupItInner != CandToGroup.
end())
1331 std::optional<std::pair<IRSimilarityCandidate *, IRSimilarityCandidate *>>
1333 *CandIt, *InnerCandIt, IndexToIncludedCand, CandToOverallGroup);
1338 if (LargerPair.has_value()) {
1339 SameStructure =
true;
1340 InnerCandIt->createCanonicalRelationFrom(
1341 *CandIt, *LargerPair.value().first, *LargerPair.value().second);
1342 CandToGroup.
insert(std::make_pair(&*InnerCandIt, OuterGroupNum));
1343 CurrentGroupPair->second.push_back(*InnerCandIt);
1349 ValueNumberMappingA.
clear();
1350 ValueNumberMappingB.
clear();
1352 *CandIt, *InnerCandIt, ValueNumberMappingA, ValueNumberMappingB);
1356 InnerCandIt->createCanonicalRelationFrom(*CandIt, ValueNumberMappingA,
1357 ValueNumberMappingB);
1358 CandToGroup.
insert(std::make_pair(&*InnerCandIt, OuterGroupNum));
1359 CurrentGroupPair->second.push_back(*InnerCandIt);
1364void IRSimilarityIdentifier::findCandidates(
1365 std::vector<IRInstructionData *> &InstrList,
1366 std::vector<unsigned> &IntegerMapping) {
1367 SuffixTree
ST(IntegerMapping);
1369 std::vector<IRSimilarityCandidate> CandsForRepSubstring;
1370 std::vector<SimilarityGroup> NewCandidateGroups;
1372 DenseMap<unsigned, SimilarityGroup> StructuralGroups;
1373 DenseMap<unsigned, DenseSet<IRSimilarityCandidate *>> IndexToIncludedCand;
1374 DenseMap<IRSimilarityCandidate *, unsigned> CandToGroup;
1381 std::vector<SuffixTree::RepeatedSubstring> RSes;
1382 for (SuffixTree::RepeatedSubstring &RS : ST)
1386 const SuffixTree::RepeatedSubstring &
RHS) {
1387 return LHS.Length >
RHS.Length;
1389 for (SuffixTree::RepeatedSubstring &RS : RSes) {
1391 CandsForRepSubstring);
1393 if (CandsForRepSubstring.size() < 2)
1397 IndexToIncludedCand, CandToGroup);
1398 for (std::pair<unsigned, SimilarityGroup> &Group : StructuralGroups) {
1402 if (Group.second.size() > 1) {
1403 SimilarityCandidates->push_back(Group.second);
1407 for (IRSimilarityCandidate &IRCand : SimilarityCandidates->back()) {
1408 for (
unsigned Idx = IRCand.getStartIdx(), Edx = IRCand.getEndIdx();
1410 IndexToIncludedCand[Idx].
insert(&IRCand);
1413 std::make_pair(&IRCand, SimilarityCandidates->size() - 1));
1418 CandsForRepSubstring.clear();
1419 StructuralGroups.clear();
1420 NewCandidateGroups.clear();
1425 ArrayRef<std::unique_ptr<Module>> Modules) {
1428 std::vector<IRInstructionData *> InstrList;
1429 std::vector<unsigned> IntegerMapping;
1430 Mapper.InstClassifier.EnableBranches = this->EnableBranches;
1431 Mapper.InstClassifier.EnableIndirectCalls = EnableIndirectCalls;
1432 Mapper.EnableMatchCallsByName = EnableMatchingCallsByName;
1433 Mapper.InstClassifier.EnableIntrinsics = EnableIntrinsics;
1434 Mapper.InstClassifier.EnableMustTailCalls = EnableMustTailCalls;
1436 populateMapper(Modules, InstrList, IntegerMapping);
1437 findCandidates(InstrList, IntegerMapping);
1439 return *SimilarityCandidates;
1444 Mapper.InstClassifier.EnableBranches = this->EnableBranches;
1445 Mapper.InstClassifier.EnableIndirectCalls = EnableIndirectCalls;
1446 Mapper.EnableMatchCallsByName = EnableMatchingCallsByName;
1447 Mapper.InstClassifier.EnableIntrinsics = EnableIntrinsics;
1448 Mapper.InstClassifier.EnableMustTailCalls = EnableMustTailCalls;
1450 std::vector<IRInstructionData *> InstrList;
1451 std::vector<unsigned> IntegerMapping;
1453 populateMapper(M, InstrList, IntegerMapping);
1454 findCandidates(InstrList, IntegerMapping);
1456 return *SimilarityCandidates;
1460 "ir-similarity-identifier",
false,
true)
1478 IRSI->findSimilarity(M);
1488 IRSI.findSimilarity(M);
1495 std::optional<SimilarityGroupList> &SimilarityCandidatesOpt =
1498 for (std::vector<IRSimilarityCandidate> &CandVec : *SimilarityCandidatesOpt) {
1499 OS << CandVec.size() <<
" candidates of length "
1500 << CandVec.begin()->getLength() <<
". Found in: \n";
1502 OS <<
" Function: " << Cand.front()->Inst->getFunction()->getName().str()
1503 <<
", Basic Block: ";
1504 if (Cand.front()->Inst->getParent()->getName().str() ==
"")
1507 OS << Cand.front()->Inst->getParent()->getName().str();
1508 OS <<
"\n Start Instruction: ";
1509 Cand.frontInstruction()->print(OS);
1510 OS <<
"\n End Instruction: ";
1511 Cand.backInstruction()->print(OS);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
bool checkNumberingAndReplace(DenseMap< unsigned, DenseSet< unsigned > > &CurrentSrcTgtNumberMapping, unsigned SourceArgVal, unsigned TargetArgVal)
Determine if operand number TargetArgVal is in the current mapping set for operand number SourceArgVa...
detail::zippy< detail::zip_shortest, SmallVector< int, 4 > &, SmallVector< int, 4 > &, ArrayRef< Value * > &, ArrayRef< Value * > & > ZippedRelativeLocationsT
static void findCandidateStructures(std::vector< IRSimilarityCandidate > &CandsForRepSubstring, DenseMap< unsigned, SimilarityGroup > &StructuralGroups, DenseMap< unsigned, DenseSet< IRSimilarityCandidate * > > &IndexToIncludedCand, DenseMap< IRSimilarityCandidate *, unsigned > &CandToOverallGroup)
From the list of IRSimilarityCandidates, perform a comparison between each IRSimilarityCandidate to d...
static void createCandidatesFromSuffixTree(const IRInstructionMapper &Mapper, std::vector< IRInstructionData * > &InstrList, std::vector< unsigned > &IntegerMapping, SuffixTree::RepeatedSubstring &RS, std::vector< IRSimilarityCandidate > &CandsForRepSubstring)
From a repeated subsequence, find all the different instances of the subsequence from the InstrList,...
static bool checkNumberingAndReplaceCommutative(const DenseMap< Value *, unsigned > &SourceValueToNumberMapping, DenseMap< unsigned, DenseSet< unsigned > > &CurrentSrcTgtNumberMapping, ArrayRef< Value * > &SourceOperands, DenseSet< unsigned > &TargetValueNumbers)
Determine if one or more of the assigned global value numbers for the operands in TargetValueNumbers ...
static std::optional< std::pair< IRSimilarityCandidate *, IRSimilarityCandidate * > > CheckLargerCands(IRSimilarityCandidate &CandA, IRSimilarityCandidate &CandB, DenseMap< unsigned, DenseSet< IRSimilarityCandidate * > > &IndexToIncludedCand, DenseMap< IRSimilarityCandidate *, unsigned > &CandToGroup)
Look for larger IRSimilarityCandidates From the previously matched IRSimilarityCandidates that fully ...
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines generic set operations that may be used on set's of different types,...
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
This class represents a function call, abstracting a target machine's calling convention.
This class is the base class for the comparison instructions.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ ICMP_SGE
signed greater or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Predicate getPredicate() const
Return the predicate for this instruction.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
bool erase(const KeyT &Val)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
Class to represent function types.
ArrayRef< Type * > params() const
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
An analysis pass that runs and returns the IRSimilarityIdentifier run on the Module.
LLVM_ABI Result run(Module &M, ModuleAnalysisManager &)
An analysis pass based on legacy pass manager that runs and returns IRSimilarityIdentifier run on the...
bool doInitialization(Module &M) override
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
bool doFinalization(Module &M) override
doFinalization - Virtual method overriden by subclasses to do any necessary clean up after all passes...
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
This is a class that wraps a range of IRInstructionData from one point to another in the vector of IR...
LLVM_ABI void createCanonicalRelationFrom(IRSimilarityCandidate &SourceCand, DenseMap< unsigned, DenseSet< unsigned > > &ToSourceMapping, DenseMap< unsigned, DenseSet< unsigned > > &FromSourceMapping)
Create a mapping for the value numbering of the calling IRSimilarityCandidate, to a different separat...
static LLVM_ABI bool isSimilar(const IRSimilarityCandidate &A, const IRSimilarityCandidate &B)
std::optional< unsigned > getGVN(Value *V)
Finds the positive number associated with V if it has been mapped.
unsigned getEndIdx() const
static LLVM_ABI bool compareAssignmentMapping(const unsigned InstValA, const unsigned &InstValB, DenseMap< unsigned, DenseSet< unsigned > > &ValueNumberMappingA, DenseMap< unsigned, DenseSet< unsigned > > &ValueNumberMappingB)
Compare the GVN of the assignment value in corresponding instructions in IRSimilarityCandidates A and...
void getBasicBlocks(DenseSet< BasicBlock * > &BBSet) const
std::optional< Value * > fromGVN(unsigned Num)
Finds the Value associate with Num if it exists.
IRInstructionDataList::iterator iterator
Instruction * frontInstruction()
static LLVM_ABI bool checkRelativeLocations(RelativeLocMapping A, RelativeLocMapping B)
Compare the relative locations in A and B and check that the distances match if both locations are co...
static LLVM_ABI bool compareStructure(const IRSimilarityCandidate &A, const IRSimilarityCandidate &B)
static LLVM_ABI void createCanonicalMappingFor(IRSimilarityCandidate &CurrCand)
Create a mapping from the value numbering to a different separate set of numbers.
static LLVM_ABI bool overlap(const IRSimilarityCandidate &A, const IRSimilarityCandidate &B)
Compare the start and end indices of the two IRSimilarityCandidates for whether they overlap.
unsigned getStartIdx() const
BasicBlock * getStartBB()
LLVM_ABI IRSimilarityCandidate(unsigned StartIdx, unsigned Len, IRInstructionData *FirstInstIt, IRInstructionData *LastInstIt)
std::optional< unsigned > getCanonicalNum(unsigned N)
Find the canonical number from the global value number N stored in the candidate.
std::optional< unsigned > fromCanonicalNum(unsigned N)
Find the global value number from the canonical number N stored in the candidate.
static LLVM_ABI bool compareNonCommutativeOperandMapping(OperandMapping A, OperandMapping B)
Compare the operands in A and B and check that the current mapping of global value numbers from A to ...
static LLVM_ABI bool compareCommutativeOperandMapping(OperandMapping A, OperandMapping B)
Compare the operands in A and B and check that the current mapping of global value numbers from A to ...
This class puts all the pieces of the IRInstructionData, IRInstructionMapper, IRSimilarityCandidate t...
void resetSimilarityCandidates()
LLVM_ABI SimilarityGroupList & findSimilarity(ArrayRef< std::unique_ptr< Module > > Modules)
std::optional< SimilarityGroupList > & getSimilarity()
A wrapper class for inspecting calls to intrinsic functions.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
iterator find(const_arg_type_t< ValueT > V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
const ParentTy * getParent() const
ilist_select_iterator_type< OptionsT, false, false > iterator
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
std::vector< SimilarityGroup > SimilarityGroupList
std::vector< IRSimilarityCandidate > SimilarityGroup
LLVM_ABI bool isClose(const IRInstructionData &A, const IRInstructionData &B)
Compare one IRInstructionData class to another IRInstructionData class for whether they are performin...
LLVM_ABI StringRef getName(ID id)
Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
LLVM_ABI bool isOverloaded(ID id)
Returns true if the intrinsic can be overloaded.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
void set_intersect(S1Ty &S1, const S2Ty &S2)
set_intersect(A, B) - Compute A := A ^ B Identical to set_intersection, except that it works on set<>...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
cl::opt< bool > DisableIndirectCalls("no-ir-sim-indirect-calls", cl::init(false), cl::ReallyHidden, cl::desc("disable outlining indirect calls."))
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
cl::opt< bool > DisableBranches("no-ir-sim-branch-matching", cl::init(false), cl::ReallyHidden, cl::desc("disable similarity matching, and outlining, " "across branches for debugging purposes."))
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
cl::opt< bool > DisableIntrinsics("no-ir-sim-intrinsics", cl::init(false), cl::ReallyHidden, cl::desc("Don't match or outline intrinsics"))
ArrayRef(const T &OneElt) -> ArrayRef< T >
static cl::opt< bool > MatchCallsByName("ir-sim-calls-by-name", cl::init(false), cl::ReallyHidden, cl::desc("only allow matching call instructions if the " "name and type signature match."))
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
A special type used by analysis passes to provide an address that identifies that particular analysis...
This provides the utilities for hashing an Instruction to an unsigned integer.
LLVM_ABI StringRef getCalleeName() const
Get the callee name that the call instruction is using for hashing the instruction.
LLVM_ABI void initializeInstruction()
Fills data stuctures for IRInstructionData when it is constructed from a.
SmallVector< int, 4 > RelativeBlockLocations
This structure holds the distances of how far "ahead of" or "behind" the target blocks of a branch,...
std::optional< std::string > CalleeName
This is only relevant if we are wrapping a CallInst.
LLVM_ABI IRInstructionData(Instruction &I, bool Legality, IRInstructionDataList &IDL)
Gather the information that is difficult to gather for an Instruction, or is changed.
LLVM_ABI ArrayRef< Value * > getBlockOperVals()
Get the BasicBlock based operands for PHINodes and BranchInsts.
Instruction * Inst
The source Instruction that is being wrapped.
IRInstructionDataList * IDL
static LLVM_ABI CmpInst::Predicate predicateForConsistency(CmpInst *CI)
A function that swaps the predicates to their less than form if they are in a greater than form.
LLVM_ABI void setPHIPredecessors(DenseMap< BasicBlock *, unsigned > &BasicBlockToInteger)
For an IRInstructionData containing a PHINode, finds the relative distances from the incoming basic b...
SmallVector< Value *, 4 > OperVals
The values of the operands in the Instruction.
LLVM_ABI void setBranchSuccessors(DenseMap< BasicBlock *, unsigned > &BasicBlockToInteger)
For an IRInstructionData containing a branch, finds the relative distances from the source basic bloc...
bool Legal
The legality of the wrapped instruction.
LLVM_ABI void setCalleeName(bool MatchByName=true)
For an IRInstructionData containing a CallInst, set the function name appropriately.
LLVM_ABI CmpInst::Predicate getPredicate() const
Get the predicate that the compare instruction is using for hashing the instruction.
std::optional< CmpInst::Predicate > RevisedPredicate
This is only relevant if we are wrapping a CmpInst where we needed to change the predicate of a compa...
Helper struct for converting the Instructions in a Module into a vector of unsigned integers.
DenseMap< IRInstructionData *, unsigned, IRInstructionDataTraits > InstructionIntegerMap
Correspondence from IRInstructionData to unsigned integers.
SpecificBumpPtrAllocator< IRInstructionDataList > * IDLAllocator
This allocator pointer is in charge of creating the IRInstructionDataList so it is not deallocated un...
SpecificBumpPtrAllocator< IRInstructionData > * InstDataAllocator
This allocator pointer is in charge of holding on to the IRInstructionData so it is not deallocated u...
bool EnableMatchCallsByName
Marks whether we should use exact function names, as well as types to find similarity between calls.
unsigned LegalInstrNumber
The next available integer to assign to a legal Instruction to.
unsigned IllegalInstrNumber
The starting illegal instruction number to map to.
InstructionClassification InstClassifier
Maps an Instruction to a member of InstrType.
bool HaveLegalRange
Marks whether we have found a set of instructions that is long enough to be considered for similarity...
LLVM_ABI IRInstructionData * allocateIRInstructionData(Instruction &I, bool Legality, IRInstructionDataList &IDL)
Get an allocated IRInstructionData struct using the InstDataAllocator.
bool CanCombineWithPrevInstr
Marks whether we found a illegal instruction in the previous step.
IRInstructionDataList * IDL
DenseMap< BasicBlock *, unsigned > BasicBlockToInteger
A mapping for a basic block in a module to its assigned number/location in the module.
LLVM_ABI IRInstructionDataList * allocateIRInstructionDataList()
Get an allocated IRInstructionDataList object using the IDLAllocator.
LLVM_ABI unsigned mapToLegalUnsigned(BasicBlock::iterator &It, std::vector< unsigned > &IntegerMappingForBB, std::vector< IRInstructionData * > &InstrListForBB)
Maps an Instruction to a legal integer.
LLVM_ABI void convertToUnsignedVec(BasicBlock &BB, std::vector< IRInstructionData * > &InstrList, std::vector< unsigned > &IntegerMapping)
Maps the Instructions in a BasicBlock BB to legal or illegal integers determined by InstrType.
bool AddedIllegalLastTime
Set if we added an illegal number in the previous step.
LLVM_ABI unsigned mapToIllegalUnsigned(BasicBlock::iterator &It, std::vector< unsigned > &IntegerMappingForBB, std::vector< IRInstructionData * > &InstrListForBB, bool End=false)
Maps an Instruction to an illegal integer.
A helper struct to hold the candidate, for a branch instruction, the relative location of a label,...
A repeated substring in the tree.