<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - ConstantHoisting illegally modifying EHPad"
   href="https://bugs.llvm.org/show_bug.cgi?id=32107">32107</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>ConstantHoisting illegally modifying EHPad
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Windows NT
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Scalar Optimizations
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>robert.olliff@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=18037" name="attach_18037" title="lit test files and patch diff">attachment 18037</a> <a href="attachment.cgi?id=18037&action=edit" title="lit test files and patch diff">[details]</a></span>
lit test files and patch diff

The attached patch file modifies Constant Hoisting so that instead of hoisting
a constant into an EHPad, it is hoisted to the idom of the EHPad.

Tests using attached files
    RUN: opt -S -consthoist < ehpad.ll 
    Result: Verifier fails, 
        "CatchSwitchInst not the first non-PHI instruction in the block."

    RUN: llc ehpad.ll
    Result: crash in 
        llvm::SelectionDAGBuilder::HandlePHINodesInSuccessorBlocks

    RUN: clang -cc1 -S -O2 -fexceptions -fcxx-exceptions -emit-codegen-only
ehpad.cpp
    Result: crash in 
        llvm::SelectionDAGBuilder::HandlePHINodesInSuccessorBlocks

In the attached program, the problem IR causing the failure is this BasicBlock:
    catch.dispatch:                                   ; preds = %2, %1
        %z.0 = phi i64 [ %call, %1 ], [ %call1, %2 ]
        %3 = catchswitch within none [label %4] unwind to caller

catch.dispatch is a catchswitch EHPad block, which are supposed to be used by
the compiler as "data only"[1], meaning that they do not have a direct
MachineBasicBlock counterpart. The problem with the block above is that it
contains a machinecode emitting instruction (phi), which means the block must
have a corresponding MachineBasicBlock. This causes confusion (and crashing)
during the SelectionDAGISel pass since the block is technically an EHPad
(catchswitch is first non-phi), but also emits machinecode (via phi). One part
of the pass[2] sees a catchswitch-EHPad block and does not create a
corresponding MachineBasicBlock, while another part[3] sees a standard
BasicBlock and crashes when attempting to use the corresponding
MachineBasicBlock. In debug configuration, this conflict is detected earlier
via an assertion during MachineBasicBlock creation. The assertion fails when a
BB is a catchswitch-EHPad and the catchswitch instruction is NOT the first
instruction[4].    

Under normal conditions, this problematic phi would have been removed via
demotion before execution of SelectionDAGISel[5]; However, in the case of
catch.dispatch, phi demotion is not run because “Constant Hoisting” added a
bitcast instruction following the phi (See Listing 1), which in turn results in
an illegal EHPad (catchswitch is not the first non-phi instruction). The end
result is that phi-demotion does not see the block as an EHPad and does not
operate upon the block[6].

Another interesting note is that, after phi-demotion, a call to
SimplifyInstructionsInBlock is made. This general optimization utility undoes
the “optimizations” Constant Hoisting did. So there seems to be some confusion
on what an optimized constant looks like.


Listing 1: Constant Hoisting

Before Constant Hoisting

catch.dispatch:                                   ; preds = %2, %1
  %z.0 = phi i64 [ %call, %1 ], [ %call1, %2 ]
  %3 = catchswitch within none [label %4] unwind to caller

; <label>:4:                                      ; preds = %catch.dispatch
  %5 = catchpad within %3 [i8* null, i32 64, i8* null]
  %call4 = tail call i64 @fn(i64 %z.0) [ "funclet"(token %5) ]
  %add = add i64 %call4, 9209618997431186100
  %call5 = tail call i64 @fn(i64 %add) [ "funclet"(token %5) ]
  %add6 = add i64 %call5, 9209618997431186100
  %call7 = tail call i64 @fn(i64 %add6) [ "funclet"(token %5) ]
  %call8 = tail call i64 @fn(i64 %call7) [ "funclet"(token %5) ]
  catchret from %5 to label %6

After Constant Hoisting

catch.dispatch:                                   ; preds = %2, %1
  %z.0 = phi i64 [ %call, %1 ], [ %call1, %2 ]
  %const = bitcast i64 9209618997431186100 to i64
  %3 = catchswitch within none [label %4] unwind to caller

; <label>:4:                                      ; preds = %catch.dispatch
  %5 = catchpad within %3 [i8* null, i32 64, i8* null]
  %call4 = tail call i64 @fn(i64 %z.0) [ "funclet"(token %5) ]
  %add = add i64 %call4, %const
  %call5 = tail call i64 @fn(i64 %add) [ "funclet"(token %5) ]
  %add6 = add i64 %call5, %const
  %call7 = tail call i64 @fn(i64 %add6) [ "funclet"(token %5) ]
  %call8 = tail call i64 @fn(i64 %call7) [ "funclet"(token %5) ]
  catchret from %5 to label %6


[1] Description,
<a href="https://github.com/llvm-mirror/llvm/commit/18329ced975b85fbcf34aaa928e5d66fe8da8282">https://github.com/llvm-mirror/llvm/commit/18329ced975b85fbcf34aaa928e5d66fe8da8282</a>
[2] SourceCode, 
<a href="https://github.com/llvm-mirror/llvm/blob/1896046c882da400cd0e898c5ef5b3cdabd9d824/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp#L265-L268">https://github.com/llvm-mirror/llvm/blob/1896046c882da400cd0e898c5ef5b3cdabd9d824/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp#L265-L268</a>
[3] SourceCode, 
<a href="https://github.com/llvm-mirror/llvm/blob/1896046c882da400cd0e898c5ef5b3cdabd9d824/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp#L8318-L8325">https://github.com/llvm-mirror/llvm/blob/1896046c882da400cd0e898c5ef5b3cdabd9d824/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp#L8318-L8325</a>
[4] SourceCode, 
<a href="https://github.com/llvm-mirror/llvm/blob/1896046c882da400cd0e898c5ef5b3cdabd9d824/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp#L266">https://github.com/llvm-mirror/llvm/blob/1896046c882da400cd0e898c5ef5b3cdabd9d824/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp#L266</a>
[5] SourceCode, 
<a href="https://github.com/llvm-mirror/llvm/blob/1896046c882da400cd0e898c5ef5b3cdabd9d824/lib/CodeGen/WinEHPrepare.cpp#L680-L707">https://github.com/llvm-mirror/llvm/blob/1896046c882da400cd0e898c5ef5b3cdabd9d824/lib/CodeGen/WinEHPrepare.cpp#L680-L707</a>
[6] SourceCode, 
<a href="https://github.com/llvm-mirror/llvm/blob/1896046c882da400cd0e898c5ef5b3cdabd9d824/lib/CodeGen/WinEHPrepare.cpp#L685-L686">https://github.com/llvm-mirror/llvm/blob/1896046c882da400cd0e898c5ef5b3cdabd9d824/lib/CodeGen/WinEHPrepare.cpp#L685-L686</a></pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>