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

Better codegen for truncated bswap #50910

Closed
davidbolvansky opened this issue Aug 20, 2021 · 8 comments
Closed

Better codegen for truncated bswap #50910

davidbolvansky opened this issue Aug 20, 2021 · 8 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla llvm:codegen

Comments

@davidbolvansky
Copy link
Collaborator

davidbolvansky commented Aug 20, 2021

Bugzilla Link 51568
Version trunk
OS Linux
CC @RKSimon,@rotateright

Extended Description

unsigned int swap_ull(unsigned long long value)
{
    return ((value & 0x00000000000000ffull) << 56)
            | ((value & 0x000000000000ff00ull) << 40)
            | ((value & 0x0000000000ff0000ull) << 24)
            | ((value & 0x00000000ff000000ull) << 8)
            | ((value & 0x000000ff00000000ull) >> 8)
            | ((value & 0x0000ff0000000000ull) >> 24)
            | ((value & 0x00ff000000000000ull) >> 40)
            | ((value & 0xff00000000000000ull) >> 56);
}

unsigned int swap_ull_builtin(unsigned long long value)
{
    return __builtin_bswap64(value);
}

Trunk -O3:

swap_ull(unsigned long long):                           # @&#8203;swap_ull(unsigned long long)
        movabs  rax, 72057589742960640
        and     rax, rdi
        bswap   rax
        shr     rdi, 56
        or      eax, edi
        ret
swap_ull_builtin(unsigned long long):                  # @&#8203;swap_ull_builtin(unsigned long long)
        mov     rax, rdi
        bswap   rax
        ret

ICC -O3:

swap_ull(unsigned long long):
        bswap     rdi                                           #&#8203;10.51
        mov       eax, edi                                      #&#8203;10.51
        ret                                                     #&#8203;10.51
swap_ull_builtin(unsigned long long):
        bswap     rdi                                           #&#8203;15.12
        mov       eax, edi                                      #&#8203;15.12
        ret                                                     #&#8203;15.12
unsigned int swap_ull(unsigned long long value)
{
    return ((value & 0x00000000000000ffull) << 56)
            | ((value & 0x000000000000ff00ull) << 40)
            | ((value & 0x0000000000ff0000ull) << 24)
            | ((value & 0x00000000ff000000ull) << 8)
            | ((value & 0x000000ff00000000ull) >> 8)
            | ((value & 0x0000ff0000000000ull) >> 24)
            | ((value & 0x00ff000000000000ull) >> 40)
            | ((value & 0xff00000000000000ull) >> 56);
}

unsigned int swap_ull_builtin(unsigned long long value)
{
    return __builtin_bswap64(value);
}
define i32 @&#8203;src(i64 %0) {
%1:
  %2 = and i64 %0, 72057594037927935
  %3 = bswap i64 %2
  %4 = lshr i64 %0, 56
  %5 = or i64 %3, %4
  %6 = trunc i64 %5 to i32
  ret i32 %6
}
=>
define i32 @&#8203;tgt(i64 %0) {
%1:
  %2 = bswap i64 %0
  %3 = trunc i64 %2 to i32
  ret i32 %3
}
Transformation seems to be correct!

https://alive2.llvm.org/ce/z/loQjOQ

@rotateright
Copy link
Contributor

Probably need some enhancement to known bits and/or demanded bits to see that we have masked off the high byte (72057594037927935 == 0x00ff...).

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 11, 2021
@RKSimon
Copy link
Collaborator

RKSimon commented Dec 31, 2021

llvm::recognizeBSwapOrBitReverseIdiom could handle this, but it might bail out due to the trunc() user of the or()

@rotateright
Copy link
Contributor

Do you know why we have the trunc user check? If I just comment it out, this bug is fixed with no regression test failures.

@RKSimon
Copy link
Collaborator

RKSimon commented Dec 31, 2021

It looks like it first appeared in https://reviews.llvm.org/D20591

When I refactored recognizeBSwapOrBitReverseIdiom to better handle truncs in https://reviews.llvm.org/D88316 it looks like I kept it, but I'm not certain if it was necessary any more.

@rotateright Are you up for dealing with this?

@rotateright rotateright self-assigned this Jan 1, 2022
@rotateright
Copy link
Contributor

Sure - it should just be a matter of removing that check and cleaning up the code. I'll look over the tests to see if there was a test that became moot with D88316.

@rotateright
Copy link
Contributor

I added a trunc test that I thought might work with:
3a23937
...but it doesn't match either way, so I'll plan to remove the trunc check as the fast fix for this bug.

@RKSimon
Copy link
Collaborator

RKSimon commented Jan 6, 2022

Thanks @rotateright

@davidbolvansky
Copy link
Collaborator Author

Thanks for the fix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla llvm:codegen
Projects
None yet
Development

No branches or pull requests

3 participants