This is an archive of the discontinued LLVM Phabricator instance.

[compiler-rt][builtins] Use c[tl]zsi macro instead of __builtin_c[tl]z
ClosedPublic

Authored by atrosinenko on Aug 25 2020, 9:10 AM.

Details

Summary

__builtin_c[tl]z accepts unsigned int argument that is not always the
same as uint32_t. For example, unsigned int is uint16_t on MSP430.

Diff Detail

Event Timeline

atrosinenko created this revision.Aug 25 2020, 9:10 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 25 2020, 9:10 AM
Herald added subscribers: Restricted Project, dberris. · View Herald Transcript
atrosinenko requested review of this revision.Aug 25 2020, 9:10 AM

We've run with changes like this for a long time to make the routines work for our out of tree target where int is also 16 bits so thumbs up from me even if I'm not sure I can formally LGTM it.

The (aWidth - 1) - clzsi(a) change is correct, but why is the ctz change?

The (aWidth - 1) - clzsi(a) change is correct, but why is the ctz change?

d.s.low and d.s.high are su_int. While some helpers from libgcc are documented with int, long, etc. types for simplicity and use machine modes under the hood, the __builtin_ctz() function (as well as clz), on the other hand, seems to really accept an int-sized argument:

$ clang --version
clang version 10.0.0-4ubuntu1 
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ clang -S -O3 -o- -x c - <<< "int f() { return __builtin_ctz(0x100000); }"
        .text
        .file   "-"
        .globl  f                       # -- Begin function f
        .p2align        4, 0x90
        .type   f,@function
f:                                      # @f
        .cfi_startproc
# %bb.0:
        movl    $20, %eax
        retq
.Lfunc_end0:
        .size   f, .Lfunc_end0-f
        .cfi_endproc
                                        # -- End function
        .ident  "clang version 10.0.0-4ubuntu1 "
        .section        ".note.GNU-stack","",@progbits
        .addrsig
$ clang -S -O3 -target msp430 -o- -x c - <<< "int f() { return __builtin_ctz(0x100000); }"
<stdin>:1:32: warning: implicit conversion from 'long' to 'unsigned int' changes value from 1048576 to 0 [-Wconstant-conversion]
int f() { return __builtin_ctz(0x100000); }
                 ~~~~~~~~~~~~~ ^~~~~~~~
        .text
        .file   "-"
        .globl  f                       ; -- Begin function f
        .p2align        1
        .type   f,@function
f:                                      ; @f
; %bb.0:
        ret
.Lfunc_end0:
        .size   f, .Lfunc_end0-f
                                        ; -- End function
        .ident  "clang version 10.0.0-4ubuntu1 "
        .section        ".note.GNU-stack","",@progbits
        .addrsig
1 warning generated.

I checked this, and it seems good to me although I would like someone else to also take a look.

The (aWidth - 1) - clzsi(a) change is correct, but why is the ctz change?

d.s.low and d.s.high are su_int. While some helpers from libgcc are documented with int, long, etc. types for simplicity and use machine modes under the hood, the __builtin_ctz() function (as well as clz), on the other hand, seems to really accept an int-sized argument:

I can confirm this. This is why I introduced the clzsi and ctzsi macros in D78662. They are not intended for use with plain int types, but for use with si_int / su_int types (that are always 32-bit, unlike int).

aykevl accepted this revision.Jan 17 2022, 5:07 AM

Looks good to me.

compiler-rt/lib/builtins/fp_extend.h
32–39

Perhaps more reliable would be the following:

#if ULONG_MAX == 0xFFFFFFFFFFFFFFFF
  return __builtin_clzl(a);
#elif ULLONG_MAX == 0xFFFFFFFFFFFFFFFF
  return __builtin_clzll(a);
#else
  #error Unsupported platform
#endif

This is what I've also used in int_types.h to detect clzsi etc. It probably would need to be tested on some more architectures though (32 and 64 bit).

This revision is now accepted and ready to land.Jan 17 2022, 5:07 AM
aykevl added inline comments.Jan 17 2022, 5:13 AM
compiler-rt/lib/builtins/fp_extend.h
32–39

In fact, it might be possible to use __builtin_clzll for all platforms (it maps to 'long long', which I think is 64-bit practically everywhere).

This revision was landed with ongoing or failed builds.Jan 30 2022, 12:06 PM
This revision was automatically updated to reflect the committed changes.