Index: lib/IR/Function.cpp =================================================================== --- lib/IR/Function.cpp +++ lib/IR/Function.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/Function.h" +#include "LLVMContextImpl.h" #include "SymbolTableListTraitsImpl.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" @@ -570,7 +571,21 @@ } else if (StructType *STyp = dyn_cast(Ty)) { if (!STyp->isLiteral()) { Result += "s_"; - Result += STyp->getName(); + if (STyp->hasName()) + Result += STyp->getName(); + else { + // Different unnamed struct types should get mangled to different names, + // so we keep a mapping of types to ids to get deterministic naming. + // The mapping is populated on demand here. + DenseMap &AnonIDs = + STyp->getContext().pImpl->AnonStructTypesIDs; + unsigned &AnonID = STyp->getContext().pImpl->AnonStructTypesUniqueID; + auto I = AnonIDs.insert({STyp, AnonID}); + if (I.second) + AnonID++; + + Result += Twine(I.first->second).str(); + } } else { Result += "sl_"; for (auto Elem : STyp->elements()) Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -1306,7 +1306,12 @@ StructTypeSet AnonStructTypes; StringMap NamedStructTypes; unsigned NamedStructTypesUniqueID = 0; - + + /// Mapping from unnamed struct types to a deterministic ID for mangling. + /// It is populated on demand. + DenseMap AnonStructTypesIDs; + unsigned AnonStructTypesUniqueID = 0; + DenseMap, ArrayType*> ArrayTypes; DenseMap, VectorType*> VectorTypes; DenseMap PointerTypes; // Pointers in AddrSpace = 0 Index: test/Transforms/Util/PredicateInfo/unnamed-types.ll =================================================================== --- /dev/null +++ test/Transforms/Util/PredicateInfo/unnamed-types.ll @@ -0,0 +1,36 @@ +; RUN: opt < %s -print-predicateinfo 2>&1 | FileCheck %s + +; Check we can use ssa.copy with unnamed types. + +; CHECK-LABEL: bb: +; CHECK: Has predicate info +; CHECK: branch predicate info { TrueEdge: 1 Comparison: %cmp1 = icmp ne %1* %arg, null Edge: [label %bb,label %bb1] } +; CHECK-NEXT: %arg.0 = call %1* @llvm.ssa.copy.p0s_{{.+}}s(%1* %arg) + +; CHECK-LABEL: bb1: +; CHECK: Has predicate info +; CHECK-NEXT: branch predicate info { TrueEdge: 0 Comparison: %cmp2 = icmp ne %0* null, %tmp Edge: [label %bb1,label %bb3] } +; CHECK-NAME: %tmp.0 = call %0* @llvm.ssa.copy.p0s_{{.+}}s(%0* %tmp) + +%0 = type opaque +%1 = type opaque + +declare i8* @fun(%1*) + +define void @f0(%0* %arg, %1* %tmp) { +bb: + %cmp1 = icmp ne %0* %arg, null + br i1 %cmp1, label %bb1, label %bb2 + +bb1: ; preds = %bb + %cmp2 = icmp ne %1* null, %tmp + br i1 %cmp2, label %bb2, label %bb3 + +bb2: ; preds = %bb + ret void + +bb3: ; preds = %bb + call i8* @fun(%1* %tmp) + %tmp2 = bitcast %0* %arg to i8* + ret void +}