update, not finished

update, not finished

#include "../include/common.h"

inline int stringCmp(__global char * buf1, __global char * buf2, int size){
        int i;
        int res = 0;
        for(i=0;i<size;i++){
                if(buf1[i] > buf2[i]){
                        res = 1;
                        break;
                }else if (buf1[i] < buf2[i]){
                        res = -1;
                        break;
                }
                if(buf1[i] == 0 && buf2[i] == 0)
                        break;
        }
        return res;
}

inline int testCon_int(int buf1, __global char* buf2, int size, int type, int rel){
        int res = 1;
	if(rel == EQ){
                res = ( buf1 == *(((__global int*)buf2)) );
	}else if (rel == GTH){
		res = ( buf1 > *(((__global int*)buf2)) );
	}else if (rel == LTH){
		res = ( buf1 < *(((__global int*)buf2)) );
	}else if (rel == GEQ){
		res = ( buf1 >= *(((__global int*)buf2)) );
	}else if (rel == LEQ){
		res = ( buf1 <= *(((__global int*)buf2)) );
	}
	return res;
}

inline int testCon_float(float buf1, __global char* buf2, int size, int type, int rel){
        int res = 1;
	if(rel == EQ){
		res = ( buf1 == *(((__global float*)buf2)) );
	}else if (rel == GTH){
		res = ( buf1 > *(((__global float*)buf2)) );
	}else if (rel == LTH){
		res = ( buf1 < *(((__global float*)buf2)) );
	}else if (rel == GEQ){
		res = ( buf1 >= *(((__global float*)buf2)) );
	}else if (rel == LEQ){
		res = ( buf1 <= *(((__global float*)buf2)) );
	}
	return res;
}

inline int testCon_string(__global char *buf1, __global char* buf2, int size, int type, int rel){
        int res = 1;

	int tmp = stringCmp(buf1,buf2,size);
	if(rel == EQ){
		res = (tmp == 0);
	}else if (rel == GTH){
		res = (tmp > 0);
	}else if (rel == LTH){
		res = (tmp < 0);
	}else if (rel == GEQ){
		res = (tmp >= 0);
	}else if (rel == LEQ){
		res = (tmp <= 0);
	}

        return res;
}

__kernel void cl_memset_int(__global int * ar, int num){
        size_t stride = get_global_size(0);
        size_t offset = get_global_id(0);

        for(size_t i=offset; i<num; i+= stride)
                ar[i] = 0;
}

__kernel void transform_dict_filter_init(__global int * dictFilter, __global int *fact, long tupleNum, int dNum,  __global int * filter, int byteNum){

	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);

        int numInt = (tupleNum * byteNum +sizeof(int) - 1) / sizeof(int) ;

        for(size_t i=offset; i<numInt; i += stride){
                int tmp = fact[i];
                unsigned long bit = 1;

                for(int j=0; j< sizeof(int)/byteNum; j++){
                        int t = (bit << ((j+1)*byteNum*8)) -1 - ((1<<(j*byteNum*8))-1);
                        int fkey = (tmp & t)>> (j*byteNum*8) ;
                        filter[i* sizeof(int)/byteNum + j] = dictFilter[fkey];
                }
        }
}

__kernel void transform_dict_filter_and(__global int * dictFilter, __global int *fact, long tupleNum, int dNum,  __global int * filter, int byteNum){

	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);

        int numInt = (tupleNum * byteNum +sizeof(int) - 1) / sizeof(int) ;

        for(size_t i=offset; i<numInt; i += stride){
                int tmp = fact[i];
                unsigned long bit = 1;

                for(int j=0; j< sizeof(int)/byteNum; j++){
                        int t = (bit << ((j+1)*byteNum*8)) -1 - ((1<<(j*byteNum*8))-1);
                        int fkey = (tmp & t)>> (j*byteNum*8) ;
                        filter[i* sizeof(int)/byteNum + j] &= dictFilter[fkey];
                }
        }
}

__kernel void transform_dict_filter_or(__global int * dictFilter, __global int *fact, long tupleNum, int dNum,  __global int * filter,int byteNum){

	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);

        int numInt = (tupleNum * byteNum +sizeof(int) - 1) / sizeof(int) ;

        for(size_t i=offset; i<numInt; i += stride){
                int tmp = fact[i];
                unsigned long bit = 1;

                for(int j=0; j< sizeof(int)/byteNum; j++){
                        int t = (bit << ((j+1)*byteNum*8)) -1 - ((1<<(j*byteNum*8))-1);
                        int fkey = (tmp & t)>> (j*byteNum*8) ;
                        filter[i* sizeof(int)/byteNum + j] |= dictFilter[fkey];
                }
        }
}

__kernel void genScanFilter_dict_init(__global char *col, int colSize, int colType, int dNum, __global struct whereExp *where, __global int *dfilter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i=tid;i<dNum;i+=stride){
                int fkey = ((__global struct dictHeader*)col)->hash[i];
                con = testCon_int(fkey,where->content,colSize,colType,where->relation);
                dfilter[i] = con;
        }
}

__kernel void genScanFilter_dict_or(__global char *col, int colSize, int colType, int dNum, __global struct whereExp *where, __global int *dfilter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i=tid;i<dNum;i+=stride){
                int fkey = ((__global struct dictHeader*)col)->hash[i];
                con = testCon_int(fkey,where->content,colSize,colType,where->relation);
                con = testCon_int(fkey,where->content,colSize,colType,where->relation);
                dfilter[i] |= con;
        }
}

__kernel void genScanFilter_dict_and(__global char *col, int colSize, int colType, int dNum, __global struct whereExp *where, __global int *dfilter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i=tid;i<dNum;i+=stride){
                int fkey = ((__global struct dictHeader*)col)->hash[i];
                con = testCon_int(fkey,where->content,colSize,colType,where->relation);
                dfilter[i] &= con;
        }
}

__kernel void genScanFilter_rle(__global char *col, int colSize, int colType, long tupleNum, __global struct whereExp *where, int andOr, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        int dNum = ((__global struct rleHeader*)col)->dictNum;

        for(size_t i = tid; i<dNum; i += stride){
                int fkey = ((__global int *)(col+sizeof(struct rleHeader)))[i];
                int fcount = ((__global int *)(col+sizeof(struct rleHeader)))[i + dNum];
                int fpos = ((__global int *)(col+sizeof(struct rleHeader)))[i + 2*dNum];

                con = testCon_int(fkey,where->content,colSize,colType,where->relation);

		for(int k=0;k<fcount;k++){
			if(andOr == AND)
				filter[fpos+k] &= con;
			else
				filter[fpos+k] |= con;
		}

        }
}

__kernel void genScanFilter_init_int_eq(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] == where;
                filter[i] = con;
        }
}
__kernel void genScanFilter_init_float_eq(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] == where;
                filter[i] = con;
        }
}
__kernel void genScanFilter_init_int_gth(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] > where;
                filter[i] = con;
        }
}

__kernel void genScanFilter_init_float_gth(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] > where;
                filter[i] = con;
        }
}

__kernel void genScanFilter_init_int_lth(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] < where;
                filter[i] = con;
        }
}
__kernel void genScanFilter_init_float_lth(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] < where;
                filter[i] = con;
        }
}
__kernel void genScanFilter_init_int_geq(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] >= where;
                filter[i] = con;
        }
}
__kernel void genScanFilter_init_float_geq(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] >= where;
                filter[i] = con;
        }
}

__kernel void genScanFilter_init_int_leq(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] <= where;
                filter[i] = con;
        }
}
__kernel void genScanFilter_init_float_leq(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] <= where;
                filter[i] = con;
        }
}

__kernel void genScanFilter_and(__global char *col, int colSize, int  colType, long tupleNum, __global struct whereExp * where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = testCon_string(col+colSize*i,where->content,colSize,colType,where->relation);
                filter[i] &= con;
        }
}

__kernel void genScanFilter_and_int_eq(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] == where;
                filter[i] &= con;
        }
}

__kernel void genScanFilter_and_float_eq(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] == where;
                filter[i] &= con;
        }
}

__kernel void genScanFilter_and_int_geq(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] >= where;
                filter[i] &= con;
        }
}

__kernel void genScanFilter_and_float_geq(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] >= where;
                filter[i] &= con;
        }
}

__kernel void genScanFilter_and_int_leq(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] <= where;
                filter[i] &= con;
        }
}

__kernel void genScanFilter_and_float_leq(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] <= where;
                filter[i] &= con;
        }
}

__kernel void genScanFilter_and_int_gth(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] > where;
                filter[i] &= con;
        }
}

__kernel void genScanFilter_and_float_gth(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] > where;
                filter[i] &= con;
        }
}

__kernel void genScanFilter_and_int_lth(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] < where;
                filter[i] &= con;
        }
}

__kernel void genScanFilter_and_float_lth(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] < where;
                filter[i] &= con;
        }
}

__kernel void genScanFilter_init(__global char *col, int colSize, int  colType, long tupleNum, __global struct whereExp * where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;
        int rel = where->relation;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = testCon_string(col+colSize*i,where->content,colSize,colType, rel);
                filter[i] = con;
        }
}

__kernel void genScanFilter_or(__global char *col, int colSize, int  colType, long tupleNum, __global struct whereExp * where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;
        int rel = where->relation;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = testCon_string(col+colSize*i,where->content,colSize,colType, rel);
                filter[i] |= con;
        }
}

__kernel void genScanFilter_or_int_eq(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] == where;
                filter[i] |= con;
        }
}
__kernel void genScanFilter_or_float_eq(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] == where;
                filter[i] |= con;
        }
}
__kernel void genScanFilter_or_int_gth(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] > where;
                filter[i] |= con;
        }
}

__kernel void genScanFilter_or_float_gth(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] > where;
                filter[i] |= con;
        }
}

__kernel void genScanFilter_or_int_lth(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] < where;
                filter[i] |= con;
        }
}
__kernel void genScanFilter_or_float_lth(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] < where;
                filter[i] |= con;
        }
}
__kernel void genScanFilter_or_int_geq(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] >= where;
                filter[i] |= con;
        }
}
__kernel void genScanFilter_or_float_geq(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] >= where;
                filter[i] |= con;
        }
}

__kernel void genScanFilter_or_int_leq(__global int *col, long tupleNum, int where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] <= where;
                filter[i] |= con;
        }
}
__kernel void genScanFilter_or_float_leq(__global float *col, long tupleNum, float where, __global int * filter){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int con;

        for(size_t i = tid; i<tupleNum;i+=stride){
                con = col[i] <= where;
                filter[i] |= con;
        }
}

__kernel void countScanNum(__global int *filter, long tupleNum, __global int * count){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int localCount = 0;

        for(size_t i = tid; i<tupleNum; i += stride){
                localCount += filter[i];
        }

        count[tid] = localCount;

}

__kernel void scan_dict_other(__global char *col, __global char * dict, int byteNum,int colSize, long tupleNum, __global int *psum, long resultNum, __global int * filter, __global char * result){

	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        __global struct dictHeader *dheader = (__global struct dictHeader*)dict;
        int pos = psum[tid] * colSize;

        for(size_t i = tid; i<tupleNum; i+= stride){
                if(filter[i] == 1){
                        int key = 0;
			char * buf = (char *)&key;

			for(int k=0;k<dheader->bitNum/8;k++)
				buf[k] = (col + sizeof(struct dictHeader) + i* dheader->bitNum/8)[k];

			int kvalue = dheader->hash[key];
			buf = (char *) &kvalue;
			for(int k=0;k<colSize;k++)
				(result+pos)[k] = buf[k];
                        pos += colSize;
                }
        }
}

__kernel void scan_dict_int(__global char *col, __global char * dict,int byteNum,int colSize, long tupleNum, __global int *psum, long resultNum, __global int * filter, __global int * result){

	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int localCount = psum[tid];
        __global struct dictHeader *dheader = (__global struct dictHeader*)dict;

        for(size_t i = tid; i<tupleNum; i+= stride){
                if(filter[i] == 1){
                        int key = 0;
			char * buf = (char *)&key;
			for(int k=0;k<byteNum;k++)
				buf[k] = (col+i*byteNum)[k];
                        result[localCount] = dheader->hash[key];
                        localCount ++;
                }
        }
}

__kernel void scan_other(__global char *col, int colSize, long tupleNum, __global int *psum, long resultNum, __global int * filter, __global char * result){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int pos = psum[tid]  * colSize;

        for(size_t i = tid; i<tupleNum;i+=stride){

                if(filter[i] == 1){
			for(int k=0;k<colSize;k++)
				(result+pos)[k] = (col+i*colSize)[k];
                        pos += colSize;
                }
        }
}

__kernel void scan_int(__global int *col, int colSize, long tupleNum, __global int *psum, long resultNum, __global int * filter, __global int * result){
	size_t stride = get_global_size(0);
	size_t tid = get_global_id(0);
        int localCount = psum[tid] ;

        for(size_t i = tid; i<tupleNum;i+=stride){

                if(filter[i] == 1){
                        result[localCount] = col[i];
                        localCount ++;
                }
        }
}

__kernel void unpack_rle(__global char * fact, __global char * rle, long tupleNum, int dNum){

	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);

        for(size_t i=offset; i<dNum; i+=stride){

                int fvalue = ((__global int *)(fact+sizeof(struct rleHeader)))[i];
                int fcount = ((__global int *)(fact+sizeof(struct rleHeader)))[i + dNum];
                int fpos = ((__global int *)(fact+sizeof(struct rleHeader)))[i + 2*dNum];

		for(int k=0;k<fcount;k++){
			((__global int*)rle)[fpos+ k] = fvalue;
		}
        }
}

//The following kernels are for traditional hash joins

__kernel void count_hash_num(__global int *dim, long  inNum, __global int *num){
	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);

        for(size_t i=offset;i<inNum;i+=stride){
                int joinKey = dim[i];
                int hKey = joinKey & (HSIZE-1);
                atomic_add(&(num[hKey]),1);
        }
}

__kernel void build_hash_table(__global int *dim, long inNum, __global int *psum, __global int * bucket){

	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);

        for(size_t i=offset;i<inNum;i+=stride){
                int joinKey = dim[i];
                int hKey = joinKey & (HSIZE-1);
                int pos = atomic_add(&psum[hKey],1) * 2;
                bucket[pos] = joinKey;
                pos += 1;
                int dimId = i+1;
                bucket[pos] = dimId;
        }

}

__kernel void count_join_result_dict(__global int *num, __global int* psum, __global int* bucket, __global char* fact, int dNum, __global int* dictFilter){

	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);

        __global struct dictHeader *dheader = (__global struct dictHeader *) fact;

        for(size_t i=offset;i<dNum;i+=stride){
                int fkey = dheader->hash[i];
                int hkey = fkey &(HSIZE-1);
                int keyNum = num[hkey];
		int fvalue = 0;

                for(int j=0;j<keyNum;j++){
                        int pSum = psum[hkey];
                        int dimKey = bucket[2*j + 2*pSum];
                        int dimId = bucket[2*j + 2*pSum + 1];
                        if( dimKey == fkey){
				fvalue = dimId;
                                break;
                        }
                }
                dictFilter[i] = fvalue;
        }

}

__kernel void filter_count(long tupleNum, __global int * count, __global int * factFilter){

        int lcount = 0;
	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);

        for(size_t i=offset; i<tupleNum; i+=stride){
                if(factFilter[i] !=0)
                        lcount ++;
        }
        count[offset] = lcount;
}

__kernel void count_join_result_rle(__global int* num, __global int* psum, __global int* bucket, __global char* fact, long tupleNum, __global int * factFilter){

	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);

        __global struct rleHeader *rheader = (__global struct rleHeader *)fact;
        int dNum = rheader->dictNum;

        for(size_t i=offset; i<dNum; i += stride){
                int fkey = ((__global int *)(fact+sizeof(struct rleHeader)))[i];
                int fcount = ((__global int *)(fact+sizeof(struct rleHeader)))[i + dNum];
                int fpos = ((__global int *)(fact+sizeof(struct rleHeader)))[i + 2*dNum];

                int hkey = fkey &(HSIZE-1);
                int keyNum = num[hkey];
                int pSum = psum[hkey];

                for(int j=0;j<keyNum;j++){

                        int dimKey = bucket[2*j + 2*pSum];
                        int dimId = bucket[2*j + 2*pSum + 1];

                        if( dimKey == fkey){

                                for(int k=0;k<fcount;k++)
                                        factFilter[fpos+k] = dimId;

                                break;
                        }
                }
        }

}

__kernel  void count_join_result(__global int* num, __global int* psum, __global int* bucket, __global int* fact, long inNum, __global int* count, __global int * factFilter){
        int lcount = 0;
	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);

        for(size_t i=offset;i<inNum;i+=stride){
                int fkey = fact[i];
                int hkey = fkey &(HSIZE-1);
                int keyNum = num[hkey];
		int fvalue = 0;

                for(int j=0;j<keyNum;j++){
                        int pSum = psum[hkey];
                        int dimKey = bucket[2*j + 2*pSum];
                        int dimId = bucket[2*j + 2*pSum + 1];
                        if( dimKey == fkey){
                                lcount ++;
				fvalue = dimId;
                                break;
                        }
                }
                factFilter[i] = fvalue;
        }

        count[offset] = lcount;
}

__kernel void rle_psum(__global int *count, __global char * fact,  long  tupleNum,  __global int * filter){

	size_t offset = get_global_id(0);
	size_t stride = get_global_size(0);

        __global struct rleHeader *rheader = (__global struct rleHeader *) fact;
        int dNum = rheader->dictNum;

        for(size_t i= offset; i<dNum; i+= stride){

                int fcount = ((__global int *)(fact+sizeof(struct rleHeader)))[i + dNum];
                int fpos = ((__global int *)(fact+sizeof(struct rleHeader)))[i + 2*dNum];
                int lcount= 0;

		for(int k=0;k<fcount;k++){
			if(filter[fpos+ k]!=0)
				lcount++;
		}
		count[i] = lcount;
        }

}

__kernel void joinFact_rle(__global int *resPsum, __global char * fact,  int attrSize, long  tupleNum, __global int * filter, __global int * result){

	size_t startIndex = get_global_id(0);
	size_t stride = get_global_size(0);

        __global struct rleHeader *rheader = (__global struct rleHeader *) fact;
        int dNum = rheader->dictNum;

        for(size_t i = startIndex; i<dNum; i += stride){
                int fkey = ((__global int *)(fact+sizeof(struct rleHeader)))[i];
                int fcount = ((__global int *)(fact+sizeof(struct rleHeader)))[i + dNum];
                int fpos = ((__global int *)(fact+sizeof(struct rleHeader)))[i + 2*dNum];

		int toffset = resPsum[i];
		for(int j=0;j<fcount;j++){
			if(filter[fpos-j] !=0){
				result[toffset] = fkey ;
				toffset ++;
			}
		}
        }

}

__kernel void joinFact_dict_other(__global int *resPsum, __global char * fact,  __global char *dict, int byteNum,int attrSize, long  num, __global int * filter, __global char * result){

	size_t startIndex = get_global_id(0);
	size_t stride = get_global_size(0);
        long localOffset = resPsum[startIndex] * attrSize;

        __global struct dictHeader *dheader = (__global struct dictHeader*)dict;

        for(size_t i=startIndex;i<num;i+=stride){
                if(filter[i] != 0){
                        int key = 0;
			char *buf = (char *) &key;
			for(int k=0;k<byteNum;k++)
				buf[k] = (fact + i*byteNum)[k];
			int kvalue = dheader->hash[key];
			buf = (char *)&kvalue;
			for(int k=0;k<attrSize;k++)
				(result + localOffset)[k] = buf[k];
                        localOffset += attrSize;
                }
        }
}

__kernel void joinFact_dict_int(__global int *resPsum, __global char * fact, __global char *dict, int byteNum, int attrSize, long  num, __global int * filter, __global int * result){

	size_t startIndex = get_global_id(0);
	size_t stride = get_global_size(0);
        long localCount = resPsum[startIndex];

        __global struct dictHeader *dheader = (__global struct dictHeader*)dict;

        for(size_t i=startIndex;i<num;i+=stride){
                if(filter[i] != 0){
                        int key = 0;
			char *buf = (char *)&key;
			for(int k=0;k<byteNum;k++)
				buf[k] = (fact + i *byteNum)[k];
                        result[localCount] = dheader->hash[key];
                        localCount ++;
                }
        }
}

__kernel void joinFact_other(__global int *resPsum, __global char * fact,  int attrSize, long  num, __global int * filter, __global char * result){

	size_t startIndex = get_global_id(0);
	size_t stride = get_global_size(0);
        long localOffset = resPsum[startIndex] * attrSize;

        for(size_t i=startIndex;i<num;i+=stride){
                if(filter[i] != 0){
			for(int k=0;k<attrSize;k++)
				(result+localOffset)[k] = (fact + i*attrSize)[k];
                        localOffset += attrSize;
                }
        }
}

__kernel void joinFact_int(__global int *resPsum, __global int * fact,  int attrSize, long  num, __global int * filter, __global int * result){

	size_t startIndex = get_global_id(0);
	size_t stride = get_global_size(0);
        long localCount = resPsum[startIndex];

        for(size_t i=startIndex;i<num;i+=stride){
                if(filter[i] != 0){
                        result[localCount] = fact[i];
                        localCount ++;
                }
        }
}

__kernel void joinDim_rle(__global int *resPsum, __global char * dim, int attrSize, long tupleNum,__global int * filter, __global int * result){

	size_t startIndex = get_global_id(0);
	size_t stride = get_global_size(0);
        long localCount = resPsum[startIndex];

        __global struct rleHeader *rheader = (__global struct rleHeader *) dim;
        int dNum = rheader->dictNum;

        for(size_t i = startIndex; i<tupleNum; i += stride){
                int dimId = filter[i];
                if(dimId != 0){
                        for(int j=0;j<dNum;j++){
                                int dkey = ((__global int *)(dim+sizeof(struct rleHeader)))[j];
                                int dcount = ((__global int *)(dim+sizeof(struct rleHeader)))[j + dNum];
                                int dpos = ((__global int *)(dim+sizeof(struct rleHeader)))[j + 2*dNum];

                                if(dpos == dimId || ((dpos < dimId) && (dpos + dcount) > dimId)){
                                        result[localCount] = dkey ;
                                        localCount ++;
                                        break;
                                }

                        }
                }
        }
}

__kernel void joinDim_dict_other(__global int *resPsum, __global char * dim, __global char *dict, int byteNum, int attrSize, long num, __global int * filter, __global char * result){

	size_t startIndex = get_global_id(0);
	size_t stride = get_global_size(0);
        long localOffset = resPsum[startIndex] * attrSize;

        __global struct dictHeader *dheader = (__global struct dictHeader*)dict;

        for(size_t i=startIndex;i<num;i+=stride){
                int dimId = filter[i];
                if( dimId != 0){
                        int key = 0;
			char *buf = (char *)&key;
			for(int k=0;k<byteNum;k++)
				buf[k] = (dim + (dimId-1) * byteNum)[k];
			int kvalue = dheader->hash[key];
			buf = (char *)&kvalue;
			for(int k=0;k<attrSize;k++)
				(result+localOffset)[k] = buf[k];
                        localOffset += attrSize;
                }
        }
}

__kernel void joinDim_dict_int(__global int *resPsum, __global char * dim, __global char *dict, int byteNum, int attrSize, long num, __global int * filter, __global int * result){

	size_t startIndex = get_global_id(0);
	size_t stride = get_global_size(0);
        long localCount = resPsum[startIndex];

        __global struct dictHeader *dheader = (__global struct dictHeader*)dict;

        for(size_t i=startIndex;i<num;i+=stride){
                int dimId = filter[i];
                if( dimId != 0){
                        int key = 0;
			char * buf = (char *)&key;
			for(int k=0;k<byteNum;k++)
				buf[k] = (dim + (dimId-1)*byteNum)[k];
                        result[localCount] = dheader->hash[key];
                        localCount ++;
                }
        }
}

__kernel void joinDim_int(__global int *resPsum, __global int * dim, int attrSize, long num, __global int * filter, __global int * result){

	size_t startIndex = get_global_id(0);
	size_t stride = get_global_size(0);
        long localCount = resPsum[startIndex];

        for(size_t i=startIndex;i<num;i+=stride){
                int dimId = filter[i];
                if( dimId != 0){
                        result[localCount] = dim[dimId-1];
                        localCount ++;
                }
        }
}

__kernel void joinDim_other(__global int *resPsum, __global char * dim, int attrSize, long num, __global int * filter, __global char * result){

	size_t startIndex = get_global_id(0);
	size_t stride = get_global_size(0);
        long localOffset = resPsum[startIndex] * attrSize;

        for(size_t i=startIndex;i<num;i+=stride){
                int dimId = filter[i];
                if( dimId != 0){
			for(int k=0;k<attrSize;k++)
				(result+localOffset)[k] = (dim + (dimId-1)*attrSize)[k];
                        localOffset += attrSize;
                }
        }
}

// for groupBy

char * gpuItoa(int value, char* result, int base){

        if (base < 2 || base > 36) {
                *result = '\0';
                return result;
        }

        char* ptr = result, *ptr1 = result, tmp_char;
        int tmp_value;

        do {
                tmp_value = value;
                value /= base;
                *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
        } while ( value );

        if (tmp_value < 0)
                *ptr++ = '-';

        *ptr-- = '\0';

        while(ptr1 < ptr) {
                tmp_char = *ptr;
                *ptr--= *ptr1;
                *ptr1++ = tmp_char;
        }
        return result;

}

char * gpuStrcpy(char * dst, const char * src){

        char * orig = dst;
        while(*src)
                *dst++ = *src++;
        *dst = '\0';

        return orig;
}

char* gpuStrncat(char *dest, const char *src, size_t n)
{
        int dest_len = 0;
        int i;

        char * tmp = dest;
        while(*tmp != '\0'){
                tmp++;
                dest_len ++;
        }

        for (i = 0 ; i < n && src[i] != '\0' ; i++)
                dest[dest_len + i] = src[i];
        dest[dest_len + i] = '\0';
        return dest;
}

char * gpuStrcat(char * dest, const char * src){
        char *tmp =dest;
        int dest_len = 0;
        int i;

        while (*tmp!= '\0'){
                tmp++ ;
                dest_len ++;
        }

        for(i=0; src[i] !='\0'; i++){
                dest[dest_len + i] = src[i];
        }

        dest[dest_len + i] = '\0';

        return dest;
}

unsigned int StringHash(const char* s)
{
    unsigned int hash = 0;
    int c;

    while((c = *s++))
    {
        hash = ((hash << 5) + hash) ^ c;
    }

    return hash;
}

__kernel void build_groupby_key(__global char * content, __global long * colOffset, int gbColNum, __global int * gbIndex, __global int * gbType, __global int * gbSize, long tupleNum, __global int * key, __global int *num){

	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);

        for(size_t i = offset; i< tupleNum; i+= stride){
                char buf[128] = {0};
                for (int j=0; j< gbColNum; j++){
                        char tbuf[32]={0};
                        int index = gbIndex[j];
			long offset = colOffset[index];

                        if (index == -1){
                                gpuItoa(1,tbuf,10);
                                gpuStrncat(buf,tbuf,1);

                        }else if (gbType[j] == STRING){
				for(int k=0;k<gbSize[j];k++)
					tbuf[k] = (content+offset+i*gbSize[j])[k];
                                gpuStrncat(buf, tbuf, gbSize[j]);

                        }else if (gbType[j] == INT){
                                int key = ((__global int *)(content+offset))[i];
                                gpuItoa(key,tbuf,10);
                                gpuStrcat(buf,tbuf);
                        }
                }
                int hkey = StringHash(buf) % HSIZE;
                key[i]= hkey;
                num[hkey] = 1;
        }
}

__kernel void count_group_num(__global int *num, int tupleNum, __global int *totalCount){
	size_t stride = get_global_size(0);
	size_t offset = get_global_id(0);
        int localCount = 0;

        for(size_t i=offset; i<tupleNum; i+= stride){
                if(num[i] == 1){
                        localCount ++;
                }
        }

        atomic_add(totalCount,localCount);
}

float getExp(__global char *content, __global int * colOffset,struct colExp exp,int pos){
	float res = 0;;
        if(exp.op == NOOP){
                if (exp.opType == CONS)
                        res = exp.opValue;
                else{
                        int index = exp.opValue;
                        res = ((__global int *)(content+colOffset[index]))[pos];
                }
	}
	return res;
}

float calMathExp(__global char *content, __global int * colOffset,struct groupByExp exp, __global struct colExp *mexp, int pos){
        float res ;

        if(exp.exp.op == NOOP){
                if (exp.exp.opType == CONS)
                        res = exp.exp.opValue;
                else{
                        int index = exp.exp.opValue;
                        res = ((__global int *)(content+colOffset[index]))[pos];
                }

        }else if(exp.exp.op == PLUS ){
                res = getExp(content,colOffset,mexp[2*pos],pos) + getExp(content, colOffset,mexp[2*pos+1],pos);

        }else if (exp.exp.op == MINUS){
                res = getExp(content,colOffset,mexp[2*pos],pos) - getExp(content, colOffset,mexp[2*pos+1],pos);

        }else if (exp.exp.op == MULTIPLY){
                res = getExp(content,colOffset,mexp[2*pos],pos) * getExp(content, colOffset,mexp[2*pos+1], pos);

        }else if (exp.exp.op == DIVIDE){
                res = getExp(content,colOffset,mexp[2*pos],pos) / getExp(content, colOffset,mexp[2*pos+1],pos);
        }

        return res;
}

// for atomic add on float type data

inline void AtomicAdd(__global float *source, float operand) {
    union {
        unsigned int intVal;
        float floatVal;
    } newVal;
    union {
        unsigned int intVal;
        float floatVal;
    } prevVal;
    do {
        prevVal.floatVal = *source;
        newVal.floatVal = prevVal.floatVal + operand;
    } while (atomic_cmpxchg((volatile __global unsigned int *)source, prevVal.intVal, newVal.intVal) != prevVal.intVal);
}

__kernel void agg_cal_cons(__global char * content, __global int* colOffset, int colNum, __global struct groupByExp* exp, __global struct colExp *mexp, __global int * gbType, __global int * gbSize, long tupleNum, __global int * key, __global int *psum,  __global char * result, __global long * resOffset){

	size_t stride = get_global_size(0);
	size_t index = get_global_id(0);

        float buf[32];
        for(int i=0;i<32;i++)
                buf[i] = 0;

        for(size_t i=index;i<tupleNum;i+=stride){

                for(int j=0;j<colNum;j++){
                        int func = exp[j].func;
                        if (func == SUM){
                                float tmpRes = calMathExp(content, colOffset,exp[j], mexp, i);
                                buf[j] += tmpRes;
                        }
                }
        }

        for(int i=0;i<colNum;i++)
                AtomicAdd(&((__global float *)(result+resOffset[i]))[0], buf[i]);
}

__kernel void agg_cal(__global char * content, __global int *colOffset, int colNum, __global struct groupByExp* exp, __global struct colExp *mexp, __global int * gbType, __global int * gbSize, long tupleNum, __global int * key, __global int *psum,  __global char * result, __global long * resOffset){

	size_t stride = get_global_size(0);
	size_t index = get_global_id(0);

        for(int i=index;i<tupleNum;i+=stride){

                int hKey = key[i];
                int offset = psum[hKey];

                for(int j=0;j<colNum;j++){
                        int func = exp[j].func;
                        if(func ==NOOP){
                                int type = exp[j].exp.opType;

                                if(type == CONS){
                                        int value = exp[j].exp.opValue;
                                        ((__global int *)(result + resOffset[j]))[offset] = value;
                                }else{
                                        int index = exp[j].exp.opValue;
                                        int attrSize = gbSize[j];
                                        if(attrSize == sizeof(int))
                                                ((__global int *)(result+resOffset[j]))[offset] = ((__global int*)(content + colOffset[index]))[i];
                                        else{
						for(int k=0;k<attrSize;k++)
							(result+resOffset[j] + offset*attrSize)[k] = (content + colOffset[index] + i*attrSize)[k];
					}
                                }

                        }else if (func == SUM){
                                float tmpRes = calMathExp(content, colOffset, exp[j],mexp, i);
                                AtomicAdd(& ((__global float *)(result+resOffset[j]))[offset], tmpRes);
                        }
                }
        }
}

// for scan
#define NUM_BANKS 16
#define LOG_NUM_BANKS 4

inline int CONFLICT_FREE_OFFSET(int index)
{
        return ((index) >> LOG_NUM_BANKS);
}

inline void loadSharedChunkFromMem(__local int *s_data,
                                                                           __global int *g_idata,
                                                                           int n, int baseIndex,
                                                                           int* ai, int* bi,
                                                                           int* mem_ai, int* mem_bi,
                                                                           int* bankOffsetA, int* bankOffsetB, int isNP2)
{
        size_t thid = get_local_id(0);
        *mem_ai = baseIndex + thid;
        *mem_bi = *mem_ai + get_local_size(0);

        *ai = thid;
        *bi = thid + get_local_size(0);

        // compute spacing to avoid bank conflicts
        *bankOffsetA = CONFLICT_FREE_OFFSET(*ai);
        *bankOffsetB = CONFLICT_FREE_OFFSET(*bi);

        s_data[*ai + *bankOffsetA] = g_idata[*mem_ai];

        if (isNP2)
        {
                s_data[*bi + *bankOffsetB] = (*bi < n) ? g_idata[*mem_bi] : 0;
        }
        else
        {
                s_data[*bi + *bankOffsetB] = g_idata[*mem_bi];
        }
}

inline void storeSharedChunkToMem(__global int* g_odata,
                                      __local int* s_data,
                                      int n,
                                      int ai, int bi,
                                      int mem_ai, int mem_bi,
                                      int bankOffsetA, int bankOffsetB, int isNP2)
{
    barrier(CLK_LOCAL_MEM_FENCE);

    g_odata[mem_ai] = s_data[ai + bankOffsetA];
    if (isNP2)
    {
        if (bi < n)
            g_odata[mem_bi] = s_data[bi + bankOffsetB];
    }
    else
    {
        g_odata[mem_bi] = s_data[bi + bankOffsetB];
    }
}

inline void clearLastElement(__local int* s_data,
                                 __global int *g_blockSums,
                                 int blockIndex, int storeSum)
{
    if (get_local_id(0) == 0)
    {
        int index = (get_local_size(0) << 1) - 1;
        index += CONFLICT_FREE_OFFSET(index);

        if (storeSum)
        {
            g_blockSums[blockIndex] = s_data[index];
        }

        s_data[index] = 0;
    }
}

inline int buildSum(__local int *s_data)
{
    int thid = get_local_id(0);
    int stride = 1;

    for (size_t d = get_local_size(0); d > 0; d >>= 1)
    {
	barrier(CLK_LOCAL_MEM_FENCE);

        if (thid < d)
        {
            int i  = mul24(mul24(2, stride), thid);
            int ai = i + stride - 1;
            int bi = ai + stride;

            ai += CONFLICT_FREE_OFFSET(ai);
            bi += CONFLICT_FREE_OFFSET(bi);

            s_data[bi] += s_data[ai];
        }

        stride *= 2;
    }

    return stride;
}

void scanRootToLeaves(__local int *s_data, int stride)
{
    int thid = get_local_id(0);

    for (size_t d = 1; d <= get_local_size(0); d *= 2)
    {
        stride >>= 1;

	barrier(CLK_LOCAL_MEM_FENCE);

        if (thid < d)
        {
            int i  = mul24(mul24(2, stride), thid);
            int ai = i + stride - 1;
            int bi = ai + stride;

            ai += CONFLICT_FREE_OFFSET(ai);
            bi += CONFLICT_FREE_OFFSET(bi);

            int t  = s_data[ai];
            s_data[ai] = s_data[bi];
            s_data[bi] += t;
        }
    }
}

void prescanBlock(__local int *data, int blockIndex, __global int *blockSums, int storeSum)
{
    int stride = buildSum(data);               // build the sum in place up the tree
    clearLastElement(data, blockSums,
                               (blockIndex == 0) ? get_group_id(0) : blockIndex, storeSum);
    scanRootToLeaves(data, stride);            // traverse down tree to build the scan
}

__kernel void prescan(__global int *g_odata,
                        __global int *g_idata,
                        __global int *g_blockSums,
                        int n,
                        int blockIndex,
                        int baseIndex, int storeSum, int isNP2, __local int * s_data
                                                )
{
    int ai, bi, mem_ai, mem_bi, bankOffsetA, bankOffsetB;
    int bid = get_group_id(0);
    int bsize = get_local_size(0);

    loadSharedChunkFromMem(s_data, g_idata, n,
                                  (baseIndex == 0) ?
                                  mul24(bid, (bsize << 1)):baseIndex,
                                  &ai, &bi, &mem_ai, &mem_bi,
                                  &bankOffsetA, &bankOffsetB, isNP2);

    prescanBlock(s_data, blockIndex, g_blockSums,storeSum);

    storeSharedChunkToMem(g_odata, s_data, n,
                                 ai, bi, mem_ai, mem_bi,
                                 bankOffsetA, bankOffsetB, isNP2);
}

__kernel void uniformAdd(__global int *g_data,
                           __global int *uniforms,
                           int n,
                           int blockOffset,
                           int baseIndex)
{
    __local int uni;
    if (get_local_id(0) == 0)
        uni = uniforms[get_group_id(0) + blockOffset];

    int bid = get_group_id(0);
    int bsize = get_local_size(0);

    int address = mul24(bid, (bsize << 1)) + baseIndex + get_local_id(0);

    barrier(CLK_LOCAL_MEM_FENCE);

    g_data[address]              += uni;
    g_data[address + get_local_size(0)] += (get_local_id(0) + get_local_size(0) < n) * uni;
}

// for materialization

__kernel void materialize(__global char * content, __global long * colOffset, int colNum, __global int *attrSize, long tupleNum, int tupleSize, __global char *result){
	size_t startIndex = get_global_id(0);
	size_t stride = get_global_size(0);

        for(size_t i=startIndex;i<tupleNum;i+=stride){
                int offset = 0;
                for(int j=0;j<colNum;j++){
                        int aSize = attrSize[j];
			for(int k=0;k<aSize;k++)
				(result + i*tupleSize + offset)[k] = (content + colOffset[j] + i*aSize)[k];
                        offset += aSize;
                }
        }
}

// for order by

#define SAMPLE_STRIDE 128
#define SHARED_SIZE_LIMIT 1024

int gpu_strcmp(const char *s1, const char *s2, int len){
        int res = 0;

        for(int i=0;i < len;i++){
                if(s1[i]<s2[i]){
                        res = -1;
                        break;
                }else if(s1[i]>s2[i]){
                        res = 1;
                        break;
                }
        }
        return res;

}

#define W (sizeof(int) * 8)
int nextPowerOfTwo(int x){
    /*
        --x;
        x |= x >> 1;
        x |= x >> 2;
        x |= x >> 4;
        x |= x >> 8;
        x |= x >> 16;
        return ++x;
    */
    return 1U << (W - __clz(x - 1));
}

int iDivUp(int a, int b){
    return ((a % b) == 0) ? (a / b) : (a / b + 1);
}

int getSampleCount(int dividend){
    return iDivUp(dividend, SAMPLE_STRIDE);
}

int binarySearchInInt(int val, int *data, int L, int stride, int sortDir){
    if (L == 0)
    {
        return 0;
    }

    int pos = 0;

    for (; stride > 0; stride >>= 1)
    {
        int newPos = umin(pos + stride, L);

        if ((sortDir && (data[newPos - 1] <= val)) || (!sortDir && (data[newPos - 1] >= val)))
        {
            pos = newPos;
        }
    }

    return pos;
}

int binarySearchExInt(int val, int *data, int L, int stride, int sortDir){
    if (L == 0)
    {
        return 0;
    }

    int pos = 0;

    for (; stride > 0; stride >>= 1)
    {
        int newPos = umin(pos + stride, L);

        if ((sortDir && (data[newPos - 1] < val)) || (!sortDir && (data[newPos - 1] > val)))
        {
            pos = newPos;
        }
    }

    return pos;
}

int binarySearchIn(char * val, char *data, int L, int stride, int sortDir, int keySize){
    if (L == 0)
    {
        return 0;
    }

    int pos = 0;

    for (; stride > 0; stride >>= 1)
    {
        int newPos = umin(pos + stride, L);

        if ((sortDir && (gpu_strcmp(data+(newPos-1)*keySize,val,keySize) != 1)) || (!sortDir && (gpu_strcmp(data + (newPos-1)*keySize,val,keySize)!=-1)))
        {
            pos = newPos;
        }
    }

    return pos;
}

int binarySearchEx(char * val, char *data, int L, int stride, int sortDir, int keySize){
    if (L == 0)
    {
        return 0;
    }

    int pos = 0;

    for (; stride > 0; stride >>= 1)
    {
        int newPos = umin(pos + stride, L);

        if ((sortDir && (gpu_strcmp(data+(newPos-1)*keySize,val,keySize) == -1)) || (!sortDir && (gpu_strcmp(data + (newPos-1)*keySize,val,keySize)==1)))
        {
            pos = newPos;
        }
    }

    return pos;
}

__kernel void generateSampleRanksKernel(
        int *d_RanksA,
        int *d_RanksB,
        char *d_SrcKey,
        int keySize,
        int stride,
        int N,
        int threadCount,
        int sortDir
)
{
    size_t pos = get_global_id(0);

    if (pos >= threadCount)
    {
        return;
    }

    const int           i = pos & ((stride / SAMPLE_STRIDE) - 1);
    const int segmentBase = (pos - i) * (2 * SAMPLE_STRIDE);
    d_SrcKey += segmentBase * keySize;
    d_RanksA += segmentBase / SAMPLE_STRIDE;
    d_RanksB += segmentBase / SAMPLE_STRIDE;

    const int segmentElementsA = stride;
    const int segmentElementsB = umin(stride, N - segmentBase - stride);
    const int  segmentSamplesA = getSampleCount(segmentElementsA);
    const int  segmentSamplesB = getSampleCount(segmentElementsB);

    if (i < segmentSamplesA)
    {
        d_RanksA[i] = i * SAMPLE_STRIDE;
        d_RanksB[i] = binarySearchEx(
                          d_SrcKey+i * SAMPLE_STRIDE*keySize, d_SrcKey + stride*keySize,
                          segmentElementsB, nextPowerOfTwo(segmentElementsB),sortDir,keySize
                      );
    }

    if (i < segmentSamplesB)
    {
        d_RanksB[(stride / SAMPLE_STRIDE) + i] = i * SAMPLE_STRIDE;
        d_RanksA[(stride / SAMPLE_STRIDE) + i] = binarySearchIn(
                                                     d_SrcKey+(stride + i * SAMPLE_STRIDE)*keySize, d_SrcKey + 0,
                                                     segmentElementsA, nextPowerOfTwo(segmentElementsA),sortDir,keySize
                                                 );
    }
}

__kernel void mergeRanksAndIndicesKernel(
    int *d_Limits,
    int *d_Ranks,
    int stride,
    int N,
    int threadCount
)
{
    size_t pos = get_global_id(0);

    if (pos >= threadCount)
    {
        return;
    }

    const int           i = pos & ((stride / SAMPLE_STRIDE) - 1);
    const int segmentBase = (pos - i) * (2 * SAMPLE_STRIDE);
    d_Ranks  += (pos - i) * 2;
    d_Limits += (pos - i) * 2;

    const int segmentElementsA = stride;
    const int segmentElementsB = umin(stride, N - segmentBase - stride);
    const int  segmentSamplesA = getSampleCount(segmentElementsA);
    const int  segmentSamplesB = getSampleCount(segmentElementsB);

    if (i < segmentSamplesA)
    {
        int dstPos = binarySearchExInt(d_Ranks[i], d_Ranks + segmentSamplesA, segmentSamplesB, nextPowerOfTwo(segmentSamplesB),1) + i;
        d_Limits[dstPos] = d_Ranks[i];
    }

    if (i < segmentSamplesB)
    {
        int dstPos = binarySearchInInt(d_Ranks[segmentSamplesA + i], d_Ranks, segmentSamplesA, nextPowerOfTwo(segmentSamplesA),1) + i;
        d_Limits[dstPos] = d_Ranks[segmentSamplesA + i];
    }
}

