[llvm-branch-commits] [clang] c28e32d - [RISCV] Lazily add RVV C intrinsics.

Hsiangkai Wang via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Oct 10 05:35:04 PDT 2021


Author: Hsiangkai Wang
Date: 2021-10-10T20:22:30+08:00
New Revision: c28e32d20fd4a334e49f64a041cbefe7cd1e8ce3

URL: https://github.com/llvm/llvm-project/commit/c28e32d20fd4a334e49f64a041cbefe7cd1e8ce3
DIFF: https://github.com/llvm/llvm-project/commit/c28e32d20fd4a334e49f64a041cbefe7cd1e8ce3.diff

LOG: [RISCV] Lazily add RVV C intrinsics.

Leverage the method OpenCL uses that adds C intrinsics when the lookup
failed. There is no need to define C intrinsics in the header file any
more. It could help to avoid the large header file to speed up the
compilation of RVV source code. Besides that, only the C intrinsics used
by the users will be added into the declaration table.

Added: 
    

Modified: 
    clang/include/clang/Basic/CMakeLists.txt
    clang/lib/Sema/SemaLookup.cpp
    clang/utils/TableGen/RISCVVEmitter.cpp
    clang/utils/TableGen/TableGen.cpp
    clang/utils/TableGen/TableGenBackends.h
    llvm/docs/CommandGuide/tblgen.rst

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt
index 8cd891385a483..b930842ae8cfd 100644
--- a/clang/include/clang/Basic/CMakeLists.txt
+++ b/clang/include/clang/Basic/CMakeLists.txt
@@ -90,3 +90,6 @@ clang_tablegen(riscv_vector_builtins.inc -gen-riscv-vector-builtins
 clang_tablegen(riscv_vector_builtin_cg.inc -gen-riscv-vector-builtin-codegen
   SOURCE riscv_vector.td
   TARGET ClangRISCVVectorBuiltinCG)
+clang_tablegen(riscv_vector_builtin_sema.inc -gen-riscv-vector-builtin-sema
+  SOURCE riscv_vector.td
+  TARGET ClangRISCVVectorBuiltinSema)

diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index db6a01543d76a..28515f461545a 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -23,6 +23,8 @@
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/Preprocessor.h"
@@ -48,6 +50,7 @@
 #include <vector>
 
 #include "OpenCLBuiltins.inc"
+#include "clang/Basic/riscv_vector_builtin_sema.inc"
 
 using namespace clang;
 using namespace sema;
@@ -895,6 +898,68 @@ static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR,
     LR.resolveKind();
 }
 
+static bool InsertRVVBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR,
+                                                  IdentifierInfo *II,
+                                                  const TargetInfo &TI,
+                                                  Preprocessor &PP) {
+  bool HasF = TI.hasFeature("f");
+  bool HasD = TI.hasFeature("d");
+  bool HasZfh = TI.hasFeature("experimental-zfh");
+  bool HasZvamo = TI.hasFeature("experimental-zvamo");
+  unsigned Features = 0;
+  if (HasF)
+    Features |= RISCVFeature_F;
+  if (HasD)
+    Features |= RISCVFeature_D;
+  if (HasZfh)
+    Features |= RISCVFeature_ZFH;
+  if (HasZvamo)
+    Features |= RISCVFeature_ZVAMO;
+
+  const RVVIntrinsicInfo *Intrinsic = std::find_if(
+      std::begin(RVVIntrinsicInfos), std::end(RVVIntrinsicInfos),
+      [II](const RVVIntrinsicInfo &RVVII) {
+        return std::strcmp(RVVII.TargetName, II->getName().data()) == 0;
+      });
+  if (Intrinsic != std::end(RVVIntrinsicInfos)) {
+    if ((Intrinsic->RequireFeatures & Features) != Intrinsic->RequireFeatures)
+      return false;
+    if (NamedDecl *FD =
+            S.LazilyCreateBuiltin(II, Intrinsic->TargetBuiltinID, S.TUScope,
+                                  LR.isForRedeclaration(), LR.getNameLoc())) {
+      LR.addDecl(FD);
+      return true;
+    }
+  }
+
+  bool Found = false;
+  std::for_each(
+      std::begin(RVVIntrinsicOverloadInfos),
+      std::end(RVVIntrinsicOverloadInfos),
+      [&S, &LR, II, &PP, &Found,
+       Features](const RVVIntrinsicOverloadInfo &RVVII) {
+        if (std::strcmp(RVVII.OverloadName, II->getName().data()) == 0) {
+          if ((RVVII.RequireFeatures & Features) != RVVII.RequireFeatures)
+            return;
+          if (NamedDecl *FD = S.LazilyCreateBuiltin(
+                  II, RVVII.TargetBuiltinID, S.TUScope, LR.isForRedeclaration(),
+                  LR.getNameLoc())) {
+            auto &IntrinsicII = PP.getIdentifierTable().get(RVVII.TargetName);
+            FD->addAttr(OverloadableAttr::CreateImplicit(S.Context));
+            FD->addAttr(
+                BuiltinAliasAttr::CreateImplicit(S.Context, &IntrinsicII));
+            LR.addDecl(FD);
+            Found = true;
+          }
+        }
+      });
+
+  if (Found)
+    LR.resolveKind();
+
+  return Found;
+}
+
 /// Lookup a builtin function, when name lookup would otherwise
 /// fail.
 bool Sema::LookupBuiltin(LookupResult &R) {
@@ -927,6 +992,12 @@ bool Sema::LookupBuiltin(LookupResult &R) {
         }
       }
 
+      const TargetInfo &TI = Context.getTargetInfo();
+      if (TI.getTriple().isRISCV() && TI.hasFeature("experimental-v")) {
+        if (InsertRVVBuiltinDeclarationsFromTable(*this, R, II, TI, PP))
+          return true;
+      }
+
       // If this is a builtin on this (or all) targets, create the decl.
       if (unsigned BuiltinID = II->getBuiltinID()) {
         // In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined

diff  --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp
index 467a8b2f52ac6..ee3a33cfde595 100644
--- a/clang/utils/TableGen/RISCVVEmitter.cpp
+++ b/clang/utils/TableGen/RISCVVEmitter.cpp
@@ -194,12 +194,6 @@ class RVVIntrinsic {
   // Emit the code block for switch body in EmitRISCVBuiltinExpr, it should
   // init the RVVIntrinsic ID and IntrinsicTypes.
   void emitCodeGenSwitchBody(raw_ostream &o) const;
-
-  // Emit the macros for mapping C/C++ intrinsic function to builtin functions.
-  void emitIntrinsicMacro(raw_ostream &o) const;
-
-  // Emit the mangled function definition.
-  void emitMangledFuncDef(raw_ostream &o) const;
 };
 
 class RVVEmitter {
@@ -222,6 +216,9 @@ class RVVEmitter {
   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
   void createCodeGen(raw_ostream &o);
 
+  /// Emit all the information needed by SemaLookup.cpp.
+  void createSema(raw_ostream &o);
+
   std::string getSuffixStr(char Type, int Log2LMUL, StringRef Prototypes);
 
 private:
@@ -235,15 +232,6 @@ class RVVEmitter {
                                   ArrayRef<std::string> PrototypeSeq);
   Optional<RVVTypePtr> computeType(BasicType BT, int Log2LMUL, StringRef Proto);
 
-  /// Emit Acrh predecessor definitions and body, assume the element of Defs are
-  /// sorted by extension.
-  void emitArchMacroAndBody(
-      std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &o,
-      std::function<void(raw_ostream &, const RVVIntrinsic &)>);
-
-  // Emit the architecture preprocessor definitions. Return true when emits
-  // non-empty string.
-  bool emitExtDefStr(uint8_t Extensions, raw_ostream &o);
   // Slice Prototypes string into sub prototype string and process each sub
   // prototype string individually in the Handler.
   void parsePrototypes(StringRef Prototypes,
@@ -836,36 +824,6 @@ void RVVIntrinsic::emitCodeGenSwitchBody(raw_ostream &OS) const {
   OS << "  break;\n";
 }
 
-void RVVIntrinsic::emitIntrinsicMacro(raw_ostream &OS) const {
-  OS << "#define " << getName() << "(";
-  if (!InputTypes.empty()) {
-    ListSeparator LS;
-    for (unsigned i = 0, e = InputTypes.size(); i != e; ++i)
-      OS << LS << "op" << i;
-  }
-  OS << ") \\\n";
-  OS << "__builtin_rvv_" << getName() << "(";
-  if (!InputTypes.empty()) {
-    ListSeparator LS;
-    for (unsigned i = 0, e = InputTypes.size(); i != e; ++i)
-      OS << LS << "(" << InputTypes[i]->getTypeStr() << ")(op" << i << ")";
-  }
-  OS << ")\n";
-}
-
-void RVVIntrinsic::emitMangledFuncDef(raw_ostream &OS) const {
-  OS << "__attribute__((clang_builtin_alias(";
-  OS << "__builtin_rvv_" << getName() << ")))\n";
-  OS << OutputType->getTypeStr() << " " << getMangledName() << "(";
-  // Emit function arguments
-  if (!InputTypes.empty()) {
-    ListSeparator LS;
-    for (unsigned i = 0; i < InputTypes.size(); ++i)
-      OS << LS << InputTypes[i]->getTypeStr() << " op" << i;
-  }
-  OS << ");\n\n";
-}
-
 //===----------------------------------------------------------------------===//
 // RVVEmitter implementation
 //===----------------------------------------------------------------------===//
@@ -960,24 +918,8 @@ void RVVEmitter::createHeader(raw_ostream &OS) {
                      return A->getRISCVExtensions() < B->getRISCVExtensions();
                    });
 
-  // Print intrinsic functions with macro
-  emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
-    Inst.emitIntrinsicMacro(OS);
-  });
-
   OS << "#define __riscv_v_intrinsic_overloading 1\n";
 
-  // Print Overloaded APIs
-  OS << "#define __rvv_overloaded static inline "
-        "__attribute__((__always_inline__, __nodebug__, __overloadable__))\n";
-
-  emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
-    if (!Inst.isMask() && !Inst.hasNoMaskedOverloaded())
-      return;
-    OS << "__rvv_overloaded ";
-    Inst.emitMangledFuncDef(OS);
-  });
-
   OS << "\n#ifdef __cplusplus\n";
   OS << "}\n";
   OS << "#endif // __riscv_vector\n";
