diff --git a/clang/docs/OpenCLSupport.rst b/clang/docs/OpenCLSupport.rst --- a/clang/docs/OpenCLSupport.rst +++ b/clang/docs/OpenCLSupport.rst @@ -339,7 +339,24 @@ .. _opencl_300: -OpenCL 3.0 Implementation Status +OpenCL C 3.0 Usage +================================ + +OpenCL C 3.0 language standard makes most OpenCL C 2.0 features optional. Optional +functionality in OpenCL C 3.0 is indicated with the presence of feature-test macros +(list of feature-test macros is `here `_). +Command-line flag :ref:`-cl-ext ` can be used to override features supported by a target. + +For cases when there is an associated extension for a specific feature (fp64 and 3d image writes) +user should specify both (extension and feature) in command-line flag: + + .. code-block:: console + + $ clang -cc1 -cl-std=CL3.0 -cl-ext=+cl_khr_fp64,+__opencl_c_fp64 ... + $ clang -cc1 -cl-std=CL3.0 -cl-ext=-cl_khr_fp64,-__opencl_c_fp64 ... + + +OpenCL C 3.0 Implementation Status ================================ The following table provides an overview of features in OpenCL C 3.0 and their diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -364,4 +364,7 @@ def warn_opencl_unsupported_core_feature : Warning< "%0 is a core feature in %select{OpenCL C|C++ for OpenCL}1 version %2 but not supported on this target">, InGroup, DefaultIgnore; + +def err_opencl_extension_and_feature_differs : Error< + "options %0 and %1 are set to different values">; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -118,7 +118,8 @@ "magnitude of floating-point constant too small for type %0; minimum is %1">, InGroup; def warn_double_const_requires_fp64 : Warning< - "double precision constant requires cl_khr_fp64, casting to single precision">; + "double precision constant requires %select{cl_khr_fp64|cl_khr_fp64 and __opencl_c_fp64}0, " + "casting to single precision">; def err_half_const_requires_fp16 : Error< "half precision constant requires cl_khr_fp16">; @@ -10027,6 +10028,8 @@ def ext_opencl_double_without_pragma : Extension< "Clang permits use of type 'double' regardless pragma if 'cl_khr_fp64' is" " supported">; +def err_opencl_double_requires_extension : Error< + "use of type 'double' requires %select{cl_khr_fp64|cl_khr_fp64 and __opencl_c_fp64}0 support">; def warn_opencl_generic_address_space_arg : Warning< "passing non-generic address space pointer to %0" " may cause dynamic conversion affecting performance">, diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -743,7 +743,20 @@ diagnoseNotSupportedCore(#Ext, __VA_ARGS__); #include "clang/Basic/OpenCLExtensions.def" - // For now assume that OpenCL target is always - // valid and just provide necessary diagnostics + // Validate that feature macros are set properly for OpenCL C 3.0. + // In other cases assume that target is always valid. + if (Opts.OpenCLCPlusPlus || Opts.OpenCLVersion < 300) + return true; + + // Feature and corresponding equivalent extension must be set + // simultaneously to the same value. + for (auto &ExtAndFeat : {std::make_pair("cl_khr_fp64", "__opencl_c_fp64")}) + if (hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.first) != + hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.second)) { + Diags.Report(diag::err_opencl_extension_and_feature_differs) + << ExtAndFeat.first << ExtAndFeat.second; + return false; + } + return true; } diff --git a/clang/lib/Basic/Targets/AMDGPU.h b/clang/lib/Basic/Targets/AMDGPU.h --- a/clang/lib/Basic/Targets/AMDGPU.h +++ b/clang/lib/Basic/Targets/AMDGPU.h @@ -292,6 +292,7 @@ bool IsAMDGCN = isAMDGCN(getTriple()); Opts["cl_khr_fp64"] = hasFP64(); + Opts["__opencl_c_fp64"] = hasFP64(); if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) { Opts["cl_khr_byte_addressable_store"] = true; diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h --- a/clang/lib/Basic/Targets/NVPTX.h +++ b/clang/lib/Basic/Targets/NVPTX.h @@ -136,6 +136,7 @@ Opts["__cl_clang_non_portable_kernel_param_types"] = true; Opts["cl_khr_fp64"] = true; + Opts["__opencl_c_fp64"] = true; Opts["cl_khr_byte_addressable_store"] = true; Opts["cl_khr_global_int32_base_atomics"] = true; Opts["cl_khr_global_int32_extended_atomics"] = true; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -135,8 +135,9 @@ // We should do it here because target knows nothing about // language options when it's being created. - if (getLangOpts().OpenCL) - getTarget().validateOpenCLTarget(getLangOpts(), getDiagnostics()); + if (getLangOpts().OpenCL && + !getTarget().validateOpenCLTarget(getLangOpts(), getDiagnostics())) + return false; // Inform the target of the language options. // FIXME: We shouldn't need to do this, the target should be immutable once diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3830,7 +3830,8 @@ } else if (getLangOpts().OpenCL && !getOpenCLOptions().isAvailableOption( "cl_khr_fp64", getLangOpts())) { // Impose single-precision float type when cl_khr_fp64 is not enabled. - Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64); + Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64) + << (getLangOpts().OpenCLVersion >= 300); Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get(); } } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1526,8 +1526,9 @@ case DeclSpec::TST_double: if (S.getLangOpts().OpenCL) { if (!S.getOpenCLOptions().isSupported("cl_khr_fp64", S.getLangOpts())) - S.Diag(DS.getTypeSpecTypeLoc(), diag::err_opencl_requires_extension) - << 0 << Context.DoubleTy << "cl_khr_fp64"; + S.Diag(DS.getTypeSpecTypeLoc(), + diag::err_opencl_double_requires_extension) + << (S.getLangOpts().OpenCLVersion >= 300); else if (!S.getOpenCLOptions().isAvailableOption("cl_khr_fp64", S.getLangOpts())) S.Diag(DS.getTypeSpecTypeLoc(), diag::ext_opencl_double_without_pragma); } diff --git a/clang/test/CodeGenOpenCL/printf.cl b/clang/test/CodeGenOpenCL/printf.cl --- a/clang/test/CodeGenOpenCL/printf.cl +++ b/clang/test/CodeGenOpenCL/printf.cl @@ -1,10 +1,12 @@ // RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=-+cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=FP64,ALL %s // RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=-cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=NOFP64,ALL %s +// RUN: %clang_cc1 -cl-std=CL3.0 -cl-ext=+__opencl_c_fp64,+cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=FP64,ALL %s +// RUN: %clang_cc1 -cl-std=CL3.0 -cl-ext=-__opencl_c_fp64,-cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=NOFP64,ALL %s typedef __attribute__((ext_vector_type(2))) float float2; typedef __attribute__((ext_vector_type(2))) half half2; -#ifdef cl_khr_fp64 +#if defined(cl_khr_fp64) || defined(__opencl_c_fp64) typedef __attribute__((ext_vector_type(2))) double double2; #endif @@ -28,7 +30,7 @@ printf("%v2hf", arg); } -#ifdef cl_khr_fp64 +#if defined(cl_khr_fp64) || defined(__opencl_c_fp64) // FP64-LABEL: @test_printf_double2( // FP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.2, i32 0, i32 0), <2 x double> %0) kernel void test_printf_double2(double2 arg) { diff --git a/clang/test/Misc/opencl-c-3.0.incorrect_options.cl b/clang/test/Misc/opencl-c-3.0.incorrect_options.cl new file mode 100644 --- /dev/null +++ b/clang/test/Misc/opencl-c-3.0.incorrect_options.cl @@ -0,0 +1,4 @@ +// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=-__opencl_c_fp64,+cl_khr_fp64 %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_fp64,-cl_khr_fp64 %s 2>&1 | FileCheck %s + +// CHECK: error: options cl_khr_fp64 and __opencl_c_fp64 are set to different values diff --git a/clang/test/SemaOpenCL/extensions.cl b/clang/test/SemaOpenCL/fp64-fp16-options.cl rename from clang/test/SemaOpenCL/extensions.cl rename to clang/test/SemaOpenCL/fp64-fp16-options.cl --- a/clang/test/SemaOpenCL/extensions.cl +++ b/clang/test/SemaOpenCL/fp64-fp16-options.cl @@ -5,6 +5,7 @@ // Test with a target not supporting fp64. // RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -DNOFP64 -DNOFP16 +// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -DNOFP64 -DNOFP16 // Test with some extensions enabled or disabled by cmd-line args // @@ -16,12 +17,18 @@ // RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all // RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all,-cl_khr_fp64 -DNOFP64 // RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=-all,+cl_khr_fp64 -DNOFP16 +// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -DNOFP64 -DNOFP16 +// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all -DFP64 +// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all,-__opencl_c_fp64,-cl_khr_fp64 -DNOFP64 // // Concatenating // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-cl_khr_fp64 -cl-ext=+cl_khr_fp64 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-cl_khr_fp64,+cl_khr_fp64 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -cl-ext=+cl_khr_fp64 -cl-ext=+cl_khr_fp16 -cl-ext=-cl_khr_fp64 -DNOFP64 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -cl-ext=+cl_khr_fp64,-cl_khr_fp64,+cl_khr_fp16 -DNOFP64 +// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-__opencl_c_fp64,-cl_khr_fp64 -cl-ext=+__opencl_c_fp64,+cl_khr_fp64 -DFP64 +// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-__opencl_c_fp64,+__opencl_c_fp64,+cl_khr_fp64 -DFP64 +// RUN: %clang_cc1 -cl-std=CL3.0 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-__opencl_c_fp64,-cl_khr_fp64 -DNOFP64 // Test with -finclude-default-header, which includes opencl-c.h. opencl-c.h // disables all extensions by default, but supported core extensions for a @@ -85,18 +92,30 @@ void f2(void) { double d; #ifdef NOFP64 -// expected-error@-2{{use of type 'double' requires cl_khr_fp64 support}} +#if (defined(__OPENCL_C_VERSION__) && __OPENCL_C_VERSION__ >= 300) +// expected-error@-3{{use of type 'double' requires cl_khr_fp64 and __opencl_c_fp64 support}} +#else +// expected-error@-5{{use of type 'double' requires cl_khr_fp64 support}} +#endif #endif typedef double double4 __attribute__((ext_vector_type(4))); double4 d4 = {0.0f, 2.0f, 3.0f, 1.0f}; #ifdef NOFP64 -// expected-error@-3 {{use of type 'double' requires cl_khr_fp64 support}} +#if (defined(__OPENCL_C_VERSION__) && __OPENCL_C_VERSION__ >= 300) +// expected-error@-4 {{use of type 'double' requires cl_khr_fp64 and __opencl_c_fp64 support}} +#else +// expected-error@-6 {{use of type 'double' requires cl_khr_fp64 support}} +#endif #endif (void) 1.0; #ifdef NOFP64 -// expected-warning@-2{{double precision constant requires cl_khr_fp64, casting to single precision}} +#if (defined(__OPENCL_C_VERSION__) && __OPENCL_C_VERSION__ >= 300) +// expected-warning@-3{{double precision constant requires cl_khr_fp64 and __opencl_c_fp64, casting to single precision}} +#else +// expected-warning@-5{{double precision constant requires cl_khr_fp64, casting to single precision}} +#endif #endif }