svenvh created this revision.
svenvh added a reviewer: Anastasia.
svenvh added a project: clang.
Herald added subscribers: ldrumm, yaxunl.
svenvh requested review of this revision.
Herald added a subscriber: cfe-commits.

Add functionality to assign extensions to types in `OpenCLBuiltins.td` and use 
that information to filter candidates that should not be exposed if a type is 
not available.

Most of the changes affect the addition of scalar base types into the `QT` 
vector in the generated `OCL2Qual` function (that is, the switch statement as 
described in step 1 in the `OCL2Qual` top comment).  For types that are 
associated with an extension, the QualType is now added only if the 
corresponding extension macro is defined.

The old code was as follows for the `FGenTypeN` GenericType, which represents 
all floating point types for all vector sizes.

  case OCLT_FGenTypeN:
    QT.append({Context.FloatTy, Context.DoubleTy, Context.HalfTy, 
Context.FloatTy, Context.DoubleTy, Context.HalfTy, Context.FloatTy, ...
    GenTypeNumTypes = 3;
    GenVectorSizes = ListVecAndScalar;
    break;

With this patch, the generated code becomes:

  case OCLT_FGenTypeN: {
    SmallVector<QualType, 3> TypeList;
    TypeList.push_back(Context.FloatTy);
    if (S.getPreprocessor().isMacroDefined("cl_khr_fp64")) {
      TypeList.push_back(Context.DoubleTy);
    }
    if (S.getPreprocessor().isMacroDefined("cl_khr_fp16")) {
      TypeList.push_back(Context.HalfTy);
    }
    GenTypeNumTypes = TypeList.size();
    QT.reserve(18);
    for (unsigned I = 0; I < 6; I++) {
      QT.append(TypeList);
    }
    GenVectorSizes = ListVecAndScalar;
    break;
  }


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D100209

Files:
  clang/lib/Sema/OpenCLBuiltins.td
  clang/lib/Sema/SemaLookup.cpp
  clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl
  clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp

Index: clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
===================================================================
--- clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
+++ clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
@@ -705,34 +705,45 @@
 
   // Switch cases for generic types.
   for (const auto *GenType : Records.getAllDerivedDefinitions("GenericType")) {
-    OS << "    case OCLT_" << GenType->getValueAsString("Name") << ":\n";
-    OS << "      QT.append({";
+    OS << "    case OCLT_" << GenType->getValueAsString("Name") << ": {\n";
 
     // Build the Cartesian product of (vector sizes) x (types).  Only insert
     // the plain scalar types for now; other type information such as vector
     // size and type qualifiers will be added after the switch statement.
-    for (unsigned I = 0; I < GenType->getValueAsDef("VectorList")
-                                 ->getValueAsListOfInts("List")
-                                 .size();
-         I++) {
-      for (const auto *T :
-           GenType->getValueAsDef("TypeList")->getValueAsListOfDefs("List")) {
-        OS << T->getValueAsDef("QTExpr")->getValueAsString("TypeExpr") << ", ";
+    std::vector<Record *> BaseTypes =
+        GenType->getValueAsDef("TypeList")->getValueAsListOfDefs("List");
+
+    // Collect all QualTypes for a single vector size into TypeList.
+    OS << "      SmallVector<QualType, " << BaseTypes.size() << "> TypeList;\n";
+    for (const auto *T : BaseTypes) {
+      StringRef Ext =
+          T->getValueAsDef("Extension")->getValueAsString("ExtName");
+      if (!Ext.empty()) {
+        OS << "      if (S.getPreprocessor().isMacroDefined(\"" << Ext
+           << "\")) {\n  ";
+      }
+      OS << "      TypeList.push_back("
+         << T->getValueAsDef("QTExpr")->getValueAsString("TypeExpr") << ");\n";
+      if (!Ext.empty()) {
+        OS << "      }\n";
       }
     }
-    OS << "});\n";
-    // GenTypeNumTypes is the number of types in the GenType
-    // (e.g. float/double/half).
-    OS << "      GenTypeNumTypes = "
-       << GenType->getValueAsDef("TypeList")->getValueAsListOfDefs("List")
-              .size()
-       << ";\n";
+    OS << "      GenTypeNumTypes = TypeList.size();\n";
+
+    // Duplicate the TypeList for every vector size.
+    std::vector<int64_t> VectorList =
+        GenType->getValueAsDef("VectorList")->getValueAsListOfInts("List");
+    OS << "      QT.reserve(" << VectorList.size() * BaseTypes.size() << ");\n"
+       << "      for (unsigned I = 0; I < " << VectorList.size() << "; I++) {\n"
+       << "        QT.append(TypeList);\n"
+       << "      }\n";
+
     // GenVectorSizes is the list of vector sizes for this GenType.
-    // QT contains GenTypeNumTypes * #GenVectorSizes elements.
     OS << "      GenVectorSizes = List"
        << GenType->getValueAsDef("VectorList")->getValueAsString("Name")
-       << ";\n";
-    OS << "      break;\n";
+       << ";\n"
+       << "      break;\n"
+       << "    }\n";
   }
 
   // Switch cases for non generic, non image types (int, int4, float, ...).
@@ -755,9 +766,20 @@
     if (QT->getValueAsBit("IsAbstract") == 1)
       continue;
     // Emit the cases for non generic, non image types.
-    OS << "    case OCLT_" << T->getValueAsString("Name") << ":\n"
-       << "      QT.push_back(" << QT->getValueAsString("TypeExpr") << ");\n"
-       << "      break;\n";
+    OS << "    case OCLT_" << T->getValueAsString("Name") << ":\n";
+
+    StringRef Ext = T->getValueAsDef("Extension")->getValueAsString("ExtName");
+    // If this type depends on an extension, ensure the extension macro is
+    // defined.
+    if (!Ext.empty()) {
+      OS << "      if (S.getPreprocessor().isMacroDefined(\"" << Ext
+         << "\")) {\n  ";
+    }
+    OS << "      QT.push_back(" << QT->getValueAsString("TypeExpr") << ");\n";
+    if (!Ext.empty()) {
+      OS << "      }\n";
+    }
+    OS << "      break;\n";
   }
 
   // End of switch statement.
Index: clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl
===================================================================
--- clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl
+++ clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl
@@ -6,6 +6,7 @@
 // RUN: %clang_cc1 %s -triple spir -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL2.0 -fdeclare-opencl-builtins -finclude-default-header
 // RUN: %clang_cc1 %s -triple spir -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CLC++ -fdeclare-opencl-builtins -DNO_HEADER
 // RUN: %clang_cc1 %s -triple spir -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CLC++ -fdeclare-opencl-builtins -finclude-default-header
+// RUN: %clang_cc1 %s -triple spir -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL2.0 -fdeclare-opencl-builtins -finclude-default-header -cl-ext=-cl_khr_fp64 -DNO_FP64
 
 // Test the -fdeclare-opencl-builtins option.  This is not a completeness
 // test, so it should not test for all builtins defined by OpenCL.  Instead
@@ -122,15 +123,19 @@
 #endif
 
 kernel void basic_conversion() {
-  double d;
   float f;
   char2 c2;
   long2 l2;
   float4 f4;
   int4 i4;
 
+#ifdef NO_FP64
+  (void)convert_double_rtp(f);
+  // expected-error@-1{{implicit declaration of function 'convert_double_rtp' is invalid in OpenCL}}
+#else
+  double d;
   f = convert_float(d);
-  d = convert_double_rtp(f);
+#endif
   l2 = convert_long2_rtz(c2);
   i4 = convert_int4_sat(f4);
 }
@@ -271,3 +276,13 @@
 // expected-error@-2{{implicit declaration of function 'get_enqueued_local_size' is invalid in OpenCL}}
 #endif
 }
+
+#ifdef NO_FP64
+void test_extension_types(char2 c2) {
+  // We should see 6 candidates for float and half types, and none for double types.
+  int i = isnan(c2);
+  // expected-error@-1{{no matching function for call to 'isnan'}}
+  // expected-note@-2 6 {{candidate function not viable: no known conversion from '__private char2' (vector of 2 'char' values) to 'float}}
+  // expected-note@-3 6 {{candidate function not viable: no known conversion from '__private char2' (vector of 2 'char' values) to 'half}}
+}
+#endif
Index: clang/lib/Sema/SemaLookup.cpp
===================================================================
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -759,11 +759,17 @@
       Context.getDefaultCallingConvention(false, false, true));
   PI.Variadic = false;
 
+  if (RetTypes.size() == 0)
+    return;
+
   // Create FunctionTypes for each (gen)type.
   for (unsigned IGenType = 0; IGenType < GenTypeMaxCnt; IGenType++) {
     SmallVector<QualType, 5> ArgList;
 
     for (unsigned A = 0; A < ArgTypes.size(); A++) {
+      if (ArgTypes[A].size() == 0)
+        return;
+
       // Builtins such as "max" have an "sgentype" argument that represents
       // the corresponding scalar type of a gentype.  The number of gentypes
       // must be a multiple of the number of sgentypes.
Index: clang/lib/Sema/OpenCLBuiltins.td
===================================================================
--- clang/lib/Sema/OpenCLBuiltins.td
+++ clang/lib/Sema/OpenCLBuiltins.td
@@ -50,6 +50,14 @@
 // Extension associated to a builtin function.
 class FunctionExtension<string _Ext> : AbstractExtension<_Ext>;
 
+// Extension associated to a type.
+class TypeExtension<string _Ext> : AbstractExtension<_Ext>;
+
+// TypeExtension definitions.
+def NoTypeExt   : TypeExtension<"">;
+def Fp16TypeExt : TypeExtension<"cl_khr_fp16">;
+def Fp64TypeExt : TypeExtension<"cl_khr_fp64">;
+
 // FunctionExtension definitions.
 def FuncExtNone                          : FunctionExtension<"">;
 def FuncExtKhrSubgroups                  : FunctionExtension<"cl_khr_subgroups">;
@@ -119,6 +127,8 @@
   string AccessQualifier = "";
   // Address space.
   string AddrSpace = DefaultAS.Name;
+  // Extension that needs to be enabled to expose a builtin that uses this type.
+  TypeExtension Extension = NoTypeExt;
 }
 
 // OpenCL vector types (e.g. int2, int3, int16, float8, ...).
@@ -130,6 +140,7 @@
   let IsConst = _Ty.IsConst;
   let IsVolatile = _Ty.IsVolatile;
   let AddrSpace = _Ty.AddrSpace;
+  let Extension = _Ty.Extension;
 }
 
 // OpenCL pointer types (e.g. int*, float*, ...).
@@ -142,6 +153,7 @@
   let IsConst = _Ty.IsConst;
   let IsVolatile = _Ty.IsVolatile;
   let AccessQualifier = _Ty.AccessQualifier;
+  let Extension = _Ty.Extension;
 }
 
 // OpenCL const types (e.g. const int).
