[llvm] [clang] [flang] [AArch64][Driver] Better handling of target feature dependencies (PR #78270)

Tomas Matheson via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 17 08:26:54 PST 2024


================
@@ -150,3 +153,137 @@ void AArch64::PrintSupportedExtensions(StringMap<StringRef> DescMap) {
     }
   }
 }
+
+const llvm::AArch64::ExtensionInfo &
+lookupExtensionByID(llvm::AArch64::ArchExtKind ExtID) {
+  for (const auto &E : llvm::AArch64::Extensions)
+    if (E.ID == ExtID)
+      return E;
+  assert(false && "Invalid extension ID");
+}
+
+void AArch64::ExtensionSet::enable(ArchExtKind E) {
+  if (Enabled.test(E))
+    return;
+
+  LLVM_DEBUG(llvm::dbgs() << "Enable " << lookupExtensionByID(E).Name << "\n");
+
+  Touched.set(E);
+  Enabled.set(E);
+
+  // Recursively enable all features that this one depends on. This handles all
+  // of the simple cases, where the behaviour doesn't depend on the base
+  // architecture version.
+  for (auto Dep : ExtensionDependencies)
+    if (E == Dep.Later)
+      enable(Dep.Earlier);
+
+  // Special cases for dependencies which vary depending on the base
+  // architecture version.
+  if (BaseArch) {
+    // +sve implies +f32mm if the base architecture is v8.6A+ or v9.1A+
+    // It isn't the case in general that sve implies both f64mm and f32mm
+    if (E == AEK_SVE && BaseArch->is_superset(ARMV8_6A))
+      enable(AEK_F32MM);
+
+    // +fp16 implies +fp16fml for v8.4A+, but not v9.0-A+
+    if (E == AEK_FP16 && BaseArch->is_superset(ARMV8_4A) &&
+        !BaseArch->is_superset(ARMV9A))
+      enable(AEK_FP16FML);
+
+    // For all architectures, +crypto enables +aes and +sha2.
+    if (E == AEK_CRYPTO) {
+      enable(AEK_AES);
+      enable(AEK_SHA2);
+    }
+
+    // For v8.4A+ and v9.0A+, +crypto also enables +sha3 and +sm4.
+    if (E == AEK_CRYPTO && BaseArch->is_superset(ARMV8_4A)) {
+      enable(AEK_SHA3);
+      enable(AEK_SM4);
+    }
+  }
+}
+
+void AArch64::ExtensionSet::disable(ArchExtKind E) {
+  // -crypto always disables aes, sha2, sha3 and sm4, even for architectures
+  // where the latter two would not be enabled by +crypto.
+  if (E == AEK_CRYPTO) {
+    disable(AEK_AES);
+    disable(AEK_SHA2);
+    disable(AEK_SHA3);
+    disable(AEK_SM4);
+  }
+
+  if (!Enabled.test(E))
+    return;
+
+  LLVM_DEBUG(llvm::dbgs() << "Disable " << lookupExtensionByID(E).Name << "\n");
+
+  Touched.set(E);
+  Enabled.reset(E);
+
+  // Recursively disable all features that depends on this one.
+  for (auto Dep : ExtensionDependencies)
+    if (E == Dep.Earlier)
+      disable(Dep.Later);
+}
+
+void AArch64::ExtensionSet::toLLVMFeatureList(
+    std::vector<StringRef> &Features) const {
+  if (BaseArch && !BaseArch->ArchFeature.empty())
+    Features.push_back(BaseArch->ArchFeature);
+
+  for (const auto &E : Extensions) {
+    if (E.Feature.empty() || !Touched.test(E.ID))
+      continue;
+    if (Enabled.test(E.ID))
+      Features.push_back(E.Feature);
+    else
+      Features.push_back(E.NegFeature);
----------------
tmatheson-arm wrote:

When exactly do we need negative features?

https://github.com/llvm/llvm-project/pull/78270


More information about the cfe-commits mailing list