[X86][MS] Add 80bit long double support for Windows

MSVC currently doesn't support 80 bits long double. But ICC does support
it on Windows. Besides, there're also some users asked for this feature.
We can find the discussions from stackoverflow, msdn etc.

Given Clang has already support `-mlong-double-80`, extending it to
support for Windows seems worthwhile.

Reviewed By: rnk, erichkeane

Differential Revision: https://reviews.llvm.org/D115441
This commit is contained in:
Phoebe Wang 2022-02-14 12:55:43 +08:00
parent 15dfe03022
commit 3e19ba36fc
3 changed files with 48 additions and 3 deletions

View File

@ -449,6 +449,20 @@ void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
} 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;
}
}
}
}

View File

@ -3456,6 +3456,8 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts,
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 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
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);

View File

@ -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;
}