Index: test/NaCl/ARM/divrem-guards.ll |
diff --git a/test/NaCl/ARM/divrem-guards.ll b/test/NaCl/ARM/divrem-guards.ll |
new file mode 100644 |
index 0000000000000000000000000000000000000000..822ae848d4d08d252ce2f4fa91ee4582b3dae67e |
--- /dev/null |
+++ b/test/NaCl/ARM/divrem-guards.ll |
@@ -0,0 +1,104 @@ |
+; RUN: opt < %s -insert-divide-check -S | FileCheck -check-prefix=OPT %s |
+; RUN: llc -mtriple=armv7-unknown-nacl -sfi-branch -filetype=obj %s -o - \ |
+; RUN: | llvm-objdump -disassemble -triple armv7 -mattr=+nacl-trap - \ |
+; RUN: | FileCheck -check-prefix=ARM %s |
+ |
+ |
+; Check for all four operators that need guards. |
+define i32 @mysdiv(i32 %x, i32 %y) #0 { |
+entry: |
+ %div1 = sdiv i32 %x, %y |
+; OPT: %0 = icmp eq i32 %y, 0 |
+; OPT-NEXT: br i1 %0, label %divrem.by.zero, label %guarded.divrem |
+; OPT: guarded.divrem: |
+; OPT-NEXT: sdiv |
+; OPT-NEXT: ret |
+; OPT: divrem.by.zero: |
+; OPT-NEXT: call void @llvm.trap() |
+; OPT-NEXT: unreachable |
+; ARM: cmp r1, #0 |
+; ARM-NEXT: beq |
+ ret i32 %div1 |
+; ARM: f0 de fe e7 |
+} |
+ |
+define i32 @myudiv(i32 %x, i32 %y) #0 { |
+entry: |
+ %div1 = udiv i32 %x, %y |
+; OPT: %0 = icmp eq i32 %y, 0 |
+; OPT-NEXT: br i1 %0, label %divrem.by.zero, label %guarded.divrem |
+; OPT: guarded.divrem: |
+; OPT-NEXT: udiv |
+; OPT-NEXT: ret |
+; OPT: divrem.by.zero: |
+; OPT-NEXT: call void @llvm.trap() |
+; OPT-NEXT: unreachable |
+; ARM: cmp r1, #0 |
+; ARM-NEXT: beq |
+ ret i32 %div1 |
+; ARM: f0 de fe e7 |
+} |
+ |
+define i32 @mysrem(i32 %x, i32 %y) #0 { |
+entry: |
+ %rem1 = srem i32 %x, %y |
+; OPT: %0 = icmp eq i32 %y, 0 |
+; OPT-NEXT: br i1 %0, label %divrem.by.zero, label %guarded.divrem |
+; OPT: guarded.divrem: |
+; OPT-NEXT: srem |
+; OPT-NEXT: ret |
+; OPT: divrem.by.zero: |
+; OPT-NEXT: call void @llvm.trap() |
+; OPT-NEXT: unreachable |
+; ARM: cmp r1, #0 |
+; ARM-NEXT: beq |
+ ret i32 %rem1 |
+; ARM: f0 de fe e7 |
+} |
+ |
+define i32 @myurem(i32 %x, i32 %y) #0 { |
+entry: |
+ %rem1 = urem i32 %x, %y |
+; OPT: %0 = icmp eq i32 %y, 0 |
+; OPT-NEXT: br i1 %0, label %divrem.by.zero, label %guarded.divrem |
+; OPT: guarded.divrem: |
+; OPT-NEXT: urem |
+; OPT-NEXT: ret |
+; OPT: divrem.by.zero: |
+; OPT-NEXT: call void @llvm.trap() |
+; OPT-NEXT: unreachable |
+; ARM: cmp r1, #0 |
+; ARM-NEXT: beq |
+ ret i32 %rem1 |
+; ARM: f0 de fe e7 |
+} |
+ |
+; Divides by non-zero constants should not be guarded. |
+define i32 @mysdiv_const(i32 %x) #0 { |
+entry: |
+ %div1 = sdiv i32 %x, 10 |
+; OPT-NOT: icmp |
+; OPT-NOT: br |
+; OPT-NOT: guarded.divrem: |
+; OPT-NOT: divrem.by.zero: |
+; OPT-NOT: call void @llvm.trap() |
+; OPT-NOT: unreachable |
+; ARM-NOT: cmp r1, #0 |
+; ARM-NOT: f0 de fe e7 |
+ ret i32 %div1 |
+} |
+ |
+; Divides by explicit zero should prefixed by a trap. |
+define i32 @mysdiv_zero(i32 %x) #0 { |
+entry: |
+ %div1 = sdiv i32 %x, 0 |
+; OPT-NOT: guarded.divrem: |
+; OPT-NOT: divrem.by.zero: |
+; OPT: call void @llvm.trap() |
+; OPT-NEXT: sdiv |
+; ARM-NOT: cmp r1, #0 |
+; ARM: f0 de fe e7 |
+ ret i32 %div1 |
+} |
+ |
+attributes #0 = { nounwind } |