Skip to content

Redundant zero-extension when bswap follows load #3345

Open
@dvulakh

Description

@dvulakh

Example program:

type bigstring =
  (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t

external unsafe_get_16
  :  bigstring
  -> pos:int64#
  -> int
  = "%caml_bigstring_get16u_indexed_by_int64#"

external swap16 : int -> int = "%bswap16"

let unsafe_get_16_swp t ~pos = unsafe_get_16 t ~pos |> swap16

cmm (post #3336):

 (+
   (<<
     (bswap_16
       (let ba_data/383 (load_mut int (+a t/380 8))
         (load_mut unsigned int16 (+ ba_data/383 pos/381))))
     1)
   1))

asm (post #3336):

movq	8(%rax), %rax
movzwq	(%rax,%rbx), %rax
xchg	%ah, %al
movzwq	%ax, %rax
leaq	1(%rax,%rax), %rax
ret

The second movzwq is a noop, because the bottom 16 bits of %rax were populated with a zero-extending load and then byte-swapped, so there is no reason to sign extend again.

Simplifying the code here needs to happen very late in the compiler: bswap remains an opaque operation that conceals the zero-extension from cmm onward, all the way until asm is emitted.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions