llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.04k stars 11.98k forks source link

LLVM 19.1.0 clang-cl x86 target, /fp:fast, acosf breaks link #109599

Closed Nick-Kooij closed 3 weeks ago

Nick-Kooij commented 1 month ago

The following program prints π and exits:

#include <cmath>
#include <cstdio>

int main( int argc, char** argv ) {
    printf( "%f\n", acosf( 0.0f ) * 2 );
    return 0;
}

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:

lld-link : error : undefined symbol: _acosf

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.

Nick-Kooij commented 1 month 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

arsenm commented 1 month ago

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

zufuliu commented 1 month ago

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:\>
zufuliu commented 1 month ago

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. image

arsenm commented 1 month ago

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?

zufuliu commented 1 month ago

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).

zufuliu commented 1 month ago

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

zufuliu commented 1 month ago

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"}
efriedma-quic commented 1 month ago

See #101268 (which was merged to main, but not 19).

zufuliu commented 1 month ago

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)
farzonl commented 1 month ago

@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?

arsenm commented 1 month ago

#101268 (comment)

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?

farzonl commented 1 month ago

@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?

efriedma-quic commented 1 month ago

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.

h-vetinari commented 3 weeks ago

The backport https://github.com/llvm/llvm-project/pull/111218 was now released with LLVM 19.1.2

llvmbot commented 3 weeks ago

@llvm/issue-subscribers-backend-x86

Author: None (Nick-Kooij)

The following program prints π and exits: ```` #include <cmath> #include <cstdio> int main( int argc, char** argv ) { printf( "%f\n", acosf( 0.0f ) * 2 ); return 0; } ```` 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: ```` lld-link : error : undefined symbol: _acosf ```` ## Steps to reproduce: * Obtained [LLVM-19.1.0-win64.exe](https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.0/LLVM-19.1.0-win64.exe) from the official Assests. * Install on **Windows 11** with **Visual Studio 2022 17.11.4** * Must build a *x86* target * x64 targets link and run properly * Must use the /fp:fast fast math mode compiler switch 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.