azabaznov created this revision. azabaznov added reviewers: Anastasia, yaxunl, svenvh. Herald added a subscriber: ldrumm. azabaznov requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
This feature requires support of __opencl_c_generic_address_space, so diagnostics for that is provided as well. The main problem with device enqueue feature is that block literal for block with no captures emitted in global address space. This is not correct if feature for program scope, global variables are not supported. This patch: - Disables generation blocks with constant address space (yet) if feature for program scope global variables is not supported, since such blocks always have no captures. Global blocks are not allowed in any other address space then constant if feature for program scope global variables is not supported. - For local blocks without captures, generate block literal is local scope with use of generic address space. This is achieved adding checks during code generation and not treating block literal with no captures as constant expressions. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D112230 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Sema/Sema.h clang/lib/AST/ExprConstant.cpp clang/lib/Basic/OpenCLOptions.cpp clang/lib/Basic/TargetInfo.cpp clang/lib/CodeGen/CGBlocks.cpp clang/lib/CodeGen/CGOpenCLRuntime.cpp clang/lib/CodeGen/CGOpenCLRuntime.h clang/lib/Headers/opencl-c-base.h clang/lib/Headers/opencl-c.h clang/lib/Sema/Sema.cpp clang/lib/Sema/SemaDecl.cpp clang/test/CodeGenOpenCL/address-spaces-mangling.cl clang/test/CodeGenOpenCL/address-spaces.cl clang/test/CodeGenOpenCL/blocks.cl clang/test/CodeGenOpenCL/blocks_no_global_literal.cl clang/test/Frontend/opencl.cl clang/test/Misc/opencl-c-3.0.incorrect_options.cl clang/test/SemaOpenCL/constant-blocks-unsupported-cl3.0.cl clang/test/SemaOpenCL/invalid-block.cl clang/test/SemaOpenCL/invalid-device-enqueue-types-cl3.0.cl clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl clang/test/SemaOpenCL/storageclass.cl
Index: clang/test/SemaOpenCL/storageclass.cl =================================================================== --- clang/test/SemaOpenCL/storageclass.cl +++ clang/test/SemaOpenCL/storageclass.cl @@ -1,10 +1,10 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2 -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=+__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=+__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=+__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=-__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=+__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=-__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=+__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=-__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=+__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space static constant int G1 = 0; Index: clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl =================================================================== --- clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl +++ clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2 -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_pipes,-__opencl_c_generic_address_space -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=-__opencl_c_pipes,-__opencl_c_generic_address_space +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_pipes,-__opencl_c_generic_address_space,-__opencl_c_device_enqueue +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++2021 -cl-ext=-__opencl_c_pipes,-__opencl_c_generic_address_space,-__opencl_c_device_enqueue void foo(read_only pipe int p); #if __OPENCL_C_VERSION__ > 120 Index: clang/test/SemaOpenCL/invalid-device-enqueue-types-cl3.0.cl =================================================================== --- /dev/null +++ clang/test/SemaOpenCL/invalid-device-enqueue-types-cl3.0.cl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -verify -fblocks -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space %s +// RUN: %clang_cc1 -verify -fblocks -cl-std=CL3.0 -cl-ext=-__opencl_c_device_enqueue,-__opencl_c_generic_address_space,-__opencl_c_pipes %s + +void f() { + clk_event_t e; + queue_t q; +#ifndef __opencl_c_device_enqueue +// expected-error@-3 {{use of undeclared identifier 'clk_event_t'}} +// expected-error@-3 {{use of undeclared identifier 'queue_t'}} +#else +// expected-no-diagnostics +#endif +} Index: clang/test/SemaOpenCL/invalid-block.cl =================================================================== --- clang/test/SemaOpenCL/invalid-block.cl +++ clang/test/SemaOpenCL/invalid-block.cl @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -verify -fblocks -cl-std=CL2.0 %s +// RUN: %clang_cc1 -verify -fblocks -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space %s // OpenCL v2.0 s6.12.5 void f0(int (^const bl)()); // expected-error{{declaring function parameter of type 'int (__generic ^const __private)(void)' is not allowed}} Index: clang/test/SemaOpenCL/constant-blocks-unsupported-cl3.0.cl =================================================================== --- /dev/null +++ clang/test/SemaOpenCL/constant-blocks-unsupported-cl3.0.cl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -verify -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,-__opencl_c_program_scope_global_variables %s + +void (^constant block_A)(int) = ^(void) { + return; +}; + +void f() { + void (^constant block_B)(int) = ^(void) { + return; + }; +// expected-error@-8 {{constant blocks not supported yet without __opencl_c_program_scope_global_variables feature for OpenCL C 3.0}} +// expected-error@-4 {{constant blocks not supported yet without __opencl_c_program_scope_global_variables feature for OpenCL C 3.0}} +} Index: clang/test/Misc/opencl-c-3.0.incorrect_options.cl =================================================================== --- clang/test/Misc/opencl-c-3.0.incorrect_options.cl +++ clang/test/Misc/opencl-c-3.0.incorrect_options.cl @@ -4,18 +4,22 @@ // RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_fp64,-cl_khr_fp64 %s 2>&1 | FileCheck -check-prefix=CHECK-FP64 %s // RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_read_write_images,-__opencl_c_images %s 2>&1 | FileCheck -check-prefix=CHECK-READ-WRITE-IMAGES %s // RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_read_write_images,-__opencl_c_images %s 2>&1 | FileCheck -check-prefix=CHECK-READ-WRITE-IMAGES %s -// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_pipes,-__opencl_c_generic_address_space %s 2>&1 | FileCheck -check-prefix=CHECK-PIPES %s -// RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_pipes,-__opencl_c_generic_address_space %s 2>&1 | FileCheck -check-prefix=CHECK-PIPES %s +// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_pipes,-__opencl_c_generic_address_space,-__opencl_c_device_enqueue %s 2>&1 | FileCheck -check-prefix=CHECK-PIPES %s +// RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_pipes,-__opencl_c_generic_address_space,-__opencl_c_device_enqueue %s 2>&1 | FileCheck -check-prefix=CHECK-PIPES %s // RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_3d_image_writes,+__opencl_c_images,-cl_khr_3d_image_writes %s 2>&1 | FileCheck -check-prefix=CHECK-3D-WRITE-IMAGES-DIFF %s // RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_3d_image_writes,-__opencl_c_images %s 2>&1 | FileCheck -check-prefix=CHECK-3D-WRITE-IMAGES-DEPS %s // RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_3d_image_writes,+__opencl_c_images,-cl_khr_3d_image_writes %s 2>&1 | FileCheck -check-prefix=CHECK-3D-WRITE-IMAGES-DIFF %s // RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_3d_image_writes,-__opencl_c_images %s 2>&1 | FileCheck -check-prefix=CHECK-3D-WRITE-IMAGES-DEPS %s +// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_device_enqueue,-__opencl_c_generic_address_space,-__opencl_c_pipes %s 2>&1 | FileCheck -check-prefix=CHECK-DEVICE-ENQUEUE %s +// RUN: not %clang_cc1 -cl-std=clc++2021 -triple spir-unknown-unknown -cl-ext=+__opencl_c_device_enqueue,-__opencl_c_generic_address_space,-__opencl_c_pipes %s 2>&1 | FileCheck -check-prefix=CHECK-DEVICE-ENQUEUE %s // CHECK-FP64: error: options cl_khr_fp64 and __opencl_c_fp64 are set to different values // CHECK-READ-WRITE-IMAGES: error: feature __opencl_c_read_write_images requires support of __opencl_c_images feature -// CHECK-3D-WRITE-IMAGES-DIFF: options cl_khr_3d_image_writes and __opencl_c_3d_image_writes are set to different values +// CHECK-3D-WRITE-IMAGES-DIFF: error: options cl_khr_3d_image_writes and __opencl_c_3d_image_writes are set to different values // CHECK-3D-WRITE-IMAGES-DEPS: error: feature __opencl_c_3d_image_writes requires support of __opencl_c_images feature // CHECK-PIPES: error: feature __opencl_c_pipes requires support of __opencl_c_generic_address_space feature + +// CHECK-DEVICE-ENQUEUE: error: feature __opencl_c_device_enqueue requires support of __opencl_c_generic_address_space feature Index: clang/test/Frontend/opencl.cl =================================================================== --- clang/test/Frontend/opencl.cl +++ clang/test/Frontend/opencl.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only -DSYNTAX +// RUN: %clang_cc1 %s -verify -fsyntax-only // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.1 -DSYNTAX // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.2 -DSYNTAX // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL2.0 -DSYNTAX @@ -11,6 +11,7 @@ // RUN: %clang_cc1 -cl-std=CL1.2 -cl-strict-aliasing -fblocks %s 2>&1 | FileCheck --check-prefix=CHECK-INVALID-OPENCL-VERSION12 %s // RUN: %clang_cc1 -cl-std=CL2.0 -cl-strict-aliasing %s 2>&1 | FileCheck --check-prefix=CHECK-INVALID-OPENCL-VERSION20 %s // RUN: %clang_cc1 -cl-std=clc++1.0 -cl-strict-aliasing -fblocks %s 2>&1 | FileCheck --check-prefix=CHECK-INVALID-OPENCLCPP-VERSION10 %s +// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_device_enqueue,-__opencl_c_pipes,-__opencl_c_generic_address_space #ifdef SYNTAX class test{ @@ -25,7 +26,7 @@ typedef int (^bl_t)(void); #if defined(__OPENCL_C_VERSION__) || defined(__OPENCL_CPP_VERSION__) #if !defined(BLOCKS) && (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ != CL_VERSION_2_0) - // expected-error@-3{{blocks support disabled - compile with -fblocks or for OpenCL 2.0}} + // expected-error@-3{{blocks support disabled - compile with -fblocks or for OpenCL C 2.0 or OpenCL C 3.0 with __opencl_c_device_enqueue feature}} #endif #else // expected-error@-6{{blocks support disabled - compile with -fblocks or pick a deployment target that supports them}} Index: clang/test/CodeGenOpenCL/blocks_no_global_literal.cl =================================================================== --- /dev/null +++ clang/test/CodeGenOpenCL/blocks_no_global_literal.cl @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,-__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck -check-prefixes=SPIR %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,-__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=AMDGCN %s + +// SPIR: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* } +// AMDGCN: %struct.__opencl_block_literal_generic = type { i32, i32, i8* } +// SPIR-NOT: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8 addrspace(4)* } { i32 12, i32 4, i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) to i8 addrspace(4)*) } +// AMDGCN-NOT: @__block_literal_global = internal addrspace(1) constant { i32, i32, i8* } { i32 16, i32 8, i8* bitcast (void (i8*, i8 addrspace(3)*)* @block_A_block_invoke to i8*) } + +void foo(local void *ptr){ + void (^block_A)(local void *) = ^(local void *a) { + return; + }; + // SPIR: %[[block:.*]] = alloca <{ i32, i32, i8 addrspace(4)* }> + // AMDGCN: %[[block:.*]] = alloca <{ i32, i32, i8* }> + // SPIR: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)* }>, <{ i32, i32, i8 addrspace(4)* }>* %[[block]], i32 0, i32 0 + // AMDGCN: %[[block_size:.*]] = getelementptr inbounds <{ i32, i32, i8* }>, <{ i32, i32, i8* }> addrspace(5)* %[[block]], i32 0, i32 0 + // SPIR: store i32 12, i32* %[[block_size]] + // AMDGCN: store i32 16, i32 addrspace(5)* %[[block_size]] + // SPIR: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)* }>, <{ i32, i32, i8 addrspace(4)* }>* %[[block]], i32 0, i32 1 + // AMDGCN: %[[block_align:.*]] = getelementptr inbounds <{ i32, i32, i8* }>, <{ i32, i32, i8* }> addrspace(5)* %[[block]], i32 0, i32 1 + // SPIR: store i32 4, i32* %[[block_align]] + // AMDGCN: store i32 8, i32 addrspace(5)* %[[block_align]] + // SPIR: %[[block_invoke:.*]] = getelementptr inbounds <{ i32, i32, i8 addrspace(4)* }>, <{ i32, i32, i8 addrspace(4)* }>* %[[block:.*]], i32 0, i32 2 + // SPIR: store i8 addrspace(4)* addrspacecast (i8* bitcast (void (i8 addrspace(4)*, i8 addrspace(3)*)* @__foo_block_invoke to i8*) to i8 addrspace(4)*), i8 addrspace(4)** %[[block_invoke]] + // AMDGCN: %[[block_invoke:.*]] = getelementptr inbounds <{ i32, i32, i8* }>, <{ i32, i32, i8* }> addrspace(5)* %[[block:.*]], i32 0, i32 2 + // AMDGCN: store i8* bitcast (void (i8*, i8 addrspace(3)*)* @__foo_block_invoke to i8*), i8* addrspace(5)* %[[block_invoke]] +} + +// SPIR-LABEL: define internal {{.*}}void @__foo_block_invoke(i8 addrspace(4)* %.block_descriptor, i8 addrspace(3)* %a) +// AMDGCN-LABEL: define internal {{.*}}void @__foo_block_invoke(i8* %.block_descriptor, i8 addrspace(3)* %a) Index: clang/test/CodeGenOpenCL/blocks.cl =================================================================== --- clang/test/CodeGenOpenCL/blocks.cl +++ clang/test/CodeGenOpenCL/blocks.cl @@ -2,6 +2,10 @@ // RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=COMMON,AMDGCN %s // RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -debug-info-kind=limited -triple spir-unknown-unknown | FileCheck -check-prefixes=CHECK-DEBUG %s // RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -O0 -debug-info-kind=limited -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=CHECK-DEBUG %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,+__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck -check-prefixes=COMMON,SPIR %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,+__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=COMMON,AMDGCN %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,+__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -debug-info-kind=limited -triple spir-unknown-unknown | FileCheck -check-prefixes=CHECK-DEBUG %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_device_enqueue,+__opencl_c_generic_address_space,+__opencl_c_program_scope_global_variables -emit-llvm -o - -O0 -debug-info-kind=limited -triple amdgcn-amd-amdhsa | FileCheck -check-prefixes=CHECK-DEBUG %s // SPIR: %struct.__opencl_block_literal_generic = type { i32, i32, i8 addrspace(4)* } // AMDGCN: %struct.__opencl_block_literal_generic = type { i32, i32, i8* } Index: clang/test/CodeGenOpenCL/address-spaces.cl =================================================================== --- clang/test/CodeGenOpenCL/address-spaces.cl +++ clang/test/CodeGenOpenCL/address-spaces.cl @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -O0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR -// RUN: %clang_cc1 %s -O0 -cl-std=CL3.0 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR -// RUN: %clang_cc1 %s -O0 -cl-std=clc++2021 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR +// RUN: %clang_cc1 %s -O0 -cl-std=CL3.0 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR +// RUN: %clang_cc1 %s -O0 -cl-std=clc++2021 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR // RUN: %clang_cc1 %s -O0 -DCL20 -cl-std=CL2.0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CL20,CL20SPIR // RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s // RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -cl-std=CL3.0 -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s Index: clang/test/CodeGenOpenCL/address-spaces-mangling.cl =================================================================== --- clang/test/CodeGenOpenCL/address-spaces-mangling.cl +++ clang/test/CodeGenOpenCL/address-spaces-mangling.cl @@ -9,9 +9,9 @@ // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL2.0 -emit-llvm -o - | FileCheck -check-prefix=OCL-20 %s // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL1.2 -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space -emit-llvm -o - | FileCheck -check-prefix=OCL-20 %s -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL3.0 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL3.0 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++2021 -cl-ext=+__opencl_c_generic_address_space -emit-llvm -o - | FileCheck -check-prefix=OCL-20 %s -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++2021 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++2021 -cl-ext=-__opencl_c_generic_address_space,-__opencl_c_pipes,-__opencl_c_device_enqueue -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s // We can't name this f as private is equivalent to default // no specifier given address space so we get multiple definition Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -8021,6 +8021,14 @@ } if (T->isBlockPointerType()) { + if ((T.getAddressSpace() == LangAS::opencl_constant) && + !getOpenCLOptions().areProgramScopeVariablesSupported( + getLangOpts())) { + Diag(NewVD->getLocation(), diag::err_constant_blocks_not_supported); + NewVD->setInvalidDecl(); + return; + } + // OpenCL v2.0 s6.12.5 - Any block declaration must be const qualified and // can't use 'extern' storage class. if (!T.isConstQualified()) { Index: clang/lib/Sema/Sema.cpp =================================================================== --- clang/lib/Sema/Sema.cpp +++ clang/lib/Sema/Sema.cpp @@ -324,9 +324,13 @@ Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts()); addImplicitTypedef("sampler_t", Context.OCLSamplerTy); addImplicitTypedef("event_t", Context.OCLEventTy); - if (getLangOpts().getOpenCLCompatibleVersion() >= 200) { - addImplicitTypedef("clk_event_t", Context.OCLClkEventTy); - addImplicitTypedef("queue_t", Context.OCLQueueTy); + auto OCLCompatibleVersion = getLangOpts().getOpenCLCompatibleVersion(); + if (OCLCompatibleVersion >= 200) { + if ((OCLCompatibleVersion == 200) || + (OCLCompatibleVersion == 300 && getLangOpts().Blocks)) { + addImplicitTypedef("clk_event_t", Context.OCLClkEventTy); + addImplicitTypedef("queue_t", Context.OCLQueueTy); + } if (getLangOpts().OpenCLPipes) addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy); addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy)); @@ -394,7 +398,6 @@ } } - #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ if (getOpenCLOptions().isSupported(#Ext, getLangOpts())) { \ addImplicitTypedef(#ExtType, Context.Id##Ty); \ Index: clang/lib/Headers/opencl-c.h =================================================================== --- clang/lib/Headers/opencl-c.h +++ clang/lib/Headers/opencl-c.h @@ -16447,6 +16447,7 @@ // OpenCL v2.0 s6.13.17 - Enqueue Kernels #if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#ifdef __opencl_c_device_enqueue ndrange_t __ovld ndrange_1D(size_t); ndrange_t __ovld ndrange_1D(size_t, size_t); ndrange_t __ovld ndrange_1D(size_t, size_t, size_t); @@ -16474,6 +16475,8 @@ void __ovld capture_event_profiling_info(clk_event_t, clk_profiling_info, __global void* value); queue_t __ovld get_default_queue(void); +#endif //__opencl_c_device_enqueue + #endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // OpenCL Extension v2.0 s9.17 - Sub-groups Index: clang/lib/Headers/opencl-c-base.h =================================================================== --- clang/lib/Headers/opencl-c-base.h +++ clang/lib/Headers/opencl-c-base.h @@ -498,12 +498,14 @@ #define MAX_WORK_DIM 3 +#ifdef __opencl_c_device_enqueue typedef struct { unsigned int workDimension; size_t globalWorkOffset[MAX_WORK_DIM]; size_t globalWorkSize[MAX_WORK_DIM]; size_t localWorkSize[MAX_WORK_DIM]; } ndrange_t; +#endif // __opencl_c_device_enqueue #endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) Index: clang/lib/CodeGen/CGOpenCLRuntime.h =================================================================== --- clang/lib/CodeGen/CGOpenCLRuntime.h +++ clang/lib/CodeGen/CGOpenCLRuntime.h @@ -95,6 +95,9 @@ /// \return LLVM block invoke function emitted for an expression derived from /// the block expression. llvm::Function *getInvokeFunction(const Expr *E); + + /// \return true if block can be emitted as global. + bool blockCanBeGlobal(); }; } Index: clang/lib/CodeGen/CGOpenCLRuntime.cpp =================================================================== --- clang/lib/CodeGen/CGOpenCLRuntime.cpp +++ clang/lib/CodeGen/CGOpenCLRuntime.cpp @@ -184,3 +184,17 @@ EnqueuedBlockMap[Block].Kernel = F; return EnqueuedBlockMap[Block]; } + +// Always generate global blocks for OpenCL C 2.0. +// For higher OpenCL versions check __opencl_c_program_scope_global_variable +// feature support. +bool CGOpenCLRuntime::blockCanBeGlobal() { + const auto &LO = CGM.getLangOpts(); + assert(LO.OpenCL && (LO.getOpenCLCompatibleVersion() >= 200) && + "Not expecting to generate blocks"); + if (LO.getOpenCLCompatibleVersion() == 200) + return true; + const auto &OpenCLFeaturesMap = CGM.getTarget().getSupportedOpenCLOpts(); + return CGM.getTarget().hasFeatureEnabled( + OpenCLFeaturesMap, "__opencl_c_program_scope_global_variables"); +} Index: clang/lib/CodeGen/CGBlocks.cpp =================================================================== --- clang/lib/CodeGen/CGBlocks.cpp +++ clang/lib/CodeGen/CGBlocks.cpp @@ -527,18 +527,22 @@ SmallVector<llvm::Type*, 8> elementTypes; initializeForBlockHeader(CGM, info, elementTypes); bool hasNonConstantCustomFields = false; + // OpenCL doesn't support global blocks if the feature for program scope + // global variables is not supported. + bool globalBlockIsSupported = + !CGM.getLangOpts().OpenCL || CGM.getOpenCLRuntime().blockCanBeGlobal(); if (auto *OpenCLHelper = CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) hasNonConstantCustomFields = !OpenCLHelper->areAllCustomFieldValuesConstant(info); - if (!block->hasCaptures() && !hasNonConstantCustomFields) { + if (!block->hasCaptures() && !hasNonConstantCustomFields && + globalBlockIsSupported) { info.StructureType = llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); info.CanBeGlobal = true; return; - } - else if (C.getLangOpts().ObjC && - CGM.getLangOpts().getGC() == LangOptions::NonGC) + } else if (C.getLangOpts().ObjC && + CGM.getLangOpts().getGC() == LangOptions::NonGC) info.HasCapturedVariableLayout = true; // Collect the layout chunks. @@ -664,7 +668,8 @@ if (layout.empty()) { info.StructureType = llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); - info.CanBeGlobal = true; + if (globalBlockIsSupported) + info.CanBeGlobal = true; return; } @@ -1294,7 +1299,6 @@ // Compute information about the layout, etc., of this block. computeBlockInfo(*this, nullptr, blockInfo); - // Using that metadata, generate the actual block function. { CodeGenFunction::DeclMapTy LocalDeclMap; Index: clang/lib/Basic/TargetInfo.cpp =================================================================== --- clang/lib/Basic/TargetInfo.cpp +++ clang/lib/Basic/TargetInfo.cpp @@ -416,6 +416,8 @@ OpenCLFeaturesMap, "__opencl_c_generic_address_space"); Opts.OpenCLPipes = hasFeatureEnabled(OpenCLFeaturesMap, "__opencl_c_pipes"); + Opts.Blocks = + hasFeatureEnabled(OpenCLFeaturesMap, "__opencl_c_device_enqueue"); } } Index: clang/lib/Basic/OpenCLOptions.cpp =================================================================== --- clang/lib/Basic/OpenCLOptions.cpp +++ clang/lib/Basic/OpenCLOptions.cpp @@ -113,7 +113,8 @@ static const llvm::StringMap<llvm::StringRef> DependentFeaturesMap = { {"__opencl_c_read_write_images", "__opencl_c_images"}, {"__opencl_c_3d_image_writes", "__opencl_c_images"}, - {"__opencl_c_pipes", "__opencl_c_generic_address_space"}}; + {"__opencl_c_pipes", "__opencl_c_generic_address_space"}, + {"__opencl_c_device_enqueue", "__opencl_c_generic_address_space"}}; auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts(); Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -8614,11 +8614,7 @@ { return Success(E); } bool VisitCallExpr(const CallExpr *E); bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); - bool VisitBlockExpr(const BlockExpr *E) { - if (!E->getBlockDecl()->hasCaptures()) - return Success(E); - return Error(E); - } + bool VisitBlockExpr(const BlockExpr *E); bool VisitCXXThisExpr(const CXXThisExpr *E) { // Can't look at 'this' when checking a potential constant expression. if (Info.checkingPotentialConstantExpression()) @@ -9549,6 +9545,23 @@ return true; } + +bool PointerExprEvaluator::VisitBlockExpr(const BlockExpr *E) { + if (!E->getBlockDecl()->hasCaptures()) { + if (!Info.Ctx.getLangOpts().OpenCL) + return Success(E); + + const auto &OpenCLFeaturesMap = + Info.Ctx.getTargetInfo().getSupportedOpenCLOpts(); + return (Info.Ctx.getLangOpts().getOpenCLCompatibleVersion() == 200) || + Info.Ctx.getTargetInfo().hasFeatureEnabled( + OpenCLFeaturesMap, + "__opencl_c_program_scope_global_variables") + ? Success(E) + : Error(E); + } + return Error(E); +} //===----------------------------------------------------------------------===// // Member Pointer Evaluation //===----------------------------------------------------------------------===// Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -1568,6 +1568,7 @@ const LangOptions &getLangOpts() const { return LangOpts; } OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; } + const OpenCLOptions &getOpenCLOptions() const { return OpenCLFeatures; } FPOptions &getCurFPFeatures() { return CurFPFeatures; } DiagnosticsEngine &getDiagnostics() const { return Diags; } Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9520,9 +9520,12 @@ // Blocks def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks" - " or %select{pick a deployment target that supports them|for OpenCL 2.0}0">; + " or %select{pick a deployment target that supports them|for OpenCL C 2.0" + " or OpenCL C 3.0 with __opencl_c_device_enqueue feature}0">; def err_block_returning_array_function : Error< "block cannot return %select{array|function}0 type %1">; +def err_constant_blocks_not_supported : Error<"constant blocks not supported yet" + " without __opencl_c_program_scope_global_variables feature for OpenCL C 3.0">; // Builtin annotation def err_builtin_annotation_first_arg : Error<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits