[llvm] r331573 - LowerTypeTests: Fix non-determinism in code that handles icall branch funnels.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Fri May 4 17:51:55 PDT 2018


Author: pcc
Date: Fri May  4 17:51:55 2018
New Revision: 331573

URL: http://llvm.org/viewvc/llvm-project?rev=331573&view=rev
Log:
LowerTypeTests: Fix non-determinism in code that handles icall branch funnels.

This was exposed by enabling expensive checks, which causes llvm::sort
to sort randomly.

Differential Revision: https://reviews.llvm.org/D45901

Modified:
    llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp

Modified: llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp?rev=331573&r1=331572&r2=331573&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp Fri May  4 17:51:55 2018
@@ -297,11 +297,13 @@ public:
 struct ICallBranchFunnel final
     : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
   static ICallBranchFunnel *create(BumpPtrAllocator &Alloc, CallInst *CI,
-                                   ArrayRef<GlobalTypeMember *> Targets) {
+                                   ArrayRef<GlobalTypeMember *> Targets,
+                                   unsigned UniqueId) {
     auto *Call = static_cast<ICallBranchFunnel *>(
         Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.size()),
                        alignof(ICallBranchFunnel)));
     Call->CI = CI;
+    Call->UniqueId = UniqueId;
     Call->NTargets = Targets.size();
     std::uninitialized_copy(Targets.begin(), Targets.end(),
                             Call->getTrailingObjects<GlobalTypeMember *>());
@@ -313,6 +315,8 @@ struct ICallBranchFunnel final
     return makeArrayRef(getTrailingObjects<GlobalTypeMember *>(), NTargets);
   }
 
+  unsigned UniqueId;
+
 private:
   size_t NTargets;
 };
@@ -1664,11 +1668,11 @@ bool LowerTypeTestsModule::lower() {
   // identifiers.
   BumpPtrAllocator Alloc;
   struct TIInfo {
-    unsigned Index;
+    unsigned UniqueId;
     std::vector<GlobalTypeMember *> RefGlobals;
   };
   DenseMap<Metadata *, TIInfo> TypeIdInfo;
-  unsigned I = 0;
+  unsigned CurUniqueId = 0;
   SmallVector<MDNode *, 2> Types;
 
   struct ExportedFunctionInfo {
@@ -1756,7 +1760,7 @@ bool LowerTypeTestsModule::lower() {
     for (MDNode *Type : Types) {
       verifyTypeMDNode(&GO, Type);
       auto &Info = TypeIdInfo[Type->getOperand(1)];
-      Info.Index = ++I;
+      Info.UniqueId = ++CurUniqueId;
       Info.RefGlobals.push_back(GTM);
     }
   }
@@ -1825,8 +1829,9 @@ bool LowerTypeTestsModule::lower() {
       }
 
       GlobalClasses.unionSets(
-          CurSet, GlobalClasses.findLeader(GlobalClasses.insert(
-                      ICallBranchFunnel::create(Alloc, CI, Targets))));
+          CurSet, GlobalClasses.findLeader(
+                      GlobalClasses.insert(ICallBranchFunnel::create(
+                          Alloc, CI, Targets, ++CurUniqueId))));
     }
   }
 
@@ -1863,13 +1868,15 @@ bool LowerTypeTestsModule::lower() {
       continue;
     ++NumTypeIdDisjointSets;
 
-    unsigned MaxIndex = 0;
+    unsigned MaxUniqueId = 0;
     for (GlobalClassesTy::member_iterator MI = GlobalClasses.member_begin(I);
          MI != GlobalClasses.member_end(); ++MI) {
-      if ((*MI).is<Metadata *>())
-        MaxIndex = std::max(MaxIndex, TypeIdInfo[MI->get<Metadata *>()].Index);
+      if (auto *MD = MI->dyn_cast<Metadata *>())
+        MaxUniqueId = std::max(MaxUniqueId, TypeIdInfo[MD].UniqueId);
+      else if (auto *BF = MI->dyn_cast<ICallBranchFunnel *>())
+        MaxUniqueId = std::max(MaxUniqueId, BF->UniqueId);
     }
-    Sets.emplace_back(I, MaxIndex);
+    Sets.emplace_back(I, MaxUniqueId);
   }
   llvm::sort(Sets.begin(), Sets.end(),
              [](const std::pair<GlobalClassesTy::iterator, unsigned> &S1,
@@ -1894,12 +1901,18 @@ bool LowerTypeTestsModule::lower() {
         ICallBranchFunnels.push_back(MI->get<ICallBranchFunnel *>());
     }
 
-    // Order type identifiers by global index for determinism. This ordering is
-    // stable as there is a one-to-one mapping between metadata and indices.
+    // Order type identifiers by unique ID for determinism. This ordering is
+    // stable as there is a one-to-one mapping between metadata and unique IDs.
     llvm::sort(TypeIds.begin(), TypeIds.end(), [&](Metadata *M1, Metadata *M2) {
-      return TypeIdInfo[M1].Index < TypeIdInfo[M2].Index;
+      return TypeIdInfo[M1].UniqueId < TypeIdInfo[M2].UniqueId;
     });
 
+    // Same for the branch funnels.
+    llvm::sort(ICallBranchFunnels.begin(), ICallBranchFunnels.end(),
+               [&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
+                 return F1->UniqueId < F2->UniqueId;
+               });
+
     // Build bitsets for this disjoint set.
     buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
   }




More information about the llvm-commits mailing list