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);
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!");
363 "Tried to assign DenseMap tombstone or empty key to instruction.");
365 "Tried to assign DenseMap tombstone or empty key to instruction.");
390 std::vector<IRInstructionData *> &InstrListForBB,
bool End) {
403 InstrListForBB.push_back(
ID);
411 "Instruction mapping overflow!");
414 "IllegalInstrNumber cannot be DenseMap tombstone or empty key!");
417 "IllegalInstrNumber cannot be DenseMap tombstone or empty key!");
425 : StartIdx(StartIdx), Len(Len) {
427 assert(FirstInstIt !=
nullptr &&
"Instruction is nullptr!");
428 assert(LastInstIt !=
nullptr &&
"Instruction is nullptr!");
429 assert(StartIdx + Len > StartIdx &&
430 "Overflow for IRSimilarityCandidate range?");
431 assert(Len - 1 ==
static_cast<unsigned>(std::distance(
433 "Length of the first and last IRInstructionData do not match the "
451 unsigned LocalValNumber = 1;
453 for (
unsigned Loc = StartIdx;
Loc < StartIdx + Len;
Loc++,
ID++) {
456 for (
Value *Arg :
ID->OperVals)
457 if (ValueToNumber.try_emplace(Arg, LocalValNumber).second) {
458 NumberToValue.try_emplace(LocalValNumber, Arg);
464 if (ValueToNumber.try_emplace(
ID->Inst, LocalValNumber).second) {
465 NumberToValue.try_emplace(LocalValNumber,
ID->Inst);
473 FirstInst = FirstInstIt;
474 LastInst = LastInstIt;
480 if (ValueToNumber.try_emplace(BB, LocalValNumber).second) {
481 NumberToValue.try_emplace(LocalValNumber, BB);
489 if (
A.getLength() !=
B.getLength())
492 auto InstrDataForBoth =
495 return all_of(InstrDataForBoth,
496 [](std::tuple<IRInstructionData &, IRInstructionData &> R) {
499 if (!
A.Legal || !
B.Legal)
537 for (
Value *V : SourceOperands) {
538 ArgVal = SourceValueToNumberMapping.
find(V)->second;
541 std::tie(ValueMappingIt, WasInserted) = CurrentSrcTgtNumberMapping.insert(
542 std::make_pair(ArgVal, TargetValueNumbers));
548 for (
unsigned &Curr : ValueMappingIt->second)
550 if (TargetValueNumbers.
contains(Curr))
558 if (NewSet.
size() != ValueMappingIt->second.
size())
559 ValueMappingIt->second.
swap(NewSet);
563 if (ValueMappingIt->second.
size() != 1)
566 unsigned ValToRemove = *ValueMappingIt->second.
begin();
570 for (
Value *InnerV : SourceOperands) {
574 unsigned InnerVal = SourceValueToNumberMapping.
find(InnerV)->second;
575 ValueMappingIt = CurrentSrcTgtNumberMapping.
find(InnerVal);
576 if (ValueMappingIt == CurrentSrcTgtNumberMapping.
end())
579 ValueMappingIt->second.
erase(ValToRemove);
580 if (ValueMappingIt->second.
empty())
601 unsigned SourceArgVal,
unsigned TargetArgVal) {
620 std::tie(Val, WasInserted) = CurrentSrcTgtNumberMapping.insert(
633 if (TargetSet.
size() > 1 && TargetSet.
contains(TargetArgVal)) {
635 TargetSet.
insert(TargetArgVal);
640 return TargetSet.
contains(TargetArgVal);
649 unsigned OperandLength =
A.OperVals.size();
652 for (
unsigned Idx = 0; Idx < OperandLength; Idx++, VItA++, VItB++) {
653 unsigned OperValA =
A.IRSC.ValueToNumber.find(*VItA)->second;
654 unsigned OperValB =
B.IRSC.ValueToNumber.find(*VItB)->second;
684 unsigned OperandLength =
A.OperVals.size();
687 for (
unsigned Idx = 0; Idx < OperandLength;
688 Idx++, VItA++, VItB++) {
689 ValueNumbersA.
insert(
A.IRSC.ValueToNumber.find(*VItA)->second);
690 ValueNumbersB.
insert(
B.IRSC.ValueToNumber.find(*VItB)->second);
697 A.ValueNumberMapping,
A.OperVals,
705 B.ValueNumberMapping,
B.OperVals,
713 const unsigned InstValA,
const unsigned &InstValB,
718 std::tie(ValueMappingIt, WasInserted) = ValueNumberMappingA.insert(
720 if (!WasInserted && !ValueMappingIt->second.
contains(InstValB))
722 else if (ValueMappingIt->second.
size() != 1) {
723 for (
unsigned OtherVal : ValueMappingIt->second) {
724 if (OtherVal == InstValB)
726 auto OtherValIt = ValueNumberMappingA.find(OtherVal);
727 if (OtherValIt == ValueNumberMappingA.end())
729 OtherValIt->second.erase(InstValA);
731 ValueNumberMappingA.erase(ValueMappingIt);
732 std::tie(ValueMappingIt, WasInserted) = ValueNumberMappingA.insert(
748 A.IRSC.getBasicBlocks(BasicBlockA);
749 B.IRSC.getBasicBlocks(BasicBlockB);
752 bool AContained = BasicBlockA.
contains(ABB);
753 bool BContained = BasicBlockB.
contains(BBB);
757 if (AContained != BContained)
763 return A.RelativeLocation ==
B.RelativeLocation;
783 if (
A.getLength() !=
B.getLength())
786 if (
A.ValueToNumber.size() !=
B.ValueToNumber.size())
798 unsigned SectionLength =
A.getStartIdx() +
A.getLength();
799 for (
unsigned Loc =
A.getStartIdx();
Loc < SectionLength;
800 ItA++, ItB++,
Loc++) {
808 if (!ItA->Legal || !ItB->Legal)
815 unsigned InstValA =
A.ValueToNumber.find(IA)->second;
816 unsigned InstValB =
B.ValueToNumber.find(IB)->second;
820 ValueNumberMappingB))
824 ValueNumberMappingA))
833 {
A, OperValsA, ValueNumberMappingA},
834 {
B, OperValsB, ValueNumberMappingB}))
841 {
A, OperValsA, ValueNumberMappingA},
842 {
B, OperValsB, ValueNumberMappingB}))
857 IA->getOpcode() != IB->getOpcode())
867 if (RelBlockLocsA.
size() != RelBlockLocsB.
size() &&
872 "Block information vectors not the same size.");
874 "Block information vectors not the same size.");
877 zip(RelBlockLocsA, RelBlockLocsB, ABL, BBL);
878 if (
any_of(ZippedRelativeLocations,
879 [&
A, &
B](std::tuple<int, int, Value *, Value *> R) {
881 {
A, std::get<0>(R), std::get<2>(R)},
882 {
B, std::get<1>(R), std::get<3>(R)});
896 return X.StartIdx <=
Y.getEndIdx() &&
Y.StartIdx >=
X.StartIdx;
899 return DoesOverlap(
A,
B) || DoesOverlap(
B,
A);
902void IRSimilarityIdentifier::populateMapper(
903 Module &M, std::vector<IRInstructionData *> &InstrList,
904 std::vector<unsigned> &IntegerMapping) {
906 std::vector<IRInstructionData *> InstrListForModule;
907 std::vector<unsigned> IntegerMappingForModule;
910 Mapper.initializeForBBs(M);
922 Mapper.convertToUnsignedVec(BB, InstrListForModule,
923 IntegerMappingForModule);
927 Mapper.mapToIllegalUnsigned(It, IntegerMappingForModule, InstrListForModule,
929 if (InstrListForModule.size() > 0)
930 Mapper.IDL->push_back(*InstrListForModule.back());
940void IRSimilarityIdentifier::populateMapper(
941 ArrayRef<std::unique_ptr<Module>> &Modules,
942 std::vector<IRInstructionData *> &InstrList,
943 std::vector<unsigned> &IntegerMapping) {
946 for (
const std::unique_ptr<Module> &M : Modules)
947 populateMapper(*M, InstrList, IntegerMapping);
962 std::vector<IRSimilarityCandidate> &CandsForRepSubstring) {
964 unsigned StringLen = RS.Length;
969 for (
const unsigned &StartIdx : RS.StartIndices) {
970 unsigned EndIdx = StartIdx + StringLen - 1;
973 bool ContainsIllegal =
false;
974 for (
unsigned CurrIdx = StartIdx; CurrIdx <= EndIdx; CurrIdx++) {
975 unsigned Key = IntegerMapping[CurrIdx];
976 if (
Key > Mapper.IllegalInstrNumber) {
977 ContainsIllegal =
true;
990 std::vector<IRInstructionData *>::iterator StartIt = InstrList.
begin();
991 std::advance(StartIt, StartIdx);
992 std::vector<IRInstructionData *>::iterator EndIt = InstrList.
begin();
993 std::advance(EndIt, EndIdx);
995 CandsForRepSubstring.emplace_back(StartIdx, StringLen, *StartIt, *EndIt);
1003 assert(SourceCand.CanonNumToNumber.
size() != 0 &&
1004 "Base canonical relationship is empty!");
1005 assert(SourceCand.NumberToCanonNum.
size() != 0 &&
1006 "Base canonical relationship is empty!");
1008 assert(CanonNumToNumber.size() == 0 &&
"Canonical Relationship is non-empty");
1009 assert(NumberToCanonNum.size() == 0 &&
"Canonical Relationship is non-empty");
1016 unsigned SourceGVN = GVNMapping.first;
1018 assert(GVNMapping.second.size() != 0 &&
"Possible GVNs is 0!");
1025 if (GVNMapping.second.size() > 1) {
1027 for (
unsigned Val : GVNMapping.second) {
1034 FromSourceMapping.find(Val);
1036 if (!It->second.
contains(SourceGVN))
1045 assert(Found &&
"Could not find matching value for source GVN");
1049 ResultGVN = *GVNMapping.second.begin();
1052 UsedGVNs.
insert(ResultGVN);
1055 CanonNumToNumber.insert(std::make_pair(CanonNum, SourceGVN));
1056 NumberToCanonNum.insert(std::make_pair(SourceGVN, CanonNum));
1068 unsigned BBGVNForCurrCand = ValueToNumber.find(BB)->second;
1072 if (NumberToCanonNum.contains(BBGVNForCurrCand))
1078 Value *FirstOutlineInst =
1081 unsigned FirstInstGVN = *
getGVN(FirstOutlineInst);
1086 unsigned SourceBBGVN = *SourceCand.
getGVN(SourceBB);
1088 CanonNumToNumber.insert(std::make_pair(SourceCanonBBGVN, BBGVNForCurrCand));
1089 NumberToCanonNum.insert(std::make_pair(BBGVNForCurrCand, SourceCanonBBGVN));
1097 "Canonical Relationship is non-empty");
1099 "Canonical Relationship is non-empty");
1101 assert(!SourceCandLarge.CanonNumToNumber.
empty() &&
1102 "Canonical Relationship is non-empty");
1103 assert(!SourceCandLarge.NumberToCanonNum.
empty() &&
1104 "Canonical Relationship is non-empty");
1106 assert(!TargetCandLarge.CanonNumToNumber.
empty() &&
1107 "Canonical Relationship is non-empty");
1108 assert(!TargetCandLarge.NumberToCanonNum.
empty() &&
1109 "Canonical Relationship is non-empty");
1111 assert(CanonNumToNumber.empty() &&
"Canonical Relationship is non-empty");
1112 assert(NumberToCanonNum.empty() &&
"Canonical Relationship is non-empty");
1118 for (std::pair<Value *, unsigned> &ValueNumPair : ValueToNumber) {
1119 Value *CurrVal = ValueNumPair.first;
1120 unsigned TargetCandGVN = ValueNumPair.second;
1124 std::optional<unsigned> OLargeTargetGVN = TargetCandLarge.
getGVN(CurrVal);
1125 assert(OLargeTargetGVN.has_value() &&
"GVN not found for Value");
1128 std::optional<unsigned> OTargetCandCanon =
1130 assert(OTargetCandCanon.has_value() &&
1131 "Canononical Number not found for GVN");
1134 std::optional<unsigned> OLargeSourceGVN =
1136 assert(OLargeSourceGVN.has_value() &&
1137 "GVN Number not found for Canonical Number");
1140 std::optional<Value *> OLargeSourceV =
1141 SourceCandLarge.
fromGVN(OLargeSourceGVN.value());
1142 assert(OLargeSourceV.has_value() &&
"Value not found for GVN");
1145 std::optional<unsigned> OSourceGVN =
1146 SourceCand.
getGVN(OLargeSourceV.value());
1147 assert(OSourceGVN.has_value() &&
"GVN Number not found for Value");
1150 std::optional<unsigned> OSourceCanon =
1152 assert(OSourceCanon.has_value() &&
"Canon Number not found for GVN");
1156 CanonNumToNumber.insert(
1157 std::make_pair(OSourceCanon.value(), TargetCandGVN));
1158 NumberToCanonNum.insert(
1159 std::make_pair(TargetCandGVN, OSourceCanon.value()));
1165 assert(CurrCand.CanonNumToNumber.
size() == 0 &&
1166 "Canonical Relationship is non-empty");
1167 assert(CurrCand.NumberToCanonNum.
size() == 0 &&
1168 "Canonical Relationship is non-empty");
1170 unsigned CanonNum = 0;
1173 for (std::pair<unsigned, Value *> &NumToVal : CurrCand.NumberToValue) {
1174 CurrCand.NumberToCanonNum.
insert(std::make_pair(NumToVal.first, CanonNum));
1175 CurrCand.CanonNumToNumber.
insert(std::make_pair(CanonNum, NumToVal.first));
1193static std::optional<
1194 std::pair<IRSimilarityCandidate *, IRSimilarityCandidate *>>
1206 auto IdxToCandidateIt = IndexToIncludedCand.
find(CandA.
getStartIdx());
1207 std::optional<std::pair<IRSimilarityCandidate *, IRSimilarityCandidate *>>
1214 if (IdxToCandidateIt == IndexToIncludedCand.end())
1220 unsigned GroupNum = CandToGroup.
find(MatchedCand)->second;
1221 IncludedGroupAndCandA.
insert(std::make_pair(GroupNum, MatchedCand));
1222 IncludedGroupsA.
insert(GroupNum);
1227 IdxToCandidateIt = IndexToIncludedCand.find(CandBStart);
1228 if (IdxToCandidateIt == IndexToIncludedCand.end())
1234 unsigned GroupNum = CandToGroup.
find(MatchedCand)->second;
1235 IncludedGroupAndCandB.
insert(std::make_pair(GroupNum, MatchedCand));
1236 IncludedGroupsB.
insert(GroupNum);
1245 if (IncludedGroupsA.
empty())
1249 auto ItA = IncludedGroupAndCandA.
find(*IncludedGroupsA.
begin());
1250 auto ItB = IncludedGroupAndCandB.
find(*IncludedGroupsA.
begin());
1251 Result = std::make_pair(ItA->second, ItB->second);
1269 std::vector<IRSimilarityCandidate> &CandsForRepSubstring,
1274 std::vector<IRSimilarityCandidate>::iterator CandIt, CandEndIt, InnerCandIt,
1289 unsigned CurrentGroupNum = 0;
1290 unsigned OuterGroupNum;
1299 for (CandIt = CandsForRepSubstring.begin(),
1300 CandEndIt = CandsForRepSubstring.end();
1301 CandIt != CandEndIt; CandIt++) {
1305 std::tie(CandToGroupIt, Inserted) =
1306 CandToGroup.
try_emplace(&*CandIt, CurrentGroupNum);
1311 OuterGroupNum = CandToGroupIt->second;
1315 CurrentGroupPair = StructuralGroups.
find(OuterGroupNum);
1316 if (CurrentGroupPair == StructuralGroups.
end()) {
1318 std::tie(CurrentGroupPair, Inserted) = StructuralGroups.
insert(
1326 for (InnerCandIt = std::next(CandIt),
1327 InnerCandEndIt = CandsForRepSubstring.end();
1328 InnerCandIt != InnerCandEndIt; InnerCandIt++) {
1331 CandToGroupItInner = CandToGroup.
find(&*InnerCandIt);
1332 if (CandToGroupItInner != CandToGroup.
end())
1337 std::optional<std::pair<IRSimilarityCandidate *, IRSimilarityCandidate *>>
1339 *CandIt, *InnerCandIt, IndexToIncludedCand, CandToOverallGroup);
1344 if (LargerPair.has_value()) {
1345 SameStructure =
true;
1346 InnerCandIt->createCanonicalRelationFrom(
1347 *CandIt, *LargerPair.value().first, *LargerPair.value().second);
1348 CandToGroup.
insert(std::make_pair(&*InnerCandIt, OuterGroupNum));
1349 CurrentGroupPair->second.push_back(*InnerCandIt);
1355 ValueNumberMappingA.
clear();
1356 ValueNumberMappingB.
clear();
1358 *CandIt, *InnerCandIt, ValueNumberMappingA, ValueNumberMappingB);
1362 InnerCandIt->createCanonicalRelationFrom(*CandIt, ValueNumberMappingA,
1363 ValueNumberMappingB);
1364 CandToGroup.
insert(std::make_pair(&*InnerCandIt, OuterGroupNum));
1365 CurrentGroupPair->second.push_back(*InnerCandIt);
1370void IRSimilarityIdentifier::findCandidates(
1371 std::vector<IRInstructionData *> &InstrList,
1372 std::vector<unsigned> &IntegerMapping) {
1373 SuffixTree
ST(IntegerMapping);
1375 std::vector<IRSimilarityCandidate> CandsForRepSubstring;
1376 std::vector<SimilarityGroup> NewCandidateGroups;
1378 DenseMap<unsigned, SimilarityGroup> StructuralGroups;
1379 DenseMap<unsigned, DenseSet<IRSimilarityCandidate *>> IndexToIncludedCand;
1380 DenseMap<IRSimilarityCandidate *, unsigned> CandToGroup;
1387 std::vector<SuffixTree::RepeatedSubstring> RSes;
1388 for (SuffixTree::RepeatedSubstring &RS : ST)
1392 const SuffixTree::RepeatedSubstring &
RHS) {
1393 return LHS.Length >
RHS.Length;
1395 for (SuffixTree::RepeatedSubstring &RS : RSes) {
1397 CandsForRepSubstring);
1399 if (CandsForRepSubstring.size() < 2)
1403 IndexToIncludedCand, CandToGroup);
1404 for (std::pair<unsigned, SimilarityGroup> &Group : StructuralGroups) {
1408 if (Group.second.size() > 1) {
1409 SimilarityCandidates->push_back(Group.second);
1413 for (IRSimilarityCandidate &IRCand : SimilarityCandidates->back()) {
1414 for (
unsigned Idx = IRCand.getStartIdx(), Edx = IRCand.getEndIdx();
1416 IndexToIncludedCand[Idx].
insert(&IRCand);
1419 std::make_pair(&IRCand, SimilarityCandidates->size() - 1));
1424 CandsForRepSubstring.clear();
1425 StructuralGroups.clear();
1426 NewCandidateGroups.clear();
1431 ArrayRef<std::unique_ptr<Module>> Modules) {
1434 std::vector<IRInstructionData *> InstrList;
1435 std::vector<unsigned> IntegerMapping;
1436 Mapper.InstClassifier.EnableBranches = this->EnableBranches;
1437 Mapper.InstClassifier.EnableIndirectCalls = EnableIndirectCalls;
1438 Mapper.EnableMatchCallsByName = EnableMatchingCallsByName;
1439 Mapper.InstClassifier.EnableIntrinsics = EnableIntrinsics;
1440 Mapper.InstClassifier.EnableMustTailCalls = EnableMustTailCalls;
1442 populateMapper(Modules, InstrList, IntegerMapping);
1443 findCandidates(InstrList, IntegerMapping);
1445 return *SimilarityCandidates;
1450 Mapper.InstClassifier.EnableBranches = this->EnableBranches;
1451 Mapper.InstClassifier.EnableIndirectCalls = EnableIndirectCalls;
1452 Mapper.EnableMatchCallsByName = EnableMatchingCallsByName;
1453 Mapper.InstClassifier.EnableIntrinsics = EnableIntrinsics;
1454 Mapper.InstClassifier.EnableMustTailCalls = EnableMustTailCalls;
1456 std::vector<IRInstructionData *> InstrList;
1457 std::vector<unsigned> IntegerMapping;
1459 populateMapper(M, InstrList, IntegerMapping);
1460 findCandidates(InstrList, IntegerMapping);
1462 return *SimilarityCandidates;
1466 "ir-similarity-identifier",
false,
true)
1484 IRSI->findSimilarity(M);
1494 IRSI.findSimilarity(M);
1501 std::optional<SimilarityGroupList> &SimilarityCandidatesOpt =
1504 for (std::vector<IRSimilarityCandidate> &CandVec : *SimilarityCandidatesOpt) {
1505 OS << CandVec.size() <<
" candidates of length "
1506 << CandVec.begin()->getLength() <<
". Found in: \n";
1508 OS <<
" Function: " << Cand.front()->Inst->getFunction()->getName().str()
1509 <<
", Basic Block: ";
1510 if (Cand.front()->Inst->getParent()->getName().str() ==
"")
1513 OS << Cand.front()->Inst->getParent()->getName().str();
1514 OS <<
"\n Start Instruction: ";
1515 Cand.frontInstruction()->print(OS);
1516 OS <<
"\n End Instruction: ";
1517 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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - 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.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - 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...
An information struct used to provide DenseMap with the various necessary components for a given valu...
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,...
Incoming for lane mask phi as machine instruction, incoming register Reg and incoming block Block are...
A repeated substring in the tree.