@@ -1052,18 +1052,57 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
1052
1052
return true ;
1053
1053
}
1054
1054
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
+
1055
1100
// Parse AArch64 Target attributes, which are a comma separated list of:
1056
1101
// "arch=<arch>" - parsed to features as per -march=..
1057
1102
// "cpu=<cpu>" - parsed to features as per -mcpu=.., with CPU set to <cpu>
1058
1103
// "tune=<cpu>" - TuneCPU set to <cpu>
1059
1104
// "feature", "no-feature" - Add (or remove) feature.
1060
1105
// "+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.
1067
1106
ParsedTargetAttr AArch64TargetInfo::parseTargetAttr (StringRef Features) const {
1068
1107
ParsedTargetAttr Ret;
1069
1108
if (Features == " default" )
@@ -1073,26 +1112,23 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
1073
1112
bool FoundArch = false ;
1074
1113
1075
1114
auto SplitAndAddFeatures = [](StringRef FeatString,
1076
- std::vector<std::string> &Features,
1077
- llvm::AArch64::ExtensionSet &FeatureBits) {
1115
+ std::vector<std::string> &Features) {
1078
1116
SmallVector<StringRef, 8 > SplitFeatures;
1079
1117
FeatString.split (SplitFeatures, StringRef (" +" ), -1 , false );
1080
1118
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 ());
1087
1122
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 ());
1089
1129
}
1090
1130
};
1091
1131
1092
- llvm::AArch64::ExtensionSet FeatureBits;
1093
- // Reconstruct the bitset from the command line option features.
1094
- FeatureBits.reconstructFromParsedFeatures (getTargetOpts ().FeaturesAsWritten );
1095
-
1096
1132
for (auto &Feature : AttrFeatures) {
1097
1133
Feature = Feature.trim ();
1098
1134
if (Feature.starts_with (" fpmath=" ))
@@ -1115,9 +1151,9 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
1115
1151
// Ret.Features.
1116
1152
if (!AI)
1117
1153
continue ;
1118
- FeatureBits. addArchDefaults (*AI );
1154
+ Ret. Features . push_back (AI-> ArchFeature . str () );
1119
1155
// Add any extra features, after the +
1120
- SplitAndAddFeatures (Split.second , Ret.Features , FeatureBits );
1156
+ SplitAndAddFeatures (Split.second , Ret.Features );
1121
1157
} else if (Feature.starts_with (" cpu=" )) {
1122
1158
if (!Ret.CPU .empty ())
1123
1159
Ret.Duplicate = " cpu=" ;
@@ -1127,30 +1163,33 @@ ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
1127
1163
std::pair<StringRef, StringRef> Split =
1128
1164
Feature.split (" =" ).second .trim ().split (" +" );
1129
1165
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 );
1134
1167
}
1135
1168
} else if (Feature.starts_with (" tune=" )) {
1136
1169
if (!Ret.Tune .empty ())
1137
1170
Ret.Duplicate = " tune=" ;
1138
1171
else
1139
1172
Ret.Tune = Feature.split (" =" ).second .trim ();
1140
1173
} 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 ());
1142
1182
} 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 ());
1149
1189
else
1150
1190
Ret.Features .push_back (" +" + Feature.str ());
1151
1191
}
1152
1192
}
1153
- FeatureBits.toLLVMFeatureList (Ret.Features );
1154
1193
return Ret;
1155
1194
}
1156
1195
0 commit comments