@@ -185,8 +185,13 @@ int FunctionComparator::cmpAttrs(const AttributeList L,
185185 return 0 ;
186186}
187187
188- int FunctionComparator::cmpMetadata (const Metadata *L,
189- const Metadata *R) const {
188+ int FunctionComparator::cmpMetadata (
189+ const Metadata *L, const Metadata *R,
190+ SmallPtrSetImpl<const MDNode *> &SeenL,
191+ SmallPtrSetImpl<const MDNode *> &SeenR) const {
192+ if (L == R)
193+ return 0 ;
194+
190195 // TODO: the following routine coerce the metadata contents into constants
191196 // or MDStrings before comparison.
192197 // It ignores any other cases, so that the metadata nodes are considered
@@ -207,22 +212,51 @@ int FunctionComparator::cmpMetadata(const Metadata *L,
207212
208213 auto *CL = dyn_cast<ConstantAsMetadata>(L);
209214 auto *CR = dyn_cast<ConstantAsMetadata>(R);
210- if (CL == CR)
211- return 0 ;
212- if (!CL)
215+ if (CL && CR) {
216+ if (!CL)
217+ return -1 ;
218+ if (!CR)
219+ return 1 ;
220+ return cmpConstants (CL->getValue (), CR->getValue ());
221+ }
222+
223+ auto *NodeL = dyn_cast<const MDNode>(L);
224+ auto *NodeR = dyn_cast<const MDNode>(R);
225+ if (NodeL && NodeR)
226+ return cmpMDNode (NodeL, NodeR, SeenL, SeenR);
227+
228+ if (NodeR)
213229 return -1 ;
214- if (!CR)
230+
231+ if (NodeL)
215232 return 1 ;
216- return cmpConstants (CL->getValue (), CR->getValue ());
233+
234+ assert (false );
235+
236+ return 0 ;
217237}
218238
219- int FunctionComparator::cmpMDNode (const MDNode *L, const MDNode *R) const {
239+ int FunctionComparator::cmpMDNode (
240+ const MDNode *L, const MDNode *R, SmallPtrSetImpl<const MDNode *> &SeenL,
241+ SmallPtrSetImpl<const MDNode *> &SeenR) const {
220242 if (L == R)
221243 return 0 ;
222244 if (!L)
223245 return -1 ;
224246 if (!R)
225247 return 1 ;
248+
249+ // Check if we already checked either L or R previosuly. This can be the case
250+ // for metadata nodes with cycles.
251+ bool AlreadySeenL = !SeenL.insert (L).second ;
252+ bool AlreadySeenR = !SeenR.insert (R).second ;
253+ if (AlreadySeenL && AlreadySeenR)
254+ return 0 ;
255+ if (AlreadySeenR)
256+ return -1 ;
257+ if (AlreadySeenL)
258+ return 1 ;
259+
226260 // TODO: Note that as this is metadata, it is possible to drop and/or merge
227261 // this data when considering functions to merge. Thus this comparison would
228262 // return 0 (i.e. equivalent), but merging would become more complicated
@@ -232,7 +266,7 @@ int FunctionComparator::cmpMDNode(const MDNode *L, const MDNode *R) const {
232266 if (int Res = cmpNumbers (L->getNumOperands (), R->getNumOperands ()))
233267 return Res;
234268 for (size_t I = 0 ; I < L->getNumOperands (); ++I)
235- if (int Res = cmpMetadata (L->getOperand (I), R->getOperand (I)))
269+ if (int Res = cmpMetadata (L->getOperand (I), R->getOperand (I), SeenL, SeenR ))
236270 return Res;
237271 return 0 ;
238272}
@@ -254,7 +288,10 @@ int FunctionComparator::cmpInstMetadata(Instruction const *L,
254288 auto const [KeyR, MR] = MDR[I];
255289 if (int Res = cmpNumbers (KeyL, KeyR))
256290 return Res;
257- if (int Res = cmpMDNode (ML, MR))
291+
292+ SmallPtrSet<const MDNode *, 4 > SeenL;
293+ SmallPtrSet<const MDNode *, 4 > SeenR;
294+ if (int Res = cmpMDNode (ML, MR, SeenL, SeenR))
258295 return Res;
259296 }
260297 return 0 ;
@@ -721,8 +758,11 @@ int FunctionComparator::cmpOperations(const Instruction *L,
721758 if (int Res = cmpNumbers (CI->getTailCallKind (),
722759 cast<CallInst>(R)->getTailCallKind ()))
723760 return Res;
761+
762+ SmallPtrSet<const MDNode *, 4 > SeenL;
763+ SmallPtrSet<const MDNode *, 4 > SeenR;
724764 return cmpMDNode (L->getMetadata (LLVMContext::MD_range),
725- R->getMetadata (LLVMContext::MD_range));
765+ R->getMetadata (LLVMContext::MD_range), SeenL, SeenR );
726766 }
727767 if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(L)) {
728768 ArrayRef<unsigned > LIndices = IVI->getIndices ();
@@ -895,11 +935,10 @@ int FunctionComparator::cmpValues(const Value *L, const Value *R) const {
895935 const MetadataAsValue *MetadataValueL = dyn_cast<MetadataAsValue>(L);
896936 const MetadataAsValue *MetadataValueR = dyn_cast<MetadataAsValue>(R);
897937 if (MetadataValueL && MetadataValueR) {
898- if (MetadataValueL == MetadataValueR)
899- return 0 ;
900-
938+ SmallPtrSet<const MDNode *, 4 > SeenL;
939+ SmallPtrSet<const MDNode *, 4 > SeenR;
901940 return cmpMetadata (MetadataValueL->getMetadata (),
902- MetadataValueR->getMetadata ());
941+ MetadataValueR->getMetadata (), SeenL, SeenR );
903942 }
904943
905944 if (MetadataValueL)
0 commit comments