Re: 'Call clzl check' breaks cross compilation (was: PATCH 13/22] Coarray caf_shmem final patch set)

Richard Biener <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.fortran
Message-ID <CAFiYyc3SynpZbNBSncZe-L-Oa0+N7A48_+Nfj1Tz=odN4HAzbw@mail.gmail.com>
On Fri, Feb 27, 2026 at 1:40 PM Andre Vehreschild <[email protected]> wrote:
>
> Hi Richard,
>
> > > > > > --- a/libgfortran/acinclude.m4
> > > > > > +++ b/libgfortran/acinclude.m4
> > > > > ...
> > > > > > +AC_DEFUN([LIBGFOR_CHECK_SANE_BUILTIN_CLZL], [
> > > > > > +  AC_RUN_IFELSE([AC_LANG_PROGRAM([[
> > > > > > +      int main()
> > > > > > +      {
> > > > > > +     return __builtin_clzl(256) != 8;
> > > > > > +      }]], [[]])],
> > > > > > +    AC_DEFINE(HAVE_SANE_BUILTIN_CLZL, 1,
> > > > > > +      [Define if __builtin_clzl behaves as expected.])
> > > > > > +    AM_CONDITIONAL([HAVE_SANE_BUILTIN_CLZL],true),
> > > > > > +    [AM_CONDITIONAL([HAVE_SANE_BUILTIN_CLZL],false)])
> > > > > > +])
> > > >
> > > > What does this test anyway?  clzl (256) should not return 8 but 55.
> > > > Did  you want to check c_T_zl here?  I suggest to simply drop this given
> > > > it's broken?
>
> At the point of use of clzl we want to sort requests for memory blocks into
> buckets by size. The clzl is intended to give the most significant bit the size
> requested fits into. To my understanding of the mnenonic clzl does exactly
> that. And using __builtin_clzl was my way to prevent me from using an asm {}
> block.
>
> Therefore clzl(256) should deliver 8 because 1<<8 is 256. On some platforms
> clzl delivers 55 like you pointed out, but that is of no use to use.

No, clzl (256ul) should be 55, because 1 << (64 - 55 - 1) is 256.

> > > I'm also not convinced by
> > >
> > > static size_t
> > > next_power_of_two (size_t size)
> > > {
> > > #ifdef HAVE_SANE_BUILTIN_CLZL
> > >   assert (size);
> > > #if (__INTPTR_WIDTH__ == 64)
> > >   return 1 << (VOIDP_BITS - __builtin_clzl (size - 1));
> > > #else
> > >
> > > which uses VOIDP_BITS, not 'unsigned long' bits, and it seems to
> > > correlate size_t width with unsigned long width by using INTPTR_WIDTH.
> > > What do you do for long == 32bits targets (windows) which have 64bit
> > > pointers?  You want to use __builtin_clzll there I think.
>
> Er. INTPTR_WIDTH is the with of a pointer on the platform in question. Is it
> not? I could have used VOIDPTR_WIDTH or REALPTR_WIDTH, right? Or to put it the
> other way around: For platforms that have 64 bit pointer width, how do I detect
> them in a portable way?
>
> > >
> > > Of course the FP fallback
> > >
> > > #else
> > >   return 1 << (int)ceil(log2(size));
> > > #endif
> > >
> > > is also a bit questionable.  See gcc/hwint.{h,cc} for ceil_log2 on
> > > uint64_t.
> >
> > That said, libgfortran is always built by the just built GCC, so
> > __builtin_clzll should always be available and correct.  Just use it.
>
> That would be nice, but is not the case on windows, where clzl (256) returns 55
> which is why we do all this fuss.

Which is correct.  So the fuss must be because of sth else.

> So what would be the best way to resolve this?

As said, simply do

static size_t
next_power_of_two (size_t size)
{
  return (size_t)1 << (__SIZEOF_LONG_LONG__ * 8 - __builtin_clzll (size - 1));
}

Richard.

> Regards,
>         Andre
>
> >
> > Richard.
> >
> > >
> > > Richard.
> > >
> > > >
> > > > Richard.
> > > >
> > > > > This fails with:
> > > > >
> > > > > configure: error: in
> > > > > build-gcc-trunk-offload-amdgcn/amdgcn-amdhsa/libgfortran' configure:
> > > > > error: cannot run test program while cross compiling
> > > > >
> > > > > Namely, the generated configure file contains:
> > > > > > # Check if __builtin_clzl behaves (it doesn't on Msys2/ucrt64).
> > > > > >
> > > > > >    if test "$cross_compiling" = yes; then :
> > > > > >    { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':"
> > > > > > >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
> > > > > > as_fn_error $? "cannot run test program while cross compiling
> > > > > > See \`config.log' for more details" "$LINENO" 5; }
> > > > > > else
> > > > >
> > > > > In the code, you can either use code like:
> > > > >    if test "$cross_compiling" != no; then
> > > > > for the current code and the following in an else branch.
> > > > > Or just the following:
> > > > >
> > > > >    case "${host}" in
> > > > >    *-*-mingw32*)
> > > > >        ....
> > > > >      ;;
> > > > >    *)
> > > > >      ....
> > > > >      ;;
> > > > >    esac
> > > > >
> > > > > In any case, AC_RUN_IFELSE is wrong for cross compilation,
> > > > > AC_COMPILE_IFELSE is fine.
> > > > >
> > > > > Tobias
> > > > >
>
>
> --
> Andre Vehreschild * Email: vehre ad gmx dot de
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.