diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -449,6 +449,20 @@ } else if (Opts.LongDoubleSize == 128) { LongDoubleWidth = LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::IEEEquad(); + } else if (Opts.LongDoubleSize == 80) { + LongDoubleFormat = &llvm::APFloat::x87DoubleExtended(); + if (getTriple().isWindowsMSVCEnvironment()) { + LongDoubleWidth = 128; + LongDoubleAlign = 128; + } else { // Linux + if (getTriple().getArch() == llvm::Triple::x86) { + LongDoubleWidth = 96; + LongDoubleAlign = 32; + } else { + LongDoubleWidth = 128; + LongDoubleAlign = 128; + } + } } } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3456,6 +3456,8 @@ GenerateArg(Args, OPT_mlong_double_128, SA); else if (Opts.LongDoubleSize == 64) GenerateArg(Args, OPT_mlong_double_64, SA); + else if (Opts.LongDoubleSize == 80) + GenerateArg(Args, OPT_mlong_double_80, SA); // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='. @@ -3838,9 +3840,16 @@ Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; if (!Opts.NoBuiltin) getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs); - Opts.LongDoubleSize = Args.hasArg(OPT_mlong_double_128) - ? 128 - : Args.hasArg(OPT_mlong_double_64) ? 64 : 0; + if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) { + if (A->getOption().matches(options::OPT_mlong_double_64)) + Opts.LongDoubleSize = 64; + else if (A->getOption().matches(options::OPT_mlong_double_80)) + Opts.LongDoubleSize = 80; + else if (A->getOption().matches(options::OPT_mlong_double_128)) + Opts.LongDoubleSize = 128; + else + Opts.LongDoubleSize = 0; + } if (Opts.FastRelaxedMath) Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); llvm::sort(Opts.ModuleFeatures); diff --git a/clang/test/CodeGen/X86/long-double-config-size.c b/clang/test/CodeGen/X86/long-double-config-size.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/X86/long-double-config-size.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-windows-msvc %s -emit-llvm -mlong-double-64 -o - | FileCheck %s --check-prefix=SIZE64 +// RUN: %clang_cc1 -triple i386-windows-msvc %s -emit-llvm -mlong-double-80 -o - | FileCheck %s --check-prefix=SIZE80 +// RUN: %clang_cc1 -triple x86_64-windows-msvc %s -emit-llvm -mlong-double-80 -o - | FileCheck %s --check-prefix=SIZE80 +// RUN: %clang_cc1 -triple x86_64-windows-msvc %s -emit-llvm -mlong-double-128 -o - | FileCheck %s --check-prefix=SIZE128 +// RUN: %clang_cc1 -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=SIZE64 + +long double global; +// SIZE64: @global = dso_local global double 0 +// SIZE80: @global = dso_local global x86_fp80 0xK{{0+}}, align 16 +// SIZE128: @global = dso_local global fp128 0 + +long double func(long double param) { + // SIZE64: define dso_local double @func(double noundef %param) + // SIZE80: define dso_local x86_fp80 @func(x86_fp80 noundef %param) + // SIZE128: define dso_local fp128 @func(fp128 noundef %param) + long double local = param; + // SIZE64: alloca double + // SIZE80: alloca x86_fp80, align 16 + // SIZE128: alloca fp128 + local = param; + return local + param; +}