# Division by nonzero

**URL:** <https://users.rust-lang.org/t/division-by-nonzero/12822>\
**Category:** uncategorized\
**Created:** [September 11, 2017, 4:40pm UTC](https://users.rust-lang.org/t/division-by-nonzero/12822 "2017-09-11T16:40:12Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![leonardo](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/leonardo/32/1690_2.png) [@leonardo](https://users.rust-lang.org/u/leonardo)\
**Post date:** [September 11, 2017, 4:40pm UTC](https://users.rust-lang.org/t/division-by-nonzero/12822/1 "2017-09-11T16:40:12Z")

</div>

I've noticed that compiling this code

```
#[no_mangle]
pub fn d1(x: u64, y: u64) -> u64 { x / (y + 1) }

```

with:  
-C opt-level=3 -C target-cpu=native

I get:

```
d1:
	subq	$40, %rsp
	movq	%rdx, %r8
	addq	$1, %r8
	je	.LBB3_5
	movq	%rcx, %rax
	orq	%r8, %rax
	shrq	$32, %rax
	je	.LBB3_2
	xorl	%edx, %edx
	movq	%rcx, %rax
	divq	%r8
	jmp	.LBB3_4
.LBB3_2:
	xorl	%edx, %edx
	movl	%ecx, %eax
	divl	%r8d
.LBB3_4:
	addq	$40, %rsp
	retq
.LBB3_5:
	leaq	panic_loc.3(%rip), %rcx
	callq	_ZN4core9panicking5panic17h69e14964566759a9E
	ud2

```

In the function d1 the y argument is unsigned, so y+1 can't be zero, so what's the point of that panic section?

Edit: Is the panic meant to catch the case where y== u32::MAX?

---

<div class="post-metadata">

**Author:** ![vitalyd](https://avatars.discourse-cdn.com/v4/letter/v/edb3f5/32.png) [@vitalyd](https://users.rust-lang.org/u/vitalyd)\
**Post date:** [September 11, 2017, 4:44pm UTC](https://users.rust-lang.org/t/division-by-nonzero/12822/2 "2017-09-11T16:44:57Z")

</div>

Right, it's jumping to that panic BB only when the `addq $1, %r8` sets the zero flag, which means you wrapped around the `u64`.

---

<div class="post-metadata">

**Author:** ![ethernet](https://avatars.discourse-cdn.com/v4/letter/e/a9adbd/32.png) [@ethernet](https://users.rust-lang.org/u/ethernet)\
**Post date:** [September 11, 2017, 4:47pm UTC](https://users.rust-lang.org/t/division-by-nonzero/12822/3 "2017-09-11T16:47:44Z")

</div>

Unsigned arithmetic can wrap around, and is well defined to do so, unlike signed. So, yes, it needs to check because it could be 0 on the bottom after the increment.

You could try using saturating\_add and see if the potential panic goes away.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/cuviper/32/3156_2.png) [@cuviper](https://users.rust-lang.org/u/cuviper)\
**Post date:** [September 11, 2017, 4:50pm UTC](https://users.rust-lang.org/t/division-by-nonzero/12822/4 "2017-09-11T16:50:11Z")

</div>

> [@ethernet](#):
>
> Unsigned arithmetic can wrap around, and is well defined to do so, unlike signed.

That's a C-ism. In Rust, unsigned and signed overflow is treated equally -- either as a debug assert or a modular/2's-complement wrap around.

---

<div class="post-metadata">

**Author:** ![vitalyd](https://avatars.discourse-cdn.com/v4/letter/v/edb3f5/32.png) [@vitalyd](https://users.rust-lang.org/u/vitalyd)\
**Post date:** [September 11, 2017, 5:03pm UTC](https://users.rust-lang.org/t/division-by-nonzero/12822/5 "2017-09-11T17:03:58Z")

</div>

> [@ethernet](#):
>
> You could try using saturating\_add and see if the potential panic goes away.

Unfortunately, no.

```rust
example::d1:
        addq $1, %rsi
        movq $-1, %rcx
        cmovaeq %rsi, %rcx
        testq %rcx, %rcx
        je .LBB1_5
        movq %rdi, %rax
        orq %rcx, %rax
        shrq $32, %rax
        je .LBB1_2
        xorl %edx, %edx
        movq %rdi, %rax
        divq %rcx
        retq
.LBB1_2:
        xorl %edx, %edx
        movl %edi, %eax
        divl %ecx
        retq
.LBB1_5:
        pushq %rbp
        movq %rsp, %rbp
        leaq panic_loc.2(%rip), %rdi
        callq core::panicking::panic@PLT
```

It actually looks like the saturating\_add is potentially missing an LLVM attribute to indicate that it doesn't wrap. As a result, the generated asm contains the useless `testq` and `je` instructions.

---

<div class="post-metadata">

**Author:** ![leonardo](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/leonardo/32/1690_2.png) [@leonardo](https://users.rust-lang.org/u/leonardo)\
**Post date:** [September 11, 2017, 5:58pm UTC](https://users.rust-lang.org/t/division-by-nonzero/12822/6 "2017-09-11T17:58:19Z")

</div>

> [@vitalyd](#):
>
> It actually looks like the saturating\_add is potentially missing an LLVM attribute to indicate that it doesn’t wrap. As a result, the generated asm contains the useless testq and je instructions.

This seems fit for a bug report.

---

<div class="post-metadata">

**Author:** ![vitalyd](https://avatars.discourse-cdn.com/v4/letter/v/edb3f5/32.png) [@vitalyd](https://users.rust-lang.org/u/vitalyd)\
**Post date:** [September 11, 2017, 6:32pm UTC](https://users.rust-lang.org/t/division-by-nonzero/12822/7 "2017-09-11T18:32:31Z")

</div>

~~I'll do that in a bit and paste the link here (unless someone is already doing this).~~  
[https://github.com/rust-lang/rust/issues/44500](https://github.com/rust-lang/rust/issues/44500)

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steffahn/32/47569_2.png) [@steffahn](https://users.rust-lang.org/u/steffahn)\
**Post date:** [January 12, 2023, 8:45am UTC](https://users.rust-lang.org/t/division-by-nonzero/12822/8 "2023-01-12T08:45:31Z")

</div>


