Index: llvm/lib/IR/Value.cpp =================================================================== --- llvm/lib/IR/Value.cpp +++ llvm/lib/IR/Value.cpp @@ -315,45 +315,43 @@ } void Value::setNameImpl(const Twine &NewName) { - // Fast-path: LLVMContext can be set to strip out non-GlobalValue names - if (getContext().shouldDiscardValueNames() && !isa(this)) - return; - // Fast path for common IRBuilder case of setName("") when there is no name. if (NewName.isTriviallyEmpty() && !hasName()) return; - SmallString<256> NameData; - StringRef NameRef = NewName.toStringRef(NameData); - assert(NameRef.find_first_of(0) == StringRef::npos && - "Null bytes are not allowed in names"); - - // Name isn't changing? - if (getName() == NameRef) - return; - - assert(!getType()->isVoidTy() && "Cannot assign a name to void values!"); - // Get the symbol table to update for this object. ValueSymbolTable *ST; if (getSymTab(this, ST)) return; // Cannot set a name on this value (e.g. constant). - if (!ST) { // No symbol table to update? Just do the change. - if (NameRef.empty()) { - // Free the name for this value. - destroyValueName(); + // Avoiding NewName.toStringRef(NameData) initialize and use NameData and + // NameRef only if they are needed to set the new name. Even if the new name + // is not needed the current name still needs to be removed. + SmallString<256> NameData; + StringRef NameRef; + + if ((!getContext().shouldDiscardValueNames() || isa(this)) && + !NewName.isTriviallyEmpty()) { + NameRef = NewName.toStringRef(NameData); + assert(NameRef.find_first_of(0) == StringRef::npos && + "Null bytes are not allowed in names"); + + // Name isn't changing? + if (getName() == NameRef) return; - } + } - // NOTE: Could optimize for the case the name is shrinking to not deallocate - // then reallocated. - destroyValueName(); + assert((NameRef.empty() || !getType()->isVoidTy()) && + "Cannot assign a name to void values!"); + if (!ST) { // No symbol table to update? Just do the change. + destroyValueName(); // Create the new name. - MallocAllocator Allocator; - setValueName(ValueName::create(NameRef, Allocator)); - getValueName()->setValue(this); + if (!NameRef.empty()) { + MallocAllocator Allocator; + setValueName(ValueName::create(NameRef, Allocator)); + getValueName()->setValue(this); + } return; } @@ -363,13 +361,11 @@ // Remove old name. ST->removeValueName(getValueName()); destroyValueName(); - - if (NameRef.empty()) - return; } // Name is changing to something new. - setValueName(ST->createValueName(NameRef, this)); + if (!NameRef.empty()) + setValueName(ST->createValueName(NameRef, this)); } void Value::setName(const Twine &NewName) { Index: llvm/unittests/IR/BasicBlockTest.cpp =================================================================== --- llvm/unittests/IR/BasicBlockTest.cpp +++ llvm/unittests/IR/BasicBlockTest.cpp @@ -541,5 +541,44 @@ BB0->erase(BB0->begin(), BB0->end()); EXPECT_TRUE(BB0->empty()); } + +TEST(BasicBlockTest, DiscardValueNames) { + const char *ModuleString = "declare void @f(i32 %dangling)"; + SMDiagnostic Err; + LLVMContext Ctx; + { // Scope of M. + auto M = parseAssemblyString(ModuleString, Err, Ctx); + ASSERT_TRUE(M.get()); + ASSERT_FALSE(Ctx.shouldDiscardValueNames()); + } + { // Scope of M. + auto M = parseAssemblyString(ModuleString, Err, Ctx); + ASSERT_TRUE(M.get()); + Ctx.setDiscardValueNames(true); + } +} + +TEST(BasicBlockTest, DiscardValueNames2) { + SMDiagnostic Err; + LLVMContext Ctx; + Module M("Mod", Ctx); + auto FTy = FunctionType::get(Type::getVoidTy(M.getContext()), + {Type::getInt32Ty(Ctx)}, /*isVarArg=*/false); + { // Scope of F. + Function *F = Function::Create(FTy, Function::ExternalLinkage, "f", &M); + F->getArg(0)->setName("dangling"); + F->removeFromParent(); + ASSERT_FALSE(Ctx.shouldDiscardValueNames()); + delete F; + } + { // Scope of F. + Function *F = Function::Create(FTy, Function::ExternalLinkage, "f", &M); + F->getArg(0)->setName("dangling"); + F->removeFromParent(); + Ctx.setDiscardValueNames(true); + delete F; + } +} + } // End anonymous namespace. } // End llvm namespace.