From c97536e6a7834212aafd25f2673234fc88b5e5bb Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 17 Aug 2008 04:40:13 +0000 Subject: [PATCH] avoid string thrashing when formatting names in output. This speeds up release-asserts llvm-dis on kc++ from 1.86s to 1.04s (~79%) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54868 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/VMCore/AsmWriter.cpp | 184 +++++++++++++++++++++++++++------------ 1 file changed, 130 insertions(+), 54 deletions(-) diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 3b2dca22da3..fa512e01711 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -211,6 +211,72 @@ static std::string getLLVMName(const std::string &Name, PrefixType Prefix) { } } +/// PrintLLVMName - Turn the specified name into an 'LLVM name', which is either +/// prefixed with % (if the string only contains simple characters) or is +/// surrounded with ""'s (if it has special chars in it). Print it out. +static void PrintLLVMName(std::ostream &OS, const ValueName *Name, + PrefixType Prefix) { + assert(Name && "Cannot get empty name!"); + switch (Prefix) { + default: assert(0 && "Bad prefix!"); + case GlobalPrefix: OS << '@'; break; + case LabelPrefix: break; + case LocalPrefix: OS << '%'; break; + } + + // Scan the name to see if it needs quotes first. + const char *NameStr = Name->getKeyData(); + unsigned NameLen = Name->getKeyLength(); + + bool NeedsQuotes = NameStr[0] >= '0' && NameStr[0] <= '9'; + if (!NeedsQuotes) { + for (unsigned i = 0; i != NameLen; ++i) { + char C = NameStr[i]; + if (!isalnum(C) && C != '-' && C != '.' && C != '_') { + NeedsQuotes = true; + break; + } + } + } + + // If we didn't need any quotes, just write out the name in one blast. + if (!NeedsQuotes) { + OS.write(NameStr, NameLen); + return; + } + + // Okay, we need quotes. Output the quotes and escape any scary characters as + // needed. + OS << '"'; + for (unsigned i = 0; i != NameLen; ++i) { + char C = NameStr[i]; + assert(C != '"' && "Illegal character in LLVM value name!"); + if (C == '\\') { + OS << "\\\\"; + } else if (isprint(C)) { + OS << C; + } else { + OS << "\\"; + char hex1 = (C >> 4) & 0x0F; + if (hex1 < 10) + OS << (hex1 + '0'); + else + OS << (hex1 - 10 + 'A'); + char hex2 = C & 0x0F; + if (hex2 < 10) + OS << (hex2 + '0'); + else + OS << (hex2 - 10 + 'A'); + } + } + OS << '"'; +} + +static void PrintLLVMName(std::ostream &OS, const Value *V) { + PrintLLVMName(OS, V->getValueName(), + isa(V) ? GlobalPrefix : LocalPrefix); +} + /// fillTypeNameTable - If the module has a symbol table, take all global types /// and stuff their names into the TypeNames map. @@ -626,25 +692,35 @@ static void WriteAsOperandInternal(std::ostream &Out, const Value *V, std::map &TypeTable, SlotMachine *Machine) { Out << ' '; - if (V->hasName()) - Out << getLLVMName(V->getName(), - isa(V) ? GlobalPrefix : LocalPrefix); - else { - const Constant *CV = dyn_cast(V); - if (CV && !isa(CV)) { - WriteConstantInt(Out, CV, TypeTable, Machine); - } else if (const InlineAsm *IA = dyn_cast(V)) { - Out << "asm "; - if (IA->hasSideEffects()) - Out << "sideeffect "; - Out << '"'; - PrintEscapedString(IA->getAsmString(), Out); - Out << "\", \""; - PrintEscapedString(IA->getConstraintString(), Out); - Out << '"'; + if (V->hasName()) { + PrintLLVMName(Out, V); + return; + } + + const Constant *CV = dyn_cast(V); + if (CV && !isa(CV)) { + WriteConstantInt(Out, CV, TypeTable, Machine); + } else if (const InlineAsm *IA = dyn_cast(V)) { + Out << "asm "; + if (IA->hasSideEffects()) + Out << "sideeffect "; + Out << '"'; + PrintEscapedString(IA->getAsmString(), Out); + Out << "\", \""; + PrintEscapedString(IA->getConstraintString(), Out); + Out << '"'; + } else { + char Prefix = '%'; + int Slot; + if (Machine) { + if (const GlobalValue *GV = dyn_cast(V)) { + Slot = Machine->getGlobalSlot(GV); + Prefix = '@'; + } else { + Slot = Machine->getLocalSlot(V); + } } else { - char Prefix = '%'; - int Slot; + Machine = createSlotMachine(V); if (Machine) { if (const GlobalValue *GV = dyn_cast(V)) { Slot = Machine->getGlobalSlot(GV); @@ -653,24 +729,14 @@ static void WriteAsOperandInternal(std::ostream &Out, const Value *V, Slot = Machine->getLocalSlot(V); } } else { - Machine = createSlotMachine(V); - if (Machine) { - if (const GlobalValue *GV = dyn_cast(V)) { - Slot = Machine->getGlobalSlot(GV); - Prefix = '@'; - } else { - Slot = Machine->getLocalSlot(V); - } - } else { - Slot = -1; - } - delete Machine; + Slot = -1; } - if (Slot != -1) - Out << Prefix << Slot; - else - Out << ""; + delete Machine; } + if (Slot != -1) + Out << Prefix << Slot; + else + Out << ""; } } @@ -900,7 +966,10 @@ void AssemblyWriter::printModule(const Module *M) { } void AssemblyWriter::printGlobal(const GlobalVariable *GV) { - if (GV->hasName()) Out << getLLVMName(GV->getName(), GlobalPrefix) << " = "; + if (GV->hasName()) { + PrintLLVMName(Out, GV); + Out << " = "; + } if (!GV->hasInitializer()) { switch (GV->getLinkage()) { @@ -935,11 +1004,8 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { Out << (GV->isConstant() ? "constant " : "global "); printType(GV->getType()->getElementType()); - if (GV->hasInitializer()) { - Constant* C = cast(GV->getInitializer()); - assert(C && "GlobalVar initializer isn't constant?"); + if (GV->hasInitializer()) writeOperand(GV->getInitializer(), false); - } if (unsigned AddressSpace = GV->getType()->getAddressSpace()) Out << " addrspace(" << AddressSpace << ") "; @@ -957,8 +1023,10 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { // Don't crash when dumping partially built GA if (!GA->hasName()) Out << "<> = "; - else - Out << getLLVMName(GA->getName(), GlobalPrefix) << " = "; + else { + PrintLLVMName(Out, GA); + Out << " = "; + } switch (GA->getVisibility()) { default: assert(0 && "Invalid visibility style!"); case GlobalValue::DefaultVisibility: break; @@ -980,18 +1048,20 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { if (const GlobalVariable *GV = dyn_cast(Aliasee)) { printType(GV->getType()); - Out << " " << getLLVMName(GV->getName(), GlobalPrefix); + Out << ' '; + PrintLLVMName(Out, GV); } else if (const Function *F = dyn_cast(Aliasee)) { printType(F->getFunctionType()); Out << "* "; - if (!F->getName().empty()) - Out << getLLVMName(F->getName(), GlobalPrefix); + if (!F->hasName()) + PrintLLVMName(Out, F); else Out << "@\"\""; } else if (const GlobalAlias *GA = dyn_cast(Aliasee)) { printType(GA->getType()); - Out << " " << getLLVMName(GA->getName(), GlobalPrefix); + Out << " "; + PrintLLVMName(Out, GA); } else { const ConstantExpr *CE = 0; if ((CE = dyn_cast(Aliasee)) && @@ -1067,7 +1137,7 @@ void AssemblyWriter::printFunction(const Function *F) { const PAListPtr &Attrs = F->getParamAttrs(); printType(F->getReturnType()) << ' '; if (!F->getName().empty()) - Out << getLLVMName(F->getName(), GlobalPrefix); + PrintLLVMName(Out, F); else Out << "@\"\""; Out << '('; @@ -1144,15 +1214,19 @@ void AssemblyWriter::printArgument(const Argument *Arg, Out << ' ' << ParamAttr::getAsString(Attrs); // Output name, if available... - if (Arg->hasName()) - Out << ' ' << getLLVMName(Arg->getName(), LocalPrefix); + if (Arg->hasName()) { + Out << ' '; + PrintLLVMName(Out, Arg); + } } /// printBasicBlock - This member is called for each basic block in a method. /// void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { if (BB->hasName()) { // Print out the label if it exists... - Out << "\n" << getLLVMName(BB->getName(), LabelPrefix) << ':'; + Out << "\n"; + PrintLLVMName(Out, BB->getValueName(), LabelPrefix); + Out << ':'; } else if (!BB->use_empty()) { // Don't print block # of no uses... Out << "\n;