Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

checked_div happy path #73731

Closed
leonardo-m opened this issue Jun 25, 2020 · 8 comments · Fixed by #73938
Closed

checked_div happy path #73731

leonardo-m opened this issue Jun 25, 2020 · 8 comments · Fixed by #73938
Assignees
Labels
A-codegen Area: Code generation T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@leonardo-m
Copy link

leonardo-m commented Jun 25, 2020

This is a kind of enhancement suggestion. Given this function:

pub fn foo7(n: u32, v: u32) -> Option<u32> {
    n.checked_div(v + 1)
}

Compiled wih rustc 1.46.0-nightly (67100f6 2020-06-24) with good optimization flags gives:

example::foo7:
	inc     esi
	jne     .LBB0_3
	xor     eax, eax
	ret
.LBB0_3:
	mov     eax, edi
	xor     edx, edx
	div     esi
	mov     edx, eax
	mov     eax, 1
	ret

But I think the happy path should be with the denominator != 0 (that hopefully is the most common case), instead of the case with a division by zero.

So I've done few more experiments:

#![feature(core_intrinsics)]
use std::intrinsics::{unchecked_div, unlikely, likely};

pub fn checked_div1(this: u32, rhs: u32) -> Option<u32> {
    match rhs {
        0 => None,
        rhs => Some(unsafe { unchecked_div(this, rhs) }),
    }
}

pub fn foo1(n: u32, v: u32) -> Option<u32> {
    checked_div1(n, v + 1)
}

pub fn checked_div2(this: u32, rhs: u32) -> Option<u32> {
    if rhs != 0 {
        Some(unsafe { unchecked_div(this, rhs) })
    } else {
        None         
    }
}

pub fn foo2(n: u32, v: u32) -> Option<u32> {
    checked_div2(n, v + 1)
}

pub fn checked_div3(this: u32, rhs: u32) -> Option<u32> {
    if unlikely(rhs == 0) {
        None
    } else {
        Some(unsafe { unchecked_div(this, rhs) })
    }
}

pub fn foo3(n: u32, v: u32) -> Option<u32> {
    checked_div3(n, v + 1)
}

pub fn foo4(n: u32, v: u32) -> Option<u32> {
    if likely(v + 1 != 0) {
        Some(unsafe { unchecked_div(n, v + 1) })
    } else {
        None        
    }
}

The asm:

example::checked_div1:
	test    esi, esi
	je      .LBB0_1
	mov     eax, edi
	xor     edx, edx
	div     esi
	mov     edx, eax
	mov     eax, 1
	ret
.LBB0_1:
	xor     eax, eax
	ret

example::foo1:
	inc     esi
	jne     .LBB1_2
	xor     eax, eax
	ret
.LBB1_2:
	mov     eax, edi
	xor     edx, edx
	div     esi
	mov     edx, eax
	mov     eax, 1
	ret

This issue has been assigned to @nbdd0121 via this comment.

@nagisa nagisa added the A-codegen Area: Code generation label Jun 25, 2020
@nagisa
Copy link
Member

nagisa commented Jun 25, 2020

Ideally/most cleanly solved with some branch weight annotation that we don’t have implemented yet.

I wouldn’t rely much on re-arranging Rust code much as that can break again on a whim.

@leonardo-m
Copy link
Author

Isn't std::intrinsics::likely a branch weight annotation? Isn't it working in Rust?

@nagisa
Copy link
Member

nagisa commented Jun 25, 2020

Oh I guess that ended up being added, I skimmed past that part in your report. Yeah in that case we should just go with one of the if unlikely options.

@nbdd0121
Copy link
Contributor

I had a try, but it cannot yet be implemented because likely/unlikely are not yet const intrinsics.

@nbdd0121
Copy link
Contributor

Okay I have a working version here. However this would be blocked until likely and unlikely is made const.

@rustbot claim

@rustbot rustbot self-assigned this Jun 26, 2020
@LeSeulArtichaut LeSeulArtichaut added S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jun 26, 2020
@nagisa
Copy link
Member

nagisa commented Jun 26, 2020

@oli-obk @RalfJung any reason we cannot or should not make the likely/unlikely intrinsic const?

@RalfJung
Copy link
Member

RalfJung commented Jun 26, 2020

None that I can think of. But this requires T-lang approval (through FCP I presume) as it is an intrinsic. Better make it a separate PR.

@nbdd0121
Copy link
Contributor

nbdd0121 commented Jul 1, 2020

@rustbot modify labels: -S-blocked

@rustbot rustbot removed the S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. label Jul 1, 2020
@bors bors closed this as completed in 4f536f2 Jul 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants