@@ -2850,10 +2850,113 @@ void CodeGenFunction::EmitMultiVersionResolver(
28502850 case llvm::Triple::aarch64:
28512851 EmitAArch64MultiVersionResolver (Resolver, Options);
28522852 return ;
2853+ case llvm::Triple::riscv32:
2854+ case llvm::Triple::riscv64:
2855+ EmitRISCVMultiVersionResolver (Resolver, Options);
2856+ return ;
28532857
28542858 default :
2855- assert (false && " Only implemented for x86 and AArch64 targets" );
2859+ assert (false && " Only implemented for x86, AArch64 and RISC-V targets" );
2860+ }
2861+ }
2862+
2863+ void CodeGenFunction::EmitRISCVMultiVersionResolver (
2864+ llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
2865+
2866+ if (getContext ().getTargetInfo ().getTriple ().getOS () !=
2867+ llvm::Triple::OSType::Linux) {
2868+ CGM.getDiags ().Report (diag::err_os_unsupport_riscv_target_clones);
2869+ return ;
2870+ }
2871+
2872+ llvm::BasicBlock *CurBlock = createBasicBlock (" resolver_entry" , Resolver);
2873+ Builder.SetInsertPoint (CurBlock);
2874+ EmitRISCVCpuInit ();
2875+
2876+ bool SupportsIFunc = getContext ().getTargetInfo ().supportsIFunc ();
2877+ bool HasDefault = false ;
2878+ int DefaultIndex = 0 ;
2879+ // Check the each candidate function.
2880+ for (unsigned Index = 0 ; Index < Options.size (); Index++) {
2881+
2882+ if (Options[Index].Conditions .Features [0 ].starts_with (" default" )) {
2883+ HasDefault = true ;
2884+ DefaultIndex = Index;
2885+ continue ;
2886+ }
2887+
2888+ Builder.SetInsertPoint (CurBlock);
2889+
2890+ std::vector<std::string> TargetAttrFeats =
2891+ getContext ()
2892+ .getTargetInfo ()
2893+ .parseTargetAttr (Options[Index].Conditions .Features [0 ])
2894+ .Features ;
2895+
2896+ if (!TargetAttrFeats.empty ()) {
2897+ // If this function doens't need override, then merge with module level
2898+ // target features. Otherwise, remain the current target features.
2899+ auto I = llvm::find (TargetAttrFeats, " +__RISCV_TargetAttrNeedOverride" );
2900+ if (I == TargetAttrFeats.end ())
2901+ TargetAttrFeats.insert (TargetAttrFeats.begin (),
2902+ Target.getTargetOpts ().FeaturesAsWritten .begin (),
2903+ Target.getTargetOpts ().FeaturesAsWritten .end ());
2904+ else
2905+ TargetAttrFeats.erase (I);
2906+
2907+ // Only consider +<extension-feature>.
2908+ llvm::SmallVector<StringRef, 8 > PlusTargetAttrFeats;
2909+ for (StringRef Feat : TargetAttrFeats) {
2910+ if (!getContext ().getTargetInfo ().isValidFeatureName (
2911+ Feat.substr (1 ).str ()))
2912+ continue ;
2913+ if (Feat.starts_with (" +" ))
2914+ PlusTargetAttrFeats.push_back (Feat.substr (1 ));
2915+ }
2916+
2917+ llvm::BasicBlock *SecondCond =
2918+ createBasicBlock (" resovler_cond" , Resolver);
2919+
2920+ Builder.SetInsertPoint (SecondCond);
2921+ unsigned MaxGroupIDUsed = 0 ;
2922+ llvm::Value *SecondCondition =
2923+ EmitRISCVCpuSupports (PlusTargetAttrFeats, MaxGroupIDUsed);
2924+
2925+ Builder.SetInsertPoint (CurBlock);
2926+ llvm::Value *FirstCondition = EmitRISCVFeatureBitsLength (MaxGroupIDUsed);
2927+
2928+ llvm::BasicBlock *RetBlock =
2929+ createBasicBlock (" resolver_return" , Resolver);
2930+ CGBuilderTy RetBuilder (*this , RetBlock);
2931+ CreateMultiVersionResolverReturn (CGM, Resolver, RetBuilder,
2932+ Options[Index].Function , SupportsIFunc);
2933+ llvm::BasicBlock *ElseBlock = createBasicBlock (" resolver_else" , Resolver);
2934+
2935+ Builder.SetInsertPoint (CurBlock);
2936+ Builder.CreateCondBr (FirstCondition, SecondCond, ElseBlock);
2937+
2938+ Builder.SetInsertPoint (SecondCond);
2939+ Builder.CreateCondBr (SecondCondition, RetBlock, ElseBlock);
2940+
2941+ CurBlock = ElseBlock;
2942+ }
28562943 }
2944+
2945+ // Finally, emit the default one.
2946+ if (HasDefault) {
2947+ Builder.SetInsertPoint (CurBlock);
2948+ CreateMultiVersionResolverReturn (
2949+ CGM, Resolver, Builder, Options[DefaultIndex].Function , SupportsIFunc);
2950+ return ;
2951+ }
2952+
2953+ // If no generic/default, emit an unreachable.
2954+ Builder.SetInsertPoint (CurBlock);
2955+ llvm::CallInst *TrapCall = EmitTrapCall (llvm::Intrinsic::trap);
2956+ TrapCall->setDoesNotReturn ();
2957+ TrapCall->setDoesNotThrow ();
2958+ Builder.CreateUnreachable ();
2959+ Builder.ClearInsertionPoint ();
28572960}
28582961
28592962void CodeGenFunction::EmitAArch64MultiVersionResolver (
0 commit comments