[llvm-commits] [llvm] r41718 - in /llvm/trunk/lib/CodeGen: DwarfWriter.cpp MachineModuleInfo.cpp SelectionDAG/SelectionDAGISel.cpp

Duncan Sands baldrick at free.fr
Wed Sep 5 04:27:53 PDT 2007


Author: baldrick
Date: Wed Sep  5 06:27:52 2007
New Revision: 41718

URL: http://llvm.org/viewvc/llvm-project?rev=41718&view=rev
Log:
Fix PR1628.  When exception handling is turned on,
labels are generated bracketing each call (not just
invokes).  This is used to generate entries in
the exception table required by the C++ personality.
However it gets in the way of tail-merging.  This
patch solves the problem by no longer placing labels
around ordinary calls.  Instead we generate entries
in the exception table that cover every instruction
in the function that wasn't covered by an invoke
range (the range given by the labels around the invoke).
As an optimization, such entries are only generated for
parts of the function that contain a call, since for
the moment those are the only instructions that can
throw an exception [1].  As a happy consequence, we
now get a smaller exception table, since the same
region can cover many calls.  While there, I also
implemented folding of invoke ranges - successive
ranges are merged when safe to do so.  Finally, if
a selector contains only a cleanup, there's a special
shorthand for it - place a 0 in the call-site entry.
I implemented this while there.  As a result, the
exception table output (excluding filters) is now
optimal - it cannot be made smaller [2].  The
problem with throw filters is that folding them
optimally is hard, and the benefit of folding them is
minimal.

[1] I tested that having trapping instructions (eg
divide by zero) in such a region doesn't cause trouble.
[2] It could be made smaller with the help of higher
layers, eg by having branch folding reorder basic blocks
ending in invokes with the same landing pad so they
follow each other.  I don't know if this is worth doing.

Modified:
    llvm/trunk/lib/CodeGen/DwarfWriter.cpp
    llvm/trunk/lib/CodeGen/MachineModuleInfo.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Modified: llvm/trunk/lib/CodeGen/DwarfWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/DwarfWriter.cpp?rev=41718&r1=41717&r2=41718&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/DwarfWriter.cpp (original)
+++ llvm/trunk/lib/CodeGen/DwarfWriter.cpp Wed Sep  5 06:27:52 2007
@@ -2896,7 +2896,7 @@
       O << UsedDirective << EHFrameInfo.FnName << ".eh\n\n";
   }
 
-  /// EmitExceptionTable - Emit landpads and actions.
+  /// EmitExceptionTable - Emit landing pads and actions.
   ///
   /// The general organization of the table is complex, but the basic concepts
   /// are easy.  First there is a header which describes the location and
@@ -2951,19 +2951,31 @@
     static bool isPod() { return true; }
   };
 
-  struct PadSite {
-    unsigned PadIndex;
-    unsigned SiteIndex;
-  };
-
-  typedef DenseMap<unsigned, PadSite, KeyInfo> PadMapType;
-
+  /// ActionEntry - Structure describing an entry in the actions table.
   struct ActionEntry {
     int ValueForTypeID; // The value to write - may not be equal to the type id.
     int NextAction;
     struct ActionEntry *Previous;
   };
 
+  /// PadRange - Structure holding a try-range and the associated landing pad.
+  struct PadRange {
+    // The index of the landing pad.
+    unsigned PadIndex;
+    // The index of the begin and end labels in the landing pad's label lists.
+    unsigned RangeIndex;
+  };
+
+  typedef DenseMap<unsigned, PadRange, KeyInfo> RangeMapType;
+
+  /// CallSiteEntry - Structure describing an entry in the call-site table.
+  struct CallSiteEntry {
+    unsigned BeginLabel; // zero indicates the start of the function.
+    unsigned EndLabel;   // zero indicates the end of the function.
+    unsigned PadLabel;   // zero indicates that there is no landing pad.
+    unsigned Action;
+  };
+
   void EmitExceptionTable() {
     // Map all labels and get rid of any dead landing pads.
     MMI->TidyLandingPads();
@@ -2981,13 +2993,6 @@
       LandingPads.push_back(&PadInfos[i]);
     std::sort(LandingPads.begin(), LandingPads.end(), PadLT);
 
-    // Gather first action index for each landing pad site.
-    SmallVector<unsigned, 64> FirstActions;
-    FirstActions.reserve(PadInfos.size());
-
-    // The actions table.
-    SmallVector<ActionEntry, 32> Actions;
-
     // Negative type ids index into FilterIds, positive type ids index into
     // TypeInfos.  The value written for a positive type id is just the type
     // id itself.  For a negative type id, however, the value written is the
@@ -3007,14 +3012,14 @@
       Offset -= Asm->SizeULEB128(*I);
     }
 
-    // Compute sizes for exception table.
-    unsigned SizeSites = 0;
-    unsigned SizeActions = 0;
+    // Compute the actions table and gather the first action index for each
+    // landing pad site.
+    SmallVector<ActionEntry, 32> Actions;
+    SmallVector<unsigned, 64> FirstActions;
+    FirstActions.reserve(LandingPads.size());
 
-    // Look at each landing pad site to compute size.  We need the size of each
-    // landing pad site info and the size of the landing pad's actions.
     int FirstAction = 0;
-
+    unsigned SizeActions = 0;
     for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
       const LandingPadInfo *LP = LandingPads[i];
       const std::vector<int> &TypeIds = LP->TypeIds;
@@ -3063,14 +3068,96 @@
 
       // Compute this sites contribution to size.
       SizeActions += SizeSiteActions;
-      unsigned M = LP->BeginLabels.size();
-      SizeSites += M*(sizeof(int32_t) +               // Site start.
-                      sizeof(int32_t) +               // Site length.
-                      sizeof(int32_t) +               // Landing pad.
-                      Asm->SizeULEB128(FirstAction)); // Action.
     }
-    
+
+    // Compute the call-site table.  Entries must be ordered by address.
+    SmallVector<CallSiteEntry, 64> CallSites;
+
+    RangeMapType PadMap;
+    for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
+      const LandingPadInfo *LandingPad = LandingPads[i];
+      for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
+        unsigned BeginLabel = LandingPad->BeginLabels[j];
+        assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
+        PadRange P = { i, j };
+        PadMap[BeginLabel] = P;
+      }
+    }
+
+    bool MayThrow = false;
+    unsigned LastLabel = 0;
+    const TargetInstrInfo *TII = MF->getTarget().getInstrInfo();
+    for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
+         I != E; ++I) {
+      for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
+           MI != E; ++MI) {
+        if (MI->getOpcode() != TargetInstrInfo::LABEL) {
+          MayThrow |= TII->isCall(MI->getOpcode());
+          continue;
+        }
+
+        unsigned BeginLabel = MI->getOperand(0).getImmedValue();
+        assert(BeginLabel && "Invalid label!");
+        if (BeginLabel == LastLabel) {
+          MayThrow = false;
+          continue;
+        }
+
+        RangeMapType::iterator L = PadMap.find(BeginLabel);
+
+        if (L == PadMap.end())
+          continue;
+
+        PadRange P = L->second;
+        const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
+
+        assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
+               "Inconsistent landing pad map!");
+
+        // If some instruction between the previous try-range and this one may
+        // throw, create a call-site entry with no landing pad for the region
+        // between the try-ranges.
+        if (MayThrow) {
+          CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0};
+          CallSites.push_back(Site);
+        }
+
+        LastLabel = LandingPad->EndLabels[P.RangeIndex];
+        CallSiteEntry Site = {BeginLabel, LastLabel,
+          LandingPad->LandingPadLabel, FirstActions[P.PadIndex]};
+
+        assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel &&
+               "Invalid landing pad!");
+
+        // Try to merge with the previous call-site.
+        if (CallSites.size()) {
+          CallSiteEntry &Prev = CallSites[CallSites.size()-1];
+          if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) {
+            // Extend the range of the previous entry.
+            Prev.EndLabel = Site.EndLabel;
+            continue;
+          }
+        }
+
+        // Otherwise, create a new call-site.
+        CallSites.push_back(Site);
+      }
+    }
+    // If some instruction between the previous try-range and the end of the
+    // function may throw, create a call-site entry with no landing pad for the
+    // region following the try-range.
+    if (MayThrow) {
+      CallSiteEntry Site = {LastLabel, 0, 0, 0};
+      CallSites.push_back(Site);
+    }
+
     // Final tallies.
