blob: e5b13eff7ed4c2ba548bf10bf905c01ea95b6893 [file] [log] [blame]
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <stdio.h>
#include <string.h>
#include "harness/testHarness.h"
#include "harness/typeWrappers.h"
#include <vector>
#include "procs.h"
#include "utils.h"
#include <time.h>
#ifdef CL_VERSION_2_0
static const char* block_global_scope[] =
{
NL, "int __constant globalVar = 7;"
NL, "int (^__constant globalBlock)(int) = ^int(int num)"
NL, "{"
NL, " return globalVar * num * (1+ get_global_id(0));"
NL, "};"
NL, "kernel void block_global_scope(__global int* res)"
NL, "{"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " res[tid] = globalBlock(3) - 21*(tid + 1);"
NL, "}"
NL
};
static const char* block_kernel_scope[] =
{
NL, "kernel void block_kernel_scope(__global int* res)"
NL, "{"
NL, " int multiplier = 3;"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return num * multiplier;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " multiplier = 8;"
NL, " res[tid] = kernelBlock(7) - 21;"
NL, "}"
NL
};
static const char* block_statement_scope[] =
{
NL, "kernel void block_statement_scope(__global int* res)"
NL, "{"
NL, " int multiplier = 0;"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " multiplier = 9;"
NL, " res[tid] = ^int(int num) { return multiplier * num; } (11) - 99;"
NL, "}"
NL
};
static const char* block_function_scope[] =
{
NL, "int fnTest(int a)"
NL, "{"
NL, " int localVar = 17;"
NL, " int (^functionBlock)(int) = ^(int num)"
NL, " {"
NL, " return localVar * num;"
NL, " };"
NL, " return 111 - functionBlock(a+1);"
NL, "}"
NL, "kernel void block_function_scope(__global int* res)"
NL, "{"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " res[tid] = fnTest(5) - 9;"
NL, "}"
NL
};
static const char* block_nested_scope[] =
{
NL, "kernel void block_nested_scope(__global int* res)"
NL, "{"
NL, " int multiplier = 3;"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " int (^innerBlock)(int) = ^(int n)"
NL, " {"
NL, " return multiplier * n;"
NL, " };"
NL, " return num * innerBlock(23);"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " multiplier = 8;"
NL, " res[tid] = kernelBlock(13) - 897;"
NL, "}"
NL
};
static const char* block_arg_struct[] =
{
NL, "struct two_ints {"
NL, " short x;"
NL, " long y;"
NL, "};"
NL, "struct two_structs {"
NL, " struct two_ints a;"
NL, " struct two_ints b;"
NL, "};"
NL, "kernel void block_arg_struct(__global int* res)"
NL, "{"
NL, " int (^kernelBlock)(struct two_ints, struct two_structs) = ^int(struct two_ints ti, struct two_structs ts)"
NL, " {"
NL, " return ti.x * ti.y * ts.a.x * ts.a.y * ts.b.x * ts.b.y;"
NL, " };"
NL, " struct two_ints i;"
NL, " i.x = 2;"
NL, " i.y = 3;"
NL, " struct two_structs s;"
NL, " s.a.x = 4;"
NL, " s.a.y = 5;"
NL, " s.b.x = 6;"
NL, " s.b.y = 7;"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " res[tid] = kernelBlock(i,s) - 5040;"
NL, "}"
NL
};
static const char* block_arg_types_mix[] =
{
NL, "union number {"
NL, " long l;"
NL, " float f;"
NL, "};"
NL, "enum color {"
NL, " RED = 0,"
NL, " GREEN,"
NL, " BLUE" // Using this value - it is actualy "2"
NL, "};"
NL, "typedef int _INT ;"
NL, "typedef char _ACHAR[3] ;"
NL, "kernel void block_arg_types_mix(__global int* res)"
NL, "{"
NL, " int (^kernelBlock)(_INT, _ACHAR, union number, enum color, int, int, int, int, int, int, int, int, int, int, int, int, int) ="
NL, " ^int(_INT bi, _ACHAR bch, union number bn, enum color bc, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8,"
NL, " int i9, int i10, int i11, int i12, int i13)"
NL, " {"
NL, " return bi * bch[0] * bch[1] * bch[2] * bn.l * bc - i1 - i2 - i3 - i4 - i5 - i6 - i7 - i8 - i9 - i10 - i11 - i12 - i13;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " _INT x = -5;"
NL, " _ACHAR char_arr = { 1, 2, 3 };"
NL, " union number n;"
NL, " n.l = 4;"
NL, " enum color c = BLUE;"
NL, " res[tid] = kernelBlock(x,char_arr,n,c,1,2,3,4,5,6,7,8,9,10,11,12,13) + 331;"
NL, "}"
NL
};
static const char* block_arg_pointer[] =
{
NL, "struct two_ints {"
NL, " short x;"
NL, " long y;"
NL, "};"
NL, "kernel void block_arg_pointer(__global int* res)"
NL, "{"
NL, " int (^kernelBlock)(struct two_ints*, struct two_ints*, int*, int*) = "
NL, " ^int(struct two_ints* bs1, struct two_ints* bs2, int* bi1, int* bi2)"
NL, " {"
NL, " return (*bs1).x * (*bs1).y * (*bs2).x * (*bs2).y * (*bi1) * (*bi2);"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " struct two_ints s[2];"
NL, " s[0].x = 4;"
NL, " s[0].y = 5;"
NL, " struct two_ints* ps = s + 1;"
NL, " (*ps).x = 6;"
NL, " (*ps).y = 7;"
NL, " int i = 2;"
NL, " int * pi = &i;"
NL, " res[tid] = kernelBlock(s,ps,&i,pi) - 3360;"
NL, "}"
NL
};
static const char* block_arg_global_p[] =
{
NL, "kernel void block_arg_global_p(__global int* res)"
NL, "{"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " typedef __global int* int_ptr_to_global_t;"
NL, " int_ptr_to_global_t (^kernelBlock)(__global int*, int) =^ int_ptr_to_global_t (__global int* bres, int btid)"
NL, " {"
NL, " bres[tid] = 5;"
NL, " return bres;"
NL, " };"
NL, " res = kernelBlock(res, tid);"
NL, " res[tid] -= 5;"
NL, "}"
NL
};
static const char* block_arg_const_p[] =
{
NL, "constant int ci = 8;"
NL, "kernel void block_arg_const_p(__global int* res)"
NL, "{"
NL, " __constant int* (^kernelBlock)(__constant int*) = ^(__constant int* bpci)"
NL, " {"
NL, " return bpci;"
NL, " };"
NL, " constant int* pci = &ci;"
NL, " constant int* pci_check;"
NL, " pci_check = kernelBlock(pci);"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = pci == pci_check ? 0 : -1;"
NL, "}"
NL
};
static const char* block_ret_struct[] =
{
NL, "kernel void block_ret_struct(__global int* res)"
NL, "{"
NL, " struct A {"
NL, " int a;"
NL, " }; "
NL, " struct A (^kernelBlock)(struct A) = ^struct A(struct A a)"
NL, " { "
NL, " a.a = 6;"
NL, " return a;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " struct A aa;"
NL, " aa.a = 5;"
NL, " res[tid] = kernelBlock(aa).a - 6;"
NL, "}"
NL
};
static const char* block_arg_global_var[] =
{
NL, "constant int gi = 8;"
NL, "kernel void block_arg_global_var(__global int* res)"
NL, "{"
NL, " int (^kernelBlock)(int) = ^(int bgi)"
NL, " {"
NL, " return bgi - 8;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = kernelBlock(gi);"
NL, "}"
NL
};
static const char* block_in_for_init[] =
{
NL, "kernel void block_in_for_init(__global int* res)"
NL, "{"
NL, " int multiplier = 3;"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return num * multiplier;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = 27;"
NL, " for(int i=kernelBlock(9); i>0; i--)"
NL, " {"
NL, " res[tid]--;"
NL, " }"
NL, "}"
NL
};
static const char* block_in_for_cond[] =
{
NL, "kernel void block_in_for_cond(__global int* res)"
NL, "{"
NL, " int multiplier = 3;"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return num * multiplier;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = 39;"
NL, " for(int i=0; i<kernelBlock(13); i++)"
NL, " {"
NL, " res[tid]--;"
NL, " }"
NL, "}"
NL
};
static const char* block_in_for_iter[] =
{
NL, "kernel void block_in_for_iter(__global int* res)"
NL, "{"
NL, " int multiplier = 2;"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return num * multiplier;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = 4;"
NL, " for(int i=2; i<17; i=kernelBlock(i))"
NL, " {"
NL, " res[tid]--;"
NL, " }"
NL, "}"
NL
};
static const char* block_in_while_cond[] =
{
NL, "kernel void block_in_while_cond(__global int* res)"
NL, "{"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return res[num];"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = 27*(tid+1);"
NL, " while(kernelBlock(tid))"
NL, " {"
NL, " res[tid]--;"
NL, " }"
NL, "}"
NL
};
static const char* block_in_while_body[] =
{
NL, "kernel void block_in_while_body(__global int* res)"
NL, "{"
NL, " int multiplier = 3;"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return num * multiplier;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " int i = 7;"
NL, " res[tid] = 3*(7+6+5+4+3+2+1);"
NL, " while(i)"
NL, " {"
NL, " res[tid]-=kernelBlock(i--);"
NL, " }"
NL, "}"
NL
};
static const char* block_in_do_while_body[] =
{
NL, "kernel void block_in_do_while_body(__global int* res)"
NL, "{"
NL, " int multiplier = 3;"
NL, " size_t tid = get_global_id(0);"
NL, " int i = 100;"
NL, " res[tid] = 3*5050;"
NL, " do"
NL, " {"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return num * multiplier;"
NL, " };"
NL, " res[tid]-=kernelBlock(i--);"
NL, " } while(i);"
NL, "}"
NL
};
static const char* block_cond_statement[] =
{
NL, "kernel void block_cond_statement(__global int* res)"
NL, "{"
NL, " int multiplier = 2;"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return num * multiplier;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = 120;"
NL, " res[tid] = (kernelBlock(2) == 4) ? res[tid] - 30 : res[tid] - 1;"
NL, " res[tid] = (kernelBlock(2) == 5) ? res[tid] - 3 : res[tid] - 30;"
NL, " res[tid] = (1) ? res[tid] - kernelBlock(15) : res[tid] - 7;"
NL, " res[tid] = (0) ? res[tid] - 13 : res[tid] - kernelBlock(15);"
NL, "}"
NL
};
static const char* block_in_if_cond[] =
{
NL, "kernel void block_in_if_cond(__global int* res)"
NL, "{"
NL, " int multiplier = 2;"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return num * multiplier;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = 7;"
NL, " if (kernelBlock(5))"
NL, " {"
NL, " res[tid]-= 3;"
NL, " }"
NL, " if (kernelBlock(0))"
NL, " {"
NL, " res[tid]-= 2;"
NL, " }"
NL, " else"
NL, " {"
NL, " res[tid]-= 4;"
NL, " }"
NL, "}"
NL
};
static const char* block_in_if_branch[] =
{
NL, "kernel void block_in_if_branch(__global int* res)"
NL, "{"
NL, " int multiplier = 2;"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return num * multiplier;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = 7;"
NL, " if (kernelBlock(5))"
NL, " {"
NL, " res[tid]-= ^(int num){ return num - 1; }(4);" // res[tid]-=3;
NL, " }"
NL, " if (kernelBlock(0))"
NL, " {"
NL, " res[tid]-= ^(int num){ return num - 1; }(3);" // res[tid]-=2;
NL, " }"
NL, " else"
NL, " {"
NL, " int (^ifBlock)(int) = ^(int num)"
NL, " {"
NL, " return num + 1;"
NL, " };"
NL, " res[tid]-= ifBlock(3);" // res[tid]-=4;
NL, " }"
NL, "}"
NL
};
static const char* block_switch_cond[] =
{
NL, "kernel void block_switch_cond(__global int* res)"
NL, "{"
NL, " int multiplier = 2;"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return num * multiplier;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = 12;"
NL, " int i = 1;"
NL, " while(i <= 3)"
NL, " {"
NL, " switch (kernelBlock(i))"
NL, " {"
NL, " case 2:"
NL, " res[tid] = res[tid] - 2;"
NL, " break;"
NL, " case 4:"
NL, " res[tid] = res[tid] - 4;"
NL, " break;"
NL, " case 6:"
NL, " res[tid] = res[tid] - 6;"
NL, " break;"
NL, " default:"
NL, " break;"
NL, " }"
NL, " i++;"
NL, " }"
NL, "}"
NL
};
static const char* block_switch_case[] =
{
NL, "kernel void block_switch_case(__global int* res)"
NL, "{"
NL, " int multiplier = 2;"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " return num * multiplier;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = 12;"
NL, " int i = 1;"
NL, " while(i <= 3)"
NL, " {"
NL, " switch (kernelBlock(i))"
NL, " {"
NL, " case 2:"
NL, " res[tid]-=^(int num){ return num - 1; }(3);" // res[tid]-=2;
NL, " break;"
NL, " case 4:"
NL, " {"
NL, " int (^caseBlock)(int) = ^(int num)"
NL, " {"
NL, " return num + 1;"
NL, " };"
NL, " res[tid]-=caseBlock(3);" // res[tid]-=4;
NL, " break;"
NL, " }"
NL, " case 6:"
NL, " res[tid]-=kernelBlock(3);" // res[tid]-=6;
NL, " break;"
NL, " default:"
NL, " break;"
NL, " }"
NL, " i++;"
NL, " }"
NL, "}"
NL
};
// Accessing data from Block
static const char* block_access_program_data[] =
{
NL, "int __constant globalVar1 = 7;"
NL, "int __constant globalVar2 = 11;"
NL, "int __constant globalVar3 = 13;"
NL, "int (^__constant globalBlock)(int) = ^int(int num)"
NL, "{"
NL, " return globalVar1 * num;"
NL, "};"
NL, "kernel void block_access_program_data(__global int* res)"
NL, "{"
NL, " int (^ kernelBlock)(int) = ^int(int num)"
NL, " {"
NL, " return globalVar2 * num;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = tid + 1;"
NL, " res[tid] = globalBlock(res[tid]);"
NL, " res[tid] = kernelBlock(res[tid]);"
NL, " res[tid] = ^(int num){ return globalVar3*num; }(res[tid]) - (7*11*13)*(tid + 1);"
NL, "}"
NL
};
static const char* block_access_kernel_data[] =
{
NL, "kernel void block_access_kernel_data(__global int* res)"
NL, "{"
NL, " int var1 = 7;"
NL, " int var2 = 11;"
NL, " int var3 = 13;"
NL, " int (^ kernelBlock)(int) = ^int(int num)"
NL, " {"
NL, " int (^ nestedBlock)(int) = ^int (int num)"
NL, " {"
NL, " return var1 * num;"
NL, " };"
NL, " return var2 * nestedBlock(num);"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = tid + 1;"
NL, " res[tid] = kernelBlock(res[tid]);"
NL, " res[tid] = ^(int num){ return var3*num; }(res[tid]) - (7*11*13)*(tid + 1);"
NL, "}"
NL
};
static const char* block_access_chained_data[] =
{
NL, "kernel void block_access_chained_data(__global int* res)"
NL, "{"
NL, " int (^ kernelBlock)(int) = ^int(int num)"
NL, " {"
NL, " int var1 = 7;"
NL, " int var2 = 11;"
NL, " int var3 = 13;"
NL, " int (^ nestedBlock1)(int) = ^int (int num)"
NL, " {"
NL, " int (^ nestedBlock2) (int) = ^int (int num)"
NL, " {"
NL, " return var2 * ^(int num){ return var3*num; }(num);"
NL, " };"
NL, " return var1 * nestedBlock2(num);"
NL, " };"
NL, " return nestedBlock1(num);"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = tid + 1;"
NL, " res[tid] = kernelBlock(res[tid]) - (7*11*13)*(tid + 1);"
NL, "}"
NL
};
static const char* block_access_volatile_data[] =
{
NL, "kernel void block_access_volatile_data(__global int* res)"
NL, "{"
NL, " int var1 = 7;"
NL, " int var2 = 11;"
NL, " volatile int var3 = 13;"
NL, ""
NL, " int (^ kernelBlock)(int) = ^int(int num)"
NL, " {"
NL, " int (^ nestedBlock)(int) = ^int (int num)"
NL, " {"
NL, " return var1 * num;"
NL, " };"
NL, " return var2 * nestedBlock(num);"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = tid + 1;"
NL, " res[tid] = kernelBlock(res[tid]);"
NL, " res[tid] = ^(int num){ return var3*num; }(res[tid]) - (7*11*13)*(tid + 1);"
NL, "}"
NL
};
static const char* block_typedef_kernel[] =
{
NL, "kernel void block_typedef_kernel(__global int* res)"
NL, "{"
NL, " typedef int* (^block_t)(int*);"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " int i[4] = { 3, 4, 4, 1 };"
NL, " int *temp = i; // workaround clang bug"
NL, " block_t kernelBlock = ^(int* pi)"
NL, " {"
NL, " block_t b = ^(int* n) { return n - 1; };"
NL, " return pi + *(b(temp+4));"
NL, " };"
NL, " switch (*(kernelBlock(i))) {"
NL, " case 4:"
NL, " res[tid] += *(kernelBlock(i+1));"
NL, " break;"
NL, " default:"
NL, " res[tid] = -100;"
NL, " break;"
NL, " }"
NL, " res[tid] += *(kernelBlock(i)) - 7;"
NL, "}"
NL
};
static const char* block_typedef_func[] =
{
NL, "int func(int fi)"
NL, "{"
NL, " typedef int (^block_t)(int);"
NL, " const block_t funcBlock = ^(int bi)"
NL, " {"
NL, " typedef short (^block2_t)(short);"
NL, " block2_t nestedBlock = ^(short ni)"
NL, " {"
NL, " return (short)(ni - 1);"
NL, " };"
NL, " return bi * nestedBlock(3);"
NL, " };"
NL, " return funcBlock(fi * 2);"
NL, "}"
NL, "kernel void block_typedef_func(__global int* res)"
NL, "{"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " res[tid] = func(1) - 4;"
NL, "}"
NL
};
static const char* block_typedef_stmnt_if[] =
{
NL, "kernel void block_typedef_stmnt_if(__global int* res)"
NL, "{ "
NL, " int flag = 1;"
NL, " int sum = 0;"
NL, " if (flag) {"
NL, " typedef int (^block_t)(int);"
NL, " const block_t kernelBlock = ^(int bi)"
NL, " {"
NL, " block_t b = ^(int bi)"
NL, " {"
NL, " return bi + 1;"
NL, " };"
NL, " return bi + b(1);"
NL, " };"
NL, " sum = kernelBlock(sum);"
NL, " }"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = sum - 2;"
NL, "}"
NL
};
static const char* block_typedef_loop[] =
{
NL, "kernel void block_typedef_loop(__global int* res)"
NL, "{ "
NL, " int sum = -1;"
NL, " for (int i = 0; i < 3; i++) {"
NL, " typedef int (^block_t)(void);"
NL, " const block_t kernelBlock = ^()"
NL, " {"
NL, " return i + 1;"
NL, " };"
NL, " sum += kernelBlock();"
NL, " }"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = sum - 5;"
NL, "}"
NL
};
static const char* block_typedef_mltpl_func[] =
{
NL, "int func(int fi)"
NL, "{"
NL, " typedef int (^block_t)(int);"
NL, " typedef int (^block2_t)(int);"
NL, " const block_t funcBlock1 = ^(int bi) { return bi; };"
NL, " const block2_t funcBlock2 = ^(int bi)"
NL, " {"
NL, " typedef short (^block3_t)(short);"
NL, " typedef short (^block4_t)(short);"
NL, " const block3_t nestedBlock1 = ^(short ni)"
NL, " {"
NL, " return (short)(ni - 1);"
NL, " };"
NL, " const block4_t nestedBlock2 = ^(short ni)"
NL, " {"
NL, " return (short)(ni - 2);"
NL, " };"
NL, " return bi * nestedBlock1(3) * nestedBlock2(3);"
NL, " };"
NL, " return funcBlock2(fi * 2) + funcBlock1(1);"
NL, "}"
NL, "kernel void block_typedef_mltpl_func(__global int* res)"
NL, "{"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " typedef int (^block1_t)(int);"
NL, " typedef int (^block2_t)(int);"
NL, " const block1_t kernelBlock1 = ^(int bi) { return bi + 8; };"
NL, " const block2_t kernelBlock2 = ^(int bi) { return bi + 3; };"
NL, " res[tid] = func(1) - kernelBlock1(2) / kernelBlock2(-1);"
NL, "}"
NL
};
static const char* block_typedef_mltpl_stmnt[] =
{
NL, "kernel void block_typedef_mltpl_stmnt(__global int* res)"
NL, "{"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " int a;"
NL, " do"
NL, " {"
NL, " typedef float (^blockf_t)(float);"
NL, " typedef int (^blocki_t)(int);"
NL, " const blockf_t blockF = ^(float bi) { return (float)(bi + 3.3); };"
NL, " const blocki_t blockI = ^(int bi) { return bi + 2; };"
NL, " if ((blockF(.0)-blockI(0)) > 0)"
NL, " {"
NL, " typedef uint (^block_t)(uint);"
NL, " const block_t nestedBlock = ^(uint bi) { return (uint)(bi + 4); };"
NL, " a = nestedBlock(1) + nestedBlock(2);"
NL, " break;"
NL, " }"
NL, " } while(1); "
NL, " res[tid] = a - 11;"
NL, "}"
NL
};
static const char* block_typedef_mltpl_g[] =
{
NL, "typedef int (^block1_t)(float, int); "
NL, "constant block1_t b1 = ^(float fi, int ii) { return (int)(ii + fi); };"
NL, "typedef int (^block2_t)(float, int);"
NL, "constant block2_t b2 = ^(float fi, int ii) { return (int)(ii + fi); };"
NL, "typedef float (^block3_t)(int, int);"
NL, "constant block3_t b3 = ^(int i1, int i2) { return (float)(i1 + i2); };"
NL, "typedef int (^block4_t)(float, float);"
NL, "kernel void block_typedef_mltpl_g(__global int* res)"
NL, "{"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " block4_t b4 = ^(float f1, float f2) { return (int)(f1 + f2); };"
NL, " res[tid] = b1(1.1, b2(1.1, 1)) - b4(b3(1,1), 1.1);"
NL, "}"
NL
};
static const char* block_literal[] =
{
NL, "int func()"
NL, "{"
NL, " return ^(int i) {"
NL, " return ^(ushort us)"
NL, " {"
NL, " return (int)us + i;"
NL, " }(3);"
NL, " }(7) - 10;"
NL, "}"
NL, "kernel void block_literal(__global int* res)"
NL, "{"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " res[tid] = func();"
NL, "}"
NL
};
static const char* block_complex[] =
{
NL, "kernel void block_complex(__global int* res)"
NL, "{"
NL, " int (^kernelBlock)(int) = ^(int num)"
NL, " {"
NL, " int result = 1;"
NL, " for (int i = 0; i < num; i++)"
NL, " {"
NL, " switch(i)"
NL, " {"
NL, " case 0:"
NL, " case 1:"
NL, " case 2:"
NL, " result += i;"
NL, " break;"
NL, " case 3:"
NL, " if (result < num)"
NL, " result += i;"
NL, " else"
NL, " result += i * 2;"
NL, " break;"
NL, " case 4:"
NL, " while (1)"
NL, " {"
NL, " result++;"
NL, " if (result)"
NL, " goto ret;"
NL, " }"
NL, " break;"
NL, " default:"
NL, " return 777;"
NL, " }"
NL, " }"
NL, " ret: ;"
NL, " while (num) {"
NL, " num--;"
NL, " if (num % 2 == 0)"
NL, " continue;"
NL, " result++;"
NL, " }"
NL, " return result;"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " res[tid] = kernelBlock(7) - 11;"
NL, "}"
NL
};
static const char* block_empty[] =
{
NL, "kernel void block_empty(__global int* res)"
NL, "{"
NL, " void (^kernelBlock)(void) = ^(){};"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " kernelBlock();"
NL, " res[tid] = 0;"
NL, "}"
NL
};
static const char* block_builtin[] =
{
NL, "kernel void block_builtin(__global int* res)"
NL, "{"
NL, " int b = 3;"
NL, " int (^kernelBlock)(int) = ^(int a)"
NL, " {"
NL, " return (int)abs(a - b);"
NL, " };"
NL, " size_t tid = get_global_id(0);"
NL, " res[tid] = -1;"
NL, " res[tid] = kernelBlock(2) - 1;"
NL, "}"
NL
};
static const char* block_barrier[] =
{
NL, "kernel void block_barrier(__global int* res)"
NL, "{"
NL, " int b = 3;"
NL, " size_t tid = get_global_id(0);"
NL, " size_t lsz = get_local_size(0);"
NL, " size_t gid = get_group_id(0);"
NL, " size_t idx = gid*lsz;"
NL, ""
NL, " res[tid]=lsz;"
NL, " barrier(CLK_GLOBAL_MEM_FENCE);"
NL, " int (^kernelBlock)(int) = ^(int a)"
NL, " {"
NL, " atomic_dec(res+idx);"
NL, " barrier(CLK_GLOBAL_MEM_FENCE);"
NL, " return (int)abs(a - b) - (res[idx] != 0 ? 0 : 1);"
NL, " };"
NL, ""
NL, " int d = kernelBlock(2);"
NL, " res[tid] = d;"
NL, "}"
NL
};
static const kernel_src sources_execute_block[] =
{
// Simple blocks
KERNEL(block_global_scope),
KERNEL(block_kernel_scope),
KERNEL(block_statement_scope),
KERNEL(block_function_scope),
KERNEL(block_nested_scope),
// Kernels with Block in for/while/if/switch
KERNEL(block_in_for_init),
KERNEL(block_in_for_cond),
KERNEL(block_in_for_iter),
KERNEL(block_in_while_cond),
KERNEL(block_in_while_body),
KERNEL(block_in_do_while_body),
KERNEL(block_cond_statement),
KERNEL(block_in_if_cond),
KERNEL(block_in_if_branch),
KERNEL(block_switch_cond),
KERNEL(block_switch_case),
KERNEL(block_literal),
// Accessing data from block
KERNEL(block_access_program_data),
KERNEL(block_access_kernel_data),
KERNEL(block_access_chained_data),
KERNEL(block_access_volatile_data),
// Block args
KERNEL(block_arg_struct),
KERNEL(block_arg_types_mix),
KERNEL(block_arg_pointer),
KERNEL(block_arg_global_p),
KERNEL(block_arg_const_p),
KERNEL(block_ret_struct),
KERNEL(block_arg_global_var),
// Block in typedef
KERNEL(block_typedef_kernel),
KERNEL(block_typedef_func),
KERNEL(block_typedef_stmnt_if),
KERNEL(block_typedef_loop),
KERNEL(block_typedef_mltpl_func),
KERNEL(block_typedef_mltpl_stmnt),
KERNEL(block_typedef_mltpl_g),
// Non - trivial blocks
KERNEL(block_complex),
KERNEL(block_empty),
KERNEL(block_builtin),
KERNEL(block_barrier),
};
static const size_t num_kernels_execute_block = arr_size(sources_execute_block);
static int check_kernel_results(cl_int* results, cl_int len)
{
for(cl_int i = 0; i < len; ++i)
{
if(results[i] != 0) return i;
}
return -1;
}
int test_execute_block(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
{
size_t i;
size_t ret_len;
cl_int n, err_ret, res = 0;
clCommandQueueWrapper dev_queue;
cl_int kernel_results[MAX_GWS] = {0xDEADBEEF};
size_t max_local_size = 1;
err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_local_size), &max_local_size, &ret_len);
test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_WORK_GROUP_SIZE) failed");
size_t global_size = MAX_GWS;
size_t local_size = (max_local_size > global_size/16) ? global_size/16 : max_local_size;
size_t failCnt = 0;
for(i = 0; i < num_kernels_execute_block; ++i)
{
if (!gKernelName.empty() && gKernelName != sources_execute_block[i].kernel_name)
continue;
log_info("Running '%s' kernel (%d of %d) ...\n", sources_execute_block[i].kernel_name, i + 1, num_kernels_execute_block);
err_ret = run_n_kernel_args(context, queue, sources_execute_block[i].lines, sources_execute_block[i].num_lines, sources_execute_block[i].kernel_name, local_size, global_size, kernel_results, sizeof(kernel_results), 0, NULL);
if(check_error(err_ret, "'%s' kernel execution failed", sources_execute_block[i].kernel_name)) { ++failCnt; res = -1; }
else if((n = check_kernel_results(kernel_results, arr_size(kernel_results))) >= 0 && check_error(-1, "'%s' kernel results validation failed: [%d] returned %d expected 0", sources_execute_block[i].kernel_name, n, kernel_results[n])) { ++failCnt; res = -1; }
else log_info("'%s' kernel is OK.\n", sources_execute_block[i].kernel_name);
}
if (failCnt > 0)
{
log_error("ERROR: %d of %d kernels failed.\n", failCnt, num_kernels_execute_block);
}
return res;
}
#endif