Skip to content

Missed optimization for *(ptr << 2) #62093

Closed
@WaffleLapkin

Description

@WaffleLapkin

For this function (which is essentially *(ptr << 2)) llvm generates the following assembly:

define noundef i32 @shift_read2(ptr noundef nonnull %packed) unnamed_addr #1 personality ptr @rust_eh_personality {
start:
  %n.i.i = ptrtoint ptr %packed to i64
  %offset.i.i.i = mul i64 %n.i.i, 3
  %0 = getelementptr i8, ptr %packed, i64 %offset.i.i.i
  %1 = icmp ne ptr %0, null
  tail call void @llvm.assume(i1 %1)
  %2 = load i32, ptr %0, align 4 ; , !noundef !10
  ret i32 %2
}
shift_read2:                            # @shift_read2
        lea     rax, [rdi + 2*rdi]
        mov     eax, dword ptr [rdi + rax]
        ret

This looks suboptimal, since a single instruction can be generated instead:

shift_read2:                            # @shift_read2
        mov     eax, dword ptr [4*rdi]
        ret

Moreover if you change the function slightly (replace 3 by 7 which is equivalent to replacing *(ptr << 2) by *(ptr << 3)) the generated assembly is better:

define noundef i32 @shift_read3(ptr noundef nonnull %packed) unnamed_addr #1 personality ptr @rust_eh_personality {
start:
  %n.i.i = ptrtoint ptr %packed to i64
  %offset.i.i.i = mul i64 %n.i.i, 7
  %0 = getelementptr i8, ptr %packed, i64 %offset.i.i.i
  %1 = icmp ne ptr %0, null
  tail call void @llvm.assume(i1 %1)
  %2 = load i32, ptr %0, align 4 ; , !noundef !10
  ret i32 %2
}
shift_read3:                            # @shift_read3
        mov     eax, dword ptr [8*rdi]
        ret

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions