- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Closed
Labels
I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
Rustc seems unable to use the fact that NonZeroU64 isn't zero:
use std::num::NonZeroU64;
#[inline(never)]
fn foo(x: u64, y: NonZeroU64) -> u64 {
    x / y.get()
}
Gives the asm (with -O):
_ZN4test3foo17h70af812d10d8d714E:
    subq    $40, %rsp
    testq   %rdx, %rdx
    je  .LBB9_2
    movq    %rdx, %r8
    xorl    %edx, %edx
    movq    %rcx, %rax
    divq    %r8
    addq    $40, %rsp
    retq
.LBB9_2:
    leaq    .L__unnamed_6(%rip), %rcx
    callq   _ZN4core9panicking5panic17h6a1e45881f6169d7E
    ud2
Adding an assume() solves the problem:
#![feature(core_intrinsics)]
use std::num::NonZeroU64;
use std::intrinsics::assume;
#[inline(never)]
fn foo2(x: u64, y: NonZeroU64) -> u64 {
    let y2 = y.get();
    unsafe { assume(y2 != 0); }
    x / y2
}
_ZN5test24foo217hf17fb494647eabb3E:
    movq    %rdx, %r8
    xorl    %edx, %edx
    movq    %rcx, %rax
    divq    %r8
    retq
Perhaps such assume() should be added at the end of NonZeroU64::get()?
m0n0chr0m3, slanterns and schneiderfelipe
Metadata
Metadata
Assignees
Labels
I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.