/*===================== begin_copyright_notice ==================================

Copyright (c) 2017 Intel Corporation

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 NONINFRINGEMENT.
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.


======================= end_copyright_notice ==================================*/

//*****************************************************************************/
// Image Atomics (Intel Vendor Extension)
//*****************************************************************************/

INLINE int OVERLOADABLE intel_atomic_and(image1d_buffer_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_and_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_and(image1d_buffer_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_and_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_or(image1d_buffer_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_or_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_or(image1d_buffer_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_or_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_xor(image1d_buffer_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_xor_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_xor(image1d_buffer_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_xor_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_xchg(image1d_buffer_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_xchg_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_xchg(image1d_buffer_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_xchg_i32( image_id, c, val );
}

float OVERLOADABLE intel_atomic_xchg(image1d_buffer_t image, int coord, float val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int ival = as_int( val );
    int4 c = (int4)( coord, 0, 0, 0 );
    int i = __builtin_IB_image_atomic_xchg_i32( image_id, c, ival );
    return as_float( i );
}

INLINE int OVERLOADABLE intel_atomic_inc(image1d_buffer_t image, int coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_inc_i32( image_id, c );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_inc(image1d_buffer_t image, int coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_dec(image1d_buffer_t image, int coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_dec_i32( image_id, c );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_dec(image1d_buffer_t image, int coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_add(image1d_buffer_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_add(image1d_buffer_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_sub(image1d_buffer_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, -val );
}

INLINE uint OVERLOADABLE intel_atomic_sub(image1d_buffer_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, -val );
}

INLINE int OVERLOADABLE intel_atomic_cmpxchg(image1d_buffer_t image, int coord, int cmp, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, c, cmp, val );
}

INLINE uint OVERLOADABLE intel_atomic_cmpxchg(image1d_buffer_t image, int coord, uint cmp, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, c, cmp, val );
}

INLINE int OVERLOADABLE intel_atomic_min(image1d_buffer_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_min_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_min(image1d_buffer_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_min_u32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_max(image1d_buffer_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_max_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_max(image1d_buffer_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_max_u32( image_id, c, val );
}


// image1d_t

INLINE int OVERLOADABLE intel_atomic_and(image1d_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_and_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_and(image1d_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_and_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_or(image1d_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_or_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_or(image1d_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_or_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_xor(image1d_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_xor_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_xor(image1d_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_xor_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_xchg(image1d_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_xchg_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_xchg(image1d_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_xchg_i32( image_id, c, val );
}

float OVERLOADABLE intel_atomic_xchg(image1d_t image, int coord, float val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int ival = as_int( val );
    int4 c = (int4)( coord, 0, 0, 0 );
    int i = __builtin_IB_image_atomic_xchg_i32( image_id, c, ival );
    return as_float( i );
}

INLINE int OVERLOADABLE intel_atomic_inc(image1d_t image, int coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_inc_i32( image_id, c );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_inc(image1d_t image, int coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_dec(image1d_t image, int coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_dec_i32( image_id, c );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_dec(image1d_t image, int coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_add(image1d_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_add(image1d_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_sub(image1d_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, -val );
}

INLINE uint OVERLOADABLE intel_atomic_sub(image1d_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, -val );
}

INLINE int OVERLOADABLE intel_atomic_cmpxchg(image1d_t image, int coord, int cmp, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, c, cmp, val );
}

INLINE uint OVERLOADABLE intel_atomic_cmpxchg(image1d_t image, int coord, uint cmp, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, c, cmp, val );
}

INLINE int OVERLOADABLE intel_atomic_min(image1d_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_min_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_min(image1d_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_min_u32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_max(image1d_t image, int coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_max_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_max(image1d_t image, int coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0, 0 );
    return __builtin_IB_image_atomic_max_u32( image_id, c, val );
}


// image1d_array_t

INLINE int OVERLOADABLE intel_atomic_and(image1d_array_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_and_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_and(image1d_array_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_and_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_or(image1d_array_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_or_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_or(image1d_array_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_or_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_xor(image1d_array_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_xor_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_xor(image1d_array_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_xor_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_xchg(image1d_array_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_xchg_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_xchg(image1d_array_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_xchg_i32( image_id, c, val );
}

float OVERLOADABLE intel_atomic_xchg(image1d_array_t image, int2 coord, float val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int ival = as_int( val );
    int4 c = (int4)( coord, 0, 0 );
    int i = __builtin_IB_image_atomic_xchg_i32( image_id, c, ival );
    return as_float( i );
}

INLINE int OVERLOADABLE intel_atomic_inc(image1d_array_t image, int2 coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_inc_i32( image_id, c );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_inc(image1d_array_t image, int2 coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_dec(image1d_array_t image, int2 coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_dec_i32( image_id, c );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_dec(image1d_array_t image, int2 coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_add(image1d_array_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_add(image1d_array_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_sub(image1d_array_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, -val );
}

INLINE uint OVERLOADABLE intel_atomic_sub(image1d_array_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, -val );
}

INLINE int OVERLOADABLE intel_atomic_cmpxchg(image1d_array_t image, int2 coord, int cmp, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, c, cmp, val );
}

INLINE uint OVERLOADABLE intel_atomic_cmpxchg(image1d_array_t image, int2 coord, uint cmp, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, c, cmp, val );
}

INLINE int OVERLOADABLE intel_atomic_min(image1d_array_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_min_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_min(image1d_array_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_min_u32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_max(image1d_array_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_max_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_max(image1d_array_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_max_u32( image_id, c, val );
}


// image2d_t

INLINE int OVERLOADABLE intel_atomic_and(image2d_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_and_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_and(image2d_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_and_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_or(image2d_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_or_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_or(image2d_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_or_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_xor(image2d_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_xor_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_xor(image2d_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_xor_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_xchg(image2d_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_xchg_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_xchg(image2d_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_xchg_i32( image_id, c, val );
}

float OVERLOADABLE intel_atomic_xchg(image2d_t image, int2 coord, float val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int ival = as_int( val );
    int4 c = (int4)( coord, 0, 0 );
    int i = __builtin_IB_image_atomic_xchg_i32( image_id, c, ival );
    return as_float( i );
}

INLINE int OVERLOADABLE intel_atomic_inc(image2d_t image, int2 coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_inc_i32( image_id, c );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_inc(image2d_t image, int2 coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_dec(image2d_t image, int2 coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_dec_i32( image_id, c );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_dec(image2d_t image, int2 coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_add(image2d_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_add(image2d_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_sub(image2d_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, -val );
}

INLINE uint OVERLOADABLE intel_atomic_sub(image2d_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_add_i32( image_id, c, -val );
}

INLINE int OVERLOADABLE intel_atomic_cmpxchg(image2d_t image, int2 coord, int cmp, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, c, cmp, val );
}

INLINE uint OVERLOADABLE intel_atomic_cmpxchg(image2d_t image, int2 coord, uint cmp, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, c, cmp, val );
}

INLINE int OVERLOADABLE intel_atomic_min(image2d_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_min_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_min(image2d_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_min_u32( image_id, c, val );
}

INLINE int OVERLOADABLE intel_atomic_max(image2d_t image, int2 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_max_i32( image_id, c, val );
}

INLINE uint OVERLOADABLE intel_atomic_max(image2d_t image, int2 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int4 c = (int4)( coord, 0, 0 );
    return __builtin_IB_image_atomic_max_u32( image_id, c, val );
}


// image2d_array_t

INLINE int OVERLOADABLE intel_atomic_and(image2d_array_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_and_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_and(image2d_array_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_and_i32( image_id, coord, val );
}

INLINE int OVERLOADABLE intel_atomic_or(image2d_array_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_or_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_or(image2d_array_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_or_i32( image_id, coord, val );
}

INLINE int OVERLOADABLE intel_atomic_xor(image2d_array_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_xor_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_xor(image2d_array_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_xor_i32( image_id, coord, val );
}

INLINE int OVERLOADABLE intel_atomic_xchg(image2d_array_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_xchg_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_xchg(image2d_array_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_xchg_i32( image_id, coord, val );
}

float OVERLOADABLE intel_atomic_xchg(image2d_array_t image, int4 coord, float val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int ival = as_int( val );
    int i = __builtin_IB_image_atomic_xchg_i32( image_id, coord, ival );
    return as_float( i );
}

INLINE int OVERLOADABLE intel_atomic_inc(image2d_array_t image, int4 coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_inc_i32( image_id, coord );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_inc(image2d_array_t image, int4 coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_dec(image2d_array_t image, int4 coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_dec_i32( image_id, coord );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_dec(image2d_array_t image, int4 coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_add(image2d_array_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_add_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_add(image2d_array_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_add_i32( image_id, coord, val );
}

INLINE int OVERLOADABLE intel_atomic_sub(image2d_array_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_add_i32( image_id, coord, -val );
}

INLINE uint OVERLOADABLE intel_atomic_sub(image2d_array_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_add_i32( image_id, coord, -val );
}

INLINE int OVERLOADABLE intel_atomic_cmpxchg(image2d_array_t image, int4 coord, int cmp, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, coord, cmp, val );
}

INLINE uint OVERLOADABLE intel_atomic_cmpxchg(image2d_array_t image, int4 coord, uint cmp, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, coord, cmp, val );
}

INLINE int OVERLOADABLE intel_atomic_min(image2d_array_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_min_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_min(image2d_array_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_min_u32( image_id, coord, val );
}

INLINE int OVERLOADABLE intel_atomic_max(image2d_array_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_max_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_max(image2d_array_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_max_u32( image_id, coord, val );
}


// image3d_t

INLINE int OVERLOADABLE intel_atomic_and(image3d_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_and_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_and(image3d_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_and_i32( image_id, coord, val );
}

INLINE int OVERLOADABLE intel_atomic_or(image3d_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_or_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_or(image3d_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_or_i32( image_id, coord, val );
}

INLINE int OVERLOADABLE intel_atomic_xor(image3d_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_xor_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_xor(image3d_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_xor_i32( image_id, coord, val );
}

INLINE int OVERLOADABLE intel_atomic_xchg(image3d_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_xchg_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_xchg(image3d_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_xchg_i32( image_id, coord, val );
}

float OVERLOADABLE intel_atomic_xchg(image3d_t image, int4 coord, float val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int ival = as_int( val );
    int i = __builtin_IB_image_atomic_xchg_i32( image_id, coord, ival );
    return as_float( i );
}

INLINE int OVERLOADABLE intel_atomic_inc(image3d_t image, int4 coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_inc_i32( image_id, coord );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_inc(image3d_t image, int4 coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_dec(image3d_t image, int4 coord)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_dec_i32( image_id, coord );
}

// Can't have both the int and uint versions as they differ only on return value
// TODO: Which one do we want?
//INLINE uint OVERLOADABLE intel_atomic_dec(image3d_t image, int4 coord)
//{
//    return 0; // TODO
//}

INLINE int OVERLOADABLE intel_atomic_add(image3d_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_add_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_add(image3d_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_add_i32( image_id, coord, val );
}

INLINE int OVERLOADABLE intel_atomic_sub(image3d_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_add_i32( image_id, coord, -val );
}

INLINE uint OVERLOADABLE intel_atomic_sub(image3d_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_add_i32( image_id, coord, -val );
}

INLINE int OVERLOADABLE intel_atomic_cmpxchg(image3d_t image, int4 coord, int cmp, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, coord, cmp, val );
}

INLINE uint OVERLOADABLE intel_atomic_cmpxchg(image3d_t image, int4 coord, uint cmp, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_cmpxchg_i32( image_id, coord, cmp, val );
}

INLINE int OVERLOADABLE intel_atomic_min(image3d_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_min_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_min(image3d_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_min_u32( image_id, coord, val );
}

INLINE int OVERLOADABLE intel_atomic_max(image3d_t image, int4 coord, int val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_max_i32( image_id, coord, val );
}

INLINE uint OVERLOADABLE intel_atomic_max(image3d_t image, int4 coord, uint val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    return __builtin_IB_image_atomic_max_u32( image_id, coord, val );
}


// image2d_depth_t

float OVERLOADABLE intel_atomic_xchg(image2d_depth_t image, int2 coord, float val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int ival = as_int( val );
    int4 c = (int4)( coord, 0, 0 );
    int i = __builtin_IB_image_atomic_xchg_i32( image_id, c, ival );
    return as_float( i );
}


// image2d_array_depth_t

float OVERLOADABLE intel_atomic_xchg(image2d_array_depth_t image, int4 coord, float val)
{
    int image_id = (int)__builtin_astype(image, __global void*);
    int ival = as_int( val );
    int i = __builtin_IB_image_atomic_xchg_i32( image_id, coord, ival );
    return as_float( i );
}

