[llvm-dev] libcalls vs. size of int (original) (raw)
Björn Pettersson A via llvm-dev llvm-dev at lists.llvm.org
Sun Mar 28 15:04:06 PDT 2021
- Previous message: [llvm-dev] libcalls vs. size of int
- Next message: [llvm-dev] LLVM C api changes
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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!=siint 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 libclangrt 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 ifsizeof(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
- Previous message: [llvm-dev] libcalls vs. size of int
- Next message: [llvm-dev] LLVM C api changes
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]