================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits