[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