[llvm] r328246 - [MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Roman Tereshin via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 22 14:29:07 PDT 2018
Author: rtereshin
Date: Thu Mar 22 14:29:07 2018
New Revision: 328246
URL: http://llvm.org/viewvc/llvm-project?rev=328246&view=rev
Log:
[MIR] Making MIR Printing, opt -dot-cfg, and -debug printing faster
Value::printAsOperand has been scanning the entire module just to
print a single value as an operand, regardless being asked to print a
type or not at all, and regardless really needing to scan the module
to print a type.
It made some of the users of the method exceptionally slow on large
IR-modules (or large MIR-files with large IR-modules embedded).
This patch defers scanning a module looking for struct types, mostly
numbered struct types, as much as possible, speeding up those users
w/o changing any APIs at all.
See speedup examples below:
Release Build:
# 83 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 133 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
Release + Asserts Build:
# 95 seconds -> 5.5 seconds
time ./bin/llc -start-before=irtranslator -stop-after=irtranslator \
-global-isel -global-isel-abort=2 -simplify-mir sqlite3.O0.ll -o \
sqlite3.O0.ll.regbankselected.mir
# 146 seconds -> 6.2 seconds
time ./bin/opt sqlite3.O0.ll -dot-cfg -disable-output
# 1096 seconds -> 553 seconds
time ./bin/llc -debug-only=isel -fast-isel=false -stop-after=isel \
sqlite3.O0.ll -o /dev/null 2> err
where sqlite3.O0.ll is non-optimized IR produced from
sqlite-amalgamation (http://sqlite.org/download.html), which is entire
SQLite3 implementation in a single C-file.
Benchmarked on 4-cores / 8 threads PCI-E SSD iMac running macOS
Reviewers: dexonsmith, bkramer, void, chandlerc, aditya_nandakumar, dsanders, qcolombet,
Reviewed By: bogner
Subscribers: thegameg, llvm-commits
Differential Revision: https://reviews.llvm.org/D44132
Modified:
llvm/trunk/lib/IR/AsmWriter.cpp
llvm/trunk/unittests/IR/ValueTest.cpp
Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=328246&r1=328245&r2=328246&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Thu Mar 22 14:29:07 2018
@@ -458,27 +458,73 @@ namespace {
class TypePrinting {
public:
- /// NamedTypes - The named types that are used by the current module.
- TypeFinder NamedTypes;
-
- /// NumberedTypes - The numbered types, along with their value.
- DenseMap<StructType*, unsigned> NumberedTypes;
+ TypePrinting(const Module *M = nullptr) : DeferredM(M) {}
- TypePrinting() = default;
TypePrinting(const TypePrinting &) = delete;
TypePrinting &operator=(const TypePrinting &) = delete;
- void incorporateTypes(const Module &M);
+ /// The named types that are used by the current module.
+ TypeFinder &getNamedTypes();
+
+ /// The numbered types, number to type mapping.
+ std::vector<StructType *> &getNumberedTypes();
+
+ bool empty();
void print(Type *Ty, raw_ostream &OS);
void printStructBody(StructType *Ty, raw_ostream &OS);
+
+private:
+ void incorporateTypes();
+
+ /// A module to process lazily when needed. Set to nullptr as soon as used.
+ const Module *DeferredM;
+
+ TypeFinder NamedTypes;
+
+ // The numbered types, along with their value.
+ DenseMap<StructType *, unsigned> Type2Number;
+
+ std::vector<StructType *> NumberedTypes;
};
} // end anonymous namespace
-void TypePrinting::incorporateTypes(const Module &M) {
- NamedTypes.run(M, false);
+TypeFinder &TypePrinting::getNamedTypes() {
+ incorporateTypes();
+ return NamedTypes;
+}
+
+std::vector<StructType *> &TypePrinting::getNumberedTypes() {
+ incorporateTypes();
+
+ // We know all the numbers that each type is used and we know that it is a
+ // dense assignment. Convert the map to an index table, if it's not done
+ // already (judging from the sizes):
+ if (NumberedTypes.size() == Type2Number.size())
+ return NumberedTypes;
+
+ NumberedTypes.resize(Type2Number.size());
+ for (const auto &P : Type2Number) {
+ assert(P.second < NumberedTypes.size() && "Didn't get a dense numbering?");
+ assert(!NumberedTypes[P.second] && "Didn't get a unique numbering?");
+ NumberedTypes[P.second] = P.first;
+ }
+ return NumberedTypes;
+}
+
+bool TypePrinting::empty() {
+ incorporateTypes();
+ return NamedTypes.empty() && Type2Number.empty();
+}
+
+void TypePrinting::incorporateTypes() {
+ if (!DeferredM)
+ return;
+
+ NamedTypes.run(*DeferredM, false);
+ DeferredM = nullptr;
// The list of struct types we got back includes all the struct types, split
// the unnamed ones out to a numbering and remove the anonymous structs.
@@ -493,7 +539,7 @@ void TypePrinting::incorporateTypes(cons
continue;
if (STy->getName().empty())
- NumberedTypes[STy] = NextNumber++;
+ Type2Number[STy] = NextNumber++;
else
*NextToUse++ = STy;
}
@@ -501,9 +547,8 @@ void TypePrinting::incorporateTypes(cons
NamedTypes.erase(NextToUse, NamedTypes.end());
}
-
-/// CalcTypeName - Write the specified type to the specified raw_ostream, making
-/// use of type names or up references to shorten the type name where possible.
+/// Write the specified type to the specified raw_ostream, making use of type
+/// names or up references to shorten the type name where possible.
void TypePrinting::print(Type *Ty, raw_ostream &OS) {
switch (Ty->getTypeID()) {
case Type::VoidTyID: OS << "void"; return;
@@ -547,8 +592,9 @@ void TypePrinting::print(Type *Ty, raw_o
if (!STy->getName().empty())
return PrintLLVMName(OS, STy->getName(), LocalPrefix);
- DenseMap<StructType*, unsigned>::iterator I = NumberedTypes.find(STy);
- if (I != NumberedTypes.end())
+ incorporateTypes();
+ const auto I = Type2Number.find(STy);
+ if (I != Type2Number.end())
OS << '%' << I->second;
else // Not enumerated, print the hex address.
OS << "%\"type " << STy << '\"';
@@ -2206,12 +2252,11 @@ private:
AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
const Module *M, AssemblyAnnotationWriter *AAW,
bool IsForDebug, bool ShouldPreserveUseListOrder)
- : Out(o), TheModule(M), Machine(Mac), AnnotationWriter(AAW),
+ : Out(o), TheModule(M), Machine(Mac), TypePrinter(M), AnnotationWriter(AAW),
IsForDebug(IsForDebug),
ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {
if (!TheModule)
return;
- TypePrinter.incorporateTypes(*TheModule);
for (const GlobalObject &GO : TheModule->global_objects())
if (const Comdat *C = GO.getComdat())
Comdats.insert(C);
@@ -2665,39 +2710,30 @@ void AssemblyWriter::printComdat(const C
}
void AssemblyWriter::printTypeIdentities() {
- if (TypePrinter.NumberedTypes.empty() &&
- TypePrinter.NamedTypes.empty())
+ if (TypePrinter.empty())
return;
Out << '\n';
- // We know all the numbers that each type is used and we know that it is a
- // dense assignment. Convert the map to an index table.
- std::vector<StructType*> NumberedTypes(TypePrinter.NumberedTypes.size());
- for (DenseMap<StructType*, unsigned>::iterator I =
- TypePrinter.NumberedTypes.begin(), E = TypePrinter.NumberedTypes.end();
- I != E; ++I) {
- assert(I->second < NumberedTypes.size() && "Didn't get a dense numbering?");
- NumberedTypes[I->second] = I->first;
- }
-
// Emit all numbered types.
- for (unsigned i = 0, e = NumberedTypes.size(); i != e; ++i) {
- Out << '%' << i << " = type ";
+ auto &NumberedTypes = TypePrinter.getNumberedTypes();
+ for (unsigned I = 0, E = NumberedTypes.size(); I != E; ++I) {
+ Out << '%' << I << " = type ";
// Make sure we print out at least one level of the type structure, so
// that we do not get %2 = type %2
- TypePrinter.printStructBody(NumberedTypes[i], Out);
+ TypePrinter.printStructBody(NumberedTypes[I], Out);
Out << '\n';
}
- for (unsigned i = 0, e = TypePrinter.NamedTypes.size(); i != e; ++i) {
- PrintLLVMName(Out, TypePrinter.NamedTypes[i]->getName(), LocalPrefix);
+ auto &NamedTypes = TypePrinter.getNamedTypes();
+ for (unsigned I = 0, E = NamedTypes.size(); I != E; ++I) {
+ PrintLLVMName(Out, NamedTypes[I]->getName(), LocalPrefix);
Out << " = type ";
// Make sure we print out at least one level of the type structure, so
// that we do not get %FILE = type %FILE
- TypePrinter.printStructBody(TypePrinter.NamedTypes[i], Out);
+ TypePrinter.printStructBody(NamedTypes[I], Out);
Out << '\n';
}
}
@@ -3567,9 +3603,7 @@ static bool printWithoutType(const Value
static void printAsOperandImpl(const Value &V, raw_ostream &O, bool PrintType,
ModuleSlotTracker &MST) {
- TypePrinting TypePrinter;
- if (const Module *M = MST.getModule())
- TypePrinter.incorporateTypes(*M);
+ TypePrinting TypePrinter(MST.getModule());
if (PrintType) {
TypePrinter.print(V.getType(), O);
O << ' ';
@@ -3608,9 +3642,7 @@ static void printMetadataImpl(raw_ostrea
bool OnlyAsOperand) {
formatted_raw_ostream OS(ROS);
- TypePrinting TypePrinter;
- if (M)
- TypePrinter.incorporateTypes(*M);
+ TypePrinting TypePrinter(M);
WriteAsOperandInternal(OS, &MD, &TypePrinter, MST.getMachine(), M,
/* FromValue */ true);
Modified: llvm/trunk/unittests/IR/ValueTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/ValueTest.cpp?rev=328246&r1=328245&r2=328246&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/ValueTest.cpp (original)
+++ llvm/trunk/unittests/IR/ValueTest.cpp Thu Mar 22 14:29:07 2018
@@ -112,7 +112,13 @@ TEST(ValueTest, printSlots) {
// without a slot tracker.
LLVMContext C;
- const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"
+ const char *ModuleString = "@g0 = external global %500\n"
+ "@g1 = external global %900\n"
+ "\n"
+ "%900 = type { i32, i32 }\n"
+ "%500 = type { i32 }\n"
+ "\n"
+ "define void @f(i32 %x, i32 %y) {\n"
"entry:\n"
" %0 = add i32 %y, 1\n"
" %1 = add i32 %y, 1\n"
@@ -132,6 +138,11 @@ TEST(ValueTest, printSlots) {
Instruction *I1 = &*++BB.begin();
ASSERT_TRUE(I1);
+ GlobalVariable *G0 = M->getGlobalVariable("g0");
+ ASSERT_TRUE(G0);
+ GlobalVariable *G1 = M->getGlobalVariable("g1");
+ ASSERT_TRUE(G1);
+
ModuleSlotTracker MST(M.get());
#define CHECK_PRINT(INST, STR) \
@@ -172,6 +183,8 @@ TEST(ValueTest, printSlots) {
CHECK_PRINT_AS_OPERAND(I1, false, "%1");
CHECK_PRINT_AS_OPERAND(I0, true, "i32 %0");
CHECK_PRINT_AS_OPERAND(I1, true, "i32 %1");
+ CHECK_PRINT_AS_OPERAND(G0, true, "%0* @g0");
+ CHECK_PRINT_AS_OPERAND(G1, true, "%1* @g1");
#undef CHECK_PRINT_AS_OPERAND
}
More information about the llvm-commits
mailing list