Skip to content

Commit

Permalink
ARM: ensure that the Windows DBZ check is in range
Browse files Browse the repository at this point in the history
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!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@285312 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
compnerd committed Oct 27, 2016
1 parent 07e9e1a commit b5143b0
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 44 deletions.
11 changes: 3 additions & 8 deletions lib/Target/ARM/ARMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8594,16 +8594,11 @@ ARMTargetLowering::EmitLowered__dbzchk(MachineInstr &MI,
std::next(MachineBasicBlock::iterator(MI)), MBB->end());
ContBB->transferSuccessorsAndUpdatePHIs(MBB);

MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
MF->push_back(TrapBB);
BuildMI(TrapBB, DL, TII->get(ARM::t2UDF)).addImm(249);
MBB->addSuccessor(TrapBB);

BuildMI(*MBB, MI, DL, TII->get(ARM::tCBZ))
BuildMI(*MBB, MI, DL, TII->get(ARM::tCBNZ))
.addReg(MI.getOperand(0).getReg())
.addMBB(TrapBB);
AddDefaultPred(BuildMI(*MBB, MI, DL, TII->get(ARM::t2B)).addMBB(ContBB));
.addMBB(ContBB);
MBB->addSuccessor(ContBB);
BuildMI(*MBB, MI, DL, TII->get(ARM::t__brkdiv0));

MI.eraseFromParent();
return ContBB;
Expand Down
7 changes: 7 additions & 0 deletions lib/Target/ARM/ARMInstrThumb.td
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,13 @@ def tUDF : TI<(outs), (ins imm0_255:$imm8), IIC_Br, "udf\t$imm8",
let Inst{7-0} = imm8;
}

def t__brkdiv0 : TI<(outs), (ins), IIC_Br, "__brkdiv0",
[(int_arm_undefined 249)]>, Encoding16,
Requires<[IsThumb, IsWindows]> {
let Inst = 0xdef9;
let isTerminator = 1;
}

// Zero-extend byte
def tUXTB : // A8.6.262
T1pIMiscEncode<{0,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm),
Expand Down
38 changes: 14 additions & 24 deletions test/CodeGen/ARM/Windows/dbzchk.ll
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,12 @@ return:
}

; CHECK-DIV-DAG: BB#0
; CHECK-DIV-DAG: Successors according to CFG: BB#5({{.*}}) BB#4
; CHECK-DIV-DAG: Successors according to CFG: BB#1({{.*}}) BB#2
; CHECK-DIV-DAG: BB#1
; CHECK-DIV-DAG: Successors according to CFG: BB#3
; CHECK-DIV-DAG: BB#2
; CHECK-DIV-DAG: Successors according to CFG: BB#3
; CHECK-DIV-DAG: BB#3
; CHECK-DIV-DAG: BB#4
; CHECK-DIV-DAG: Successors according to CFG: BB#1({{.*}}) BB#2
; CHECK-DIV-DAG: BB#5

; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -o /dev/null %s 2>&1 | FileCheck %s -check-prefix CHECK-MOD

Expand Down Expand Up @@ -72,11 +69,10 @@ return:
; CHECK-MOD-DAG: BB#0
; CHECK-MOD-DAG: Successors according to CFG: BB#2({{.*}}) BB#1
; CHECK-MOD-DAG: BB#1
; CHECK-MOD-DAG: Successors according to CFG: BB#4({{.*}}) BB#3
; CHECK-MOD-DAG: BB#2
; CHECK-MOD-DAG: Successors according to CFG: BB#3
; CHECK-MOD-DAG: BB#3
; CHECK-MOD-DAG: Successors according to CFG: BB#2
; CHECK-MOD-DAG: BB#4
; CHECK-MOD-DAG: BB#2

; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -filetype asm -o /dev/null %s 2>&1 | FileCheck %s -check-prefix CHECK-CFG
; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-CFG-ASM
Expand Down Expand Up @@ -123,25 +119,19 @@ attributes #0 = { optsize }
; CHECK-CFG-DAG: t2B <BB#3>

; CHECK-CFG-DAG: BB#2
; CHECK-CFG-DAG: tCBZ %vreg{{[0-9]}}, <BB#5>
; CHECK-CFG-DAG: t2B <BB#4>
; CHECK-CFG-DAG: tCBNZ %vreg{{[0-9]}}, <BB#4>
; CHECK-CFG-DAG: t__brkdiv0

; CHECK-CFG-DAG: BB#4

; CHECK-CFG-DAG: BB#3
; CHECK-CFG-DAG: tBX_RET

