@@ -1064,57 +1064,17 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
1064
1064
return true ;
1065
1065
}
1066
1066
1067
- bool AArch64TargetInfo::initFeatureMap (
1068
- llvm::StringMap<bool > &Features, DiagnosticsEngine &Diags, StringRef CPU,
1069
- const std::vector<std::string> &FeaturesVec) const {
1070
- std::vector<std::string> UpdatedFeaturesVec;
1071
- // Parse the CPU and add any implied features.
1072
- std::optional<llvm::AArch64::CpuInfo> CpuInfo = llvm::AArch64::parseCpu (CPU);
1073
- if (CpuInfo) {
1074
- auto Exts = CpuInfo->getImpliedExtensions ();
1075
- std::vector<StringRef> CPUFeats;
1076
- llvm::AArch64::getExtensionFeatures (Exts, CPUFeats);
1077
- for (auto F : CPUFeats) {
1078
- assert ((F[0 ] == ' +' || F[0 ] == ' -' ) && " Expected +/- in target feature!" );
1079
- UpdatedFeaturesVec.push_back (F.str ());
1080
- }
1081
- }
1082
-
1083
- // Process target and dependent features. This is done in two loops collecting
1084
- // them into UpdatedFeaturesVec: first to add dependent '+'features, second to
1085
- // add target '+/-'features that can later disable some of features added on
1086
- // the first loop. Function Multi Versioning features begin with '?'.
1087
- for (const auto &Feature : FeaturesVec)
1088
- if (((Feature[0 ] == ' ?' || Feature[0 ] == ' +' )) &&
1089
- AArch64TargetInfo::doesFeatureAffectCodeGen (Feature.substr (1 ))) {
1090
- StringRef DepFeatures =
1091
- AArch64TargetInfo::getFeatureDependencies (Feature.substr (1 ));
1092
- SmallVector<StringRef, 1 > AttrFeatures;
1093
- DepFeatures.split (AttrFeatures, " ," );
1094
- for (auto F : AttrFeatures)
1095
- UpdatedFeaturesVec.push_back (F.str ());
1096
- }
1097
- for (const auto &Feature : FeaturesVec)
1098
- if (Feature[0 ] != ' ?' ) {
1099
- std::string UpdatedFeature = Feature;
1100
- if (Feature[0 ] == ' +' ) {
1101
- std::optional<llvm::AArch64::ExtensionInfo> Extension =
1102
- llvm::AArch64::parseArchExtension (Feature.substr (1 ));
1103
- if (Extension)
1104
- UpdatedFeature = Extension->Feature .str ();
1105
- }
1106
- UpdatedFeaturesVec.push_back (UpdatedFeature);
1107
- }
1108
-
1109
- return TargetInfo::initFeatureMap (Features, Diags, CPU, UpdatedFeaturesVec);
1110
- }
1111
-
1112
1067
// Parse AArch64 Target attributes, which are a comma separated list of:
1113
1068
// "arch=<arch>" - parsed to features as per -march=..
1114
1069
// "cpu=<cpu>" - parsed to features as per -mcpu=.., with CPU set to <cpu>
1115
1070
// "tune=<cpu>" - TuneCPU set to <cpu>
1116
1071
// "feature", "no-feature" - Add (or remove) feature.
1117
1072
// "+feature", "+nofeature" - Add (or remove) feature.
1073
+ //
1074
+ // A feature may correspond to an Extension (anything with a corresponding
1075
+ // AEK_), in which case an ExtensionSet is used to parse it and expand its
1076
+ // dependencies. If the feature does not yield a successful parse then it
1077
+ // is passed through.
1118
1078
ParsedTargetAttr AArch64TargetInfo::parseTargetAttr (StringRef Features) const {
1119
1079
ParsedTargetAttr Ret;
1120
1080
if (Features == " default" )
@@ -1124,23 +1084,31 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
1124
1084
bool FoundArch = false ;
1125
1085
1126
1086
auto SplitAndAddFeatures = [](StringRef FeatString,
1127
- std::vector<std::string> &Features) {
1087
+ std::vector<std::string> &Features,
1088
+ llvm::AArch64::ExtensionSet &FeatureBits) {
1128
1089
SmallVector<StringRef, 8 > SplitFeatures;
1129
1090
FeatString.split (SplitFeatures, StringRef (" +" ), -1 , false );
1130
1091
for (StringRef Feature : SplitFeatures) {
1131
- StringRef FeatureName = llvm::AArch64::getArchExtFeature (Feature);
1132
- if (!FeatureName.empty ())
1133
- Features.push_back (FeatureName.str ());
1092
+ if (FeatureBits.parseModifier (Feature))
1093
+ continue ;
1094
+ // Pass through anything that failed to parse so that we can emit
1095
+ // diagnostics, as well as valid internal feature names.
1096
+ //
1097
+ // FIXME: We should consider rejecting internal feature names like
1098
+ // neon, v8a, etc.
1099
+ // FIXME: We should consider emitting diagnostics here.
1100
+ if (Feature.starts_with (" no" ))
1101
+ Features.push_back (" -" + Feature.drop_front (2 ).str ());
1134
1102
else
1135
- // Pushing the original feature string to give a sema error later on
1136
- // when they get checked.
1137
- if (Feature.starts_with (" no" ))
1138
- Features.push_back (" -" + Feature.drop_front (2 ).str ());
1139
- else
1140
- Features.push_back (" +" + Feature.str ());
1103
+ Features.push_back (" +" + Feature.str ());
1141
1104
}
1142
1105
};
1143
1106
1107
+ llvm::AArch64::ExtensionSet FeatureBits;
1108
+ // Reconstruct the bitset from the command line option features.
1109
+ FeatureBits.reconstructFromParsedFeatures (getTargetOpts ().FeaturesAsWritten ,
1110
+ Ret.Features );
1111
+
1144
1112
for (auto &Feature : AttrFeatures) {
1145
1113
Feature = Feature.trim ();
1146
1114
if (Feature.starts_with (" fpmath=" ))
@@ -1163,9 +1131,9 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
1163
1131
// Ret.Features.
1164
1132
if (!AI)
1165
1133
continue ;
1166
- Ret. Features . push_back (AI-> ArchFeature . str () );
1134
+ FeatureBits. addArchDefaults (*AI );
1167
1135
// Add any extra features, after the +
1168
- SplitAndAddFeatures (Split.second , Ret.Features );
1136
+ SplitAndAddFeatures (Split.second , Ret.Features , FeatureBits );
1169
1137
} else if (Feature.starts_with (" cpu=" )) {
1170
1138
if (!Ret.CPU .empty ())
1171
1139
Ret.Duplicate = " cpu=" ;
@@ -1175,33 +1143,34 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
1175
1143
std::pair<StringRef, StringRef> Split =
1176
1144
Feature.split (" =" ).second .trim ().split (" +" );
1177
1145
Ret.CPU = Split.first ;
1178
- SplitAndAddFeatures (Split.second , Ret.Features );
1146
+ if (auto CpuInfo = llvm::AArch64::parseCpu (Ret.CPU )) {
1147
+ FeatureBits.addCPUDefaults (*CpuInfo);
1148
+ SplitAndAddFeatures (Split.second , Ret.Features , FeatureBits);
1149
+ }
1179
1150
}
1180
1151
} else if (Feature.starts_with (" tune=" )) {
1181
1152
if (!Ret.Tune .empty ())
1182
1153
Ret.Duplicate = " tune=" ;
1183
1154
else
1184
1155
Ret.Tune = Feature.split (" =" ).second .trim ();
1185
1156
} else if (Feature.starts_with (" +" )) {
1186
- SplitAndAddFeatures (Feature, Ret.Features );
1187
- } else if (Feature.starts_with (" no-" )) {
1188
- StringRef FeatureName =
1189
- llvm::AArch64::getArchExtFeature (Feature.split (" -" ).second );
1190
- if (!FeatureName.empty ())
1191
- Ret.Features .push_back (" -" + FeatureName.drop_front (1 ).str ());
1192
- else
1193
- Ret.Features .push_back (" -" + Feature.split (" -" ).second .str ());
1157
+ SplitAndAddFeatures (Feature, Ret.Features , FeatureBits);
1194
1158
} else {
1195
- // Try parsing the string to the internal target feature name. If it is
1196
- // invalid, add the original string (which could already be an internal
1197
- // name). These should be checked later by isValidFeatureName.
1198
- StringRef FeatureName = llvm::AArch64::getArchExtFeature (Feature);
1199
- if (!FeatureName.empty ())
1200
- Ret.Features .push_back (FeatureName.str ());
1159
+ if (FeatureBits.parseModifier (Feature, /* AllowNoDashForm = */ true ))
1160
+ continue ;
1161
+ // Pass through anything that failed to parse so that we can emit
1162
+ // diagnostics, as well as valid internal feature names.
1163
+ //
1164
+ // FIXME: We should consider rejecting internal feature names like
1165
+ // neon, v8a, etc.
1166
+ // FIXME: We should consider emitting diagnostics here.
1167
+ if (Feature.starts_with (" no-" ))
1168
+ Ret.Features .push_back (" -" + Feature.drop_front (3 ).str ());
1201
1169
else
1202
1170
Ret.Features .push_back (" +" + Feature.str ());
1203
1171
}
1204
1172
}
1173
+ FeatureBits.toLLVMFeatureList (Ret.Features );
1205
1174
return Ret;
1206
1175
}
1207
1176
0 commit comments