[PATCH] D12434: [WinEH] Teach SimplfyCFG to eliminate empty cleanup pads.

Joseph Tremoulet via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 2 10:53:06 PDT 2015


JosephTremoulet added inline comments.

================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:3045
@@ -2942,2 +3044,3 @@
 
-  // The landingpad is now unreachable.  Zap it.
+  assert(UnwindDest || BB->getFirstNonPHI() == BB->begin());
+  if (UnwindDest) {
----------------
`assert` seems too strong here.  Any PHI in an empty unwinds-to-caller cleanuppad must be dead (have no uses), but it would still be legal IR, right?  I'd think that in the unwinds-to-caller case this should simply erase any PHIs it finds.

================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:3058-3059
@@ +3057,4 @@
+        if (DestPN->getIncomingBlock(Idx) == BB) {
+          // The value has to be a PHI because we've check that there are no
+          // other instructions in the block we are removing.
+          PHINode *SrcPN = cast<PHINode>(DestPN->getIncomingValue(Idx));
----------------
It could be a non-PHI value that dominates the empty cleanup, though, couldn't it?  So something like

```
struct S { ... }; // has empty destructor
void foo() {
  int state = bar();
  try {
    {
      S s;
      may_throw();
    } // empty cleanup for s here
    state = 2;
    may_throw();
  } catch (...) {
    // This is UnwindDest and should have a PHI for state where IncomingBlock is the empty cleanuppad
    // and IncomingValue is the call to bar, not a PHI in the empty cleanup.
    code;
  }
}
```

or with a constant:

```
struct S { ... }; // has empty destructor
void foo() {
  int state = 1;
  try {
    {
      S s;
      may_throw();
    } // empty cleanup for s here
    state = 2;
    may_throw();
  } catch (...) {
    // This is UnwindDest and should have a PHI for state where IncomingBlock is the empty cleanuppad
    // and IncomingValue is 1, not a PHI in the empty cleanup
    code;
  }
}
```

Happily, I think in these cases you can just take the current incoming value in `DestPN` and associate it with `UnwindDest`'s new predecessors. 

================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:3066-3069
@@ +3065,6 @@
+               SrcIdx != SrcE; ++SrcIdx) {
+            // If the destination PHI node already has an entry for this block
+            // we can just leave that.  Otherwise, add an incoming value.
+            if (DestPN->getBasicBlockIndex(SrcPN->getIncomingBlock(SrcIdx))
+                  == -1) {
+              DestPN->addIncoming(SrcPN->getIncomingValue(SrcIdx),
----------------
I don't think the destination PHI node can already have an entry for this block:
  - `SrcPN` was a PHI in a cleanuppad, so `SrcPN->getIncomingBlock(SrcIdx)` must have reached the cleanuppad by an unwind edge
  - `DestPN` is in `UnwindDest`, which must be an EH pad and therefore all its predecessors must reach `UnwindDest` by an unwind edge
  - No instruction has multiple unwind edges, so nothing could have unwind edges to both `UnwindDest` and the empty cleanup


================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:3074
@@ +3073,3 @@
+          }
+          SrcPN->eraseFromParent();
+          break;
----------------
I think it's possible that SrcPN could have another use on another PHI in UnwindDest, and/or that it could have a non-PHI use.  So I don't think you want to erase it here, I think instead you want the loop below to check if it has any uses and erase it if not.

Actually, you may want to move the loop below outside the `if(UnwindDest)` and let it be the thing that erases useless PHIs when the empty cleanup unwinds to caller.

================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:3089
@@ +3088,3 @@
+      for (auto *pred : predecessors(UnwindDest))
+        if (PN->getBasicBlockIndex(pred) == -1 && pred != BB)
+          PN->addIncoming(UndefValue::get(PN->getType()), pred);
----------------
Likewise, I think the getBasicBlockIndex check here is superfluous.


Repository:
  rL LLVM

http://reviews.llvm.org/D12434





More information about the llvm-commits mailing list