@@ -1169,41 +1111,65 @@ Optional<RVVTypePtr> RVVEmitter::computeType(BasicType BT, int Log2LMUL,
   return llvm::None;
 }
 
-void RVVEmitter::emitArchMacroAndBody(
-    std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &OS,
-    std::function<void(raw_ostream &, const RVVIntrinsic &)> PrintBody) {
-  uint8_t PrevExt = (*Defs.begin())->getRISCVExtensions();
-  bool NeedEndif = emitExtDefStr(PrevExt, OS);
-  for (auto &Def : Defs) {
-    uint8_t CurExt = Def->getRISCVExtensions();
-    if (CurExt != PrevExt) {
-      if (NeedEndif)
-        OS << "#endif\n\n";
-      NeedEndif = emitExtDefStr(CurExt, OS);
-      PrevExt = CurExt;
-    }
-    if (Def->hasAutoDef())
-      PrintBody(OS, *Def);
+static void emitFeatureCheckStr(uint8_t Extents, raw_ostream &OS) {
+  if (Extents == RISCVExtension::Basic) {
+    OS << 0;
+    return;
   }
-  if (NeedEndif)
-    OS << "#endif\n\n";
-}
-
-bool RVVEmitter::emitExtDefStr(uint8_t Extents, raw_ostream &OS) {
-  if (Extents == RISCVExtension::Basic)
-    return false;
-  OS << "#if ";
-  ListSeparator LS(" && ");
+  ListSeparator LS("|");
   if (Extents & RISCVExtension::F)
-    OS << LS << "defined(__riscv_f)";
+    OS << LS << "RISCVFeature_F";
   if (Extents & RISCVExtension::D)
-    OS << LS << "defined(__riscv_d)";
+    OS << LS << "RISCVFeature_D";
   if (Extents & RISCVExtension::Zfh)
-    OS << LS << "defined(__riscv_zfh)";
+    OS << LS << "RISCVFeature_ZFH";
   if (Extents & RISCVExtension::Zvamo)
-    OS << LS << "defined(__riscv_zvamo)";
-  OS << "\n";
-  return true;
+    OS << LS << "RISCVFeature_ZVAMO";
+}
+
+void RVVEmitter::createSema(raw_ostream &OS) {
+  OS << "enum RISCVFeatures {\n";
+  OS << "  RISCVFeature_F = 1 << 1,\n";
+  OS << "  RISCVFeature_D = 1 << 2,\n";
+  OS << "  RISCVFeature_ZFH = 1 << 3,\n";
+  OS << "  RISCVFeature_ZVAMO = 1 << 4,\n";
+  OS << "};\n\n";
+
+  OS << "struct RVVIntrinsicInfo {\n";
+  OS << "  const char *TargetName;\n";
+  OS << "  unsigned TargetBuiltinID;\n";
+  OS << "  unsigned RequireFeatures;\n";
+  OS << "};\n\n";
+
+  OS << "struct RVVIntrinsicOverloadInfo {\n";
+  OS << "  const char *TargetName;\n";
+  OS << "  const char *OverloadName;\n";
+  OS << "  unsigned TargetBuiltinID;\n";
+  OS << "  unsigned RequireFeatures;\n";
+  OS << "};\n\n";
+
+  std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
+  createRVVIntrinsics(Defs);
+  OS << "static const RVVIntrinsicInfo RVVIntrinsicInfos[] = {\n";
+  for (auto &Def : Defs) {
+    OS << "  {\"" << Def->getName() << "\", ";
+    OS << "RISCV::BI__builtin_rvv_" << Def->getName() << ", ";
+    emitFeatureCheckStr(Def->getRISCVExtensions(), OS);
+    OS << "},\n";
+  }
+  OS << "};\n\n";
+
+  OS << "static const RVVIntrinsicOverloadInfo RVVIntrinsicOverloadInfos[] = {\n";
+  for (auto &Def : Defs) {
+    if (!Def->isMask() && !Def->hasNoMaskedOverloaded())
+      continue;
+    OS << "  {\"__builtin_rvv_" << Def->getName() << "\", ";
+    OS << "\"" << Def->getMangledName() << "\", ";
+    OS << "RISCV::BI__builtin_rvv_" << Def->getName() << ", ";
+    emitFeatureCheckStr(Def->getRISCVExtensions(), OS);
+    OS << "},\n";
+  }
+  OS << "};\n\n";
 }
 
 namespace clang {
@@ -1219,4 +1185,8 @@ void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
   RVVEmitter(Records).createCodeGen(OS);
 }
 
+void EmitRVVBuiltinSema(RecordKeeper &Records, raw_ostream &OS) {
+  RVVEmitter(Records).createSema(OS);
+}
+
 } // End namespace clang

diff  --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp
index 55d62fa9f9bdc..a3fd5a07d0fb6 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -86,6 +86,7 @@ enum ActionType {
   GenRISCVVectorHeader,
   GenRISCVVectorBuiltins,
   GenRISCVVectorBuiltinCG,
+  GenRISCVVectorBuiltinSema,
   GenAttrDocs,
   GenDiagDocs,
   GenOptDocs,
@@ -237,6 +238,8 @@ cl::opt<ActionType> Action(
                    "Generate riscv_vector_builtins.inc for clang"),
         clEnumValN(GenRISCVVectorBuiltinCG, "gen-riscv-vector-builtin-codegen",
                    "Generate riscv_vector_builtin_cg.inc for clang"),
+        clEnumValN(GenRISCVVectorBuiltinSema, "gen-riscv-vector-builtin-sema",
+                   "Generate riscv_vector_builtin_sema.inc for clang"),
         clEnumValN(GenAttrDocs, "gen-attr-docs",
                    "Generate attribute documentation"),
         clEnumValN(GenDiagDocs, "gen-diag-docs",
@@ -446,6 +449,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
   case GenRISCVVectorBuiltinCG:
     EmitRVVBuiltinCG(Records, OS);
     break;
+  case GenRISCVVectorBuiltinSema:
+    EmitRVVBuiltinSema(Records, OS);
+    break;
   case GenAttrDocs:
     EmitClangAttrDocs(Records, OS);
     break;

diff  --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h
index 6930f242681f2..3696fb294510a 100644
--- a/clang/utils/TableGen/TableGenBackends.h
+++ b/clang/utils/TableGen/TableGenBackends.h
@@ -109,6 +109,7 @@ void EmitMveBuiltinAliases(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 void EmitRVVHeader(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 void EmitRVVBuiltins(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 void EmitRVVBuiltinCG(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitRVVBuiltinSema(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 
 void EmitCdeHeader(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 void EmitCdeBuiltinDef(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);

diff  --git a/llvm/docs/CommandGuide/tblgen.rst b/llvm/docs/CommandGuide/tblgen.rst
index a7c254901392a..eac9cce471610 100644
--- a/llvm/docs/CommandGuide/tblgen.rst
+++ b/llvm/docs/CommandGuide/tblgen.rst
@@ -348,6 +348,10 @@ clang-tblgen Options
 
   Generate ``riscv_vector_builtin_cg.inc`` for Clang.
 
+.. option:: -gen-riscv-vector-builtin-sema
+
+  Generate ``riscv_vector_builtin_sema.inc`` for Clang.
+
 .. option:: -gen-attr-docs
 
   Generate attribute documentation.


        


More information about the llvm-branch-commits mailing list