; CHECK-CFG-DAG: BB#5
; CHECK-CFG-DAG: t2UDF 249

; CHECK-CFG-ASM-LABEL: h:
; CHECK-CFG-ASM: cbz r{{[0-9]}}, .LBB2_2
; CHECK-CFG-ASM: b .LBB2_4
; CHECK-CFG-ASM: cbnz r{{[0-9]}}, .LBB2_2
; CHECK-CFG-ASM: __brkdiv0
; CHECK-CFG-ASM-LABEL: .LBB2_2:
; CHECK-CFG-ASM-NEXT: udf.w #249
; CHECK-CFG-ASM-LABEL: .LBB2_4:
; CHECK-CFG-ASM: bl __rt_udiv
; CHECK-CFG-ASM: pop.w {r11, pc}

; RUN: llc -O0 -mtriple thumbv7--windows-itanium -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-WIN__DBZCHK

Expand Down Expand Up @@ -182,11 +172,11 @@ return:
}

; CHECK-WIN__DBZCHK-LABEL: j:
; CHECK-WIN__DBZCHK: cbz r{{[0-7]}}, .LBB
; CHECK-WIN__DBZCHK-NOT: cbz r8, .LBB
; CHECK-WIN__DBZCHK-NOT: cbz r9, .LBB
; CHECK-WIN__DBZCHK-NOT: cbz r10, .LBB
; CHECK-WIN__DBZCHK-NOT: cbz r11, .LBB
; CHECK-WIN__DBZCHK-NOT: cbz ip, .LBB
; CHECK-WIN__DBZCHK-NOT: cbz lr, .LBB
; CHECK-WIN__DBZCHK: cbnz r{{[0-7]}}, .LBB
; CHECK-WIN__DBZCHK-NOT: cbnz r8, .LBB
; CHECK-WIN__DBZCHK-NOT: cbnz r9, .LBB
; CHECK-WIN__DBZCHK-NOT: cbnz r10, .LBB
; CHECK-WIN__DBZCHK-NOT: cbnz r11, .LBB
; CHECK-WIN__DBZCHK-NOT: cbnz ip, .LBB
; CHECK-WIN__DBZCHK-NOT: cbnz lr, .LBB

15 changes: 15 additions & 0 deletions test/CodeGen/ARM/Windows/division-range.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
; RUN: llc -O0 -mtriple thumbv7--windows-itanium -filetype obj -o - %s | llvm-objdump -disassemble - | FileCheck %s

declare i32 @llvm.arm.space(i32, i32)

define arm_aapcs_vfpcc i32 @f(i32 %n, i32 %d) local_unnamed_addr {
entry:
%div = sdiv i32 %n, %d
call i32 @llvm.arm.space(i32 128, i32 undef)
ret i32 %div
}

; CHECK: cbnz r1, #0
; CHECK: __brkdiv0
; CHECK: bl

20 changes: 8 additions & 12 deletions test/CodeGen/ARM/Windows/division.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ entry:
}

; CHECK-LABEL: sdiv32:
; CHECK: cbz r0
; CHECK: b
; CHECK: udf.w #249
; CHECK: cbnz r0
; CHECK: __brkdiv0
; CHECK: bl __rt_sdiv

define arm_aapcs_vfpcc i32 @udiv32(i32 %divisor, i32 %divident) {
Expand All @@ -20,9 +19,8 @@ entry:
}

; CHECK-LABEL: udiv32:
; CHECK: cbz r0
; CHECK: b
; CHECK: udf.w #249
; CHECK: cbnz r0
; CHECK: __brkdiv0
; CHECK: bl __rt_udiv

define arm_aapcs_vfpcc i64 @sdiv64(i64 %divisor, i64 %divident) {
Expand All @@ -33,9 +31,8 @@ entry:

; CHECK-LABEL: sdiv64:
; CHECK: orr.w r4, r0, r1
; CHECK-NEXT: cbz r4
; CHECK: b
; CHECK: udf.w #249
; CHECK-NEXT: cbnz r4
; CHECK: __brkdiv0
; CHECK: bl __rt_sdiv64

define arm_aapcs_vfpcc i64 @udiv64(i64 %divisor, i64 %divident) {
Expand All @@ -46,8 +43,7 @@ entry:

; CHECK-LABEL: udiv64:
; CHECK: orr.w r4, r0, r1
; CHECK-NEXT: cbz r4
; CHECK: b
; CHECK: udf.w #249
; CHECK-NEXT: cbnz r4
; CHECK: __brkdiv0
; CHECK: bl __rt_udiv64

0 comments on commit b5143b0

Please sign in to comment.