From 075d2e3c598ec6c67a0b7bad6435b29154b742e7 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 27 Oct 2016 16:59:22 +0000 Subject: [PATCH] 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 | 11 ++----- llvm/lib/Target/ARM/ARMInstrThumb.td | 7 +++++ llvm/test/CodeGen/ARM/Windows/dbzchk.ll | 38 +++++++++---------------- llvm/test/CodeGen/ARM/Windows/division-range.ll | 15 ++++++++++ llvm/test/CodeGen/ARM/Windows/division.ll | 20 ++++++------- 5 files changed, 47 insertions(+), 44 deletions(-) create mode 100644 llvm/test/CodeGen/ARM/Windows/division-range.ll diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 7d89319..12f3247 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -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; diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index 72623a4..1ae9c51 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -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), diff --git a/llvm/test/CodeGen/ARM/Windows/dbzchk.ll b/llvm/test/CodeGen/ARM/Windows/dbzchk.ll index c078e09..af23cb2 100644 --- a/llvm/test/CodeGen/ARM/Windows/dbzchk.ll +++ b/llvm/test/CodeGen/ARM/Windows/dbzchk.ll @@ -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 @@ -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 @@ -123,25 +119,19 @@ attributes #0 = { optsize } ; CHECK-CFG-DAG: t2B ; CHECK-CFG-DAG: BB#2 -; CHECK-CFG-DAG: tCBZ %vreg{{[0-9]}}, -; CHECK-CFG-DAG: t2B +; CHECK-CFG-DAG: tCBNZ %vreg{{[0-9]}}, +; 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 @@ -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 diff --git a/llvm/test/CodeGen/ARM/Windows/division-range.ll b/llvm/test/CodeGen/ARM/Windows/division-range.ll new file mode 100644 index 0000000..9b1920c --- /dev/null +++ b/llvm/test/CodeGen/ARM/Windows/division-range.ll @@ -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 + diff --git a/llvm/test/CodeGen/ARM/Windows/division.ll b/llvm/test/CodeGen/ARM/Windows/division.ll index f4704ea..b149cb0 100644 --- a/llvm/test/CodeGen/ARM/Windows/division.ll +++ b/llvm/test/CodeGen/ARM/Windows/division.ll @@ -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) { @@ -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) { @@ -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) { @@ -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 -- 2.7.4