Index: include/llvm/Transforms/Utils/PredicateInfo.h =================================================================== --- include/llvm/Transforms/Utils/PredicateInfo.h +++ include/llvm/Transforms/Utils/PredicateInfo.h @@ -261,6 +261,9 @@ // The set of edges along which we can only handle phi uses, due to critical // edges. DenseSet> EdgeUsesOnly; + // The set of ssa_copy declarations we created or already existed and had 0 + // users. + SmallPtrSet CreatedDeclarations; }; // This pass does eager building and then printing of PredicateInfo. It is used Index: lib/Transforms/Utils/PredicateInfo.cpp =================================================================== --- lib/Transforms/Utils/PredicateInfo.cpp +++ lib/Transforms/Utils/PredicateInfo.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CFG.h" #include "llvm/IR/AssemblyAnnotationWriter.h" @@ -24,6 +25,7 @@ #include "llvm/IR/Dominators.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" @@ -479,6 +481,97 @@ renameUses(OpsToRename); } +// A modified version of getMangledTypeStr from lib/IR/Function.cpp, which uses +// the pointer to a unnamed type in the mangled name. This guarantees unique +// names for different unnamed types, even when building PredicateInfo for +// multiple functions and is a workaround for PR38117, because solving it in a +// fully general way is tricky (FIXME). +static std::string +getMangledTypeStr(Type *Ty) { + std::string Result; + if (PointerType *PTyp = dyn_cast(Ty)) { + Result += "p" + utostr(PTyp->getAddressSpace()) + + getMangledTypeStr(PTyp->getElementType()); + } else if (ArrayType *ATyp = dyn_cast(Ty)) { + Result += "a" + utostr(ATyp->getNumElements()) + + getMangledTypeStr(ATyp->getElementType()); + } else if (StructType *STyp = dyn_cast(Ty)) { + if (!STyp->isLiteral()) { + Result += "s_"; + if (STyp->hasName()) + Result += STyp->getName(); + else + Result += utostr((uintptr_t) STyp); + } else { + Result += "sl_"; + for (auto Elem : STyp->elements()) + Result += getMangledTypeStr(Elem); + } + // Ensure nested structs are distinguishable. + Result += "s"; + } else if (FunctionType *FT = dyn_cast(Ty)) { + Result += "f_" + getMangledTypeStr(FT->getReturnType()); + for (size_t i = 0; i < FT->getNumParams(); i++) + Result += getMangledTypeStr(FT->getParamType(i)); + if (FT->isVarArg()) + Result += "vararg"; + // Ensure nested function types are distinguishable. + Result += "f"; + } else if (isa(Ty)) { + Result += "v" + utostr(Ty->getVectorNumElements()) + + getMangledTypeStr(Ty->getVectorElementType()); + } else if (Ty) { + switch (Ty->getTypeID()) { + default: + llvm_unreachable("Unhandled type"); + case Type::VoidTyID: + Result += "isVoid"; + break; + case Type::MetadataTyID: + Result += "Metadata"; + break; + case Type::HalfTyID: + Result += "f16"; + break; + case Type::FloatTyID: + Result += "f32"; + break; + case Type::DoubleTyID: + Result += "f64"; + break; + case Type::X86_FP80TyID: + Result += "f80"; + break; + case Type::FP128TyID: + Result += "f128"; + break; + case Type::PPC_FP128TyID: + Result += "ppcf128"; + break; + case Type::X86_MMXTyID: + Result += "x86mmx"; + break; + case Type::IntegerTyID: + Result += "i" + utostr(cast(Ty)->getBitWidth()); + break; + } + } + return Result; +} + +// Create ssa_copy declaration with custom mangling, to support different +// unnamed types. We remove the declarations when destroying PredicateInfo, +// because it would fail re-mangling. +static Function * +getCopyDeclaration(Module *M, ArrayRef Tys) { + std::string Name("llvm.ssa.copy"); + for (Type *Ty : Tys) + Name += "." + getMangledTypeStr(Ty); + + return cast(M->getOrInsertFunction( + Name, getType(M->getContext(), Intrinsic::ssa_copy, Tys))); +} + // Given the renaming stack, make all the operands currently on the stack real // by inserting them into the IR. Return the last operation's value. Value *PredicateInfo::materializeStack(unsigned int &Counter, @@ -507,8 +600,12 @@ // order in the case of multiple predicateinfo in the same block. if (isa(ValInfo)) { IRBuilder<> B(getBranchTerminator(ValInfo)); - Function *IF = Intrinsic::getDeclaration( - F.getParent(), Intrinsic::ssa_copy, Op->getType()); + Function *IF = + getCopyDeclaration(F.getParent(), Op->getType()); + // If we created the declaration or it has zero users, we have to remove + // it. + if (IF->user_begin() == IF->user_end()) + CreatedDeclarations.insert(IF); CallInst *PIC = B.CreateCall(IF, Op, Op->getName() + "." + Twine(Counter++)); PredicateMap.insert({PIC, ValInfo}); @@ -518,9 +615,13 @@ assert(PAssume && "Should not have gotten here without it being an assume"); IRBuilder<> B(PAssume->AssumeInst); - Function *IF = Intrinsic::getDeclaration( - F.getParent(), Intrinsic::ssa_copy, Op->getType()); + Function *IF = + getCopyDeclaration(F.getParent(), Op->getType()); CallInst *PIC = B.CreateCall(IF, Op); + // If we created the declaration or it has zero users, we have to remove + // it. + if (IF->user_begin() == IF->user_end()) + CreatedDeclarations.insert(IF); PredicateMap.insert({PIC, ValInfo}); Result.Def = PIC; } @@ -704,7 +805,16 @@ buildPredicateInfo(); } -PredicateInfo::~PredicateInfo() {} +PredicateInfo::~PredicateInfo() { + // Remove all declarations we created or had 0 users before. The + // PredicateInfo consumers are responsible for remove the ssa_copy calls + // created. + for (Function *F : CreatedDeclarations) { + assert(F->user_begin() == F->user_end() && + "PredicateInfo consumer did not remove all SSA copies."); + F->eraseFromParent(); + } +} void PredicateInfo::verifyPredicateInfo() const {} @@ -722,6 +832,20 @@ AU.addRequired(); } +// Replace ssa_copy calls created by PredicateInfo with their operand. +static void replaceCreatedSSACopys(PredicateInfo &PredInfo, Function &F) { + for (auto I = inst_begin(F), E = inst_end(F); I != E;) { + Instruction *Inst = &*I++; + const auto *PI = PredInfo.getPredicateInfoFor(Inst); + auto *II = dyn_cast(Inst); + if (!PI || !II || II->getIntrinsicID() != Intrinsic::ssa_copy) + continue; + + Inst->replaceAllUsesWith(II->getOperand(0)); + Inst->eraseFromParent(); + } +} + bool PredicateInfoPrinterLegacyPass::runOnFunction(Function &F) { auto &DT = getAnalysis().getDomTree(); auto &AC = getAnalysis().getAssumptionCache(F); @@ -729,6 +853,8 @@ PredInfo->print(dbgs()); if (VerifyPredicateInfo) PredInfo->verifyPredicateInfo(); + + replaceCreatedSSACopys(*PredInfo, F); return false; } @@ -737,8 +863,10 @@ auto &DT = AM.getResult(F); auto &AC = AM.getResult(F); OS << "PredicateInfo for function: " << F.getName() << "\n"; - make_unique(F, DT, AC)->print(OS); + auto PredInfo = make_unique(F, DT, AC); + PredInfo->print(OS); + replaceCreatedSSACopys(*PredInfo, F); return PreservedAnalyses::all(); } Index: test/Transforms/NewGVN/pr33305.ll =================================================================== --- test/Transforms/NewGVN/pr33305.ll +++ test/Transforms/NewGVN/pr33305.ll @@ -76,7 +76,7 @@ ; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[PUTS2:%.*]] = tail call i32 @puts(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @str.2, i64 0, i64 0)) -; CHECK-NEXT: tail call void @abort() #4 +; CHECK-NEXT: tail call void @abort() ; CHECK-NEXT: unreachable ; CHECK: if.end: ; CHECK-NEXT: [[PUTS:%.*]] = tail call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @str, i64 0, i64 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 + +%1 = type opaque +%0 = type opaque + +; 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 %0* %arg, null Edge: [label %bb,label %bb1] } +; CHECK-NEXT: %arg.0 = call %0* @llvm.ssa.copy.{{.+}}(%0* %arg) + +; CHECK-LABEL: bb1: +; CHECK: Has predicate info +; CHECK-NEXT: branch predicate info { TrueEdge: 0 Comparison: %cmp2 = icmp ne %1* null, %tmp Edge: [label %bb1,label %bb3] } +; CHECK-NAME: %tmp.0 = call %1* @llvm.ssa.copy.{{.+}}(%1* %tmp) + +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 + %u1 = call i8* @fun(%1* %tmp) + %tmp2 = bitcast %0* %arg to i8* + ret void +} + +declare i8* @fun(%1*)