@@ -1052,18 +1052,57 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
10521052 return true ;
10531053}
10541054
1055+ bool AArch64TargetInfo::initFeatureMap (
1056+ llvm::StringMap<bool > &Features, DiagnosticsEngine &Diags, StringRef CPU,
1057+ const std::vector<std::string> &FeaturesVec) const {
1058+ std::vector<std::string> UpdatedFeaturesVec;
1059+ // Parse the CPU and add any implied features.
1060+ std::optional<llvm::AArch64::CpuInfo> CpuInfo = llvm::AArch64::parseCpu (CPU);
1061+ if (CpuInfo) {
1062+ auto Exts = CpuInfo->getImpliedExtensions ();
1063+ std::vector<StringRef> CPUFeats;
1064+ llvm::AArch64::getExtensionFeatures (Exts, CPUFeats);
1065+ for (auto F : CPUFeats) {
1066+ assert ((F[0 ] == ' +' || F[0 ] == ' -' ) && " Expected +/- in target feature!" );
1067+ UpdatedFeaturesVec.push_back (F.str ());
1068+ }
1069+ }
1070+
1071+ // Process target and dependent features. This is done in two loops collecting
1072+ // them into UpdatedFeaturesVec: first to add dependent '+'features, second to
1073+ // add target '+/-'features that can later disable some of features added on
1074+ // the first loop. Function Multi Versioning features begin with '?'.
1075+ for (const auto &Feature : FeaturesVec)
1076+ if (((Feature[0 ] == ' ?' || Feature[0 ] == ' +' )) &&
1077+ AArch64TargetInfo::doesFeatureAffectCodeGen (Feature.substr (1 ))) {
1078+ StringRef DepFeatures =
1079+ AArch64TargetInfo::getFeatureDependencies (Feature.substr (1 ));
1080+ SmallVector<StringRef, 1 > AttrFeatures;
1081+ DepFeatures.split (AttrFeatures, " ," );
1082+ for (auto F : AttrFeatures)
1083+ UpdatedFeaturesVec.push_back (F.str ());
1084+ }
1085+ for (const auto &Feature : FeaturesVec)
1086+ if (Feature[0 ] != ' ?' ) {
1087+ std::string UpdatedFeature = Feature;
1088+ if (Feature[0 ] == ' +' ) {
1089+ std::optional<llvm::AArch64::ExtensionInfo> Extension =
1090+ llvm::AArch64::parseArchExtension (Feature.substr (1 ));
1091+ if (Extension)
1092+ UpdatedFeature = Extension->Feature .str ();
1093+ }
1094+ UpdatedFeaturesVec.push_back (UpdatedFeature);
1095+ }
1096+
1097+ return TargetInfo::initFeatureMap (Features, Diags, CPU, UpdatedFeaturesVec);
1098+ }
1099+
10551100// Parse AArch64 Target attributes, which are a comma separated list of:
10561101// "arch=<arch>" - parsed to features as per -march=..
10571102// "cpu=<cpu>" - parsed to features as per -mcpu=.., with CPU set to <cpu>
10581103// "tune=<cpu>" - TuneCPU set to <cpu>
10591104// "feature", "no-feature" - Add (or remove) feature.
10601105// "+feature", "+nofeature" - Add (or remove) feature.
1061- //
1062- // A feature may correspond to an Extension (anything with a corresponding
1063- // AEK_), in which case an ExtensionSet is used to parse it and expand its
1064- // dependencies. Otherwise the feature is passed through (e.g. +v8.1a,
1065- // +outline-atomics, -fmv, etc). Features coming from the command line are
1066- // already parsed, therefore their dependencies do not need expansion.
10671106ParsedTargetAttr AArch64TargetInfo::parseTargetAttr (StringRef Features) const {
10681107 ParsedTargetAttr Ret;
10691108 if (Features == " default" )
@@ -1073,26 +1112,23 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
10731112 bool FoundArch = false ;
10741113
10751114 auto SplitAndAddFeatures = [](StringRef FeatString,
1076- std::vector<std::string> &Features,
1077- llvm::AArch64::ExtensionSet &FeatureBits) {
1115+ std::vector<std::string> &Features) {
10781116 SmallVector<StringRef, 8 > SplitFeatures;
10791117 FeatString.split (SplitFeatures, StringRef (" +" ), -1 , false );
10801118 for (StringRef Feature : SplitFeatures) {
1081- if (FeatureBits.parseModifier (Feature, /* AllowNoDashForm = */ true ))
1082- continue ;
1083- // Pass through features that are not extensions, e.g. +v8.1a,
1084- // +outline-atomics, -fmv, etc.
1085- if (Feature.starts_with (" no" ))
1086- Features.push_back (" -" + Feature.drop_front (2 ).str ());
1119+ StringRef FeatureName = llvm::AArch64::getArchExtFeature (Feature);
1120+ if (!FeatureName.empty ())
1121+ Features.push_back (FeatureName.str ());
10871122 else
1088- Features.push_back (" +" + Feature.str ());
1123+ // Pushing the original feature string to give a sema error later on
1124+ // when they get checked.
1125+ if (Feature.starts_with (" no" ))
1126+ Features.push_back (" -" + Feature.drop_front (2 ).str ());
1127+ else
1128+ Features.push_back (" +" + Feature.str ());
10891129 }
10901130 };
10911131
1092- llvm::AArch64::ExtensionSet FeatureBits;
1093- // Reconstruct the bitset from the command line option features.
1094- FeatureBits.reconstructFromParsedFeatures (getTargetOpts ().FeaturesAsWritten );
1095-
10961132 for (auto &Feature : AttrFeatures) {
10971133 Feature = Feature.trim ();
10981134 if (Feature.starts_with (" fpmath=" ))
@@ -1115,9 +1151,9 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
11151151 // Ret.Features.
11161152 if (!AI)
11171153 continue ;
1118- FeatureBits. addArchDefaults (*AI );
1154+ Ret. Features . push_back (AI-> ArchFeature . str () );
11191155 // Add any extra features, after the +
1120- SplitAndAddFeatures (Split.second , Ret.Features , FeatureBits );
1156+ SplitAndAddFeatures (Split.second , Ret.Features );
11211157 } else if (Feature.starts_with (" cpu=" )) {
11221158 if (!Ret.CPU .empty ())
11231159 Ret.Duplicate = " cpu=" ;
@@ -1127,30 +1163,33 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
11271163 std::pair<StringRef, StringRef> Split =
11281164 Feature.split (" =" ).second .trim ().split (" +" );
11291165 Ret.CPU = Split.first ;
1130- if (auto CpuInfo = llvm::AArch64::parseCpu (Ret.CPU )) {
1131- FeatureBits.addCPUDefaults (*CpuInfo);
1132- SplitAndAddFeatures (Split.second , Ret.Features , FeatureBits);
1133- }
1166+ SplitAndAddFeatures (Split.second , Ret.Features );
11341167 }
11351168 } else if (Feature.starts_with (" tune=" )) {
11361169 if (!Ret.Tune .empty ())
11371170 Ret.Duplicate = " tune=" ;
11381171 else
11391172 Ret.Tune = Feature.split (" =" ).second .trim ();
11401173 } else if (Feature.starts_with (" +" )) {
1141- SplitAndAddFeatures (Feature, Ret.Features , FeatureBits);
1174+ SplitAndAddFeatures (Feature, Ret.Features );
1175+ } else if (Feature.starts_with (" no-" )) {
1176+ StringRef FeatureName =
1177+ llvm::AArch64::getArchExtFeature (Feature.split (" -" ).second );
1178+ if (!FeatureName.empty ())
1179+ Ret.Features .push_back (" -" + FeatureName.drop_front (1 ).str ());
1180+ else
1181+ Ret.Features .push_back (" -" + Feature.split (" -" ).second .str ());
11421182 } else {
1143- if (FeatureBits. parseModifier (Feature, /* AllowNoDashForm = */ true ))
1144- continue ;
1145- // Pass through features that are not extensions, e.g. +v8.1a,
1146- // +outline-atomics, -fmv, etc.
1147- if (Feature. starts_with ( " no- " ))
1148- Ret.Features .push_back (" - " + Feature. drop_front ( 3 ) .str ());
1183+ // Try parsing the string to the internal target feature name. If it is
1184+ // invalid, add the original string (which could already be an internal
1185+ // name). These should be checked later by isValidFeatureName.
1186+ StringRef FeatureName = llvm::AArch64::getArchExtFeature (Feature);
1187+ if (!FeatureName. empty ( ))
1188+ Ret.Features .push_back (FeatureName .str ());
11491189 else
11501190 Ret.Features .push_back (" +" + Feature.str ());
11511191 }
11521192 }
1153- FeatureBits.toLLVMFeatureList (Ret.Features );
11541193 return Ret;
11551194}
11561195
0 commit comments