[clang] [llvm] [RISCV][FMV] Support target_clones (PR #85786)

Piyou Chen via cfe-commits cfe-commits at lists.llvm.org
Sat Jul 20 06:31:20 PDT 2024


================
@@ -2854,10 +2854,121 @@ void CodeGenFunction::EmitMultiVersionResolver(
   case llvm::Triple::aarch64:
     EmitAArch64MultiVersionResolver(Resolver, Options);
     return;
+  case llvm::Triple::riscv32:
+  case llvm::Triple::riscv64:
+    EmitRISCVMultiVersionResolver(Resolver, Options);
+    return;
 
   default:
-    assert(false && "Only implemented for x86 and AArch64 targets");
+    assert(false && "Only implemented for x86, AArch64 and RISC-V targets");
+  }
+}
+
+void CodeGenFunction::EmitRISCVMultiVersionResolver(
+    llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
+
+  if (getContext().getTargetInfo().getTriple().getOS() !=
+      llvm::Triple::OSType::Linux) {
+    CGM.getDiags().Report(diag::err_os_unsupport_riscv_target_clones);
+    return;
+  }
+
+  llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);
+  Builder.SetInsertPoint(CurBlock);
+  EmitRISCVCpuInit();
+
+  bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc();
+  bool HasDefault = false;
+  unsigned DefaultIndex = 0;
+  // Check the each candidate function.
+  for (unsigned Index = 0; Index < Options.size(); Index++) {
+
+    if (Options[Index].Conditions.Features[0].starts_with("default")) {
+      HasDefault = true;
+      DefaultIndex = Index;
+      continue;
+    }
+
+    Builder.SetInsertPoint(CurBlock);
+
+    std::vector<std::string> TargetAttrFeats =
+        getContext()
+            .getTargetInfo()
+            .parseTargetAttr(Options[Index].Conditions.Features[0])
+            .Features;
+
+    if (TargetAttrFeats.empty())
+      continue;
+
+    // Two conditions need to be checked for the current version:
+    //
+    // 1. LengthCondition: The maximum group ID of the required extension
+    //    does not exceed the runtime object's length.
+    //    __riscv_feature_bits.length > MAX_USED_GROUPID
+    //
+    // 2. FeaturesCondition: The bitmask of the required extension has been
+    //    enabled by the runtime object.
+    //    (__riscv_feature_bits.features[i] & REQUIRED_BITMASK) ==
+    //    REQUIRED_BITMASK
+    //
+    // When both conditions are met, return this version of the function.
+    // Otherwise, try the next version.
+    //
+    // if (LengthConditionVersion1 && FeaturesConditionVersion1)
+    //     return Version1;
+    // else if (LengthConditionVersion2 && FeaturesConditionVersion2)
+    //     return Version2;
+    // else if (LengthConditionVersion3 && FeaturesConditionVersion3)
+    //     return Version3;
+    // ...
+    // else
+    //     return DefaultVersion;
+    llvm::SmallVector<StringRef, 8> CurrTargetAttrFeats;
+
+    for (auto Feat : TargetAttrFeats)
+      CurrTargetAttrFeats.push_back(StringRef(Feat).substr(1));
----------------
BeMg wrote:

Current target_clones syntax only accept the individual extension, so `parseTargetAttr` always return extension with `+` sign. 

But it worth to check here again to avoid the very surprising semantics.

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


More information about the cfe-commits mailing list