[llvm-commits] [PATCH] Asm Loop Nest Comments
David Greene
dag at cray.com
Thu Jul 30 15:39:25 PDT 2009
This patch adds some comments on basic blocks detailing their loop nesting
information. It's rather verbose and expensive to generate so I put it
under an -asm-exuberant flag.
This output allows static analysis of various codegen problems and their
performance implications.
Feedback requested.
-Dave
Index: include/llvm/CodeGen/AsmPrinter.h
===================================================================
--- include/llvm/CodeGen/AsmPrinter.h (revision 77464)
+++ include/llvm/CodeGen/AsmPrinter.h (working copy)
@@ -29,6 +29,8 @@
class ConstantVector;
class GCMetadataPrinter;
class GlobalVariable;
+ class LoopInfo;
+ class Loop;
class MachineConstantPoolEntry;
class MachineConstantPoolValue;
class MachineModuleInfo;
@@ -60,6 +62,15 @@
typedef gcp_map_type::iterator gcp_iterator;
gcp_map_type GCMetadataPrinters;
+ LoopInfo *LI;
+
+ typedef DenseMap<const Loop *, MachineFunction::iterator>
+ LoopHeaderMapType;
+ LoopHeaderMapType LoopHeaderMap;
+
+ void MapLoops(MachineFunction &Fn);
+ void PrintChildLoopComment(const Loop *loop) const;
+
protected:
/// MMI - If available, this is a pointer to the current
MachineModuleInfo.
MachineModuleInfo *MMI;
@@ -123,6 +134,11 @@
///
bool VerboseAsm;
+ /// ExuberantAsm - Emit many more comments in assembly output if
+ /// this is true.
+ ///
+ bool ExuberantAsm;
+
/// Private state for PrintSpecial()
// Assign a unique ID to this machine instruction.
mutable const MachineInstr *LastMI;
@@ -226,11 +242,10 @@
unsigned AsmVariant,
const char *ExtraCode);
-
/// PrintGlobalVariable - Emit the specified global variable and its
/// initializer to the output stream.
virtual void PrintGlobalVariable(const GlobalVariable *GV) = 0;
-
+
/// SetupMachineFunction - This should be called when a new
MachineFunction
/// is being processed from runOnMachineFunction.
void SetupMachineFunction(MachineFunction &MF);
@@ -355,6 +370,8 @@
void EmitComments(const MachineInstr &MI) const;
/// EmitComments - Pretty-print comments for instructions
void EmitComments(const MCInst &MI) const;
+ /// EmitComments - Pretty-print comments for basic blocks
+ void EmitComments(const MachineBasicBlock &MBB) const;
protected:
/// EmitZeros - Emit a block of zeros.
Index: include/llvm/Support/IOManip.h
===================================================================
--- include/llvm/Support/IOManip.h (revision 0)
+++ include/llvm/Support/IOManip.h (revision 0)
@@ -0,0 +1,47 @@
+//===----------------- IOManip.h - iostream manipulators ---------*- C++
-*===//
+//
+// The LLVM Compiler Infrastructure///
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Manipulators to do special-purpose formatting.
+//
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+ /// Indent - Insert spaces into the character output stream. The
+ /// "level" is multiplied by the "scale" to calculate the number of
+ /// spaces to insert. "level" can represent something like loop
+ /// nesting level, for example.
+ ///
+ class Indent {
+ public:
+ explicit Indent(int lvl, int amt = 3)
+ : level(lvl), scale(amt) {}
+
+ template<typename OStream>
+ OStream &operator()(OStream &out) const {
+ for(int i = 0; i < level*scale; ++i) {
+ out << " ";
+ }
+ return(out);
+ }
+
+ private:
+ int level;
+ int scale;
+ };
+
+ template<typename OStream>
+ OStream &operator<<(OStream &out, const Indent &indent)
+ {
+ return(indent(out));
+ }
+
+ inline Indent indent(int lvl, int amt = 3) {
+ return(Indent(lvl, amt));
+ }
+}
Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp
===================================================================
--- lib/CodeGen/AsmPrinter/AsmPrinter.cpp (revision 77464)
+++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp (working copy)
@@ -22,12 +22,14 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/Analysis/DebugInfo.h"
+#include "llvm/Analysis/LoopInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/IOManip.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
@@ -45,6 +47,10 @@
AsmVerbose("asm-verbose", cl::desc("Add comments to directives."),
cl::init(cl::BOU_UNSET));
+static cl::opt<cl::boolOrDefault>
+AsmExuberant("asm-exuberant", cl::desc("Add many comments."),
+ cl::init(cl::BOU_FALSE));
+
char AsmPrinter::ID = 0;
AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm,
const TargetAsmInfo *T, bool VDef)
@@ -62,6 +68,11 @@
case cl::BOU_TRUE: VerboseAsm = true; break;
case cl::BOU_FALSE: VerboseAsm = false; break;
}
+ switch (AsmExuberant) {
+ case cl::BOU_UNSET: ExuberantAsm = false; break;
+ case cl::BOU_TRUE: ExuberantAsm = true; break;
+ case cl::BOU_FALSE: ExuberantAsm = false; break;
+ }
}
AsmPrinter::~AsmPrinter() {
@@ -170,6 +181,9 @@
void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
MachineFunctionPass::getAnalysisUsage(AU);
AU.addRequired<GCModuleInfo>();
+ if (ExuberantAsm) {
+ AU.addRequired<LoopInfo>();
+ }
}
bool AsmPrinter::doInitialization(Module &M) {
@@ -299,6 +313,12 @@
// What's my mangled name?
CurrentFnName = Mang->getMangledName(MF.getFunction());
IncrementFunctionNumber();
+
+ if (ExuberantAsm) {
+ LI = &getAnalysis<LoopInfo>();
+ LoopHeaderMap.clear();
+ MapLoops(MF);
+ }
}
namespace {
@@ -1626,9 +1646,9 @@
<< MBB->getNumber();
if (printColon)
O << ':';
- if (printComment && MBB->getBasicBlock())
- O << '\t' << TAI->getCommentString() << ' '
- << MBB->getBasicBlock()->getNameStr();
+ if (printComment) {
+ EmitComments(*MBB);
+ }
}
/// printPICJumpTableSetLabel - This method prints a set label for the
@@ -1759,7 +1779,7 @@
if (NameString->isString()) {
O << NameString->getAsString() << " ";
}
- }
+ }
O << DLT.Line;
if (DLT.Col != 0)
O << ":" << DLT.Col;
@@ -1790,3 +1810,106 @@
}
}
}
+
+/// EmitComments - Pretty-print comments for basic blocks
+void AsmPrinter::EmitComments(const MachineBasicBlock &MBB) const
+{
+ O.PadToColumn(TAI->getCommentColumn(), 1);
+
+ if (MBB.getBasicBlock())
+ O << '\t' << TAI->getCommentString() << ' '
+ << MBB.getBasicBlock()->getNameStr();
+
+ if (ExuberantAsm) {
+ // Add loop depth information
+ const Loop *loop = LI->getLoopFor(MBB.getBasicBlock());
+ if (loop) {
+ O << "\n";
+ O.PadToColumn(TAI->getCommentColumn(), 1);
+ O << TAI->getCommentString() << " Loop Depth " << loop->getLoopDepth()
+ << '\n';
+
+ LoopHeaderMapType::iterator i = LoopHeaderMap.find(loop);
+
+ O.PadToColumn(TAI->getCommentColumn(), 1);
+ if (i != LoopHeaderMap.end()) {
+ if (i->second == &MBB) {
+ O << TAI->getCommentString() << " Loop Header";
+ PrintChildLoopComment(loop);
+ }
+ else {
+ O << TAI->getCommentString() << " Loop Header is BB"
+ << getFunctionNumber() << "_" << i->second->getNumber();
+ }
+ }
+ else {
+ O << TAI->getCommentString() << " Unknown Loop Header BB "
+ << CurrentFnName << "_<unmapped basic block>";
+ }
+
+ if (loop->empty()) {
+ O << '\n';
+ O.PadToColumn(TAI->getCommentColumn(), 1);
+ O << TAI->getCommentString() << " Inner Loop";
+ }
+
+ // Add parent loop information
+ for (const Loop *CurLoop = loop->getParentLoop();
+ CurLoop;
+ CurLoop = CurLoop->getParentLoop()) {
+ LoopHeaderMapType::iterator j = LoopHeaderMap.find(CurLoop);
+
+ O << '\n';
+ O.PadToColumn(TAI->getCommentColumn(), 1);
+ if (j != LoopHeaderMap.end()) {
+ O << TAI->getCommentString() << indent(CurLoop->getLoopDepth()-1)
+ << " Inside Loop BB" << getFunctionNumber() << "_"
+ << j->second->getNumber() << " Depth " <<
CurLoop->getLoopDepth();
+ }
+ else {
+ O << TAI->getCommentString() << indent(CurLoop->getLoopDepth()-1)
+ << " Inside Loop BB " << CurrentFnName << "_<unmapped basic
block>"
+ << " Depth " << CurLoop->getLoopDepth();
+ }
+ }
+ }
+ }
+}
+
+void AsmPrinter::MapLoops(MachineFunction &Fn) {
+ // Find which machine basic block is the header for each loop
+ for(MachineFunction::iterator MBBI = Fn.begin(), MBBIEnd = Fn.end();
+ MBBI != MBBIEnd;
+ ++MBBI) {
+ Loop *loop = LI->getLoopFor(MBBI->getBasicBlock());
+ if (loop && loop->getHeader() == MBBI->getBasicBlock()) {
+ LoopHeaderMap.insert(std::make_pair(loop, MBBI));
+ }
+ }
+}
+
+void AsmPrinter::PrintChildLoopComment(const Loop *loop) const {
+ // Add child loop information
+ for(Loop::iterator cl = loop->begin(),
+ clend = loop->end();
+ cl != clend;
+ ++cl) {
+ LoopHeaderMapType::const_iterator cli = LoopHeaderMap.find(*cl);
+
+ O << '\n';
+ O.PadToColumn(TAI->getCommentColumn(), 1);
+
+ if (cli != LoopHeaderMap.end()) {
+ O << TAI->getCommentString() << indent((*cl)->getLoopDepth()-1)
+ << " Child Loop BB" << getFunctionNumber() << "_"
+ << cli->second->getNumber() << " Depth " << (*cl)->getLoopDepth();
+ }
+ else {
+ O << TAI->getCommentString() << indent((*cl)->getLoopDepth()-1)
+ << " Child Loop BB " << CurrentFnName << "_<unmapped basic block>"
+ << " Depth " << (*cl)->getLoopDepth();
+ }
+
+ PrintChildLoopComment(*cl);
+ }
+}
More information about the llvm-commits
mailing list