[PATCH] Work-in-progress omnibus patch for native Windows C++ EH outlining

Andy Kaylor andrew.kaylor at intel.com
Wed Feb 25 15:37:44 PST 2015


REPOSITORY
  rL LLVM

================
Comment at: include/llvm/Transforms/Utils/Cloning.h:148-149
@@ -148,1 +147,4 @@
+    StopCloningBB,
+    ///< Don't clone the terminator but clone the current block's successors.
+    CloneSuccessors
   };
----------------
rnk wrote:
> Can SkipInstruction do this also?
I actually originally coded it that way, but it seemed to me like I was overloading the meaning of SkipInstruction too much.  I don't have strong feelings about it either way.

================
Comment at: lib/CodeGen/WinEHPrepare.cpp:443-457
@@ -234,8 +442,17 @@
 
-  // FIXME: We will replace the landingpad bodies with llvm.eh.actions
-  //        calls and indirect branches here and then delete blocks
-  //        which are no longer reachable.  That will get rid of the
-  //        handlers that we have outlined.  There is code below
-  //        that looks for allocas with no uses in the parent function.
-  //        That will only happen after the pruning is implemented.
+  // Go through the blocks in the function and delete any that are no longer reachable.
+  BasicBlock *Entry = &F.getEntryBlock();
+  Function::iterator BBI = F.begin();
+  while (BBI != F.end()) {
+    // Check if this block has become dead during inlining or other
+    // simplifications. Note that the first block will appear dead, as it has
+    // not yet been wired up properly.
+    if (cast<BasicBlock>(BBI) != Entry && (pred_empty(BBI) ||
+                       BBI->getSinglePredecessor() == BBI)) {
+      BasicBlock *DeadBB = BBI++;
+      DeleteDeadBlock(DeadBB);
+      continue;
+    }
+    ++BBI;
+  }
 
----------------
rnk wrote:
> This can be just removeUnreachableBlocks(F). If we need more cleanup power, we can consider making simplifyFunctionCFG from lib/Transforms/Scalar/SimplifyCFGPass.cpp a utility.
Sounds good.  By the way, I forgot to add a comment mentioning this, but this is currently deleting too much because the indirect branch targets aren't filled in in the revised landing pads.

================
Comment at: lib/CodeGen/WinEHPrepare.cpp:1003-1009
@@ +1002,9 @@
+
+// This function parses a landing pad to see if all it does is resume.
+// If so, it would be called from within another landing pad for
+// exception handling, but since it does nothing any invoke that leads
+// to this landing pad can be replaced with a call and an unconditional
+// branch to the normal destination.  Any exceptions that occur within the
+// called function will be handled by the normal runtime exception handling
+// process.
+static bool isLandingPadEmptyResume(const BasicBlock *LPadBB) {
----------------
rnk wrote:
> Based on the comment, I think SimplifyCFG knows how to do this already. If you run SimplifyCFG() on each landing pad BB, you'll get the same behavior with none of this code.
> 
> You may need to run some other cleanup utility on the block first, though.
I saw the SimplifyResume function in SimplifyCFG.  It wouldn't work as is here because it only handles resumes in the same block as the landing pad instruction.  I considered moving some form of the logic here into SimplifyResume, but I'm not sure it really belongs there.

The case this is meant to handle looks like this:

```
catch14:                                          ; preds = %catch.dispatch11
  %exn15 = load i8** %exn.slot
  %18 = call i8* @llvm.eh.begincatch(i8* %exn15) #4
  %19 = bitcast i8* %18 to float*
  %20 = load float* %19, align 4
  store float %20, float* %f, align 4
  %21 = load float* %f, align 4
  invoke void @_Z12handle_floatf(float %21)
          to label %invoke.cont17 unwind label %lpad16

lpad16:                                           ; preds = %catch14
  %22 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
          cleanup
  %23 = extractvalue { i8*, i32 } %22, 0
  store i8* %23, i8** %exn.slot
  %24 = extractvalue { i8*, i32 } %22, 1
  store i32 %24, i32* %ehselector.slot
  call void @llvm.eh.endcatch() #4
  br label %eh.resume

eh.resume:                                        ; preds = %lpad16, %catch.dispatch11
  %exn20 = load i8** %exn.slot
  %sel21 = load i32* %ehselector.slot
  %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn20, 0
  %lpad.val22 = insertvalue { i8*, i32 } %lpad.val, i32 %sel21, 1
  resume { i8*, i32 } %lpad.val22
```
This is the landing pad for an exception inside a catch handler, but in this case the landing pad doesn't do anything except continue the search.  Since that happens automatically, we can just change the invoke in the catch handler to a call.  But there are all kinds of things here that SimplifyResume doesn't know anything about.

There are two things here that make this not a candidate for simplification in SimplifyCFG.  First, the fact that the endcatch call can be eliminated is very Windows specific.  Second, the actual resume block is shared between two landing pads.

Arguably, we could teach SimplifyResume to identify the situations in which llvm.eh.endcatch can be dropped (currently always, but in the future maybe not).  We'd also need to teach it how to consider multiple predecessors and decide which ones it can simplify.

http://reviews.llvm.org/D7886

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/






More information about the llvm-commits mailing list