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 llvm-svn: 331573
This commit is contained in:
		
							parent
							
								
									60609c9f12
								
							
						
					
					
						commit
						e04ecc88de
					
				| 
						 | 
					@ -297,11 +297,13 @@ public:
 | 
				
			||||||
struct ICallBranchFunnel final
 | 
					struct ICallBranchFunnel final
 | 
				
			||||||
    : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
 | 
					    : TrailingObjects<ICallBranchFunnel, GlobalTypeMember *> {
 | 
				
			||||||
  static ICallBranchFunnel *create(BumpPtrAllocator &Alloc, CallInst *CI,
 | 
					  static ICallBranchFunnel *create(BumpPtrAllocator &Alloc, CallInst *CI,
 | 
				
			||||||
                                   ArrayRef<GlobalTypeMember *> Targets) {
 | 
					                                   ArrayRef<GlobalTypeMember *> Targets,
 | 
				
			||||||
 | 
					                                   unsigned UniqueId) {
 | 
				
			||||||
    auto *Call = static_cast<ICallBranchFunnel *>(
 | 
					    auto *Call = static_cast<ICallBranchFunnel *>(
 | 
				
			||||||
        Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.size()),
 | 
					        Alloc.Allocate(totalSizeToAlloc<GlobalTypeMember *>(Targets.size()),
 | 
				
			||||||
                       alignof(ICallBranchFunnel)));
 | 
					                       alignof(ICallBranchFunnel)));
 | 
				
			||||||
    Call->CI = CI;
 | 
					    Call->CI = CI;
 | 
				
			||||||
 | 
					    Call->UniqueId = UniqueId;
 | 
				
			||||||
    Call->NTargets = Targets.size();
 | 
					    Call->NTargets = Targets.size();
 | 
				
			||||||
    std::uninitialized_copy(Targets.begin(), Targets.end(),
 | 
					    std::uninitialized_copy(Targets.begin(), Targets.end(),
 | 
				
			||||||
                            Call->getTrailingObjects<GlobalTypeMember *>());
 | 
					                            Call->getTrailingObjects<GlobalTypeMember *>());
 | 
				
			||||||
| 
						 | 
					@ -313,6 +315,8 @@ struct ICallBranchFunnel final
 | 
				
			||||||
    return makeArrayRef(getTrailingObjects<GlobalTypeMember *>(), NTargets);
 | 
					    return makeArrayRef(getTrailingObjects<GlobalTypeMember *>(), NTargets);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  unsigned UniqueId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  size_t NTargets;
 | 
					  size_t NTargets;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -1664,11 +1668,11 @@ bool LowerTypeTestsModule::lower() {
 | 
				
			||||||
  // identifiers.
 | 
					  // identifiers.
 | 
				
			||||||
  BumpPtrAllocator Alloc;
 | 
					  BumpPtrAllocator Alloc;
 | 
				
			||||||
  struct TIInfo {
 | 
					  struct TIInfo {
 | 
				
			||||||
    unsigned Index;
 | 
					    unsigned UniqueId;
 | 
				
			||||||
    std::vector<GlobalTypeMember *> RefGlobals;
 | 
					    std::vector<GlobalTypeMember *> RefGlobals;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  DenseMap<Metadata *, TIInfo> TypeIdInfo;
 | 
					  DenseMap<Metadata *, TIInfo> TypeIdInfo;
 | 
				
			||||||
  unsigned I = 0;
 | 
					  unsigned CurUniqueId = 0;
 | 
				
			||||||
  SmallVector<MDNode *, 2> Types;
 | 
					  SmallVector<MDNode *, 2> Types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  struct ExportedFunctionInfo {
 | 
					  struct ExportedFunctionInfo {
 | 
				
			||||||
| 
						 | 
					@ -1756,7 +1760,7 @@ bool LowerTypeTestsModule::lower() {
 | 
				
			||||||
    for (MDNode *Type : Types) {
 | 
					    for (MDNode *Type : Types) {
 | 
				
			||||||
      verifyTypeMDNode(&GO, Type);
 | 
					      verifyTypeMDNode(&GO, Type);
 | 
				
			||||||
      auto &Info = TypeIdInfo[Type->getOperand(1)];
 | 
					      auto &Info = TypeIdInfo[Type->getOperand(1)];
 | 
				
			||||||
      Info.Index = ++I;
 | 
					      Info.UniqueId = ++CurUniqueId;
 | 
				
			||||||
      Info.RefGlobals.push_back(GTM);
 | 
					      Info.RefGlobals.push_back(GTM);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -1825,8 +1829,9 @@ bool LowerTypeTestsModule::lower() {
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      GlobalClasses.unionSets(
 | 
					      GlobalClasses.unionSets(
 | 
				
			||||||
          CurSet, GlobalClasses.findLeader(GlobalClasses.insert(
 | 
					          CurSet, GlobalClasses.findLeader(
 | 
				
			||||||
                      ICallBranchFunnel::create(Alloc, CI, Targets))));
 | 
					                      GlobalClasses.insert(ICallBranchFunnel::create(
 | 
				
			||||||
 | 
					                          Alloc, CI, Targets, ++CurUniqueId))));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1863,13 +1868,15 @@ bool LowerTypeTestsModule::lower() {
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    ++NumTypeIdDisjointSets;
 | 
					    ++NumTypeIdDisjointSets;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unsigned MaxIndex = 0;
 | 
					    unsigned MaxUniqueId = 0;
 | 
				
			||||||
    for (GlobalClassesTy::member_iterator MI = GlobalClasses.member_begin(I);
 | 
					    for (GlobalClassesTy::member_iterator MI = GlobalClasses.member_begin(I);
 | 
				
			||||||
         MI != GlobalClasses.member_end(); ++MI) {
 | 
					         MI != GlobalClasses.member_end(); ++MI) {
 | 
				
			||||||
      if ((*MI).is<Metadata *>())
 | 
					      if (auto *MD = MI->dyn_cast<Metadata *>())
 | 
				
			||||||
        MaxIndex = std::max(MaxIndex, TypeIdInfo[MI->get<Metadata *>()].Index);
 | 
					        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(),
 | 
					  llvm::sort(Sets.begin(), Sets.end(),
 | 
				
			||||||
             [](const std::pair<GlobalClassesTy::iterator, unsigned> &S1,
 | 
					             [](const std::pair<GlobalClassesTy::iterator, unsigned> &S1,
 | 
				
			||||||
| 
						 | 
					@ -1894,10 +1901,16 @@ bool LowerTypeTestsModule::lower() {
 | 
				
			||||||
        ICallBranchFunnels.push_back(MI->get<ICallBranchFunnel *>());
 | 
					        ICallBranchFunnels.push_back(MI->get<ICallBranchFunnel *>());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Order type identifiers by global index for determinism. This ordering is
 | 
					    // Order type identifiers by unique ID for determinism. This ordering is
 | 
				
			||||||
    // stable as there is a one-to-one mapping between metadata and indices.
 | 
					    // stable as there is a one-to-one mapping between metadata and unique IDs.
 | 
				
			||||||
    llvm::sort(TypeIds.begin(), TypeIds.end(), [&](Metadata *M1, Metadata *M2) {
 | 
					    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.
 | 
					    // Build bitsets for this disjoint set.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue