[llvm-dev] libcalls vs. size of int
Björn Pettersson A via llvm-dev
llvm-dev at lists.llvm.org
Sun Mar 28 15:04:06 PDT 2021
A quick inventory of the "libgcc" runtimes in compiler-rt shows
a number of functions that use "int" in the ABI.
Libcalls may be emitted for these (SHL_I64, SRL_I64, SRA_I64):
ashldi3.c:COMPILER_RT_ABI di_int __ashldi3(di_int a, int b)
ashrdi3.c:COMPILER_RT_ABI di_int __ashrdi3(di_int a, int b)
lshrdi3.c:COMPILER_RT_ABI di_int __lshrdi3(di_int a, int b)
Libcalls may be emitted for these (SINTTOFP_I32_F32, SINTTOFP_I32_F128, SUNTTOFP_I32_F32, UINTTOFP_I32_F128):
floatsisf.c:COMPILER_RT_ABI fp_t __floatsisf(int a)
floatsitf.c:COMPILER_RT_ABI fp_t __floatsitf(int a)
floatunsisf.c:COMPILER_RT_ABI fp_t __floatunsisf(unsigned int a)
floatunsitf.c:COMPILER_RT_ABI fp_t __floatunsitf(unsigned int a)
Libcall is emitted via llvm.powi intrinsic (FPOWI/STRICT_FPOWI ISD nodes):
powidf2.c:COMPILER_RT_ABI double __powidf2(double a, int b)
powisf2.c:COMPILER_RT_ABI float __powisf2(float a, int b)
powitf2.c:COMPILER_RT_ABI long double __powitf2(long double a, int b)
powixf2.c:COMPILER_RT_ABI long double __powixf2(long double a, int b)
No libcalls generated to these functions afaict:
ctzdi2.c:COMPILER_RT_ABI int __ctzdi2(di_int a)
ctzsi2.c:COMPILER_RT_ABI int __ctzsi2(si_int a)
ctzti2.c:COMPILER_RT_ABI int __ctzti2(ti_int a)
ffsdi2.c:COMPILER_RT_ABI int __ffsdi2(di_int a)
ffssi2.c:COMPILER_RT_ABI int __ffssi2(si_int a)
ffsti2.c:COMPILER_RT_ABI int __ffsti2(ti_int a)
paritydi2.c:COMPILER_RT_ABI int __paritydi2(di_int a)
paritysi2.c:COMPILER_RT_ABI int __paritysi2(si_int a)
parityti2.c:COMPILER_RT_ABI int __parityti2(ti_int a)
popcountdi2.c:COMPILER_RT_ABI int __popcountdi2(di_int a)
popcountsi2.c:COMPILER_RT_ABI int __popcountsi2(si_int a)
popcountti2.c:COMPILER_RT_ABI int __popcountti2(ti_int a)
The 64-bit shift and float conversion libcalls can be avoided by backends by
using setLibcallName(Op, nullptr). I haven't checked exactly what happens and
how ISel is handling "size of int" for those, but I could not find any signs
indicating that ISel is doing anything special to ensure that the correct
"size of int" is used. So I suspect it isn't handled correctly.
For the powi family I think it is more interesting to emit libcalls even
for targets with 16-bit int. This is because the llvm.powi intrinsic is used
as a mapping to the libcall, and middle-end is doing optimizations for
llvm.powi. I've created a patch here https://reviews.llvm.org/D99439 that
solve problems around powi by changing the llvm.powi intrisic to overload
the type of the exponent argument. And making sure that any in-tree
introduction of llvm.powi uses the correct type.
I've also made another patch, as a starting point, to let SimplifyLibCalls
handle size of int better. That patch is needed as a pre-requisite for the
powi fix to let SimplifyLibCalls use the correct types when emitting calls
to llvm.powi. The patch can be found here https://reviews.llvm.org/D99438 ,
and it also fixes problems with size of int for the rewrites that emit
libcalls to ldexp/ldexpf.
I've used AVR and MSP430 in the test cases added for those patches as
those two targets are using 16-bit int types afaict.
Any reviewers for those patches (D99438 & D99439) are welcome.
/Björn
> -----Original Message-----
> From: Anatoly Trosinenko <atrosinenko at accesssoftek.com>
> Sent: den 24 mars 2021 15:20
> To: Björn Pettersson A <bjorn.a.pettersson at ericsson.com>
> Subject: Re: [llvm-dev] libcalls vs. size of int
>
> Hi!
>
> > I guess one solution here is to find all the builtins in compiler-rt that
> isn't using machine mode types and put them in a list of functions that
> depend on size of int/long etc. Then make sure we make those unavailable
> for targets with int!=si_int etc (and then one has to implement an
> replacement if those functions are needed).
>
> > Another solution could be to break compatibility with libgcc and use the
> machine mode types everywhere (or is there a requirement that builtins are
> compatible between libclang_rt and libgcc?).
>
> I do not have some definitive solution right now, but the third option
> could probably be implementing several compiler-rt functions such as
> __powsidf2 (normally aliased with __powidf2) and __powhidf2 (aliased with
> __powidf2 on 16-bit targets). This makes possible to only emit calls to
> machine mode-sized helper functions from `llc`. At the same time one will
> not end up having two functions with the same name in libgcc and compiler-
> rt and subtle differences in behavior.
>
> Since there are no such functions in libgcc, llc would have to emit
> different names when using compiler-rt and libgcc. Unfortunately, it seems
> the knowledge whether we are targeting libgcc or compiler-rt as a support
> library is lost at the time of codegen. As a workaround, llc could emit
> calls to the aforementioned overloaded functions only if `sizeof(void*) <
> 32` (this should be easily accessible via DataLayout). This may be
> considered as a limited/explicit "breaking compatibility with libgcc" but
> looks rather hackish.
Yes, this could be something we could do out-of-tree (at least) as a
hacky workaround. But when I noticed that things like __builtin_powi also
were broken (clang crashing when mapping the builtin to @llvm.powi) I
ended up proposing another solution based on using the correct type,
representing the size of int, when using llvm.powi.
>
> Anatoly
More information about the llvm-dev
mailing list