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

Reply via email to