+    unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start.
+                                             sizeof(int32_t) + // Site length.
+                                             sizeof(int32_t)); // Landing pad.
+    for (unsigned i = 0, e = CallSites.size(); i < e; ++i)
+      SizeSites += Asm->SizeULEB128(CallSites[i].Action);
+
     unsigned SizeTypes = TypeInfos.size() * TAI->getAddressSize();
 
     unsigned TypeOffset = sizeof(int8_t) + // Call site format
@@ -3106,61 +3193,44 @@
     Asm->EmitULEB128Bytes(SizeSites);
     Asm->EOL("Call-site table length");
 
-    // Emit the landing pad site information in order of address.
-    PadMapType PadMap;
-
-    for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
-      const LandingPadInfo *LandingPad = LandingPads[i];
-      for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
-        unsigned BeginLabel = LandingPad->BeginLabels[j];
-        assert(!PadMap.count(BeginLabel) && "duplicate landing pad labels!");
-        PadSite P = { i, j };
-        PadMap[BeginLabel] = P;
+    // Emit the landing pad site information.
+    for (unsigned i = 0; i < CallSites.size(); ++i) {
+      CallSiteEntry &S = CallSites[i];
+      const char *BeginTag;
+      unsigned BeginNumber;
+
+      if (!S.BeginLabel) {
+        BeginTag = "eh_func_begin";
+        BeginNumber = SubprogramCount;
+      } else {
+        BeginTag = "label";
+        BeginNumber = S.BeginLabel;
       }
-    }
 
-    for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
-         I != E; ++I) {
-      for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
-           MI != E; ++MI) {
-        if (MI->getOpcode() != TargetInstrInfo::LABEL)
-          continue;
-
-        unsigned BeginLabel = MI->getOperand(0).getImmedValue();
-        PadMapType::iterator L = PadMap.find(BeginLabel);
-
-        if (L == PadMap.end())
-          continue;
-
-        PadSite P = L->second;
-        const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
-
-        assert(BeginLabel == LandingPad->BeginLabels[P.SiteIndex] &&
-               "Inconsistent landing pad map!");
+      EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount,
+                        false, true);
+      Asm->EOL("Region start");
+
+      if (!S.EndLabel) {
+        EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber);
+      } else {
+        EmitDifference("label", S.EndLabel, BeginTag, BeginNumber);
+      }
+      Asm->EOL("Region length");
 
-        EmitSectionOffset("label", "eh_func_begin", BeginLabel, SubprogramCount,
+      if (!S.PadLabel) {
+        if (TAI->getAddressSize() == sizeof(int32_t))
+          Asm->EmitInt32(0);
+        else
+          Asm->EmitInt64(0);
+      } else {
+        EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount,
                           false, true);
-        Asm->EOL("Region start");
-
-        EmitDifference("label", LandingPad->EndLabels[P.SiteIndex],
-                       "label", BeginLabel);
-        Asm->EOL("Region length");
-
-        if (LandingPad->TypeIds.empty()) {
-          if (TAI->getAddressSize() == sizeof(int32_t))
-            Asm->EmitInt32(0);
-          else
-            Asm->EmitInt64(0);
-        } else {
-          EmitSectionOffset("label", "eh_func_begin",
-                            LandingPad->LandingPadLabel, SubprogramCount,
-                            false, true);
-        }
-        Asm->EOL("Landing pad");
-
-        Asm->EmitULEB128Bytes(FirstActions[P.PadIndex]);
-        Asm->EOL("Action");
       }
