mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
[ARM] fix "+fp.dp" in multilib selection (#67412)
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.
This commit is contained in:
parent
202de4a5c6
commit
b3c4f64943
@ -627,6 +627,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);
|
||||
|
@ -35,6 +35,21 @@
|
||||
// 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 -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
|
||||
// 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{{.*}}
|
||||
|
||||
|
@ -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
|
||||
|
@ -366,26 +366,51 @@ 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 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 supports 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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 is single-precision only, then there
|
||||
// isn't any different FPU we can return here.
|
||||
if (!ARM::isDoublePrecision(InputFPU.Restriction))
|
||||
return InputFPUKind;
|
||||
|
||||
// Otherwise, look for an FPU entry with all the same fields, except
|
||||
// that it does not support 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;
|
||||
}
|
||||
}
|
||||
@ -420,20 +445,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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user