Skip to content

i32 load + zext is merged into 64-bit load for __ptr32 on amd64 #66873

Closed
@cac03

Description

@cac03

Reproduction

https://godbolt.org/z/PGK3PEf64

__attribute((noinline))
uint64_t LoadAsLong(uint32_t* __ptr32 foo) {
	return static_cast<uint64_t>(*foo);
}

I expect that the LoadAsLong will return 42 for the test case in the godbolt listing.
But it does not.

If do not use __ptr32, then the LoadAsLong returns 42

Investigation

Clang produces the following assembly for the LoadAsLong function:

        movslq  %edi, %rax
        movq    (%rax), %rax
        retq

the assembly loads 64 bit value but had to load 32 bits.

As far as I see llvm IR for the function is correct before isel:

define dso_local noundef i64 @LoadAsLong(unsigned int ptr32_sptr*)(ptr addrspace(270) nocapture noundef readonly %foo) local_unnamed_addr {
entry:
  %0 = load i32, ptr addrspace(270) %foo, align 4
  %conv = zext i32 %0 to i64
  ret i64 %conv
}

but after isel:

# Machine code for function LoadAsLong(unsigned int ptr32_sptr*): IsSSA, TracksLiveness
Function Live Ins: $rdi in %0

bb.0.entry:
  liveins: $rdi
  %0:gr64 = COPY $rdi
  %1:gr32 = COPY %0.sub_32bit:gr64
  %2:gr64 = MOVSX64rr32 killed %1:gr32
  %3:gr64 = MOV64rm killed %2:gr64, 1, $noreg, 0, $noreg :: (load (s64) from %ir.foo, align 4, addrspace 270)
  $rax = COPY %3:gr64
  RET 0, $rax

# End machine code for function LoadAsLong(unsigned int ptr32_sptr*).

there is load (s64) from %ir.foo, align 4, addrspace 270

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