void merge(
        char *dstKey,
        int *dstVal,
        char *srcAKey,
        int *srcAVal,
        char *srcBKey,
        int *srcBVal,
        int lenA,
        int nPowTwoLenA,
        int lenB,
        int nPowTwoLenB,
        int sortDir,
        int keySize
)
{
        char keyA[64], keyB[64];
        int valA, valB, dstPosA, dstPosB;

	size_t threadId = get_local_id(0);

    if ( < lenA)
    {
	for(int i=0;i<keySize;i++)
		keyA[i] = srcAKey[threadId * keySize + i];
        valA = srcAVal[threadId];
        dstPosA = binarySearchEx(keyA, srcBKey, lenB, nPowTwoLenB, sortDir,keySize) + threadId;
    }

    if (threadId < lenB)
    {
	for(int i=0;i<keySize;i++)
		keyB[i] = srcBKey[threadId * keySize + i];
        valB = srcBVal[threadId];
        dstPosB = binarySearchIn(keyB, srcAKey, lenA, nPowTwoLenA, sortDir, keySize) + threadId;
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    if (threadId < lenA)
    {
	for(int i=0;i<keySize;i++)
		dstKey[dstPosA*keySize + i] = keyA[i];
        dstVal[dstPosA] = valA;
    }

    if (threadId < lenB)
    {
	for(int i=0;i<keySize;i++)
		dstKey[dstPosB*keySize + i] = keyB[i];
        dstVal[dstPosB] = valB;
    }
}

__global__ void mergeElementaryIntervalsKernel(
        char *d_DstKey,
        int *d_DstVal,
        char *d_SrcKey,
        int *d_SrcVal,
        int *d_LimitsA,
        int *d_LimitsB,
        int stride,
        int N,
        int sortDir,
        int keySize,
	__local char *s_key,
	__local int * s_val
)
{

	size_t blockId = get_group_id(0);
	size_t threadId = get_local_id(0);

    	const int   intervalI = blockId & ((2 * stride) / SAMPLE_STRIDE - 1);
    	const int segmentBase = (blockId - intervalI) * SAMPLE_STRIDE;
    	d_SrcKey += segmentBase * keySize;
    	d_SrcVal += segmentBase;
    	d_DstKey += segmentBase * keySize;
    	d_DstVal += segmentBase;

    	__local int startSrcA, startSrcB, lenSrcA, lenSrcB, startDstA, startDstB;

    	if (threadId == 0){
        	int segmentElementsA = stride;
        	int segmentElementsB = umin(stride, N - segmentBase - stride);
        	int  segmentSamplesA = getSampleCount(segmentElementsA);
        	int  segmentSamplesB = getSampleCount(segmentElementsB);
        	int   segmentSamples = segmentSamplesA + segmentSamplesB;

        	startSrcA    = d_LimitsA[blockId];
        	startSrcB    = d_LimitsB[blockId];
        	int endSrcA = (intervalI + 1 < segmentSamples) ? d_LimitsA[blockId + 1] : segmentElementsA;
        	int endSrcB = (intervalI + 1 < segmentSamples) ? d_LimitsB[blockId + 1] : segmentElementsB;
        	lenSrcA      = endSrcA - startSrcA;
        	lenSrcB      = endSrcB - startSrcB;
        	startDstA    = startSrcA + startSrcB;
        	startDstB    = startDstA + lenSrcA;
    	}

    barrier(CLK_LOCAL_MEM_FENCE);

    if (threadId < lenSrcA)
    {
        memcpy(s_key + threadId * keySize, d_SrcKey + (startSrcA + threadId)*keySize, keySize);
        s_val[threadId +             0] = d_SrcVal[0 + startSrcA + threadId];
    }

    if (threadId < lenSrcB)
    {
        memcpy(s_key + (threadId + SAMPLE_STRIDE)*keySize, d_SrcKey + (stride + startSrcB+threadId)*keySize,keySize);
        s_val[threadId + SAMPLE_STRIDE] = d_SrcVal[stride + startSrcB + threadId];
    }

    barrier(CLK_LOCAL_MEM_FENCE);
    merge(
        s_key,
        s_val,
        s_key + 0,
        s_val + 0,
        s_key + SAMPLE_STRIDE*keySize,
        s_val + SAMPLE_STRIDE,
        lenSrcA, SAMPLE_STRIDE,
        lenSrcB, SAMPLE_STRIDE,
        sortDir,
        keySize
    );

    barrier(CLK_LOCAL_MEM_FENCE);

    if (threadId < lenSrcA)
    {
        memcpy(d_DstKey + (startDstA + threadId)*keySize, s_key + threadId * keySize, keySize);
        d_DstVal[startDstA + threadId] = s_val[threadId];
    }

    if (threadId < lenSrcB)
    {
        memcpy(d_DstKey + (startDstB + threadId)*keySize, s_key + (lenSrcA + threadId)*keySize, keySize);
        d_DstVal[startDstB + threadId] = s_val[lenSrcA + threadId];
    }
}

__global__ static void sort_key(char * key, int tupleNum, int keySize, char *result, char *pos,int dir, __local *bufKey, __local int* bufVal){
	size_t lid = get_local_id(0);
	size_t bid = get_group_id(0);

        int gid = bid * SHARED_SIZE_LIMIT + lid;

	for(int i=0;i<keySize;i++)
		bufKey[lid*keySize + i] = key[gid+keySize + i];
        bufVal[lid] = gid;

	for(int i=0;i<keySize;i++)
		bufKey[i + (lid+blockDim.x)*keySize] = key[i+(gid+blockDim.x)*keySize];
        bufVal[lid+blockDim.x] = gid+ blockDim.x;

    	barrier(CLK_LOCAL_MEM_FENCE);

        for (int size = 2; size < tupleNum && size < SHARED_SIZE_LIMIT; size <<= 1){
                int ddd = dir ^ ((lid & (size / 2)) != 0);

                for (int stride = size / 2; stride > 0; stride >>= 1){
    			barrier(CLK_LOCAL_MEM_FENCE);
                        int pos = 2 * lid - (lid & (stride - 1));
                        Comparator(
                                bufKey+pos*keySize, bufVal[pos +      0],
                                bufKey+(pos+stride)*keySize, bufVal[pos + stride],
                                keySize,
                                ddd
                        );
                }
        }

    {
        for (int stride = blockDim.x ; stride > 0; stride >>= 1)
        {
    		barrier(CLK_LOCAL_MEM_FENCE);
            int pos = 2 * threadIdx.x - (threadIdx.x & (stride - 1));
            Comparator(
                bufKey+pos*keySize, bufVal[pos +      0],
                bufKey+(pos+stride)*keySize, bufVal[pos + stride],
                keySize,
                dir
            );
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

	for(int i=0;i<keySize;i++)
		result[i+ gid*keySize] = bufKey[lid*keySize + i];

        ((int *)pos)[gid] = bufVal[lid];

	for(int i=0;i<keySize;i++)
		result[i + (gid+blockDim.x)*keySize] = bufKey[i+ (lid+blockDim.x)*keySize];

        ((int *)pos)[gid+blockDim.x] = bufVal[lid+blockDim.x];

}

__kernel static void gather_result(char * keyPos, char ** col, int newNum, int tupleNum, int *size, int colNum, char **result){
        int stride = blockDim.x * gridDim.x;
        int index = blockIdx.x * blockDim.x + threadIdx.x;

        for(int j=0;j<colNum;j++){
                for(int i=index;i<newNum;i+=stride){
                        int pos = ((int *)keyPos)[i];
                        if(pos<tupleNum)
                                memcpy(result[j] + i*size[j], col[j] +pos*size[j], size[j]);
                }
        }
}

__kernel void build_orderby_keys(char ** content, int tupleNum, int odNum, int keySize,int *index, int * size, char *key){
        int stride = blockDim.x * gridDim.x;
        int offset = blockIdx.x * blockDim.x + threadIdx.x;

        for(int i=offset;i<tupleNum;i+=stride){
                int pos = i* keySize;

                for(int j=0;j<odNum;j++){
                        memcpy(key+pos,content[index[j]]+i*size[j],size[j]);
                        pos += size[j];
                }

        }
}


JavaCL / Interactive Image Transform Demo : - applied fixes suggested by Marco Hutter (jocl.org) for compatibility with ATI Stream 2.2 : __constant const -> __constant, no fast uncomment //*/ - Added naive denoising example

/**
	Naive denoising sample :
	Transform RGB to HSL, replace L channel by local average if the sobel operator's value is not too high and the pixel L value is not too different.
	Written by Olivier Chafik, no right reserved :-) */

// Import LibCL functions, which sources can be browsed here :
// http://code.google.com/p/nativelibs4java/source/browse/trunk/libraries/OpenCL/LibCL/src/main/resources#resources%2FLibCL
#include "LibCL/ImageConvolution.cl"
#include "LibCL/SobelOperator.cl"
#include "LibCL/rgba2hsla.cl"
#include "LibCL/hsla2rgba.cl"

// Matrix values taken from http://en.wikipedia.org/wiki/Gaussian_blur :
__constant float gaussian7x7Matrix[] = {
	0.00000067,	0.00002292,	0.00019117,	0.00038771,	0.00019117,	0.00002292,	0.00000067,
	0.00002292,	0.00078633,	0.00655965,	0.01330373,	0.00655965,	0.00078633,	0.00002292,
	0.00019117,	0.00655965,	0.05472157,	0.11098164,	0.05472157,	0.00655965,	0.00019117,
	0.00038771,	0.01330373,	0.11098164,	0.22508352,	0.11098164,	0.01330373,	0.00038771,
	0.00019117,	0.00655965,	0.05472157,	0.11098164,	0.05472157,	0.00655965,	0.00019117,
	0.00002292,	0.00078633,	0.00655965,	0.01330373,	0.00655965,	0.00078633,	0.00002292,
	0.00000067,	0.00002292,	0.00019117,	0.00038771,	0.00019117,	0.00002292,	0.00000067
};

__kernel void imageThreshold(
	read_only image2d_t inputImage,
	write_only image2d_t outputImage)
{
	int x = get_global_id(0), y = get_global_id(1);

	const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | CLK_ADDRESS_CLAMP_TO_EDGE;
	float4 pixel = read_imagef(inputImage, sampler, (int2)(x, y));

	float sobel = fabs(sobelOperatorRGBFloat(inputImage, x, y).x);
	float sobelThreshold = 0.05f;
	float averageThreshold = 0.07f;

	if (sobel < sobelThreshold) {
		// Get smoothed pixel (averaged from neighborhood with a gaussian) :
		float4 averagePixelHSLA = rgba2hsla(convolveFloatImagePixel(inputImage, x, y, gaussian7x7Matrix, 7));
		float4 pixelHSLA = rgba2hsla(pixel);

		pixelHSLA.x = averagePixelHSLA.x; // avoid chromatic aberrations : unconditionally replace Hue channel

		float4 d = fabs(pixelHSLA - averagePixelHSLA);
		if (d.x < averageThreshold && d.y < averageThreshold && d.z < averageThreshold)
			pixelHSLA.z = averagePixelHSLA.z; // replace Luminance channel by average if it's not too far away

		pixel = hsla2rgba(pixelHSLA);
	}

	write_imagef(outputImage, (int2)(x, y), pixel);
}

/**
	Naive denoising sample :
	Transform RGB to HSL, replace L channel by local average if the sobel operator's value is not too high and the pixel L value is not too different.
	Written by Olivier Chafik, no right reserved :-) */

// Import LibCL functions, which sources can be browsed here :
// http://code.google.com/p/nativelibs4java/source/browse/trunk/libraries/OpenCL/LibCL/src/main/resources#resources%2FLibCL
#include "LibCL/ImageConvolution.cl"
#include "LibCL/SobelOperator.cl"
#include "LibCL/Gaussian7x7.cl"
#include "LibCL/rgba2hsla.cl"
#include "LibCL/hsla2rgba.cl"

__kernel void imageThreshold(
	read_only image2d_t inputImage,
	write_only image2d_t outputImage)
{
	int x = get_global_id(0), y = get_global_id(1);

	const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | CLK_ADDRESS_CLAMP_TO_EDGE;
	float4 pixel = read_imagef(inputImage, sampler, (int2)(x, y));

	float sobel = fabs(sobelOperatorRGBFloat(inputImage, x, y).x);
	float sobelThreshold = 0.05f;
	float averageThreshold = 0.07f;

	if (sobel < sobelThreshold) {
		// Get smoothed pixel (averaged from neighborhood with a gaussian) :
		float4 averagePixelHSLA = rgba2hsla(convolveFloatImagePixel(inputImage, x, y, gaussian7x7Matrix, 7));
		float4 pixelHSLA = rgba2hsla(pixel);

		pixelHSLA.x = averagePixelHSLA.x; // avoid chromatic aberrations : unconditionally replace Hue channel

		float4 d = fabs(pixelHSLA - averagePixelHSLA);
		if (d.x < averageThreshold && d.y < averageThreshold && d.z < averageThreshold)
			pixelHSLA.z = averagePixelHSLA.z; // replace Luminance channel by average if it's not too far away

		pixel = hsla2rgba(pixelHSLA);
	}

	write_imagef(outputImage, (int2)(x, y), pixel);
}


create also half float version of select in kernel library

/* OpenCL built-in library: select()

   Copyright (c) 2011 Erik Schnetter <eschnetter@perimeterinstitute.ca>
                      Perimeter Institute for Theoretical Physics

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONORDEREDRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE.
*/

#include "templates.h"

/* select needs to be implemented slightly differently between scalar,
   signed vector, and unsigned vector types, due to how the relational
   operators differ between them and signed/unsigned arithmetic.

   TODO: clang appears to be generating rather inefficient code for the
   vector versions, it's extracting each component and performing
   piece-wise comparisons instead of emitting the llvm ir "select"
   instruction. It might be worth investigating fixing this.
*/

/* We implement the scalar and the vector version separately, because
   the scalar version selects on the condition being non-zero, while
   the vector version selects on the condition's MSB (i.e. sign
   bit). */

#define IMPLEMENT_SELECT_SCALAR(GTYPE, UIGTYPE) \
  GTYPE __attribute__ ((overloadable))          \
  select(GTYPE a, GTYPE b, UIGTYPE c)           \
  {                                             \
    return c ? b : a;                           \
  }

IMPLEMENT_SELECT_SCALAR(char  , char  )
IMPLEMENT_SELECT_SCALAR(char  , uchar )
IMPLEMENT_SELECT_SCALAR(uchar , char  )
IMPLEMENT_SELECT_SCALAR(uchar , uchar )
IMPLEMENT_SELECT_SCALAR(short , short )
IMPLEMENT_SELECT_SCALAR(short , ushort)
IMPLEMENT_SELECT_SCALAR(ushort, short )
IMPLEMENT_SELECT_SCALAR(ushort, ushort)
IMPLEMENT_SELECT_SCALAR(int   , int   )
IMPLEMENT_SELECT_SCALAR(int   , uint  )
IMPLEMENT_SELECT_SCALAR(uint  , int   )
IMPLEMENT_SELECT_SCALAR(uint  , uint  )
__IF_INT64(
IMPLEMENT_SELECT_SCALAR(long  , long  )
IMPLEMENT_SELECT_SCALAR(long  , ulong )
IMPLEMENT_SELECT_SCALAR(ulong , long  )
IMPLEMENT_SELECT_SCALAR(ulong , ulong ))
IMPLEMENT_SELECT_SCALAR(float , int   )
IMPLEMENT_SELECT_SCALAR(float , uint  )
__IF_FP64(
IMPLEMENT_SELECT_SCALAR(double, long  )
IMPLEMENT_SELECT_SCALAR(double, ulong ))
__IF_FP16(
IMPLEMENT_SELECT_SCALAR(half , short )
IMPLEMENT_SELECT_SCALAR(half , ushort))

#define IMPLEMENT_SELECT_VECTOR(GTYPE, UIGTYPE, IGTYPE) \
  GTYPE __attribute__ ((overloadable))                  \
  select(GTYPE a, GTYPE b, UIGTYPE c)                   \
  {                                                     \
    return *(IGTYPE*)&c < (IGTYPE)0 ? b : a;            \
  }

IMPLEMENT_SELECT_VECTOR(char2  , char2  , char2 )
IMPLEMENT_SELECT_VECTOR(char2  , uchar2 , char2 )
IMPLEMENT_SELECT_VECTOR(uchar2 , char2  , char2 )
IMPLEMENT_SELECT_VECTOR(uchar2 , uchar2 , char2 )
IMPLEMENT_SELECT_VECTOR(short2 , short2 , short2)
IMPLEMENT_SELECT_VECTOR(short2 , ushort2, short2)
IMPLEMENT_SELECT_VECTOR(ushort2, short2 , short2)
IMPLEMENT_SELECT_VECTOR(ushort2, ushort2, short2)
IMPLEMENT_SELECT_VECTOR(int2   , int2   , int2  )
IMPLEMENT_SELECT_VECTOR(int2   , uint2  , int2  )
IMPLEMENT_SELECT_VECTOR(uint2  , int2   , int2  )
IMPLEMENT_SELECT_VECTOR(uint2  , uint2  , int2  )
__IF_INT64(
IMPLEMENT_SELECT_VECTOR(long2  , long2  , long2 )
IMPLEMENT_SELECT_VECTOR(long2  , ulong2 , long2 )
IMPLEMENT_SELECT_VECTOR(ulong2 , long2  , long2 )
IMPLEMENT_SELECT_VECTOR(ulong2 , ulong2 , long2 ))
IMPLEMENT_SELECT_VECTOR(float2 , int2   , int2  )
IMPLEMENT_SELECT_VECTOR(float2 , uint2  , int2  )
__IF_FP64(
IMPLEMENT_SELECT_VECTOR(double2, long2  , long2 )
IMPLEMENT_SELECT_VECTOR(double2, ulong2 , long2 ))
__IF_FP16(
IMPLEMENT_SELECT_VECTOR(half2, short2 , short2)
IMPLEMENT_SELECT_VECTOR(half2, ushort2 , short2))

IMPLEMENT_SELECT_VECTOR(char3  , char3  , char3 )
IMPLEMENT_SELECT_VECTOR(char3  , uchar3 , char3 )
IMPLEMENT_SELECT_VECTOR(uchar3 , char3  , char3 )
IMPLEMENT_SELECT_VECTOR(uchar3 , uchar3 , char3 )
IMPLEMENT_SELECT_VECTOR(short3 , short3 , short3)
IMPLEMENT_SELECT_VECTOR(short3 , ushort3, short3)
IMPLEMENT_SELECT_VECTOR(ushort3, short3 , short3)
IMPLEMENT_SELECT_VECTOR(ushort3, ushort3, short3)
IMPLEMENT_SELECT_VECTOR(int3   , int3   , int3  )
IMPLEMENT_SELECT_VECTOR(int3   , uint3  , int3  )
IMPLEMENT_SELECT_VECTOR(uint3  , int3   , int3  )
IMPLEMENT_SELECT_VECTOR(uint3  , uint3  , int3  )
__IF_INT64(
IMPLEMENT_SELECT_VECTOR(long3  , long3  , long3 )
IMPLEMENT_SELECT_VECTOR(long3  , ulong3 , long3 )
IMPLEMENT_SELECT_VECTOR(ulong3 , long3  , long3 )
IMPLEMENT_SELECT_VECTOR(ulong3 , ulong3 , long3 ))
IMPLEMENT_SELECT_VECTOR(float3 , int3   , int3  )
IMPLEMENT_SELECT_VECTOR(float3 , uint3  , int3  )
__IF_FP64(
IMPLEMENT_SELECT_VECTOR(double3, long3  , long3 )
IMPLEMENT_SELECT_VECTOR(double3, ulong3 , long3 ))
__IF_FP16(
IMPLEMENT_SELECT_VECTOR(half3, short3 , short3)
IMPLEMENT_SELECT_VECTOR(half3, ushort3 , short3))

IMPLEMENT_SELECT_VECTOR(char4  , char4  , char4 )
IMPLEMENT_SELECT_VECTOR(char4  , uchar4 , char4 )
IMPLEMENT_SELECT_VECTOR(uchar4 , char4  , char4 )
IMPLEMENT_SELECT_VECTOR(uchar4 , uchar4 , char4 )
IMPLEMENT_SELECT_VECTOR(short4 , short4 , short4)
IMPLEMENT_SELECT_VECTOR(short4 , ushort4, short4)
IMPLEMENT_SELECT_VECTOR(ushort4, short4 , short4)
IMPLEMENT_SELECT_VECTOR(ushort4, ushort4, short4)
IMPLEMENT_SELECT_VECTOR(int4   , int4   , int4  )
IMPLEMENT_SELECT_VECTOR(int4   , uint4  , int4  )
IMPLEMENT_SELECT_VECTOR(uint4  , int4   , int4  )
IMPLEMENT_SELECT_VECTOR(uint4  , uint4  , int4  )
__IF_INT64(
IMPLEMENT_SELECT_VECTOR(long4  , long4  , long4 )
IMPLEMENT_SELECT_VECTOR(long4  , ulong4 , long4 )
IMPLEMENT_SELECT_VECTOR(ulong4 , long4  , long4 )
IMPLEMENT_SELECT_VECTOR(ulong4 , ulong4 , long4 ))
IMPLEMENT_SELECT_VECTOR(float4 , int4   , int4  )
IMPLEMENT_SELECT_VECTOR(float4 , uint4  , int4  )
__IF_FP64(
IMPLEMENT_SELECT_VECTOR(double4, long4  , long4 )
IMPLEMENT_SELECT_VECTOR(double4, ulong4 , long4 ))
__IF_FP16(
IMPLEMENT_SELECT_VECTOR(half4, short4 , short4)
IMPLEMENT_SELECT_VECTOR(half4, ushort4 , short4))

IMPLEMENT_SELECT_VECTOR(char8  , char8  , char8 )
IMPLEMENT_SELECT_VECTOR(char8  , uchar8 , char8 )
IMPLEMENT_SELECT_VECTOR(uchar8 , char8  , char8 )
IMPLEMENT_SELECT_VECTOR(uchar8 , uchar8 , char8 )
IMPLEMENT_SELECT_VECTOR(short8 , short8 , short8)
IMPLEMENT_SELECT_VECTOR(short8 , ushort8, short8)
IMPLEMENT_SELECT_VECTOR(ushort8, short8 , short8)
IMPLEMENT_SELECT_VECTOR(ushort8, ushort8, short8)
IMPLEMENT_SELECT_VECTOR(int8   , int8   , int8  )
IMPLEMENT_SELECT_VECTOR(int8   , uint8  , int8  )
IMPLEMENT_SELECT_VECTOR(uint8  , int8   , int8  )
IMPLEMENT_SELECT_VECTOR(uint8  , uint8  , int8  )
__IF_INT64(
IMPLEMENT_SELECT_VECTOR(long8  , long8  , long8 )
IMPLEMENT_SELECT_VECTOR(long8  , ulong8 , long8 )
IMPLEMENT_SELECT_VECTOR(ulong8 , long8  , long8 )
IMPLEMENT_SELECT_VECTOR(ulong8 , ulong8 , long8 ))
IMPLEMENT_SELECT_VECTOR(float8 , int8   , int8  )
IMPLEMENT_SELECT_VECTOR(float8 , uint8  , int8  )
__IF_FP64(
IMPLEMENT_SELECT_VECTOR(double8, long8  , long8 )
IMPLEMENT_SELECT_VECTOR(double8, ulong8 , long8 ))
__IF_FP16(
IMPLEMENT_SELECT_VECTOR(half8, short8 , short8)
IMPLEMENT_SELECT_VECTOR(half8, ushort8 , short8))

IMPLEMENT_SELECT_VECTOR(char16  , char16  , char16 )
IMPLEMENT_SELECT_VECTOR(char16  , uchar16 , char16 )
IMPLEMENT_SELECT_VECTOR(uchar16 , char16  , char16 )
IMPLEMENT_SELECT_VECTOR(uchar16 , uchar16 , char16 )
IMPLEMENT_SELECT_VECTOR(short16 , short16 , short16)
IMPLEMENT_SELECT_VECTOR(short16 , ushort16, short16)
IMPLEMENT_SELECT_VECTOR(ushort16, short16 , short16)
IMPLEMENT_SELECT_VECTOR(ushort16, ushort16, short16)
IMPLEMENT_SELECT_VECTOR(int16   , int16   , int16  )
IMPLEMENT_SELECT_VECTOR(int16   , uint16  , int16  )
IMPLEMENT_SELECT_VECTOR(uint16  , int16   , int16  )
IMPLEMENT_SELECT_VECTOR(uint16  , uint16  , int16  )
__IF_INT64(
IMPLEMENT_SELECT_VECTOR(long16  , long16  , long16 )
IMPLEMENT_SELECT_VECTOR(long16  , ulong16 , long16 )
IMPLEMENT_SELECT_VECTOR(ulong16 , long16  , long16 )
IMPLEMENT_SELECT_VECTOR(ulong16 , ulong16 , long16 ))
IMPLEMENT_SELECT_VECTOR(float16 , int16   , int16  )
IMPLEMENT_SELECT_VECTOR(float16 , uint16  , int16  )
__IF_FP64(
IMPLEMENT_SELECT_VECTOR(double16, long16  , long16 )
IMPLEMENT_SELECT_VECTOR(double16, ulong16 , long16 ))
__IF_FP16(
IMPLEMENT_SELECT_VECTOR(half16, short16 , short16)
IMPLEMENT_SELECT_VECTOR(half16, ushort16 , short16))

/* OpenCL built-in library: select()

   Copyright (c) 2011 Erik Schnetter <eschnetter@perimeterinstitute.ca>
                      Perimeter Institute for Theoretical Physics

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONORDEREDRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE.
*/

#include "templates.h"

/* select needs to be implemented slightly differently between scalar,
   signed vector, and unsigned vector types, due to how the relational
   operators differ between them and signed/unsigned arithmetic.

   TODO: clang appears to be generating rather inefficient code for the
   vector versions, it's extracting each component and performing
   piece-wise comparisons instead of emitting the llvm ir "select"
   instruction. It might be worth investigating fixing this.
*/

/* We implement the scalar and the vector version separately, because
   the scalar version selects on the condition being non-zero, while
   the vector version selects on the condition's MSB (i.e. sign
   bit). */

#define IMPLEMENT_SELECT_SCALAR(GTYPE, UIGTYPE) \
  GTYPE __attribute__ ((overloadable))          \
  select(GTYPE a, GTYPE b, UIGTYPE c)           \
  {                                             \
    return c ? b : a;                           \
  }

IMPLEMENT_SELECT_SCALAR(char  , char  )
IMPLEMENT_SELECT_SCALAR(char  , uchar )
IMPLEMENT_SELECT_SCALAR(uchar , char  )
IMPLEMENT_SELECT_SCALAR(uchar , uchar )
IMPLEMENT_SELECT_SCALAR(short , short )
IMPLEMENT_SELECT_SCALAR(short , ushort)
IMPLEMENT_SELECT_SCALAR(ushort, short )
IMPLEMENT_SELECT_SCALAR(ushort, ushort)
IMPLEMENT_SELECT_SCALAR(int   , int   )
IMPLEMENT_SELECT_SCALAR(int   , uint  )
IMPLEMENT_SELECT_SCALAR(uint  , int   )
IMPLEMENT_SELECT_SCALAR(uint  , uint  )
__IF_INT64(
IMPLEMENT_SELECT_SCALAR(long  , long  )
IMPLEMENT_SELECT_SCALAR(long  , ulong )
IMPLEMENT_SELECT_SCALAR(ulong , long  )
IMPLEMENT_SELECT_SCALAR(ulong , ulong ))
IMPLEMENT_SELECT_SCALAR(float , int   )
IMPLEMENT_SELECT_SCALAR(float , uint  )
__IF_FP64(
IMPLEMENT_SELECT_SCALAR(double, long  )
IMPLEMENT_SELECT_SCALAR(double, ulong ))

#define IMPLEMENT_SELECT_VECTOR(GTYPE, UIGTYPE, IGTYPE) \
  GTYPE __attribute__ ((overloadable))                  \
  select(GTYPE a, GTYPE b, UIGTYPE c)                   \
  {                                                     \
    return *(IGTYPE*)&c < (IGTYPE)0 ? b : a;            \
  }

IMPLEMENT_SELECT_VECTOR(char2  , char2  , char2 )
IMPLEMENT_SELECT_VECTOR(char2  , uchar2 , char2 )
IMPLEMENT_SELECT_VECTOR(uchar2 , char2  , char2 )
IMPLEMENT_SELECT_VECTOR(uchar2 , uchar2 , char2 )
IMPLEMENT_SELECT_VECTOR(short2 , short2 , short2)
IMPLEMENT_SELECT_VECTOR(short2 , ushort2, short2)
IMPLEMENT_SELECT_VECTOR(ushort2, short2 , short2)
IMPLEMENT_SELECT_VECTOR(ushort2, ushort2, short2)
IMPLEMENT_SELECT_VECTOR(int2   , int2   , int2  )
IMPLEMENT_SELECT_VECTOR(int2   , uint2  , int2  )
IMPLEMENT_SELECT_VECTOR(uint2  , int2   , int2  )
IMPLEMENT_SELECT_VECTOR(uint2  , uint2  , int2  )
__IF_INT64(
IMPLEMENT_SELECT_VECTOR(long2  , long2  , long2 )
IMPLEMENT_SELECT_VECTOR(long2  , ulong2 , long2 )
IMPLEMENT_SELECT_VECTOR(ulong2 , long2  , long2 )
IMPLEMENT_SELECT_VECTOR(ulong2 , ulong2 , long2 ))
IMPLEMENT_SELECT_VECTOR(float2 , int2   , int2  )
IMPLEMENT_SELECT_VECTOR(float2 , uint2  , int2  )
__IF_FP64(
IMPLEMENT_SELECT_VECTOR(double2, long2  , long2 )
IMPLEMENT_SELECT_VECTOR(double2, ulong2 , long2 ))

IMPLEMENT_SELECT_VECTOR(char3  , char3  , char3 )
IMPLEMENT_SELECT_VECTOR(char3  , uchar3 , char3 )
IMPLEMENT_SELECT_VECTOR(uchar3 , char3  , char3 )
IMPLEMENT_SELECT_VECTOR(uchar3 , uchar3 , char3 )
IMPLEMENT_SELECT_VECTOR(short3 , short3 , short3)
IMPLEMENT_SELECT_VECTOR(short3 , ushort3, short3)
IMPLEMENT_SELECT_VECTOR(ushort3, short3 , short3)
IMPLEMENT_SELECT_VECTOR(ushort3, ushort3, short3)
IMPLEMENT_SELECT_VECTOR(int3   , int3   , int3  )
IMPLEMENT_SELECT_VECTOR(int3   , uint3  , int3  )
IMPLEMENT_SELECT_VECTOR(uint3  , int3   , int3  )
IMPLEMENT_SELECT_VECTOR(uint3  , uint3  , int3  )
__IF_INT64(
IMPLEMENT_SELECT_VECTOR(long3  , long3  , long3 )
IMPLEMENT_SELECT_VECTOR(long3  , ulong3 , long3 )
IMPLEMENT_SELECT_VECTOR(ulong3 , long3  , long3 )
IMPLEMENT_SELECT_VECTOR(ulong3 , ulong3 , long3 ))
IMPLEMENT_SELECT_VECTOR(float3 , int3   , int3  )
IMPLEMENT_SELECT_VECTOR(float3 , uint3  , int3  )
__IF_FP64(
IMPLEMENT_SELECT_VECTOR(double3, long3  , long3 )
IMPLEMENT_SELECT_VECTOR(double3, ulong3 , long3 ))

IMPLEMENT_SELECT_VECTOR(char4  , char4  , char4 )
IMPLEMENT_SELECT_VECTOR(char4  , uchar4 , char4 )
IMPLEMENT_SELECT_VECTOR(uchar4 , char4  , char4 )
IMPLEMENT_SELECT_VECTOR(uchar4 , uchar4 , char4 )
IMPLEMENT_SELECT_VECTOR(short4 , short4 , short4)
IMPLEMENT_SELECT_VECTOR(short4 , ushort4, short4)
IMPLEMENT_SELECT_VECTOR(ushort4, short4 , short4)
IMPLEMENT_SELECT_VECTOR(ushort4, ushort4, short4)
IMPLEMENT_SELECT_VECTOR(int4   , int4   , int4  )
IMPLEMENT_SELECT_VECTOR(int4   , uint4  , int4  )
IMPLEMENT_SELECT_VECTOR(uint4  , int4   , int4  )
IMPLEMENT_SELECT_VECTOR(uint4  , uint4  , int4  )
__IF_INT64(
IMPLEMENT_SELECT_VECTOR(long4  , long4  , long4 )
IMPLEMENT_SELECT_VECTOR(long4  , ulong4 , long4 )
IMPLEMENT_SELECT_VECTOR(ulong4 , long4  , long4 )
IMPLEMENT_SELECT_VECTOR(ulong4 , ulong4 , long4 ))
IMPLEMENT_SELECT_VECTOR(float4 , int4   , int4  )
IMPLEMENT_SELECT_VECTOR(float4 , uint4  , int4  )
__IF_FP64(
IMPLEMENT_SELECT_VECTOR(double4, long4  , long4 )
IMPLEMENT_SELECT_VECTOR(double4, ulong4 , long4 ))

IMPLEMENT_SELECT_VECTOR(char8  , char8  , char8 )
IMPLEMENT_SELECT_VECTOR(char8  , uchar8 , char8 )
IMPLEMENT_SELECT_VECTOR(uchar8 , char8  , char8 )
IMPLEMENT_SELECT_VECTOR(uchar8 , uchar8 , char8 )
IMPLEMENT_SELECT_VECTOR(short8 , short8 , short8)
IMPLEMENT_SELECT_VECTOR(short8 , ushort8, short8)
IMPLEMENT_SELECT_VECTOR(ushort8, short8 , short8)
IMPLEMENT_SELECT_VECTOR(ushort8, ushort8, short8)
IMPLEMENT_SELECT_VECTOR(int8   , int8   , int8  )
IMPLEMENT_SELECT_VECTOR(int8   , uint8  , int8  )
IMPLEMENT_SELECT_VECTOR(uint8  , int8   , int8  )
IMPLEMENT_SELECT_VECTOR(uint8  , uint8  , int8  )
__IF_INT64(
IMPLEMENT_SELECT_VECTOR(long8  , long8  , long8 )
IMPLEMENT_SELECT_VECTOR(long8  , ulong8 , long8 )
IMPLEMENT_SELECT_VECTOR(ulong8 , long8  , long8 )
IMPLEMENT_SELECT_VECTOR(ulong8 , ulong8 , long8 ))
IMPLEMENT_SELECT_VECTOR(float8 , int8   , int8  )
IMPLEMENT_SELECT_VECTOR(float8 , uint8  , int8  )
__IF_FP64(
IMPLEMENT_SELECT_VECTOR(double8, long8  , long8 )
IMPLEMENT_SELECT_VECTOR(double8, ulong8 , long8 ))

IMPLEMENT_SELECT_VECTOR(char16  , char16  , char16 )
IMPLEMENT_SELECT_VECTOR(char16  , uchar16 , char16 )
IMPLEMENT_SELECT_VECTOR(uchar16 , char16  , char16 )
IMPLEMENT_SELECT_VECTOR(uchar16 , uchar16 , char16 )
IMPLEMENT_SELECT_VECTOR(short16 , short16 , short16)
IMPLEMENT_SELECT_VECTOR(short16 , ushort16, short16)
IMPLEMENT_SELECT_VECTOR(ushort16, short16 , short16)
IMPLEMENT_SELECT_VECTOR(ushort16, ushort16, short16)
IMPLEMENT_SELECT_VECTOR(int16   , int16   , int16  )
IMPLEMENT_SELECT_VECTOR(int16   , uint16  , int16  )
IMPLEMENT_SELECT_VECTOR(uint16  , int16   , int16  )
IMPLEMENT_SELECT_VECTOR(uint16  , uint16  , int16  )
__IF_INT64(
IMPLEMENT_SELECT_VECTOR(long16  , long16  , long16 )
IMPLEMENT_SELECT_VECTOR(long16  , ulong16 , long16 )
IMPLEMENT_SELECT_VECTOR(ulong16 , long16  , long16 )
IMPLEMENT_SELECT_VECTOR(ulong16 , ulong16 , long16 ))
IMPLEMENT_SELECT_VECTOR(float16 , int16   , int16  )
IMPLEMENT_SELECT_VECTOR(float16 , uint16  , int16  )
__IF_FP64(
IMPLEMENT_SELECT_VECTOR(double16, long16  , long16 )
IMPLEMENT_SELECT_VECTOR(double16, ulong16 , long16 ))


Fixes in the reference manual generation script.

2015-09-08  Didier Verna  <didier@didierverna.net>

	* doc/generate.cl: Preload FoCus so that we can pass its version
	number to DECLT. Use the proper package name.

;;; generate.cl --- Declt reference manual generation script

;; Copyright (C) 2010-2013, 2015 Didier Verna

;; Author: Didier Verna <didier@didierverna.net>

;; This file is part of FoCus.

;; Permission to use, copy, modify, and distribute this software for any
;; purpose with or without fee is hereby granted, provided that the above
;; copyright notice and this permission notice appear in all copies.

;; THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

;;; Commentary:

;;; Code:

(require "asdf")

(defconstant +introduction+
  "@macro focus
@t{FoCus}
@end macro

@macro cl
Common-Lisp
@end macro

@macro etc
@i{etc.}
@end macro

@focus{}

This is the @focus{} reference manual, and as such, it is not meant to be
read. It may help you find sleep in case of insomnia though.
@ifinfo
See @xref{Top, , The FoCus User Manual, focus-user},
@end ifinfo
@ifhtml
See @xref{Top, , The FoCus User Manual, user},
@end ifhtml
@ifnotinfo
@ifnothtml
@xref{Top, , , user, The FoCus User Manual},
@end ifnothtml
@end ifnotinfo
for a more human-readable guide to using @focus{}."
  "The reference manual's introductory text.")

(asdf:load-system :net.didierverna.declt)
(net.didierverna.declt:nickname-package)

;; ASDF doesn't understand my version numnbering scheme. That will change
;; soon, but in the meantime, I have to provide my version number explicitly
;; here (and so I need to load the system in order to get the VERSION
;; function).
(asdf:load-system :net.didierverna.focus)

(if (and (second sb-ext:*posix-argv*)
	 (string= (second sb-ext:*posix-argv*) "--web"))
    (declt:declt :net.didierverna.focus
		 :library-name "FoCus"
		 :texi-file "webreference.texi"
		 :info-file "focus-webreference" ; but we don't care
		 :introduction +introduction+
		 :version (net.didierverna.focus:version :long)
		 :license :bsd
		 :copyright-date "2015")
    (declt:declt :net.didierverna.focus
		 :library-name "FoCus"
		 :texi-file "reference.texi"
		 :info-file "focus-reference"
		 :introduction +introduction+
		 :version (net.didierverna.focus:version :long)
		 :license :bsd
		 :copyright-date "2015"
		 :hyperlinks t))

(uiop:quit)

;;; generate.cl ends here

;;; generate.cl --- Declt reference manual generation script

;; Copyright (C) 2010-2013, 2015 Didier Verna

;; Author: Didier Verna <didier@didierverna.net>

;; This file is part of FoCus.

;; Permission to use, copy, modify, and distribute this software for any
;; purpose with or without fee is hereby granted, provided that the above
;; copyright notice and this permission notice appear in all copies.

;; THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

;;; Commentary:

;;; Code:

(require "asdf")

(defconstant +introduction+
  "@macro focus
@t{FoCus}
@end macro

@macro cl
Common-Lisp
@end macro

@macro etc
@i{etc.}
@end macro

@focus{}

This is the @focus{} reference manual, and as such, it is not meant to be
read. It may help you find sleep in case of insomnia though.
@ifinfo
See @xref{Top, , The FoCus User Manual, focus-user},
@end ifinfo
@ifhtml
See @xref{Top, , The FoCus User Manual, user},
@end ifhtml
@ifnotinfo
@ifnothtml
@xref{Top, , , user, The FoCus User Manual},
@end ifnothtml
@end ifnotinfo
for a more human-readable guide to using @focus{}."
  "The reference manual's introductory text.")

(asdf:load-system :net.didierverna.declt)
(net.didierverna.declt:nickname-package)

;; ASDF doesn't understand my version numnbering scheme. That will change
;; soon, but in the meantime, I have to provide my version number explicitly
;; here.
(if (and (second sb-ext:*posix-argv*)
	 (string= (second sb-ext:*posix-argv*) "--web"))
    (declt:declt :net.didierverna.focus
		 :library-name "FoCus"
		 :texi-file "webreference.texi"
		 :info-file "focus-webreference" ; but we don't care
		 :introduction +introduction+
		 :version (focus:version :long)
		 :license :bsd
		 :copyright-date "2015")
    (declt:declt :net.didierverna.focus
		 :library-name "FoCus"
		 :texi-file "reference.texi"
		 :info-file "focus-reference"
		 :introduction +introduction+
		 :version (focus:version :long)
		 :license :bsd
		 :copyright-date "2015"
		 :hyperlinks t))

(uiop:quit)

;;; generate.cl ends here


Make test more robust by not checking hard coded debug info values, but instead check the relationships between them.

git-svn-id: ffe668792ed300d6c2daa1f6eba2e0aa28d7ec6c@339185 91177308-0d34-0410-b5e6-96231b3b80d8

// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn < %s | FileCheck %s --check-prefixes=COMMON,AMDGPU
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple "spir-unknown-unknown" < %s | FileCheck %s --check-prefixes=COMMON,SPIR32
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple "spir64-unknown-unknown" < %s | FileCheck %s --check-prefixes=COMMON,SPIR64
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -debug-info-kind=limited -emit-llvm -o - -triple amdgcn < %s | FileCheck %s --check-prefixes=CHECK-DEBUG

// Check that the enqueue_kernel array temporary is in the entry block to avoid
// a dynamic alloca

typedef struct {int a;} ndrange_t;

kernel void test(int i) {
// COMMON-LABEL: define {{.*}} void @test
// COMMON-LABEL: entry:
// AMDGPU: %block_sizes = alloca [1 x i64]
// SPIR32: %block_sizes = alloca [1 x i32]
// SPIR64: %block_sizes = alloca [1 x i64]
// COMMON-LABEL: if.then:
// COMMON-NOT: alloca
// CHECK-DEBUG: getelementptr {{.*}} %block_sizes, {{.*}} !dbg ![[TEMPLOCATION:[0-9]+]]
// COMMON-LABEL: if.end
  queue_t default_queue;
  unsigned flags = 0;
  ndrange_t ndrange;
  if (i)
    enqueue_kernel(default_queue, flags, ndrange, ^(local void *a) { }, 32);
}

// Check that the temporary is scoped to the `if`

// CHECK-DEBUG: ![[TESTFILE:[0-9]+]] = !DIFile(filename: "<stdin>"
// CHECK-DEBUG: ![[TESTSCOPE:[0-9]+]] = distinct !DISubprogram(name: "test", {{.*}} file: ![[TESTFILE]]
// CHECK-DEBUG: ![[IFSCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[TESTSCOPE]], file: !1, line: 24)
// CHECK-DEBUG: ![[TEMPLOCATION]] = !DILocation(line: 25, scope: ![[IFSCOPE]])

// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple amdgcn < %s | FileCheck %s --check-prefixes=COMMON,AMDGPU
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple "spir-unknown-unknown" < %s | FileCheck %s --check-prefixes=COMMON,SPIR32
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple "spir64-unknown-unknown" < %s | FileCheck %s --check-prefixes=COMMON,SPIR64
// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -debug-info-kind=limited -emit-llvm -o - -triple amdgcn < %s | FileCheck %s --check-prefixes=CHECK-DEBUG

// Check that the enqueue_kernel array temporary is in the entry block to avoid
// a dynamic alloca

typedef struct {int a;} ndrange_t;

kernel void test(int i) {
// COMMON-LABEL: define {{.*}} void @test
// COMMON-LABEL: entry:
// AMDGPU: %block_sizes = alloca [1 x i64]
// SPIR32: %block_sizes = alloca [1 x i32]
// SPIR64: %block_sizes = alloca [1 x i64]
// COMMON-LABEL: if.then:
// COMMON-NOT: alloca
// CHECK-DEBUG: getelementptr {{.*}} %block_sizes, {{.*}} !dbg !34
// COMMON-LABEL: if.end
  queue_t default_queue;
  unsigned flags = 0;
  ndrange_t ndrange;
  if (i)
    enqueue_kernel(default_queue, flags, ndrange, ^(local void *a) { }, 32);
}

// Check that the temporary is scoped to the `if`

// CHECK-DEBUG: !32 = distinct !DILexicalBlock(scope: !7, file: !1, line: 24)
// CHECK-DEBUG: !34 = !DILocation(line: 25, scope: !32)