This fixes up handling of divisions on ARM/Windows, and consistently does calls to helper functions using the windows/msvc names, instead of the libgcc naming.
251 lines
8.1 KiB
Diff
251 lines
8.1 KiB
Diff
From a6c33deef382981590bd9298b492b612bcbae521 Mon Sep 17 00:00:00 2001
|
|
From: Saleem Abdulrasool <compnerd@compnerd.org>
|
|
Date: Thu, 27 Oct 2016 16:59:22 +0000
|
|
Subject: [PATCH 8/9] 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!
|
|
|
|
Cherry-picked from SVN trunk commit 285312, git mirror commit
|
|
b5143b06a12b5.
|
|
---
|
|
lib/Target/ARM/ARMISelLowering.cpp | 11 +++------
|
|
lib/Target/ARM/ARMInstrThumb.td | 7 ++++++
|
|
test/CodeGen/ARM/Windows/dbzchk.ll | 38 +++++++++++-------------------
|
|
test/CodeGen/ARM/Windows/division-range.ll | 15 ++++++++++++
|
|
test/CodeGen/ARM/Windows/division.ll | 20 +++++++---------
|
|
5 files changed, 47 insertions(+), 44 deletions(-)
|
|
create mode 100644 test/CodeGen/ARM/Windows/division-range.ll
|
|
|
|
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
|
|
index 8db9f54..f7b09fa 100644
|
|
--- a/lib/Target/ARM/ARMISelLowering.cpp
|
|
+++ b/lib/Target/ARM/ARMISelLowering.cpp
|
|
@@ -8215,16 +8215,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/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
|
|
index 93a174f..6c759a1 100644
|
|
--- a/lib/Target/ARM/ARMInstrThumb.td
|
|
+++ b/lib/Target/ARM/ARMInstrThumb.td
|
|
@@ -1259,6 +1259,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/test/CodeGen/ARM/Windows/dbzchk.ll b/test/CodeGen/ARM/Windows/dbzchk.ll
|
|
index c078e09..af23cb2 100644
|
|
--- a/test/CodeGen/ARM/Windows/dbzchk.ll
|
|
+++ b/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 <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
|
|
|
|
@@ -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/test/CodeGen/ARM/Windows/division-range.ll b/test/CodeGen/ARM/Windows/division-range.ll
|
|
new file mode 100644
|
|
index 0000000..9b1920c
|
|
--- /dev/null
|
|
+++ b/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/test/CodeGen/ARM/Windows/division.ll b/test/CodeGen/ARM/Windows/division.ll
|
|
index f4704ea..b149cb0 100644
|
|
--- a/test/CodeGen/ARM/Windows/division.ll
|
|
+++ b/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
|
|
|