<html>
    <head>
      <base href="http://llvm.org/bugs/" />
    </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 --- - inconsistent llvm_unreachable handling causes infinite loops in release builds"
   href="http://llvm.org/bugs/show_bug.cgi?id=20810">20810</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>inconsistent llvm_unreachable handling causes infinite loops in release builds
          </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>All
          </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>Support Libraries
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>dberlin@dberlin.org
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Reproduction:

Build with CMAKE_BUILD_TYPE=Release on Linux with compiler set to G++ and using
g++ > 4.5.


run llvm-lit on /test/CodeGen/R600/infinite-loop-evergreen.ll

It will take forever (not to *execute*, but to *compile*)

Here is what happens:
lib/Target/R600/AMDILCFGStructurizer.cpp has the following code at line 1737:

 MachineBasicBlock::iterator I = BranchMI;
  unsigned ImmReg = FuncRep->getRegInfo().createVirtualRegister(I32RC);
  llvm_unreachable("Extra register needed to handle CFG");
  MachineInstr *NewMI = insertInstrBefore(I, AMDGPU::BRANCH_COND_i32);
  MachineInstrBuilder MIB(*FuncRep, NewMI);
  MIB.addMBB(LoopHeader);
  MIB.addReg(ImmReg, false);
  SHOWNEWINSTR(NewMI);
  BranchMI->eraseFromParent();
  LoopLatch->addSuccessor(DummyExitBlk);


It expects the llvm_unreachable to abort (as do a lot of other places in the
compiler), but when it doesn't, it just happily continues on (going around and
around forever, it turns out)

include/Support/ErrorHandling.h has this:

/// Use this instead of assert(0).  It conveys intent more clearly and
/// allows compilers to omit some unnecessary code.
#ifndef NDEBUG
#define llvm_unreachable(msg) \
  ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__)
#elif defined(LLVM_BUILTIN_UNREACHABLE)
#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE
#else
#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal()
#endif

(Note the request to use instead of assert(0) )


llvm_unreachable_internal prints a message, calls *abort*, then calls
LLVM_BUILTIN_UNREACHABLE if it is defined.

But as per above, if LLVM_BUILTIN_UNREACHABLE and NDEBUG are defined, we just
call LLVM_BUILTIN_UNREACHABLE

LLVM_BUILTIN_UNREACHABLE is defined as:

/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands
/// to an expression which states that it is undefined behavior for the
/// compiler to reach this point.  Otherwise is not defined.
#if __has_builtin(__builtin_unreachable) || __GNUC_PREREQ(4, 5)
# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
#elif defined(_MSC_VER)
# define LLVM_BUILTIN_UNREACHABLE __assume(false)
#endif


Thus, this llvm_unreachable expression transforms to builtin_unreachable on GCC
4.5 or above (I expect windows has a similar problem unless assume also
aborts).

However, builtin_unreachable *does not abort*. In fact, in most cases, it does
nothing.  GCC only defines it as a hint to the compiler.


If we expect llvm_unreachable to abort, the right solution is to just remove
the line
#elif defined(LLVM_BUILTIN_UNREACHABLE)
#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE

It will then always do the right thing in llvm_unreachable_internal (including
calling the unreachable builtin).

If we don't expect it to abort, then the code in places like above needs to be
modified to abort rather than infinite loop forever.</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>