ARM: ensure that the Windows DBZ check is in range
authorSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 27 Oct 2016 16:59:22 +0000 (16:59 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 27 Oct 2016 16:59:22 +0000 (16:59 +0000)
commit075d2e3c598ec6c67a0b7bad6435b29154b742e7
tree4e16e1c4765e3b3d3c7d3477fd98ae7b10bc0120
parent39f9da2a8752ae6d42c16b3a09538e83d3dedd6d
ARM: ensure that the Windows DBZ check is in range

The Windows ARM target expects the compiler to emit a division-by-zero check.
The check would use the form of:

    cmp r?, #0
    cbz .Ltrap
    b .Lbody
  .Lbody:
    ...
  .Ltrap:
    udf #249 @ __brkdiv0

This works great most of the time.  However, if the body of the function is
greater than 127 bytes, the branch target limitation of cbz becomes an issue.
This occurs in the unoptimized code generation cases sometimes (like in
compiler-rt).

Since this is a matter of correctness, possibly pay a small penalty instead.  We
now form this slightly differently:

    cbnz .Lbody
    udf #249 @ __brkdiv0
  .Lbody:
    ...

The positive case is through the branch instead of being the next instruction.
However, because of the basic block layout, the negated branch is going to be
a short distance always (2 bytes away, after the inserted __brkdiv0).

The new t__brkdiv0 instruction is required to explicitly mark the instruction as
a terminator as the generic UDF instruction is not a terminator.

Addresses PR30532!

llvm-svn: 285312
llvm/lib/Target/ARM/ARMISelLowering.cpp
llvm/lib/Target/ARM/ARMInstrThumb.td
llvm/test/CodeGen/ARM/Windows/dbzchk.ll
llvm/test/CodeGen/ARM/Windows/division-range.ll [new file with mode: 0644]
llvm/test/CodeGen/ARM/Windows/division.ll