BeMg updated this revision to Diff 552721.
BeMg added a comment.
Herald added a subscriber: sunshaoce.

Rebase and update testcase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D155935/new/

https://reviews.llvm.org/D155935

Files:
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGen/RISCV/riscv-fmv.c

Index: clang/test/CodeGen/RISCV/riscv-fmv.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/RISCV/riscv-fmv.c
@@ -0,0 +1,106 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --version 2
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zifencei \
+// RUN:  -target-feature +m -target-feature +a               \
+// RUN:  -target-feature +f -target-feature +d               \
+// RUN:  -emit-llvm %s -o - | FileCheck %s                   \
+// RUN:  --check-prefix=CHECK-IR
+
+__attribute__((target("arch=+v"))) void test1(void) {}
+__attribute__((target("arch=+v,+zbb"))) void test1(void) {}
+__attribute__((target("arch=+v,+zbb,+zicond1p0"))) void test1(void) {}
+__attribute__((target("arch=rv64gc"))) void test1(void) {}
+__attribute__((target("default"))) void test1(void) {}
+
+__attribute__((target("default"))) void test2(void) {}
+
+void test3() { test1(); test2(); }
+
+// CHECK-IR: $test1.resolver = comdat any
+// CHECK-IR: $test2.resolver = comdat any
+
+// CHECK-IR: @0 = private unnamed_addr constant [2 x i8] c"v\00", align 1
+// CHECK-IR: @1 = private unnamed_addr constant [6 x i8] c"v;zbb\00", align 1
+// CHECK-IR: @2 = private unnamed_addr constant [26 x i8] c"v;zbb;experimental-zicond\00", align 1
+// CHECK-IR: @3 = private unnamed_addr constant [25 x i8] c"m;a;f;d;c;zicsr;zifencei\00", align 1
+
+
+// CHECK-IR-LABEL: define dso_local void @test1.v
+// CHECK-IR-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK-IR-NEXT:  entry:
+// CHECK-IR-NEXT:    ret void
+//
+//
+// CHECK-IR-LABEL: define dso_local void @test1.zbb_v
+// CHECK-IR-SAME: () #[[ATTR1:[0-9]+]] {
+// CHECK-IR-NEXT:  entry:
+// CHECK-IR-NEXT:    ret void
+//
+//
+// CHECK-IR-LABEL: define dso_local void @test1.experimental-zicond_zbb_v
+// CHECK-IR-SAME: () #[[ATTR2:[0-9]+]] {
+// CHECK-IR-NEXT:  entry:
+// CHECK-IR-NEXT:    ret void
+//
+//
+// CHECK-IR-LABEL: define dso_local void @test1.zifencei_zicsr_m_f_d_c_a
+// CHECK-IR-SAME: () #[[ATTR3:[0-9]+]] {
+// CHECK-IR-NEXT:  entry:
+// CHECK-IR-NEXT:    ret void
+//
+//
+// CHECK-IR-LABEL: define dso_local void @test1
+// CHECK-IR-SAME: () #[[ATTR4:[0-9]+]] {
+// CHECK-IR-NEXT:  entry:
+// CHECK-IR-NEXT:    ret void
+//
+//
+// CHECK-IR-LABEL: define dso_local void @test2
+// CHECK-IR-SAME: () #[[ATTR4]] {
+// CHECK-IR-NEXT:  entry:
+// CHECK-IR-NEXT:    ret void
+//
+//
+// CHECK-IR-LABEL: define dso_local void @test3
+// CHECK-IR-SAME: () #[[ATTR4]] {
+// CHECK-IR-NEXT:  entry:
+// CHECK-IR-NEXT:    call void @test1.resolver()
+// CHECK-IR-NEXT:    call void @test2.resolver()
+// CHECK-IR-NEXT:    ret void
+//
+//
+// CHECK-IR-LABEL: define weak_odr void @test1.resolver() comdat {
+// CHECK-IR-NEXT:  resolver_entry:
+// CHECK-IR-NEXT:    [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB0:[0-9]+]])
+// CHECK-IR-NEXT:    br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-IR:       resolver_return:
+// CHECK-IR-NEXT:    musttail call void @test1.v()
+// CHECK-IR-NEXT:    ret void
+// CHECK-IR:       resolver_else:
+// CHECK-IR-NEXT:    [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB1:[0-9]+]])
+// CHECK-IR-NEXT:    br i1 [[TMP1]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK-IR:       resolver_return1:
+// CHECK-IR-NEXT:    musttail call void @test1.zbb_v()
+// CHECK-IR-NEXT:    ret void
+// CHECK-IR:       resolver_else2:
+// CHECK-IR-NEXT:    [[TMP2:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB2:[0-9]+]])
+// CHECK-IR-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK-IR:       resolver_return3:
+// CHECK-IR-NEXT:    musttail call void @test1.experimental-zicond_zbb_v()
+// CHECK-IR-NEXT:    ret void
+// CHECK-IR:       resolver_else4:
+// CHECK-IR-NEXT:    [[TMP3:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB3:[0-9]+]])
+// CHECK-IR-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]]
+// CHECK-IR:       resolver_return5:
+// CHECK-IR-NEXT:    musttail call void @test1.zifencei_zicsr_m_f_d_c_a()
+// CHECK-IR-NEXT:    ret void
+// CHECK-IR:       resolver_else6:
+// CHECK-IR-NEXT:    musttail call void @test1()
+// CHECK-IR-NEXT:    ret void
+//
+//
+// CHECK-IR-LABEL: define weak_odr void @test2.resolver() comdat {
+// CHECK-IR-NEXT:  resolver_entry:
+// CHECK-IR-NEXT:    musttail call void @test2()
+// CHECK-IR-NEXT:    ret void
+//
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3992,7 +3992,10 @@
             if (CurFD->getMultiVersionKind() == MultiVersionKind::Target) {
               const auto *TA = CurFD->getAttr<TargetAttr>();
               llvm::SmallVector<StringRef, 8> Feats;
-              TA->getAddedFeatures(Feats);
+              if (getTarget().getTriple().isRISCV())
+                Feats.push_back(TA->getFeaturesStr());
+              else
+                TA->getAddedFeatures(Feats);
               Options.emplace_back(cast<llvm::Function>(Func),
                                    TA->getArchitecture(), Feats);
             } else {
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -4886,6 +4886,10 @@
   void
   EmitAArch64MultiVersionResolver(llvm::Function *Resolver,
                                   ArrayRef<MultiVersionResolverOption> Options);
+  void
+  EmitRISCVMultiVersionResolver(llvm::Function *Resolver,
+                                ArrayRef<MultiVersionResolverOption> Options);
+  llvm::Value *EmitRISCVCheckFeatureFunc(std::string currFeats);
 
 private:
   QualType getVarArgType(const Expr *Arg);
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2728,7 +2728,10 @@
   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");
   }
@@ -2820,6 +2823,86 @@
   Builder.ClearInsertionPoint();
 }
 
+static std::string
+mergeRISCVTargetFeature(const std::vector<std::string> &Features) {
+  if (Features.empty())
+    return std::string();
+
+  std::string Rst = "";
+  for (unsigned i = 0; i < Features.size(); i++) {
+    Rst += Features[i].substr(1); // Remove prefix +/-
+    if (i != Features.size() - 1)
+      Rst += ";";
+  }
+  return Rst;
+}
+
+llvm::Value *
+CodeGenFunction::EmitRISCVCheckFeatureFunc(std::string CurrFeatStr) {
+  llvm::Constant *FeatStr = Builder.CreateGlobalString(CurrFeatStr);
+  llvm::Type *Args[] = {Int8PtrTy};
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(Builder.getInt1Ty(), Args, /*Variadic*/ false);
+  llvm::FunctionCallee Func =
+      CGM.CreateRuntimeFunction(FTy, "__riscv_ifunc_select");
+  cast<llvm::GlobalValue>(Func.getCallee())->setDSOLocal(true);
+  cast<llvm::GlobalValue>(Func.getCallee())
+      ->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+  return Builder.CreateCall(Func, FeatStr);
+}
+
+void CodeGenFunction::EmitRISCVMultiVersionResolver(
+    llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
+  bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc();
+
+  std::vector<MultiVersionResolverOption> CurrOptions(Options);
+
+  llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);
+  Builder.SetInsertPoint(CurBlock);
+
+  bool HasDefault = false;
+  int DefaultIndex = 0;
+  // Check the each candidate function.
+  for (unsigned Index = 0; Index < CurrOptions.size(); Index++) {
+    Builder.SetInsertPoint(CurBlock);
+
+    std::string CurrFeatStr = mergeRISCVTargetFeature(
+        getContext()
+            .getTargetInfo()
+            .parseTargetAttr(CurrOptions[Index].Conditions.Features[0])
+            .Features);
+
+    if (!CurrFeatStr.empty()) {
+      llvm::Value *Condition = EmitRISCVCheckFeatureFunc(CurrFeatStr);
+      llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver);
+      CGBuilderTy RetBuilder(*this, RetBlock);
+      CreateMultiVersionResolverReturn(CGM, Resolver, RetBuilder, CurrOptions[Index].Function,
+                                      SupportsIFunc);
+      CurBlock = createBasicBlock("resolver_else", Resolver);
+      Builder.CreateCondBr(Condition, RetBlock, CurBlock);
+    } else {
+      HasDefault = true;
+      DefaultIndex = Index;
+    }
+  }
+
+  // Finally, emit the default one.
+  if (HasDefault) {
+    Builder.SetInsertPoint(CurBlock);
+    CreateMultiVersionResolverReturn(
+        CGM, Resolver, Builder, CurrOptions[DefaultIndex].Function, SupportsIFunc);
+    return;
+  }
+
+  // If no generic/default, emit an unreachable.
+  Builder.SetInsertPoint(CurBlock);
+  llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
+  TrapCall->setDoesNotReturn();
+  TrapCall->setDoesNotThrow();
+  Builder.CreateUnreachable();
+  Builder.ClearInsertionPoint();
+}
+
 // Loc - where the diagnostic will point, where in the source code this
 //  alignment has failed.
 // SecondaryLoc - if present (will be present if sufficiently different from
Index: clang/include/clang/Basic/TargetInfo.h
===================================================================
--- clang/include/clang/Basic/TargetInfo.h
+++ clang/include/clang/Basic/TargetInfo.h
@@ -1409,7 +1409,7 @@
   /// Identify whether this target supports multiversioning of functions,
   /// which requires support for cpu_supports and cpu_is functionality.
   bool supportsMultiVersioning() const {
-    return getTriple().isX86() || getTriple().isAArch64();
+    return getTriple().isX86() || getTriple().isAArch64() || getTriple().isRISCV();
   }
 
   /// Identify whether this target supports IFuncs.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to