<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/123387>123387</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
`fmaf` is an empty unreachable function with optimizations on cortex-m33
</td>
</tr>
<tr>
<th>Labels</th>
<td>
bug,
libc
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
PiJoules
</td>
</tr>
</table>
<pre>
The generic `fmaf` implementation in llvm-libc is
```
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float, fmaf, (float x, float y, float z)) {
return fputil::fma<float>(x, y, z);
}
} // namespace LIBC_NAMESPACE_DECL
```
On cortex-m33, `fputil::fma<float>` is
```
template <> LIBC_INLINE float fma(float x, float y, float z) {
return __builtin_fmaf(x, y, z);
}
```
However, clang replaces the `__builtin_fmaf` call with a call to a normal `fmaf` at `-O0`
```
; Function Attrs: mustprogress noinline nounwind optnone
define linkonce_odr hidden noundef float @_ZN22__llvm_libc_20_0_0_git6fputil3fmaIffEET_T0_S3_S3_(float noundef %x, float noundef %y, float noundef %z) #0 comdat {
entry:
%x.addr = alloca float, align 4
%y.addr = alloca float, align 4
%z.addr = alloca float, align 4
store float %x, ptr %x.addr, align 4
store float %y, ptr %y.addr, align 4
store float %z, ptr %z.addr, align 4
%0 = load float, ptr %x.addr, align 4
%1 = load float, ptr %y.addr, align 4
%2 = load float, ptr %z.addr, align 4
%call = call float @fmaf(float noundef %0, float noundef %1, float noundef %2) #2
ret float %call
}
```
Since `fmaf` just calls `fputil::fma<float>`, we end up with a circular dependency. With `-Os` or `-O3`, clang removes the function body for `fmaf`
```
define hidden noundef float @fmaf(float %x, float %y, float %z) #0 {
entry:
unreachable
}
```
and since the entire function is `unreachable`, this just ends up becoming an empty function
```
fmaf:
.fnstart
@ %bb.0: @ %entry
.Lfunc_end0:
.size fmaf, .Lfunc_end0-fmaf
.cantunwind
.fnend
```
It seems either (1) clang is incorrectly lowering the `__builtin_fmaf` to `fmaf` or (2) llvm-libc should have tighter checks on ensuring that a builtin call won't be lowered to a libcall. I would assume this shouldn't be lowered to a libcall in the first place since `__ARM_FEATURE_FMA` is defined, but perhaps it might be permissible for any compiler to lower a builtin call to a normal function call?
This can be reproduced by building armv8m.main-unknown-none-eabi runtimes from the fuchsia cache file. Alternatively, the fma.cpp code expands to
```
namespace [[gnu::visibility("hidden")]] __llvm_libc_20_0_0_git {
namespace fputil {
inline float fma(float x, float y, float z) {
return __builtin_fmaf(x, y, z);
}
} // namespace fputil
float fmaf(float x, float y, float z);
decltype(__llvm_libc_20_0_0_git::fmaf) __fmaf_impl__ __asm__("fmaf");
decltype(__llvm_libc_20_0_0_git::fmaf) fmaf [[gnu::alias("fmaf")]];
float __fmaf_impl__ (float x, float y, float z) {
return fputil::fma(x, y, z);
}
} // namespace __llvm_libc_20_0_0_git
```
which can be compiled with
```
clang++ --target=armv8m.main-none-eabi -mthumb -mfloat-abi=softfp -march=armv8m.main+fp+dsp -mcpu=cortex-m33 -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Os -ffreestanding -nostdlibinc -fno-builtin -fno-exceptions -fno-lax-vector-conversions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti /tmp/test.cc
```
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy8V0tv4zgS_jX0pSBDpvzKwQfHD2wW6XRjOrML7EWgqJLFaYoUSMqJ8-sXJOVHEieduYxjxBLJetdXVWTWip1CXJDJLZmsB6xztTaLH-LfupNoB4UuD4vHGmGHCo3gQKZp1bCKTFMQTSuxQeWYE1qBUCDlvkmkKDgIS9Kl_07T_psuFWvQtowj3N_drvKH5bfNzx_L1SZfb1b3QGa3keT-_j_f8nBi--fD6vHu-wOh80pq5ghdQRBOV3Bcg-ewGh4P58cXQm8Ivem5Ahh0nVFQtZ0TkmRLki2rhpFsFRlnG0LngVPgEaizoM9s3RsyWwOhW0K38Kkdb2wm6fK7Aq6Nw-ekybKg-jT9RA_v2CvOc9i0kjkEkq1Itomi7x7u7x42vcmez--dcvRI75A8LzohnVB5dOxnTnht1r_0E-7R-JNcMrUDg61kHC24Gr2Nb1hPU-BMSngSrgYWn50GBkqbhsnLxGLOvyXfz8Jeyc5uYdspHpJu6ZyxJFtC01nXGr0zaC0oLZQUCkHpTj0JVYJundIKSbossfI7UqhfWnHMdWmgFmWJKpwuseq9RcZp_r8HSvPcp3Xu0zqnae7_dsJNYwizqmF3VbXZPOaPaf4z899TFI78CJ1cBORi9XB1NYaJZilw3ZRekxAyVM4cfMr4fPYsh6wsDZBsDUxKzRmcQMKk2CkYH08evnzy5WsnrdMGj27qjWudOWv1G4LDBcHhKwQvFwQvVwkInaRBb6lZedb6U60InYw-prmuGKET-jHNh7qFdPdk4eGUYD3o3qVAejUxRldXaZ8u9Fjozm7zwt7jFyKmfgrF8RJ2f3XWBf3sb0uUV-QJAVUJXXuCtDC8k8xAiS2qEhU_DOG_fi-g2XoZ2sSXrGdyLB2N3veVozpC27ceqCJBr-L7YtCj-SMAv_Lvaxi-ht8r2F3BW6cMMl6zQuJHBZGpEmzwqTcDlRPmwhoRnHrJJjrA1cJGz6MqrfdmgVw3Qu2AKcCmdYcTk_fmB_uiisNKWceM8yfGqTeoKIapL42_-fSno7npcnjvxeWoyvRofPwMrXhBgFMHvjiYhDWvBGfKxZJ7SVkpDAtvPHbnwCI2FlC4Gj2A5iMfhJgUwoJQXBuD3MkDSP2Exrvlw_bi9GU268AvgOM8lthad7KEmu0RnNjVDg3wGvkvC1oBKtv1IpgDBr2Avm9pRejMQYFRFSxj-_J8mZRDuIOnwJxZ2zUYAxvlfUro56aQ98JYB6GF9mkUjFz-8S3fbpaPf_6xybfflnE8gJj2pQ9D0Tlo0dSstSAcNN4qL6tF0whrRSExoIipg-8nrZBovAJBl7dGXjbkU-qGKpJtY8wevVmcKS_CYGt02XEsoTgERmXIW9Ps582wYUIlnfql9JNKfPNNkBUCTKecaNBCZXTTI57XVviRgAc_SBzCUjo0ijmxR3mIOEGfeUPetsB1iYDPLfOI8VH_ZNQMc-3tTnWxku2FFYWQwh0InRNKY-Eg1OcJmazJZA3X-_15Pj3zjiWy3-knjn9oFput4f042pfsoOVJj-ork3LW21Yil-7QIqHz62449YPK658HTXN_EchzyHNmmzyPjo1H6In53-Tsf9_GjknB7DvuIWhRRjTotVJ_IwwfXRK-cDN4H4sPjHxXA59qwesjoHp8lqGjvs_qUBcJvSX0FpLEMbNDR7L1Jd7OOEsaV3dNAUkTLE1YIUi2trpyVQtJwwyvX9MSelu1hN6W1u_ztiPZ-nxxgaT6cbeCpFI6sdgw5QRPhHJoWm1FqBNJdUZXEuFgk74zJ98tJFVlEK1jKpSJRGnrSikKoXjkeyxF4QWfObaer43vkj0ne-ROm4RrtUdjz3ux4yTO99V-idmD4rXRSnf22r5xTviouab1_9G6IeeX_h6Ui6y8yW7YABejWTYbjdN5Oh_Ui2qcTSbTohhlN2wyntDqZlJOxzOk42JUZpPZQCxoSifpaDQb3aTT8Xw45ePxNE2rtJzdpKNRScYpNkzIoU-RoTa7gbC2w8WIZtl8NpCsQGnDjZzSotuFRF8RSn0y-ZfJemAWoakV3c6ScSqFdfbMzQkncXF5U7fnYeJiBDmX-DDB6daJRryw6HR9eW0ddEYuaudaf9eKub4Tru6KIdcNoVsvuv9JWqP_Qu4I3QarLKHb3rD9gv4_AAD__088Hgs">