[llvm-bugs] [Bug 44448] New: __builtin_align_down() - some opts missing

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Jan 2 15:27:16 PST 2020


https://bugs.llvm.org/show_bug.cgi?id=44448

            Bug ID: 44448
           Summary: __builtin_align_down() - some opts missing
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Backend: X86
          Assignee: unassignedbugs at nondot.org
          Reporter: lebedev.ri at gmail.com
                CC: craig.topper at gmail.com, llvm-bugs at lists.llvm.org,
                    llvm-dev at redking.me.uk, spatel+llvm at rotateright.com

The `__builtin_align_down()` is naive, sane version, it results in suboptimal
assembly.
The `__builtin_align_down_GOOD()` results in optimal assembly,
identical to `__builtin_align_down_UNFRIENDLY()`.

I'm not really sure what folds are missing.
I would say that `@_Z20__builtin_align_downPcm()` is IR-canonical,
while `@_Z25__builtin_align_down_GOODPcm()` isn't,
even though the final assembly is optimal for the 'non-canonical' one.

(1) Their difference is this IR-level fold: https://rise4fun.com/Alive/sltV
^ should we be hoisting that IR `neg`, or sinking it?

Name: __builtin_align_down
  %neg = sub i64 0, %alignment
  %and = and i64 %0, %neg
  %r = sub i64 %and, %0
=>
  %neg.not = add i64 %alignment, -1
  %sub1 = and i64 %neg.not, %0
  %r = sub i64 0, %sub1


(2) In backend, we are clearly missing the following fold:
https://rise4fun.com/Alive/ZVdp

Name: ptr - (ptr & (alignment-1))  ->  ptr & (0 - alignment)
  %mask = add i64 %alignment, -1
  %bias = and i64 %ptr, %mask
  %r = sub i64 %ptr, %bias
=>
  %highbitmask = sub i64 0, %alignment
  %r = and i64 %ptr, %highbitmask

Not sure if there is more general fold than that missing?


https://godbolt.org/z/GBAsiB

#include <cstdint>
#include <cstddef>

char* __attribute__((alloc_align(2)))
__builtin_align_down(char* maybe_overbiased_ptr, size_t alignment) {
    size_t mask = alignment - 1;
    uintptr_t maybe_overbiased_intptr = (uintptr_t)maybe_overbiased_ptr;
    uintptr_t aligned_intptr = maybe_overbiased_intptr & (~mask);
    uintptr_t bias = maybe_overbiased_intptr - aligned_intptr;
    return maybe_overbiased_ptr - bias;
}

char* __attribute__((alloc_align(2)))
__builtin_align_down_GOOD(char* maybe_overbiased_ptr, size_t alignment) {
    size_t mask = alignment - 1;
    uintptr_t maybe_overbiased_intptr = (uintptr_t)maybe_overbiased_ptr;
    uintptr_t aligned_intptr = maybe_overbiased_intptr & (~mask);
    uintptr_t bias = aligned_intptr - maybe_overbiased_intptr;
    return maybe_overbiased_ptr + bias;
}

char* __attribute__((alloc_align(2)))
__builtin_align_up(char* maybe_underbiased_ptr, size_t alignment) {
    size_t mask = alignment - 1;
    uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr;
    uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + mask;
    uintptr_t aligned_intptr = aligned_biased_intptr & (~mask);
    uintptr_t bias = aligned_intptr - maybe_underbiased_intptr;
    return maybe_underbiased_ptr + bias;
}

char* __attribute__((alloc_align(2)))
__builtin_align_down_UNFRIENDLY(char* maybe_overbiased_ptr, size_t alignment) {
    size_t mask = alignment - 1;
    uintptr_t maybe_overbiased_intptr = (uintptr_t)maybe_overbiased_ptr;
    uintptr_t aligned_intptr = maybe_overbiased_intptr & (~mask);
    return (char*)aligned_intptr;
}

char* __attribute__((alloc_align(2)))
__builtin_align_up_UNFRIENDLY(char* maybe_underbiased_ptr, size_t alignment) {
    size_t mask = alignment - 1;
    uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr;
    uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + mask;
    uintptr_t aligned_intptr = aligned_biased_intptr & (~mask);
    return (char*)aligned_intptr;
}

define dso_local i8* @_Z20__builtin_align_downPcm(i8* %maybe_overbiased_ptr,
i64 %alignment) local_unnamed_addr #0 {
  %0 = ptrtoint i8* %maybe_overbiased_ptr to i64
  %neg.not = add i64 %alignment, -1
  %sub1 = and i64 %neg.not, %0
  %idx.neg = sub i64 0, %sub1
  %add.ptr = getelementptr inbounds i8, i8* %maybe_overbiased_ptr, i64 %idx.neg
  ret i8* %add.ptr
}
define dso_local i8* @_Z25__builtin_align_down_GOODPcm(i8*
%maybe_overbiased_ptr, i64 %alignment) local_unnamed_addr #0 {
  %0 = ptrtoint i8* %maybe_overbiased_ptr to i64
  %neg = sub i64 0, %alignment
  %and = and i64 %0, %neg
  %sub1 = sub i64 %and, %0
  %add.ptr = getelementptr inbounds i8, i8* %maybe_overbiased_ptr, i64 %sub1
  ret i8* %add.ptr
}

__builtin_align_down(char*, unsigned long):            #
@__builtin_align_down(char*, unsigned long)
        dec     rsi
        mov     rax, rdi
        and     rsi, rdi
        sub     rax, rsi
        ret
__builtin_align_down_GOOD(char*, unsigned long):       #
@__builtin_align_down_GOOD(char*, unsigned long)
        mov     rax, rsi
        neg     rax
        and     rax, rdi
        ret
__builtin_align_up(char*, unsigned long):              #
@__builtin_align_up(char*, unsigned long)
        lea     rax, [rsi + rdi - 1]
        neg     rsi
        and     rax, rsi
        ret


__builtin_align_down_UNFRIENDLY(char*, unsigned long): #
@__builtin_align_down_UNFRIENDLY(char*, unsigned long)
        mov     rax, rsi
        neg     rax
        and     rax, rdi
        ret
__builtin_align_up_UNFRIENDLY(char*, unsigned long):   #
@__builtin_align_up_UNFRIENDLY(char*, unsigned long)
        lea     rax, [rsi + rdi - 1]
        neg     rsi
        and     rax, rsi
        ret

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200102/db094172/attachment.html>


More information about the llvm-bugs mailing list