+      Asm->EOL("Landing pad");
+
+      Asm->EmitULEB128Bytes(S.Action);
+      Asm->EOL("Action");
     }
 
     // Emit the actions.
@@ -3183,7 +3253,7 @@
         O << Asm->getGlobalLinkName(GV);
       else
         O << "0";
-      
+
       Asm->EOL("TypeInfo");
     }
 
@@ -3193,7 +3263,7 @@
       Asm->EmitULEB128Bytes(TypeID);
       Asm->EOL("Filter TypeInfo index");
     }
-    
+
     Asm->EmitAlignment(2);
   }
 

Modified: llvm/trunk/lib/CodeGen/MachineModuleInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineModuleInfo.cpp?rev=41718&r1=41717&r2=41718&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/MachineModuleInfo.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineModuleInfo.cpp Wed Sep  5 06:27:52 2007
@@ -1740,22 +1740,18 @@
     LandingPadInfo &LandingPad = LandingPads[i];
     LandingPad.LandingPadLabel = MappedLabel(LandingPad.LandingPadLabel);
 
-    if (!LandingPad.LandingPadBlock)
-      // Must not have cleanups if no landing pad.
-      LandingPad.TypeIds.clear();
-
     // Special case: we *should* emit LPs with null LP MBB. This indicates
     // "rethrow" case.
     if (!LandingPad.LandingPadLabel && LandingPad.LandingPadBlock) {
       LandingPads.erase(LandingPads.begin() + i);
       continue;
     }
-          
+
     for (unsigned j=0; j != LandingPads[i].BeginLabels.size(); ) {
       unsigned BeginLabel = MappedLabel(LandingPad.BeginLabels[j]);
       unsigned EndLabel = MappedLabel(LandingPad.EndLabels[j]);
-            
-          
+
+
       if (!BeginLabel || !EndLabel) {
         LandingPad.BeginLabels.erase(LandingPad.BeginLabels.begin() + j);
         LandingPad.EndLabels.erase(LandingPad.EndLabels.begin() + j);
@@ -1766,7 +1762,19 @@
       LandingPad.EndLabels[j] = EndLabel;
       ++j;
     }
-    
+
+    // Remove landing pads with no try-ranges.
+    if (!LandingPads[i].BeginLabels.size()) {
+      LandingPads.erase(LandingPads.begin() + i);
+      continue;
+    }
+
+    // If there is no landing pad, ensure that the list of typeids is empty.
+    // If the only typeid is a cleanup, this is the same as having no typeids.
+    if (!LandingPad.LandingPadBlock ||
+        (LandingPad.TypeIds.size() == 1 && !LandingPad.TypeIds[0]))
+      LandingPad.TypeIds.clear();
+
     ++i;
   }
 }

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=41718&r1=41717&r2=41718&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Wed Sep  5 06:27:52 2007
@@ -2928,7 +2928,7 @@
     Args.push_back(Entry);
   }
 
-  if (ExceptionHandling && MMI) {
+  if (ExceptionHandling && MMI && LandingPad) {
     // Insert a label before the invoke call to mark the try range.  This can be
     // used to detect deletion of the invoke via the MachineModuleInfo.
     BeginLabel = MMI->NextLabelID();
@@ -2945,7 +2945,7 @@
     setValue(&I, Result.first);
   DAG.setRoot(Result.second);
 
-  if (ExceptionHandling && MMI) {
+  if (ExceptionHandling && MMI && LandingPad) {
     // Insert a label at the end of the invoke call to mark the try range.  This
     // can be used to detect deletion of the invoke via the MachineModuleInfo.
     EndLabel = MMI->NextLabelID();





More information about the llvm-commits mailing list