Closed Nick-Kooij closed 3 weeks ago
Attached is a zip archiving, ACosfTest.zip, containing a small Visual Studio 2022 17.11.4 project that show the issue.
Note: attempt to build the a x86 Build
x86_32 windows does not have acosf as a library function, at least according to the code: https://github.com/llvm/llvm-project/blob/c8e0672864abf6fb624ddde5d6a1775d8634213a/llvm/lib/Analysis/TargetLibraryInfo.cpp#L291
Constant folding is not supposed to occur for library functions which are not recognized, and thus the call should survive compilation. This code should always have failed to link. I'm not sure how you are seeing it ever pass. I see the call is not eliminated in 18 either: https://godbolt.org/z/9dcWPKKsv
This code should always have failed to link.
This is not true, msvc acosf
is defined as inline function for win32, relevant code from ucrt math.h (corecrt_math.h):
#if defined _M_X64 || defined _M_ARM || defined _M_ARM64 || defined _M_HYBRID_X86_ARM64 || defined _CORECRT_BUILD_APISET || defined _M_ARM64EC
_Check_return_ _ACRTIMP float __cdecl acosf(_In_ float _X);
_Check_return_ _ACRTIMP float __cdecl asinf(_In_ float _X);
_Check_return_ _ACRTIMP float __cdecl atan2f(_In_ float _Y, _In_ float _X);
_Check_return_ _ACRTIMP float __cdecl atanf(_In_ float _X);
_Check_return_ _ACRTIMP float __cdecl ceilf(_In_ float _X);
_Check_return_ _ACRTIMP float __cdecl cosf(_In_ float _X);
_Check_return_ _ACRTIMP float __cdecl coshf(_In_ float _X);
_Check_return_ _ACRTIMP float __cdecl expf(_In_ float _X);
#else
_Check_return_ __inline float __CRTDECL acosf(_In_ float _X)
{
return (float)acos(_X);
}
for OP's test file, open "x86 Native Tools Command Prompt for VS 2022":
**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.11.4
** Copyright (c) 2022 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x86'
D:\Program Files\Microsoft Visual Studio\2022>cd d:\
d:\>cl /fp:fast test.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.41.34120 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
test.cpp
Microsoft (R) Incremental Linker Version 14.41.34120.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:test.exe
test.obj
d:\>clang-cl --target=i686-pc-windows-msvc /fp:fast test.cpp
test-fac079.obj : error LNK2019: unresolved external symbol _acosf referenced in function _main
test.exe : fatal error LNK1120: 1 unresolved externals
clang-cl: error: linker command failed with exit code 1120 (use -v to see invocation)
d:\>clang-cl --target=i686-pc-windows-msvc test.cpp
d:\>
It's seems with fp:fast
, the inline function is not used.
d:\>clang-cl --target=i686-pc-windows-msvc /fp:fast /c test.cpp
d:\>dumpbin /all test.obj > fast.log
d:\>clang-cl --target=i686-pc-windows-msvc /c test.cpp
d:\>dumpbin /all test.obj > default.log
compare fast.log
and default.log
, _cos
is missing from fast.log
's COFF SYMBOL TABLE.
This is not true, msvc
acosf
is defined as inline function for win32, relevant code from ucrt math.h (corecrt_math.h):
Is TargetLibraryInfo wrong then, or were these added in a later version of the runtime?
or were these added in a later version of the runtime
Seems not, LLVM 18.1.8 and 19.1.0 use same headers, but COFF SYMBOL TABLE created by clang-cl 18.1.8 contains _cos
(dumpbin /all test.obj > fast18.log
output fast18.log is same as clang-cl 19.1.0's default.log except timestamp).
IR for clang-cl --target=i686-pc-windows-msvc /c -Xclang -emit-llvm test.cpp
:
; ModuleID = 'test.cpp'
source_filename = "test.cpp"
target datalayout = "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc19.41.34120"
$printf = comdat any
$acosf = comdat any
$_vfprintf_l = comdat any
$__local_stdio_printf_options = comdat any
$"??_C@_03PPOCCAPH@?$CFf?6?$AA@" = comdat any
$"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = comdat any
@"??_C@_03PPOCCAPH@?$CFf?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [4 x i8] c"%f\0A\00", comdat, align 1
@"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = linkonce_odr dso_local global i64 0, comdat, align 8
; Function Attrs: mustprogress noinline norecurse nounwind optnone sspstrong
define dso_local noundef i32 @main(i32 noundef %0, ptr noundef %1) #0 {
%3 = alloca i32, align 4
%4 = alloca ptr, align 4
%5 = alloca i32, align 4
store i32 0, ptr %3, align 4
store ptr %1, ptr %4, align 4
store i32 %0, ptr %5, align 4
%6 = call float @acosf(float noundef 0.000000e+00) #5
%7 = fmul float %6, 2.000000e+00
%8 = fpext float %7 to double
%9 = call i32 (ptr, ...) @printf(ptr noundef @"??_C@_03PPOCCAPH@?$CFf?6?$AA@", double noundef %8)
ret i32 0
}
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local i32 @printf(ptr noundef %0, ...) #1 comdat {
%2 = alloca ptr, align 4
%3 = alloca i32, align 4
%4 = alloca ptr, align 4
store ptr %0, ptr %2, align 4
call void @llvm.va_start.p0(ptr %4)
%5 = load ptr, ptr %4, align 4
%6 = load ptr, ptr %2, align 4
%7 = call ptr @__acrt_iob_func(i32 noundef 1)
%8 = call i32 @_vfprintf_l(ptr noundef %7, ptr noundef %6, ptr noundef null, ptr noundef %5)
store i32 %8, ptr %3, align 4
call void @llvm.va_end.p0(ptr %4)
%9 = load i32, ptr %3, align 4
ret i32 %9
}
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local float @acosf(float noundef %0) #1 comdat {
%2 = alloca float, align 4
store float %0, ptr %2, align 4
%3 = load float, ptr %2, align 4
%4 = fpext float %3 to double
%5 = call double @acos(double noundef %4) #5
%6 = fptrunc double %5 to float
ret float %6
}
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_start.p0(ptr) #2
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local i32 @_vfprintf_l(ptr noundef %0, ptr noundef %1, ptr noundef %2, ptr noundef %3) #1 comdat {
%5 = alloca ptr, align 4
%6 = alloca ptr, align 4
%7 = alloca ptr, align 4
%8 = alloca ptr, align 4
store ptr %3, ptr %5, align 4
store ptr %2, ptr %6, align 4
store ptr %1, ptr %7, align 4
store ptr %0, ptr %8, align 4
%9 = load ptr, ptr %5, align 4
%10 = load ptr, ptr %6, align 4
%11 = load ptr, ptr %7, align 4
%12 = load ptr, ptr %8, align 4
%13 = call ptr @__local_stdio_printf_options()
%14 = load i64, ptr %13, align 8
%15 = call i32 @__stdio_common_vfprintf(i64 noundef %14, ptr noundef %12, ptr noundef %11, ptr noundef %10, ptr noundef %9)
ret i32 %15
}
declare dso_local ptr @__acrt_iob_func(i32 noundef) #3
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_end.p0(ptr) #2
declare dso_local i32 @__stdio_common_vfprintf(i64 noundef, ptr noundef, ptr noundef, ptr noundef, ptr noundef) #3
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local ptr @__local_stdio_printf_options() #1 comdat {
ret ptr @"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA"
}
; Function Attrs: nounwind
declare dso_local double @acos(double noundef) #4
attributes #0 = { mustprogress noinline norecurse nounwind optnone sspstrong "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { mustprogress noinline nounwind optnone sspstrong "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #2 = { nocallback nofree nosync nounwind willreturn }
attributes #3 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #4 = { nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #5 = { nounwind }
!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.linker.options = !{!4, !5, !6, !7, !8, !9, !10}
!llvm.ident = !{!11}
!0 = !{i32 1, !"NumRegisterParameters", i32 0}
!1 = !{i32 1, !"wchar_size", i32 2}
!2 = !{i32 7, !"frame-pointer", i32 2}
!3 = !{i32 1, !"MaxTLSAlign", i32 65536}
!4 = !{!"/DEFAULTLIB:libcmt.lib"}
!5 = !{!"/DEFAULTLIB:oldnames.lib"}
!6 = !{!"/FAILIFMISMATCH:\22_MSC_VER=1900\22"}
!7 = !{!"/FAILIFMISMATCH:\22_ITERATOR_DEBUG_LEVEL=0\22"}
!8 = !{!"/FAILIFMISMATCH:\22RuntimeLibrary=MT_StaticRelease\22"}
!9 = !{!"/DEFAULTLIB:libcpmt.lib"}
!10 = !{!"/FAILIFMISMATCH:\22_CRT_STDIO_ISO_WIDE_SPECIFIERS=0\22"}
!11 = !{!"clang version 19.1.0"}
IR for clang-cl --target=i686-pc-windows-msvc /c /fp:fast -Xclang -emit-llvm test.cpp
:
; ModuleID = 'test.cpp'
source_filename = "test.cpp"
target datalayout = "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc19.41.34120"
$printf = comdat any
$_vfprintf_l = comdat any
$__local_stdio_printf_options = comdat any
$"??_C@_03PPOCCAPH@?$CFf?6?$AA@" = comdat any
$"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = comdat any
@"??_C@_03PPOCCAPH@?$CFf?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [4 x i8] c"%f\0A\00", comdat, align 1
@"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = linkonce_odr dso_local global i64 0, comdat, align 8
; Function Attrs: mustprogress noinline norecurse nounwind optnone sspstrong
define dso_local noundef i32 @main(i32 noundef %0, ptr noundef %1) #0 {
%3 = alloca i32, align 4
%4 = alloca ptr, align 4
%5 = alloca i32, align 4
store i32 0, ptr %3, align 4
store ptr %1, ptr %4, align 4
store i32 %0, ptr %5, align 4
%6 = call fast float @llvm.acos.f32(float 0.000000e+00)
%7 = fmul fast float %6, 2.000000e+00
%8 = fpext float %7 to double
%9 = call i32 (ptr, ...) @printf(ptr noundef @"??_C@_03PPOCCAPH@?$CFf?6?$AA@", double noundef nofpclass(nan inf) %8)
ret i32 0
}
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local i32 @printf(ptr noundef %0, ...) #1 comdat {
%2 = alloca ptr, align 4
%3 = alloca i32, align 4
%4 = alloca ptr, align 4
store ptr %0, ptr %2, align 4
call void @llvm.va_start.p0(ptr %4)
%5 = load ptr, ptr %4, align 4
%6 = load ptr, ptr %2, align 4
%7 = call ptr @__acrt_iob_func(i32 noundef 1)
%8 = call i32 @_vfprintf_l(ptr noundef %7, ptr noundef %6, ptr noundef null, ptr noundef %5)
store i32 %8, ptr %3, align 4
call void @llvm.va_end.p0(ptr %4)
%9 = load i32, ptr %3, align 4
ret i32 %9
}
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare float @llvm.acos.f32(float) #2
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_start.p0(ptr) #3
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local i32 @_vfprintf_l(ptr noundef %0, ptr noundef %1, ptr noundef %2, ptr noundef %3) #1 comdat {
%5 = alloca ptr, align 4
%6 = alloca ptr, align 4
%7 = alloca ptr, align 4
%8 = alloca ptr, align 4
store ptr %3, ptr %5, align 4
store ptr %2, ptr %6, align 4
store ptr %1, ptr %7, align 4
store ptr %0, ptr %8, align 4
%9 = load ptr, ptr %5, align 4
%10 = load ptr, ptr %6, align 4
%11 = load ptr, ptr %7, align 4
%12 = load ptr, ptr %8, align 4
%13 = call ptr @__local_stdio_printf_options()
%14 = load i64, ptr %13, align 8
%15 = call i32 @__stdio_common_vfprintf(i64 noundef %14, ptr noundef %12, ptr noundef %11, ptr noundef %10, ptr noundef %9)
ret i32 %15
}
declare dso_local ptr @__acrt_iob_func(i32 noundef) #4
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_end.p0(ptr) #3
declare dso_local i32 @__stdio_common_vfprintf(i64 noundef, ptr noundef, ptr noundef, ptr noundef, ptr noundef) #4
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local ptr @__local_stdio_printf_options() #1 comdat {
ret ptr @"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA"
}
attributes #0 = { mustprogress noinline norecurse nounwind optnone sspstrong "approx-func-fp-math"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="true" }
attributes #1 = { mustprogress noinline nounwind optnone sspstrong "approx-func-fp-math"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="true" }
attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #3 = { nocallback nofree nosync nounwind willreturn }
attributes #4 = { "approx-func-fp-math"="true" "frame-pointer"="all" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="true" }
!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.linker.options = !{!4, !5, !6, !7, !8, !9, !10}
!llvm.ident = !{!11}
!0 = !{i32 1, !"NumRegisterParameters", i32 0}
!1 = !{i32 1, !"wchar_size", i32 2}
!2 = !{i32 7, !"frame-pointer", i32 2}
!3 = !{i32 1, !"MaxTLSAlign", i32 65536}
!4 = !{!"/DEFAULTLIB:libcmt.lib"}
!5 = !{!"/DEFAULTLIB:oldnames.lib"}
!6 = !{!"/FAILIFMISMATCH:\22_MSC_VER=1900\22"}
!7 = !{!"/FAILIFMISMATCH:\22_ITERATOR_DEBUG_LEVEL=0\22"}
!8 = !{!"/FAILIFMISMATCH:\22RuntimeLibrary=MT_StaticRelease\22"}
!9 = !{!"/DEFAULTLIB:libcpmt.lib"}
!10 = !{!"/FAILIFMISMATCH:\22_CRT_STDIO_ISO_WIDE_SPECIFIERS=0\22"}
!11 = !{!"clang version 19.1.0"}
IR for clang-cl --target=i686-pc-windows-msvc /c -Xclang -ffast-math -Xclang -emit-llvm test.cpp
:
; ModuleID = 'test.cpp'
source_filename = "test.cpp"
target datalayout = "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc19.41.34120"
$printf = comdat any
$acosf = comdat any
$_vfprintf_l = comdat any
$__local_stdio_printf_options = comdat any
$"??_C@_03PPOCCAPH@?$CFf?6?$AA@" = comdat any
$"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = comdat any
@"??_C@_03PPOCCAPH@?$CFf?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [4 x i8] c"%f\0A\00", comdat, align 1
@"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = linkonce_odr dso_local global i64 0, comdat, align 8
; Function Attrs: mustprogress noinline norecurse nounwind optnone sspstrong
define dso_local noundef i32 @main(i32 noundef %0, ptr noundef %1) #0 {
%3 = alloca i32, align 4
%4 = alloca ptr, align 4
%5 = alloca i32, align 4
store i32 0, ptr %3, align 4
store ptr %1, ptr %4, align 4
store i32 %0, ptr %5, align 4
%6 = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) float @acosf(float noundef nofpclass(nan inf) 0.000000e+00) #5
%7 = fmul reassoc nnan ninf nsz arcp afn float %6, 2.000000e+00
%8 = fpext float %7 to double
%9 = call i32 (ptr, ...) @printf(ptr noundef @"??_C@_03PPOCCAPH@?$CFf?6?$AA@", double noundef nofpclass(nan inf) %8)
ret i32 0
}
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local i32 @printf(ptr noundef %0, ...) #1 comdat {
%2 = alloca ptr, align 4
%3 = alloca i32, align 4
%4 = alloca ptr, align 4
store ptr %0, ptr %2, align 4
call void @llvm.va_start.p0(ptr %4)
%5 = load ptr, ptr %4, align 4
%6 = load ptr, ptr %2, align 4
%7 = call ptr @__acrt_iob_func(i32 noundef 1)
%8 = call i32 @_vfprintf_l(ptr noundef %7, ptr noundef %6, ptr noundef null, ptr noundef %5)
store i32 %8, ptr %3, align 4
call void @llvm.va_end.p0(ptr %4)
%9 = load i32, ptr %3, align 4
ret i32 %9
}
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local nofpclass(nan inf) float @acosf(float noundef nofpclass(nan inf) %0) #1 comdat {
%2 = alloca float, align 4
store float %0, ptr %2, align 4
%3 = load float, ptr %2, align 4
%4 = fpext float %3 to double
%5 = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) double @acos(double noundef nofpclass(nan inf) %4) #5
%6 = fptrunc double %5 to float
ret float %6
}
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_start.p0(ptr) #2
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local i32 @_vfprintf_l(ptr noundef %0, ptr noundef %1, ptr noundef %2, ptr noundef %3) #1 comdat {
%5 = alloca ptr, align 4
%6 = alloca ptr, align 4
%7 = alloca ptr, align 4
%8 = alloca ptr, align 4
store ptr %3, ptr %5, align 4
store ptr %2, ptr %6, align 4
store ptr %1, ptr %7, align 4
store ptr %0, ptr %8, align 4
%9 = load ptr, ptr %5, align 4
%10 = load ptr, ptr %6, align 4
%11 = load ptr, ptr %7, align 4
%12 = load ptr, ptr %8, align 4
%13 = call ptr @__local_stdio_printf_options()
%14 = load i64, ptr %13, align 8
%15 = call i32 @__stdio_common_vfprintf(i64 noundef %14, ptr noundef %12, ptr noundef %11, ptr noundef %10, ptr noundef %9)
ret i32 %15
}
declare dso_local ptr @__acrt_iob_func(i32 noundef) #3
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_end.p0(ptr) #2
declare dso_local i32 @__stdio_common_vfprintf(i64 noundef, ptr noundef, ptr noundef, ptr noundef, ptr noundef) #3
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local ptr @__local_stdio_printf_options() #1 comdat {
ret ptr @"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA"
}
; Function Attrs: nounwind
declare dso_local nofpclass(nan inf) double @acos(double noundef nofpclass(nan inf)) #4
attributes #0 = { mustprogress noinline norecurse nounwind optnone sspstrong "approx-func-fp-math"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { mustprogress noinline nounwind optnone sspstrong "approx-func-fp-math"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #2 = { nocallback nofree nosync nounwind willreturn }
attributes #3 = { "approx-func-fp-math"="true" "frame-pointer"="all" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #4 = { nounwind "approx-func-fp-math"="true" "frame-pointer"="all" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #5 = { nounwind }
!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.linker.options = !{!4, !5, !6, !7, !8, !9, !10}
!llvm.ident = !{!11}
!0 = !{i32 1, !"NumRegisterParameters", i32 0}
!1 = !{i32 1, !"wchar_size", i32 2}
!2 = !{i32 7, !"frame-pointer", i32 2}
!3 = !{i32 1, !"MaxTLSAlign", i32 65536}
!4 = !{!"/DEFAULTLIB:libcmt.lib"}
!5 = !{!"/DEFAULTLIB:oldnames.lib"}
!6 = !{!"/FAILIFMISMATCH:\22_MSC_VER=1900\22"}
!7 = !{!"/FAILIFMISMATCH:\22_ITERATOR_DEBUG_LEVEL=0\22"}
!8 = !{!"/FAILIFMISMATCH:\22RuntimeLibrary=MT_StaticRelease\22"}
!9 = !{!"/DEFAULTLIB:libcpmt.lib"}
!10 = !{!"/FAILIFMISMATCH:\22_CRT_STDIO_ISO_WIDE_SPECIFIERS=0\22"}
!11 = !{!"clang version 19.1.0"}
according to Options.td, /fp:fast
is alias for -ffast-math
, but clang-cl --target=i686-pc-windows-msvc -Xclang -ffast-math test.cpp
links without error.
https://github.com/llvm/llvm-project/blob/0b524efa953ce4a1f41ff6abaa8e3c5f757e40e2/clang/include/clang/Driver/Options.td#L8410
IR for 18.1.8 clang-cl --target=i686-pc-windows-msvc /c /fp:fast -Xclang -emit-llvm test.cpp
(which is similar to LLVM 19.1.0's clang-cl --target=i686-pc-windows-msvc /c -Xclang -ffast-math -Xclang -emit-llvm test.cpp
):
; ModuleID = 'test.cpp'
source_filename = "test.cpp"
target datalayout = "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc19.41.34120"
$printf = comdat any
$acosf = comdat any
$_vfprintf_l = comdat any
$__local_stdio_printf_options = comdat any
$"??_C@_03PPOCCAPH@?$CFf?6?$AA@" = comdat any
$"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = comdat any
@"??_C@_03PPOCCAPH@?$CFf?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [4 x i8] c"%f\0A\00", comdat, align 1
@"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = linkonce_odr dso_local global i64 0, comdat, align 8
; Function Attrs: mustprogress noinline norecurse nounwind optnone sspstrong
define dso_local noundef i32 @main(i32 noundef %0, ptr noundef %1) #0 {
%3 = alloca i32, align 4
%4 = alloca ptr, align 4
%5 = alloca i32, align 4
store i32 0, ptr %3, align 4
store ptr %1, ptr %4, align 4
store i32 %0, ptr %5, align 4
%6 = call fast nofpclass(nan inf) float @acosf(float noundef nofpclass(nan inf) 0.000000e+00) #6
%7 = fmul fast float %6, 2.000000e+00
%8 = fpext float %7 to double
%9 = call i32 (ptr, ...) @printf(ptr noundef @"??_C@_03PPOCCAPH@?$CFf?6?$AA@", double noundef nofpclass(nan inf) %8)
ret i32 0
}
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local i32 @printf(ptr noundef %0, ...) #1 comdat {
%2 = alloca ptr, align 4
%3 = alloca i32, align 4
%4 = alloca ptr, align 4
store ptr %0, ptr %2, align 4
call void @llvm.va_start(ptr %4)
%5 = load ptr, ptr %4, align 4
%6 = load ptr, ptr %2, align 4
%7 = call ptr @__acrt_iob_func(i32 noundef 1)
%8 = call i32 @_vfprintf_l(ptr noundef %7, ptr noundef %6, ptr noundef null, ptr noundef %5)
store i32 %8, ptr %3, align 4
call void @llvm.va_end(ptr %4)
%9 = load i32, ptr %3, align 4
ret i32 %9
}
; Function Attrs: mustprogress noinline nounwind optnone sspstrong willreturn memory(none)
define linkonce_odr dso_local nofpclass(nan inf) float @acosf(float noundef nofpclass(nan inf) %0) #2 comdat {
%2 = alloca float, align 4
store float %0, ptr %2, align 4
%3 = load float, ptr %2, align 4
%4 = fpext float %3 to double
%5 = call fast nofpclass(nan inf) double @acos(double noundef nofpclass(nan inf) %4) #6
%6 = fptrunc double %5 to float
ret float %6
}
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_start(ptr) #3
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local i32 @_vfprintf_l(ptr noundef %0, ptr noundef %1, ptr noundef %2, ptr noundef %3) #1 comdat {
%5 = alloca ptr, align 4
%6 = alloca ptr, align 4
%7 = alloca ptr, align 4
%8 = alloca ptr, align 4
store ptr %3, ptr %5, align 4
store ptr %2, ptr %6, align 4
store ptr %1, ptr %7, align 4
store ptr %0, ptr %8, align 4
%9 = load ptr, ptr %5, align 4
%10 = load ptr, ptr %6, align 4
%11 = load ptr, ptr %7, align 4
%12 = load ptr, ptr %8, align 4
%13 = call ptr @__local_stdio_printf_options()
%14 = load i64, ptr %13, align 8
%15 = call i32 @__stdio_common_vfprintf(i64 noundef %14, ptr noundef %12, ptr noundef %11, ptr noundef %10, ptr noundef %9)
ret i32 %15
}
declare dso_local ptr @__acrt_iob_func(i32 noundef) #4
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_end(ptr) #3
declare dso_local i32 @__stdio_common_vfprintf(i64 noundef, ptr noundef, ptr noundef, ptr noundef, ptr noundef) #4
; Function Attrs: mustprogress noinline nounwind optnone sspstrong
define linkonce_odr dso_local ptr @__local_stdio_printf_options() #1 comdat {
ret ptr @"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA"
}
; Function Attrs: nounwind willreturn memory(none)
declare dso_local nofpclass(nan inf) double @acos(double noundef nofpclass(nan inf)) #5
attributes #0 = { mustprogress noinline norecurse nounwind optnone sspstrong "approx-func-fp-math"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="true" }
attributes #1 = { mustprogress noinline nounwind optnone sspstrong "approx-func-fp-math"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="true" }
attributes #2 = { mustprogress noinline nounwind optnone sspstrong willreturn memory(none) "approx-func-fp-math"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="true" }
attributes #3 = { nocallback nofree nosync nounwind willreturn }
attributes #4 = { "approx-func-fp-math"="true" "frame-pointer"="all" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="true" }
attributes #5 = { nounwind willreturn memory(none) "approx-func-fp-math"="true" "frame-pointer"="all" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="true" }
attributes #6 = { nounwind willreturn memory(none) }
!llvm.linker.options = !{!0, !1, !2, !3, !4, !5, !6}
!llvm.module.flags = !{!7, !8, !9, !10}
!llvm.ident = !{!11}
!0 = !{!"/DEFAULTLIB:libcmt.lib"}
!1 = !{!"/DEFAULTLIB:oldnames.lib"}
!2 = !{!"/FAILIFMISMATCH:\22_MSC_VER=1900\22"}
!3 = !{!"/FAILIFMISMATCH:\22_ITERATOR_DEBUG_LEVEL=0\22"}
!4 = !{!"/FAILIFMISMATCH:\22RuntimeLibrary=MT_StaticRelease\22"}
!5 = !{!"/DEFAULTLIB:libcpmt.lib"}
!6 = !{!"/FAILIFMISMATCH:\22_CRT_STDIO_ISO_WIDE_SPECIFIERS=0\22"}
!7 = !{i32 1, !"NumRegisterParameters", i32 0}
!8 = !{i32 1, !"wchar_size", i32 2}
!9 = !{i32 7, !"frame-pointer", i32 2}
!10 = !{i32 1, !"MaxTLSAlign", i32 65536}
!11 = !{!"clang version 18.1.8"}
See #101268 (which was merged to main, but not 19).
Still not fixed in 19.1.1.
**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.11.4
** Copyright (c) 2022 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x86'
D:\Program Files\Microsoft Visual Studio\2022>cd d:\
d:\>clang-cl --target=i686-pc-windows-msvc --version
clang version 19.1.1
Target: i686-pc-windows-msvc
Thread model: posix
InstalledDir: D:\Dev\LLVM\bin
d:\>clang-cl --target=i686-pc-windows-msvc /fp:fast test.cpp
test-92ddf8.obj : error LNK2019: unresolved external symbol _acosf referenced in function _main
test.exe : fatal error LNK1120: 1 unresolved externals
clang-cl: error: linker command failed with exit code 1120 (use -v to see invocation)
@arsenm What am I expected to do here from @tycho comment https://github.com/llvm/llvm-project/pull/101268#issuecomment-2356953469 I thought the cherry-pick was already applied 2 weeks ago?
I don't see that referenced in this issue, and I don't see the change in the release branch. I guess the auto cherry-pick failed, and the manually merged version didn't materialize?
@arsenm
If that's the case, what do you need me to do to resolve this issue? This is my first time trying to put a patch in a release, so I need some guidance on the process. Do you just want a PR targeting the 19.x branch? How do I keep the merge commit the same or does that not matter?
Yes, just a PR against the 19.x branch. The branch is configured to squash-then-merge, so it doesn't matter whether there are any merge commits.
The backport https://github.com/llvm/llvm-project/pull/111218 was now released with LLVM 19.1.2
@llvm/issue-subscribers-backend-x86
Author: None (Nick-Kooij)
The following program prints π and exits:
Compiling the above single-module program with LLVM 19.1.0 through the clang-cl driver, targeting x86, with the fast math (/fp:fast) switch fails to link:
Steps to reproduce:
This issue was introduced with LLVM 19.1.0, and is not a result of changes to Visual Studio. Prior versions, such as LLVM 18.1.8, link properly, using the aforementioned version Visual Studio.