@@ -153,6 +165,7 @@
   let IsVolatile = _Ty.IsVolatile;
   let AccessQualifier = _Ty.AccessQualifier;
   let AddrSpace = _Ty.AddrSpace;
+  let Extension = _Ty.Extension;
 }
 
 // OpenCL volatile types (e.g. volatile int).
@@ -164,6 +177,7 @@
   let IsConst = _Ty.IsConst;
   let AccessQualifier = _Ty.AccessQualifier;
   let AddrSpace = _Ty.AddrSpace;
+  let Extension = _Ty.Extension;
 }
 
 // OpenCL image types (e.g. image2d).
@@ -176,6 +190,7 @@
   let IsConst = _Ty.IsConst;
   let IsVolatile = _Ty.IsVolatile;
   let AddrSpace = _Ty.AddrSpace;
+  let Extension = _Ty.Extension;
 }
 
 // OpenCL enum type (e.g. memory_scope).
@@ -277,8 +292,12 @@
 def Long      : Type<"long",      QualType<"Context.LongTy">>;
 def ULong     : Type<"ulong",     QualType<"Context.UnsignedLongTy">>;
 def Float     : Type<"float",     QualType<"Context.FloatTy">>;
-def Double    : Type<"double",    QualType<"Context.DoubleTy">>;
-def Half      : Type<"half",      QualType<"Context.HalfTy">>;
+let Extension = Fp64TypeExt in {
+  def Double    : Type<"double",    QualType<"Context.DoubleTy">>;
+}
+let Extension = Fp16TypeExt in {
+  def Half      : Type<"half",      QualType<"Context.HalfTy">>;
+}
 def Size      : Type<"size_t",    QualType<"Context.getSizeType()">>;
 def PtrDiff   : Type<"ptrdiff_t", QualType<"Context.getPointerDiffType()">>;
 def IntPtr    : Type<"intptr_t",  QualType<"Context.getIntPtrType()">>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to