Skip to content

optimisation opportunity missed due to assert! #45371

@josephDunne

Description

@josephDunne

I have noticed interesting behaviour regarding assert! which was unexpected. I am not sure if this is a LLVM or Rust issue.

in the following code (See godbolt link below) I have a vec like structure OwnedRegion.
I want to iterate over the region (implemented as slice::IterMut) and populate an array.
I expect LLVM to do loop unrolling and loop vectorisation. If you place
the necessary intrinsics::assume to trick llvm into removing the bound check you do
indeed get the optimisations. However I wanted to replace the assume with an assert!
but that removes the optimisation even if combined with an assume! What I think is happening
is the bounds check is being reintroduced because the length check in the assert! is being moved into the for loop or elided completely because it duplicates the length check in the index operation.

What should happen is the bounds check in the for loop should be lifted/elided because of the assert!

fn main() {
    let mut region: OwnedRegion<usize> = test::black_box(OwnedRegion::empty());
    let mut my_array: [usize; 128] = [0;128];

    // !!! The following assert blocks the loop vectorization optimization !!!
    // !!! remove the following line to enable Loop vectorization !!!
    assert!(region.len > 128 );

    // I know this assume is unsafe given that we created an empty OwnedRegion. 
    // I am only looking at the output assembly to see if optimization is run 
    unsafe {  assume(region.len() > 128) };
    for i in 0..128 {
       my_array[i] = region[i];
    } 
    println!("{:?}", &my_array[..32]);
}

with assert! and assume:

inner loops is:

  cmp r15, rcx
  jbe .LBB6_5
  lea rcx, [rax - 2]
  mov rdx, qword ptr [rbx + 8*rax - 24]
  mov qword ptr [rbp + 8*rax - 1152], rdx
  cmp r15, rcx
  jbe .LBB6_4
  lea rcx, [rax - 1]
  mov rdx, qword ptr [rbx + 8*rax - 16]
  mov qword ptr [rbp + 8*rax - 1144], rdx
  cmp r15, rcx
  jbe .LBB6_8
  mov rcx, qword ptr [rbx + 8*rax - 8]
  mov qword ptr [rbp + 8*rax - 1136], rcx
  cmp r15, rax
  jbe .LBB6_10
  add rsi, 4
  mov rcx, qword ptr [rbx + 8*rax]
  mov qword ptr [rbp + 8*rax - 1128], rcx

where LBB6_4, LBB6_5, LBB6_8, and LBB6_10 jump to std::panic

with just assume:

inner loops is:

.LBB3_3:
  movups xmm0, xmmword ptr [rbx + 8*rax]
  movups xmm1, xmmword ptr [rbx + 8*rax + 16]
  movups xmmword ptr [rbp + 8*rax - 1120], xmm0
  movups xmmword ptr [rbp + 8*rax - 1104], xmm1
  movups xmm0, xmmword ptr [rbx + 8*rax + 32]
  movups xmm1, xmmword ptr [rbx + 8*rax + 48]
  movups xmmword ptr [rbp + 8*rax - 1088], xmm0
  movups xmmword ptr [rbp + 8*rax - 1072], xmm1
  movups xmm0, xmmword ptr [rbx + 8*rax + 64]
  movups xmm1, xmmword ptr [rbx + 8*rax + 80]
  movups xmmword ptr [rbp + 8*rax - 1056], xmm0
  movups xmmword ptr [rbp + 8*rax - 1040], xmm1
  movups xmm0, xmmword ptr [rbx + 8*rax + 96]
  movups xmm1, xmmword ptr [rbx + 8*rax + 112]
  movups xmmword ptr [rbp + 8*rax - 1024], xmm0
  movups xmmword ptr [rbp + 8*rax - 1008], xmm1
  add rax, 16
  cmp rax, 128
  jne .LBB3_3

here is a godbolt link

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-enhancementCategory: An issue proposing an enhancement or a PR with one.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions