Issue |
123387
|
Summary |
`fmaf` is an empty unreachable function with optimizations on cortex-m33
|
Labels |
bug,
libc
|
Assignees |
|
Reporter |
PiJoules
|
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
```
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs