Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-14476] Failure to eliminate unnecessary loads in trivial pointer program #56832

Open
Lukasa opened this issue Apr 12, 2021 · 1 comment
Open
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@Lukasa
Copy link
Contributor

Lukasa commented Apr 12, 2021

Previous ID SR-14476
Radar rdar://problem/76538003
Original Reporter @Lukasa
Type Bug
Environment

Swift 5.3 and nightly, Linux and Mac.

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: f8c7e59cf64aab2902debd4264d6bb9b

Issue Description:

Swift's API contract has always been that its typed pointers follow strict aliasing rules. (In fact, stricter-than-strict, as Swift does not inherit the char * escape-hatch of C.) As a result, we'd expect pointers of different types to have redundant loads removed.

Consider the program below:

func addTwo(x: UnsafeMutablePointer<Int16>, 
            y: UnsafeMutablePointer<Int16>, 
            increment: UnsafeMutablePointer<Int16>) {
    x.pointee &+= increment.pointee
    y.pointee &+= increment.pointee
}

func addTwoHeterogeneous(x: UnsafeMutablePointer<Int32>, 
                         y: UnsafeMutablePointer<Int32>, 
                         increment: UnsafeMutablePointer<Int16>) {
    x.pointee &+= Int32(increment.pointee)
    y.pointee &+= Int32(increment.pointee)
}

When compiled on macOS at -O and disassembled, we get this (a compiler explorer example is also available):

test.addTwo(x: Swift.UnsafeMutablePointer<Swift.Int16>, y: Swift.UnsafeMutablePointer<Swift.Int16>, increment: Swift.UnsafeMutablePointer<Swift.Int16>) -> ():
0000000100003f80    pushq   %rbp
0000000100003f81    movq    %rsp, %rbp
0000000100003f84    movzwl  (%rdx), %eax
0000000100003f87    addw    %ax, (%rdi)
0000000100003f8a    movzwl  (%rdx), %eax
0000000100003f8d    addw    %ax, (%rsi)
0000000100003f90    popq    %rbp
0000000100003f91    retq
0000000100003f92    nopw    %cs:(%rax,%rax)
0000000100003f9c    nopl    (%rax)
test.addTwoHeterogeneous(x: Swift.UnsafeMutablePointer<Swift.Int32>, y: Swift.UnsafeMutablePointer<Swift.Int32>, increment: Swift.UnsafeMutablePointer<Swift.Int16>) -> ():
0000000100003fa0    pushq   %rbp
0000000100003fa1    movq    %rsp, %rbp
0000000100003fa4    movswl  (%rdx), %eax
0000000100003fa7    addl    %eax, (%rdi)
0000000100003fa9    movswl  (%rdx), %eax
0000000100003fac    addl    %eax, (%rsi)
0000000100003fae    popq    %rbp
0000000100003faf    retq

Note that both functions generate two loads from eax, even though in addTwoHeterogeneous the second load is redundant, as the pointers may not alias.

Consider equivalent C code:

void addTwo(short *x, short *y, short *increment) {
    *x += *increment;
    *y += *increment;
}

void addTwoNoAlias(long *x, long *y, short *increment) {
    *x += *increment;
    *y += *increment;
}

Here we get the expected disassembly output when compiled on macOS at -O2 (again, a compiler explorer example is available):

_addTwo:
0000000000000000    pushq   %rbp
0000000000000001    movq    %rsp, %rbp
0000000000000004    movzwl  (%rdx), %eax
0000000000000007    addw    %ax, (%rdi)
000000000000000a    movzwl  (%rdx), %eax
000000000000000d    addw    %ax, (%rsi)
0000000000000010    popq    %rbp
0000000000000011    retq
0000000000000012    nopw    %cs:(%rax,%rax)
000000000000001c    nopl    (%rax)
_addTwoNoAlias:
0000000000000020    pushq   %rbp
0000000000000021    movq    %rsp, %rbp
0000000000000024    movswq  (%rdx), %rax
0000000000000028    addq    %rax, (%rdi)
000000000000002b    addq    %rax, (%rsi)
000000000000002e    popq    %rbp
000000000000002f    retq

Notice that in the NoAlias variant of the function there is only one load from rax.

@Lukasa
Copy link
Contributor Author

Lukasa commented Apr 12, 2021

@swift-ci create

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

1 participant