https://github.com/domin144 updated https://github.com/llvm/llvm-project/pull/67412
From 4cc2328982cc8260263aa803f2b02bff7d7b4a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20W=C3=B3jt?= <dominik.w...@arm.com> Date: Wed, 20 Sep 2023 16:39:27 +0200 Subject: [PATCH 1/2] [ARM] fix "+fp.dp" in multilib selection When the FPU was selected with "+(no)fp(.dp)" extensions in "-march" or "-mcpu" options, the FPU used for multilib selection was still the default one for given architecture or CPU. --- clang/lib/Driver/ToolChains/Arch/ARM.cpp | 5 ++ .../test/Driver/print-multi-selection-flags.c | 10 +++ .../llvm/TargetParser/ARMTargetParser.h | 8 +++ llvm/lib/TargetParser/ARMTargetParser.cpp | 69 +++++++++++++++---- 4 files changed, 77 insertions(+), 15 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp index bb66db5feae8c3b..9a042d351bda0b6 100644 --- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -626,6 +626,11 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D, if (!llvm::ARM::getFPUFeatures(FPUKind, Features)) D.Diag(clang::diag::err_drv_clang_unsupported) << std::string("-mfpu=") + AndroidFPU; + } else if (ArchArgFPUKind != llvm::ARM::FK_INVALID || + CPUArgFPUKind != llvm::ARM::FK_INVALID) { + FPUKind = + CPUArgFPUKind != llvm::ARM::FK_INVALID ? CPUArgFPUKind : ArchArgFPUKind; + (void)llvm::ARM::getFPUFeatures(FPUKind, Features); } else { if (!ForAS) { std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple); diff --git a/clang/test/Driver/print-multi-selection-flags.c b/clang/test/Driver/print-multi-selection-flags.c index 819ff242ced0026..f020a22ea128aac 100644 --- a/clang/test/Driver/print-multi-selection-flags.c +++ b/clang/test/Driver/print-multi-selection-flags.c @@ -35,6 +35,16 @@ // CHECK-MVENOFP-NOT: -march=thumbv8.1m.main{{.*}}+mve.fp{{.*}} // CHECK-MVENOFP: -mfpu=none +// RUN: %clang -print-multi-flags-experimental --target=arm-none-eabihf -march=armv8.1m.main+fp.dp | FileCheck --check-prefix=CHECK-V8_1_FP_DP %s +// CHECK-V8_1_FP_DP: -march=thumbv8.1m.main{{.*}} +// CHECK-V8_1_FP_DP: -mfloat-abi=hard +// CHECK-V8_1_FP_DP: -mfpu=fp-armv8-fullfp16-d16 + +// RUN: %clang -print-multi-flags-experimental --target=arm-none-eabihf -mcpu=cortex-m85+nofp.dp | FileCheck --check-prefix=CHECK-M85_NO_FP_DP %s +// CHECK-M85_NO_FP_DP: -march=thumbv8.1m.main{{.*}} +// CHECK-M85_NO_FP_DP: -mfloat-abi=hard +// CHECK-M85_NO_FP_DP: -mfpu=fp-armv8-fullfp16-sp-d16 + // RUN: %clang -print-multi-flags-experimental --target=aarch64-none-elf -march=armv8-a+lse | FileCheck --check-prefix=CHECK-LSE %s // CHECK-LSE: -march=aarch64{{.*}}+lse{{.*}} diff --git a/llvm/include/llvm/TargetParser/ARMTargetParser.h b/llvm/include/llvm/TargetParser/ARMTargetParser.h index b893eab1902f81b..c42d66f048fccc0 100644 --- a/llvm/include/llvm/TargetParser/ARMTargetParser.h +++ b/llvm/include/llvm/TargetParser/ARMTargetParser.h @@ -143,6 +143,14 @@ enum class FPURestriction { SP_D16 ///< Only single-precision instructions, with 16 D registers }; +inline bool isDoublePrecision(const FPURestriction restriction) { + return restriction != FPURestriction::SP_D16; +} + +inline bool has32Regs(const FPURestriction restriction) { + return restriction == FPURestriction::None; +} + // An FPU name implies one of three levels of Neon support: enum class NeonSupportLevel { None = 0, ///< No Neon diff --git a/llvm/lib/TargetParser/ARMTargetParser.cpp b/llvm/lib/TargetParser/ARMTargetParser.cpp index c84928eeb07b140..524bb4e0fd0db22 100644 --- a/llvm/lib/TargetParser/ARMTargetParser.cpp +++ b/llvm/lib/TargetParser/ARMTargetParser.cpp @@ -366,26 +366,50 @@ StringRef ARM::getArchExtFeature(StringRef ArchExt) { } static ARM::FPUKind findDoublePrecisionFPU(ARM::FPUKind InputFPUKind) { + if (InputFPUKind == ARM::FK_INVALID || InputFPUKind == ARM::FK_NONE) + return ARM::FK_INVALID; + + const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind]; + + if (ARM::isDoublePrecision(InputFPU.Restriction)) + return InputFPUKind; + + // Otherwise, look for an FPU entry with all the same fields, except + // that it supports double precision. + for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) { + if (CandidateFPU.FPUVer == InputFPU.FPUVer && + CandidateFPU.NeonSupport == InputFPU.NeonSupport && + ARM::has32Regs(CandidateFPU.Restriction) == + ARM::has32Regs(InputFPU.Restriction) && + ARM::isDoublePrecision(CandidateFPU.Restriction)) { + return CandidateFPU.ID; + } + } + + // nothing found + return ARM::FK_INVALID; +} + +static ARM::FPUKind findSinglePrecisionFPU(ARM::FPUKind InputFPUKind) { + if (InputFPUKind == ARM::FK_INVALID || InputFPUKind == ARM::FK_NONE) + return ARM::FK_INVALID; + const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind]; // If the input FPU already supports double-precision, then there // isn't any different FPU we can return here. // - // The current available FPURestriction values are None (no - // restriction), D16 (only 16 d-regs) and SP_D16 (16 d-regs - // and single precision only); there's no value representing - // SP restriction without D16. So this test just means 'is it - // SP only?'. - if (InputFPU.Restriction != ARM::FPURestriction::SP_D16) - return ARM::FK_INVALID; + if (!ARM::isDoublePrecision(InputFPU.Restriction)) + return InputFPUKind; // Otherwise, look for an FPU entry with all the same fields, except - // that SP_D16 has been replaced with just D16, representing adding - // double precision and not changing anything else. + // that it does not support double precision. for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) { if (CandidateFPU.FPUVer == InputFPU.FPUVer && CandidateFPU.NeonSupport == InputFPU.NeonSupport && - CandidateFPU.Restriction == ARM::FPURestriction::D16) { + ARM::has32Regs(CandidateFPU.Restriction) == + ARM::has32Regs(InputFPU.Restriction) && + !ARM::isDoublePrecision(CandidateFPU.Restriction)) { return CandidateFPU.ID; } } @@ -420,20 +444,35 @@ bool ARM::appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK, CPU = "generic"; if (ArchExt == "fp" || ArchExt == "fp.dp") { + const ARM::FPUKind DefaultFPU = getDefaultFPU(CPU, AK); ARM::FPUKind FPUKind; if (ArchExt == "fp.dp") { + const bool IsDP = ArgFPUKind != ARM::FK_INVALID && + ArgFPUKind != ARM::FK_NONE && + isDoublePrecision(getFPURestriction(ArgFPUKind)); if (Negated) { - Features.push_back("-fp64"); - return true; + /* If there is no FPU selected yet, we still need to set ArgFPUKind, as + * leaving it as FK_INVALID, would cause default FPU to be selected + * later and that could be double precision one. */ + if (ArgFPUKind != ARM::FK_INVALID && !IsDP) + return true; + FPUKind = findSinglePrecisionFPU(DefaultFPU); + if (FPUKind == ARM::FK_INVALID) + FPUKind = ARM::FK_NONE; + } else { + if (IsDP) + return true; + FPUKind = findDoublePrecisionFPU(DefaultFPU); + if (FPUKind == ARM::FK_INVALID) + return false; } - FPUKind = findDoublePrecisionFPU(getDefaultFPU(CPU, AK)); } else if (Negated) { FPUKind = ARM::FK_NONE; } else { - FPUKind = getDefaultFPU(CPU, AK); + FPUKind = DefaultFPU; } ArgFPUKind = FPUKind; - return ARM::getFPUFeatures(FPUKind, Features); + return true; } return StartingNumFeatures != Features.size(); } From 35d2b943e31d5caf5943f0f9a622ce1577db0791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20W=C3=B3jt?= <dominik.w...@arm.com> Date: Fri, 13 Oct 2023 13:21:20 +0200 Subject: [PATCH 2/2] Fix comments, add test case for multiple extensions --- clang/test/Driver/print-multi-selection-flags.c | 5 +++++ llvm/lib/TargetParser/ARMTargetParser.cpp | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/clang/test/Driver/print-multi-selection-flags.c b/clang/test/Driver/print-multi-selection-flags.c index f020a22ea128aac..248d9a3cdf49b22 100644 --- a/clang/test/Driver/print-multi-selection-flags.c +++ b/clang/test/Driver/print-multi-selection-flags.c @@ -40,6 +40,11 @@ // CHECK-V8_1_FP_DP: -mfloat-abi=hard // CHECK-V8_1_FP_DP: -mfpu=fp-armv8-fullfp16-d16 +// RUN: %clang -print-multi-flags-experimental --target=arm-none-eabihf -march=armv8.1m.main+nofp+fp+nofp.dp | FileCheck --check-prefix=CHECK-V8_1_NO_FP_DP %s +// CHECK-V8_1_NO_FP_DP: -march=thumbv8.1m.main{{.*}} +// CHECK-V8_1_NO_FP_DP: -mfloat-abi=hard +// CHECK-V8_1_NO_FP_DP: -mfpu=fp-armv8-fullfp16-sp-d16 + // RUN: %clang -print-multi-flags-experimental --target=arm-none-eabihf -mcpu=cortex-m85+nofp.dp | FileCheck --check-prefix=CHECK-M85_NO_FP_DP %s // CHECK-M85_NO_FP_DP: -march=thumbv8.1m.main{{.*}} // CHECK-M85_NO_FP_DP: -mfloat-abi=hard diff --git a/llvm/lib/TargetParser/ARMTargetParser.cpp b/llvm/lib/TargetParser/ARMTargetParser.cpp index 524bb4e0fd0db22..dcf26b841a7c4cb 100644 --- a/llvm/lib/TargetParser/ARMTargetParser.cpp +++ b/llvm/lib/TargetParser/ARMTargetParser.cpp @@ -371,6 +371,8 @@ static ARM::FPUKind findDoublePrecisionFPU(ARM::FPUKind InputFPUKind) { const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind]; + // If the input FPU already supports double-precision, then there + // isn't any different FPU we can return here. if (ARM::isDoublePrecision(InputFPU.Restriction)) return InputFPUKind; @@ -396,9 +398,8 @@ static ARM::FPUKind findSinglePrecisionFPU(ARM::FPUKind InputFPUKind) { const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind]; - // If the input FPU already supports double-precision, then there + // If the input FPU already is single-precision only, then there // isn't any different FPU we can return here. - // if (!ARM::isDoublePrecision(InputFPU.Restriction)) return InputFPUKind; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits