!===-- module/cudedevice.f90 -----------------------------------------------===!
!
! Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
! See https://llvm.org/LICENSE.txt for license information.
! SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
!
!===------------------------------------------------------------------------===!

! CUDA Fortran procedures available in device subprogram

module cudadevice
  use __cuda_device
  use __fortran_builtins, only: dim3 => __builtin_dim3
  use __fortran_builtins, only: c_devptr => __builtin_c_devptr
  use __fortran_builtins, only: c_devloc => __builtin_c_devloc
implicit none

  ! Synchronization Functions

  interface syncthreads
    procedure :: syncthreads
  end interface

  interface syncthreads_and
    attributes(device) integer function syncthreads_and_i4(value)
      integer(4), value :: value
    end function
    attributes(device) integer function syncthreads_and_l4(value)
      logical(4), value :: value
    end function
  end interface syncthreads_and

  interface syncthreads_count
    attributes(device) integer function syncthreads_count_i4(value)
      integer(4), value :: value
    end function
    attributes(device) integer function syncthreads_count_l4(value)
      logical(4), value :: value
    end function
  end interface syncthreads_count

  interface syncthreads_or
    attributes(device) integer function syncthreads_or_i4(value)
      integer(4), value :: value
    end function
    attributes(device) integer function syncthreads_or_l4(value)
      logical(4), value :: value
    end function
  end interface syncthreads_or

  interface
    attributes(device) subroutine syncwarp(mask)
      integer, value :: mask
    end subroutine
  end interface

  ! Memory Fences

  interface
    attributes(device) subroutine threadfence()
    end subroutine
  end interface

  interface
    attributes(device) subroutine threadfence_block()
    end subroutine
  end interface

  interface
    attributes(device) subroutine threadfence_system()
    end subroutine
  end interface

  ! Math API

  interface __fadd_rn
   attributes(device) real function __fadd_rn(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real, value :: a, b
   end function
  end interface
  
  interface __fadd_rz
   attributes(device) real function __fadd_rz(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real, value :: a, b
   end function
  end interface

  interface
    attributes(device) function __fadd_rd(x, y) bind(c)
      real, intent(in), value :: x, y
      real :: __fadd_rd
    end function
  end interface

  interface
    attributes(device) function __fadd_ru(x, y) bind(c)
      real, intent(in), value :: x, y
      real :: __fadd_ru
    end function
  end interface

  interface __fmul_rn
   attributes(device) real function __fmul_rn(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real, value :: a, b
   end function
  end interface

  interface __fmul_rz
   attributes(device) real function __fmul_rz(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real, value :: a, b
   end function
  end interface

  interface __fmul_ru
   attributes(device) real function __fmul_ru(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real, value :: a, b
   end function
  end interface

  interface __fmul_rd
   attributes(device) real function __fmul_rd(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real, value :: a, b
   end function
  end interface

  interface __fmaf_rn
   attributes(device) real function __fmaf_rn(a,b,c) bind(c)
  !dir$ ignore_tkr (d) a, (d) b, (d) c
    real, value :: a, b, c
   end function
  end interface

  interface __fmaf_rz
   attributes(device) real function __fmaf_rz(a,b,c) bind(c)
  !dir$ ignore_tkr (d) a, (d) b, (d) c
    real, value :: a, b, c
   end function
  end interface
  
  interface __fmaf_ru
   attributes(device) real function __fmaf_ru(a,b,c) bind(c)
  !dir$ ignore_tkr (d) a, (d) b, (d) c
    real, value :: a, b, c
   end function
  end interface
  
  interface __fmaf_rd
   attributes(device) real function __fmaf_rd(a,b,c) bind(c)
  !dir$ ignore_tkr (d) a, (d) b, (d) c
    real, value :: a, b, c
   end function
  end interface

  interface __frcp_rn
   attributes(device) real function __frcp_rn(a) bind(c)
  !dir$ ignore_tkr (d) a
    real, value :: a
   end function
  end interface

  interface __frcp_rz
   attributes(device) real function __frcp_rz(a) bind(c)
  !dir$ ignore_tkr (d) a
    real, value :: a
   end function
  end interface

  interface __frcp_ru
   attributes(device) real function __frcp_ru(a) bind(c)
  !dir$ ignore_tkr (d) a
    real, value :: a
   end function
  end interface

  interface __frcp_rd
   attributes(device) real function __frcp_rd(a) bind(c)
  !dir$ ignore_tkr (d) a
    real, value :: a
   end function
  end interface

  interface __fsqrt_rn
   attributes(device) real function __fsqrt_rn(a) bind(c)
  !dir$ ignore_tkr (d) a
    real, value :: a
   end function
  end interface

  interface __fsqrt_rz
   attributes(device) real function __fsqrt_rz(a) bind(c)
  !dir$ ignore_tkr (d) a
    real, value :: a
   end function
  end interface

  interface __fsqrt_ru
   attributes(device) real function __fsqrt_ru(a) bind(c)
  !dir$ ignore_tkr (d) a
    real, value :: a
   end function
  end interface

  interface __fsqrt_rd
   attributes(device) real function __fsqrt_rd(a) bind(c)
  !dir$ ignore_tkr (d) a
    real, value :: a
   end function
  end interface

  interface __fdiv_rn
   attributes(device) real function __fdiv_rn(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real, value :: a, b
   end function
  end interface

  interface __fdiv_rz
   attributes(device) real function __fdiv_rz(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real, value :: a, b
   end function
  end interface

  interface __fdiv_ru
   attributes(device) real function __fdiv_ru(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real, value :: a, b
   end function
  end interface

  interface __fdiv_rd
   attributes(device) real function __fdiv_rd(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real, value :: a, b
   end function
  end interface

  interface __dadd_rn
   attributes(device) real(8) function __dadd_rn(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b
   end function
  end interface

  interface __dadd_rz
   attributes(device) real(8) function __dadd_rz(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b
   end function
  end interface

  interface __dadd_ru
   attributes(device) real(8) function __dadd_ru(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b
   end function
  end interface

  interface __dadd_rd
   attributes(device) real(8) function __dadd_rd(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b
   end function
  end interface

  interface __dmul_rn
   attributes(device) real(8) function __dmul_rn(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b
   end function
  end interface

  interface __dmul_rz
   attributes(device) real(8) function __dmul_rz(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b
   end function
  end interface

  interface __dmul_ru
   attributes(device) real(8) function __dmul_ru(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b
   end function
  end interface

  interface __dmul_rd
   attributes(device) real(8) function __dmul_rd(a,b) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b
   end function
  end interface

  interface __fma_rn
   attributes(device) real(8) function __fma_rn(a,b,c) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b, c
   end function
  end interface

  interface __fma_rz
   attributes(device) real(8) function __fma_rz(a,b,c) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b, c
   end function
  end interface

  interface __fma_ru
   attributes(device) real(8) function __fma_ru(a,b,c) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b, c
   end function
  end interface

  interface __fma_rd
   attributes(device) real(8) function __fma_rd(a,b,c) bind(c)
  !dir$ ignore_tkr (d) a, (d) b
    real(8), value :: a, b, c
   end function
  end interface

  interface rsqrt
    attributes(device) real(4) function rsqrtf(x) bind(c,name='__nv_rsqrtf')
      real(4), value :: x
    end function
    attributes(device) real(8) function rsqrt(x) bind(c,name='__nv_rsqrt')
      real(8), value :: x
    end function
  end interface

  interface saturate
    attributes(device) real function __saturatef(r) bind(c, name='__nv_saturatef')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __sad
    attributes(device) integer function __sad(i,j,k) bind(c, name='__nv_sad')
      !dir$ ignore_tkr (d) i, (d) j, (d) k
      integer, value :: i,j,k
    end function
  end interface

  interface __usad
    attributes(device) integer function __usad(i,j,k) bind(c, name='__nv_usad')
      !dir$ ignore_tkr (d) i, (d) j, (d) k
      integer, value :: i,j,k
    end function
  end interface
  
  interface signbit
    attributes(device) integer(4) function signbitf(x) bind(c,name='__nv_signbitf')
      real(4), value :: x
    end function
    attributes(device) integer(4) function signbit(x) bind(c,name='__nv_signbitd')
      real(8), value :: x
    end function
  end interface

  interface
    attributes(device) subroutine sincosf(x, y, z) bind(c,name='__nv_sincosf')
      real(4), value :: x
      real(4), device :: y
      real(4), device :: z
    end subroutine
  end interface
  interface
    attributes(device) subroutine sincos(x, y, z) bind(c,name='__nv_sincos')
      real(8), value :: x
      real(8), device :: y
      real(8), device :: z
    end subroutine
  end interface
  interface sincos
    procedure :: sincosf
    procedure :: sincos
  end interface

  interface
    attributes(device) subroutine sincospif(x, y, z) bind(c,name='__nv_sincospif')
      real(4), value :: x
      real(4), device :: y
      real(4), device :: z
    end subroutine
  end interface
  interface
    attributes(device) subroutine sincospi(x, y, z) bind(c,name='__nv_sincospi')
      real(8), value :: x
      real(8), device :: y
      real(8), device :: z
    end subroutine
  end interface
  interface sincospi
    procedure :: sincospif
    procedure :: sincospi
  end interface

  interface
    attributes(device) real(4) function __cosf(x) bind(c, name='__nv_fast_cosf')
      real(4), value :: x
    end function
  end interface

  interface __exp10f
    attributes(device) real function __exp10f(r) bind(c, name='__nv_fast_exp10f')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __expf
    attributes(device) real function __expf(r) bind(c, name='__nv_fast_expf')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface
  
  interface __fdividef
    attributes(device) real function __fdividef(r,d) bind(c, name='__nv_fast_fdividef')
      !dir$ ignore_tkr (d) r, (d) d
      real, value :: r,d
    end function
  end interface

  interface __log10f
    attributes(device) real function __log10f(r) bind(c, name='__nv_fast_log10f')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __log2f
    attributes(device) real function __log2f(r) bind(c, name='__nv_fast_log2f')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __logf
    attributes(device) real function __logf(r) bind(c, name='__nv_fast_logf')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface
    attributes(device) real(4) function __powf(x,y) bind(c, name='__nv_fast_powf')
      !dir$ ignore_tkr (d) x, y
      real(4), value :: x, y
    end function
  end interface

  interface __sincosf
    attributes(device) subroutine __sincosf(r, s, c) bind(c, name='__nv_fast_sincosf')
      !dir$ ignore_tkr (d) r, (d) s, (d) c
      real, value :: r
      real :: s, c
    end subroutine
  end interface

  interface __sinf
    attributes(device) real function __sinf(r) bind(c, name='__nv_fast_sinf')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __tanf
    attributes(device) real function __tanf(r) bind(c, name='__nv_fast_tanf')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface
    attributes(device) real(4) function cospif(x) bind(c,name='__nv_cospif')
      real(4), value :: x
    end function
  end interface
  interface
    attributes(device) real(8) function cospi(x) bind(c,name='__nv_cospi')
      real(8), value :: x
    end function
  end interface
  interface cospi
    procedure :: cospif
    procedure :: cospi
  end interface

  interface  
    attributes(device) real(4) function sinpif(x) bind(c,name='__nv_sinpif')
      real(4), value :: x
    end function
  end interface
  interface
    attributes(device) real(8) function sinpi(x) bind(c,name='__nv_sinpi')
      real(8), value :: x
    end function
  end interface
  interface sinpi
    procedure :: sinpif
    procedure :: sinpi
  end interface
  
  interface mulhi
   attributes(device) integer function __mulhi(i,j) bind(c,name='__nv_mulhi')
  !dir$ ignore_tkr (d) i, (d) j
    integer, value :: i,j
   end function
  end interface

  interface umulhi
   attributes(device) integer function __umulhi(i,j) bind(c,name='__nv_umulhi')
  !dir$ ignore_tkr (d) i, (d) j
    integer, value :: i,j
   end function
  end interface
  
  interface mul64hi
   attributes(device) integer(8) function __mul64hi(i,j) bind(c,name='__nv_mul64hi')
  !dir$ ignore_tkr (d) i, (d) j
    integer(8), value :: i,j
   end function
  end interface
  
  interface umul64hi
   attributes(device) integer(8) function __umul64hi(i,j) bind(c,name='__nv_umul64hi')
  !dir$ ignore_tkr (d) i, (d) j
    integer(8), value :: i,j
   end function
  end interface

  interface int_as_float
    attributes(device) real function __int_as_float(i) bind(c, name='__nv_int_as_float')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
  end interface

  interface float_as_int
    attributes(device) integer function __float_as_int(i) bind(c, name='__nv_float_as_int')
      !dir$ ignore_tkr (d) i
      real, value :: i
    end function
  end interface

  interface __float2half_rn
    attributes(device) real(2) function __float2half_rn(r) bind(c, name='__nv_float2half_rn')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2int_rd
    attributes(device) integer function __float2int_rd(r) bind(c, name='__nv_float2int_rd')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2int_rn
    attributes(device) integer function __float2int_rn(r) bind(c, name='__nv_float2int_rn')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2int_ru
    attributes(device) integer function __float2int_ru(r) bind(c, name='__nv_float2int_ru')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2int_rz
    attributes(device) integer function __float2int_rz(r) bind(c, name='__nv_float2int_rz')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2uint_rd
    attributes(device) integer function __float2uint_rd(r) bind(c, name='__nv_float2uint_rd')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2uint_rn
    attributes(device) integer function __float2uint_rn(r) bind(c, name='__nv_float2uint_rn')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2uint_ru
    attributes(device) integer function __float2uint_ru(r) bind(c, name='__nv_float2uint_ru')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2uint_rz
    attributes(device) integer function __float2uint_rz(r) bind(c, name='__nv_float2uint_rz')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2ll_rd
    attributes(device) integer(8) function __float2ll_rd(r) bind(c, name='__nv_float2ll_rd')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2ll_rn
    attributes(device) integer(8) function __float2ll_rn(r) bind(c, name='__nv_float2ll_rn')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2ll_ru
    attributes(device) integer(8) function __float2ll_ru(r) bind(c, name='__nv_float2ll_ru')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2ll_rz
    attributes(device) integer(8) function __float2ll_rz(r) bind(c, name='__nv_float2ll_rz')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2ull_rd
    attributes(device) integer(8) function __float2ull_rd(r) bind(c, name='__nv_float2ull_rd')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __float2ull_rn
    attributes(device) integer(8) function __float2ull_rn(r) bind(c, name='__nv_float2ull_rn')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface
  
  interface __float2ull_ru
    attributes(device) integer(8) function __float2ull_ru(r) bind(c, name='__nv_float2ull_ru')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface
  
  interface __float2ull_rz
    attributes(device) integer(8) function __float2ull_rz(r) bind(c, name='__nv_float2ull_rz')
      !dir$ ignore_tkr (d) r
      real, value :: r
    end function
  end interface

  interface __half2float
    attributes(device) real function __half2float(i) bind(c, name='__nv_half2float')
      !dir$ ignore_tkr (d) i
      real(2), value :: i
    end function
  end interface

  interface double_as_longlong
    attributes(device) integer(8) function __double_as_longlong(i) bind(c, name='__nv_double_as_longlong')
      !dir$ ignore_tkr (d) i
      real(8), value :: i
    end function
  end interface

  interface longlong_as_double
    attributes(device) real(8) function __longlong_as_double(i) bind(c, name='__nv_longlong_as_double')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __double2int_rd
    attributes(device) integer function __double2int_rd(r) bind(c, name='__nv_double2int_rd')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2int_rn
    attributes(device) integer function __double2int_rn(r) bind(c, name='__nv_double2int_rn')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2int_ru
    attributes(device) integer function __double2int_ru(r) bind(c, name='__nv_double2int_ru')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2int_rz
    attributes(device) integer function __double2int_rz(r) bind(c, name='__nv_double2int_rz')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2uint_rd
    attributes(device) integer function __double2uint_rd(r) bind(c, name='__nv_double2uint_rd')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2uint_rn
    attributes(device) integer function __double2uint_rn(r) bind(c, name='__nv_double2uint_rn')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2uint_ru
    attributes(device) integer function __double2uint_ru(r) bind(c, name='__nv_double2uint_ru')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2uint_rz
    attributes(device) integer function __double2uint_rz(r) bind(c, name='__nv_double2uint_rz')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2float_rn
    attributes(device) real function __double2float_rn(r) bind(c, name='__nv_double2float_rn')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2float_rz
    attributes(device) real function __double2float_rz(r) bind(c, name='__nv_double2float_rz')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2float_ru
    attributes(device) real function __double2float_ru(r) bind(c, name='__nv_double2float_ru')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2float_rd
    attributes(device) real function __double2float_rd(r) bind(c, name='__nv_double2float_rd')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2loint
    attributes(device) integer function __double2loint(r) bind(c, name='__nv_double2loint')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2hiint
    attributes(device) integer function __double2hiint(r) bind(c, name='__nv_double2hiint')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __hiloint2double
    attributes(device) double precision function __hiloint2double(i, j) bind(c, name='__nv_hiloint2double')
      !dir$ ignore_tkr (d) i, (d) j
      integer, value :: i, j
    end function
  end interface

  interface __int2float_rd
    attributes(device) real function __int2float_rd(i) bind(c, name='__nv_int2float_rd')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
  end interface

  interface __int2float_rn
    attributes(device) real function __int2float_rn(i) bind(c, name='__nv_int2float_rn')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
  end interface

  interface __int2float_ru
    attributes(device) real function __int2float_ru(i) bind(c, name='__nv_int2float_ru')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
  end interface

  interface __int2float_rz
    attributes(device) real function __int2float_rz(i) bind(c, name='__nv_int2float_rz')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
  end interface

  interface __int2double_rn
    attributes(device) double precision function __int2double_rn(i) bind(c, name='__nv_int2double_rn')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
  end interface

  interface __uint2float_rd
    attributes(device) real function __uint2float_rd(i) bind(c, name='__nv_uint2float_rd')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
  end interface

  interface __uint2float_rn
    attributes(device) real function __uint2float_rn(i) bind(c, name='__nv_uint2float_rn')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
  end interface

  interface __uint2float_ru
    attributes(device) real function __uint2float_ru(i) bind(c, name='__nv_uint2float_ru')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
  end interface

  interface __uint2float_rz
    attributes(device) real function __uint2float_rz(i) bind(c, name='__nv_uint2float_rz')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
  end interface

  interface __uint2double_rn
    attributes(device) double precision function __uint2double_rn(i) bind(c, name='__nv_uint2double_rn')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
  end interface

  interface __double2ll_rd
    attributes(device) integer(8) function __double2ll_rd(r) bind(c, name='__nv_double2ll_rd')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2ll_rn
    attributes(device) integer(8) function __double2ll_rn(r) bind(c, name='__nv_double2ll_rn')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2ll_ru
    attributes(device) integer(8) function __double2ll_ru(r) bind(c, name='__nv_double2ll_ru')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2ll_rz
    attributes(device) integer(8) function __double2ll_rz(r) bind(c, name='__nv_double2ll_rz')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2ull_rd
    attributes(device) integer(8) function __double2ull_rd(r) bind(c, name='__nv_double2ull_rd')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2ull_rn
    attributes(device) integer(8) function __double2ull_rn(r) bind(c, name='__nv_double2ull_rn')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2ull_ru
    attributes(device) integer(8) function __double2ull_ru(r) bind(c, name='__nv_double2ull_ru')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __double2ull_rz
    attributes(device) integer(8) function __double2ull_rz(r) bind(c, name='__nv_double2ull_rz')
      !dir$ ignore_tkr (d) r
      double precision, value :: r
    end function
  end interface

  interface __ll2float_rd
    attributes(device) real function __ll2float_rd(i) bind(c, name='__nv_ll2float_rd')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ll2float_rn
    attributes(device) real function __ll2float_rn(i) bind(c, name='__nv_ll2float_rn')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
    end interface

  interface __ll2float_ru
    attributes(device) real function __ll2float_ru(i) bind(c, name='__nv_ll2float_ru')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ll2float_rz
    attributes(device) real function __ll2float_rz(i) bind(c, name='__nv_ll2float_rz')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ll2double_rd
    attributes(device) double precision function __ll2double_rd(i) bind(c, name='__nv_ll2double_rd')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ll2double_rn
    attributes(device) double precision function __ll2double_rn(i) bind(c, name='__nv_ll2double_rn')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ll2double_ru
    attributes(device) double precision function __ll2double_ru(i) bind(c, name='__nv_ll2double_ru')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ll2double_rz
    attributes(device) double precision function __ll2double_rz(i) bind(c, name='__nv_ll2double_rz')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ull2double_rd
    attributes(device) double precision function __ull2double_rd(i) bind(c, name='__nv_ull2double_rd')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ull2double_rn
    attributes(device) double precision function __ull2double_rn(i) bind(c, name='__nv_ull2double_rn')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ull2double_ru
    attributes(device) double precision function __ull2double_ru(i) bind(c, name='__nv_ull2double_ru')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ull2double_rz
    attributes(device) double precision function __ull2double_rz(i) bind(c, name='__nv_ull2double_rz')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ull2float_rd
    attributes(device) real function __ull2float_rd(i) bind(c, name='__nv_ull2float_rd')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ull2float_rn
    attributes(device) real function __ull2float_rn(i) bind(c, name='__nv_ull2float_rn')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ull2float_ru
    attributes(device) real function __ull2float_ru(i) bind(c, name='__nv_ull2float_ru')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ull2float_rz
    attributes(device) real function __ull2float_rz(i) bind(c, name='__nv_ull2float_rz')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __mul24
    attributes(device) integer function __mul24(i,j) bind(c, name='__nv_mul24')
      !dir$ ignore_tkr (d) i, (d) j
      integer, value :: i,j
    end function
  end interface

  interface __umul24
    attributes(device) integer function __umul24(i,j) bind(c, name='__nv_umul24')
      !dir$ ignore_tkr (d) i, (d) j
      integer, value :: i,j
    end function
  end interface

  interface __drcp_rd
    attributes(device) double precision function __drcp_rd(x) bind(c)
      !dir$ ignore_tkr (d) x
      double precision, value :: x
    end function
  end interface

  interface __drcp_rn
    attributes(device) double precision function __drcp_rn(x) bind(c)
      !dir$ ignore_tkr (d) x
      double precision, value :: x
    end function
  end interface

  interface __drcp_ru
    attributes(device) double precision function __drcp_ru(x) bind(c)
      !dir$ ignore_tkr (d) x
      double precision, value :: x
    end function
  end interface

  interface __drcp_rz
    attributes(device) double precision function __drcp_rz(x) bind(c)
      !dir$ ignore_tkr (d) x
      double precision, value :: x
    end function
  end interface

  interface __dsqrt_rd
    attributes(device) double precision function __dsqrt_rd(x) bind(c)
      !dir$ ignore_tkr (d) x
      double precision, value :: x
    end function
  end interface

  interface __dsqrt_rn
    attributes(device) double precision function __dsqrt_rn(x) bind(c)
      !dir$ ignore_tkr (d) x
      double precision, value :: x
    end function
  end interface

  interface __dsqrt_ru
    attributes(device) double precision function __dsqrt_ru(x) bind(c)
      !dir$ ignore_tkr (d) x
      double precision, value :: x
    end function
  end interface

  interface __dsqrt_rz
    attributes(device) double precision function __dsqrt_rz(x) bind(c)
      !dir$ ignore_tkr (d) x
      double precision, value :: x
    end function
  end interface

  interface __ddiv_rn
    attributes(device) double precision function __ddiv_rn(x,y) bind(c)
      !dir$ ignore_tkr (d) x, (d) y
      double precision, value :: x, y
    end function
  end interface

  interface __ddiv_rz
    attributes(device) double precision function __ddiv_rz(x,y) bind(c)
      !dir$ ignore_tkr (d) x, (d) y
      double precision, value :: x, y
    end function
  end interface

  interface __ddiv_ru
    attributes(device) double precision function __ddiv_ru(x,y) bind(c)
      !dir$ ignore_tkr (d) x, (d) y
      double precision, value :: x, y
    end function
  end interface

  interface __ddiv_rd
    attributes(device) double precision function __ddiv_rd(x,y) bind(c)
      !dir$ ignore_tkr (d) x, (d) y
      double precision, value :: x, y
    end function
  end interface

  interface __clz
    attributes(device) integer function __clz(i) bind(c, name='__nv_clz')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
    attributes(device) integer function __clzll(i) bind(c, name='__nv_clzll')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __ffs
    attributes(device) integer function __ffs(i) bind(c, name='__nv_ffs')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
    attributes(device) integer function __ffsll(i) bind(c, name='__nv_ffsll')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __popc
    attributes(device) integer function __popc(i) bind(c, name='__nv_popc')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
    attributes(device) integer function __popcll(i) bind(c, name='__nv_popcll')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  interface __brev
    attributes(device) integer function __brev(i) bind(c, name='__nv_brev')
      !dir$ ignore_tkr (d) i
      integer, value :: i
    end function
    attributes(device) integer(8) function __brevll(i) bind(c, name ='__nv_brevll')
      !dir$ ignore_tkr (d) i
      integer(8), value :: i
    end function
  end interface

  ! Atomic Operations

  interface atomicadd
    attributes(device) pure integer function atomicaddi(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    integer, intent(inout) :: address
    integer, value :: val
    end function
    attributes(device) pure real function atomicaddf(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    real, intent(inout) :: address
    real, value :: val
    end function
    attributes(device) pure real(8) function atomicaddd(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    real(8), intent(inout) :: address
    real(8), value :: val
    end function
    attributes(device) pure integer(8) function atomicaddl(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    integer(8), intent(inout) :: address
    integer(8), value :: val
    end function
    attributes(device) pure integer(4) function atomicaddr2(address, val)
      !dir$ ignore_tkr (rd) address, (d) val
      real(2), dimension(2), intent(inout) :: address
      real(2), dimension(2), intent(in) :: val
    end function
  end interface

  interface atomicaddvector
    attributes(device) pure function atomicaddvector_r2x2(address, val) result(z)
      !dir$ ignore_tkr (rd) address, (d) val
      real(2), dimension(2), intent(inout) :: address
      real(2), dimension(2), intent(in) :: val
      real(2), dimension(2) :: z
    end function

    attributes(device) pure function atomicaddvector_r4x2(address, val) result(z)
      !dir$ ignore_tkr (rd) address, (d) val
      real(4), dimension(2), intent(inout) :: address
      real(4), dimension(2), intent(in) :: val
      real(4), dimension(2) :: z
    end function
  end interface

  interface atomicaddreal4x2
    attributes(device) pure function atomicadd_r4x2(address, val) result(z)
      !dir$ ignore_tkr (rd) address, (d) val
      real(4), dimension(2), intent(inout) :: address
      real(4), dimension(2), intent(in) :: val
      real(4), dimension(2) :: z
    end function
  end interface

  interface atomicaddreal4x4
    attributes(device) pure function atomicadd_r4x4(address, val) result(z)
      !dir$ ignore_tkr (rd) address, (d) val
      real(4), dimension(4), intent(inout) :: address
      real(4), dimension(4), intent(in) :: val
      real(4), dimension(4) :: z
    end function
  end interface

  interface atomicsub
    attributes(device) pure integer function atomicsubi(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    integer, intent(inout) :: address
    integer, value :: val
    end function
    attributes(device) pure real function atomicsubf(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    real, intent(inout) :: address
    real, value :: val
    end function
    attributes(device) pure real(8) function atomicsubd(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    real(8), intent(inout) :: address
    real(8), value :: val
    end function
    attributes(device) pure integer(8) function atomicsubl(address, val)
  !dir$ ignore_tkr (d) address, (dk) val
    integer(8), intent(inout) :: address
    integer(8), value :: val
    end function
  end interface
  
  interface atomicmax
    attributes(device) pure integer function atomicmaxi(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    integer, intent(inout) :: address
    integer, value :: val
    end function
    attributes(device) pure real function atomicmaxf(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    real, intent(inout) :: address
    real, value :: val
    end function
    attributes(device) pure real(8) function atomicmaxd(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    real(8), intent(inout) :: address
    real(8), value :: val
    end function
    attributes(device) pure integer(8) function atomicmaxl(address, val)
  !dir$ ignore_tkr (d) address, (dk) val
    integer(8), intent(inout) :: address
    integer(8), value :: val
    end function
  end interface
  
  interface atomicmin
    attributes(device) pure integer function atomicmini(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    integer, intent(inout) :: address
    integer, value :: val
    end function
    attributes(device) pure real function atomicminf(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    real, intent(inout) :: address
    real, value :: val
    end function
    attributes(device) pure real(8) function atomicmind(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    real(8), intent(inout) :: address
    real(8), value :: val
    end function
    attributes(device) pure integer(8) function atomicminl(address, val)
  !dir$ ignore_tkr (d) address, (dk) val
    integer(8), intent(inout) :: address
    integer(8), value :: val
    end function
  end interface
  
  interface atomicand
    attributes(device) pure integer function atomicandi(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    integer, intent(inout) :: address
    integer, value :: val
    end function
  end interface
  
  interface atomicor
    attributes(device) pure integer function atomicori(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    integer, intent(inout) :: address
    integer, value :: val
    end function
  end interface

  interface atomicinc
    attributes(device) pure integer function atomicinci(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    integer, intent(inout) :: address
    integer, value :: val
    end function
  end interface
  
  interface atomicdec
    attributes(device) pure integer function atomicdeci(address, val)
  !dir$ ignore_tkr (d) address, (d) val
    integer, intent(inout) :: address
    integer, value :: val
    end function
  end interface

  interface atomiccas
    attributes(device) pure integer function atomiccasi(address, val, val2)
  !dir$ ignore_tkr (rd) address, (d) val, (d) val2
    integer, intent(inout) :: address
    integer, value :: val, val2
    end function
    attributes(device) pure integer(8) function atomiccasul(address, val, val2)
  !dir$ ignore_tkr (rd) address, (dk) val, (dk) val2
    integer(8), intent(inout) :: address
    integer(8), value :: val, val2
    end function
    attributes(device) pure real function atomiccasf(address, val, val2)
  !dir$ ignore_tkr (rd) address, (d) val, (d) val2
    real, intent(inout) :: address
    real, value :: val, val2
    end function
    attributes(device) pure double precision function atomiccasd(address, val, val2)
  !dir$ ignore_tkr (rd) address, (d) val, (d) val2
    double precision, intent(inout) :: address
    double precision, value :: val, val2
    end function
  end interface

  interface atomicexch
    attributes(device) pure integer function atomicexchi(address, val)
  !dir$ ignore_tkr (rd) address, (d) val
    integer, intent(inout) :: address
    integer, value :: val
    end function
    attributes(device) pure integer(8) function atomicexchul(address, val)
  !dir$ ignore_tkr (rd) address, (dk) val
    integer(8), intent(inout) :: address
    integer(8), value :: val
    end function
    attributes(device) pure real function atomicexchf(address, val)
  !dir$ ignore_tkr (rd) address, (d) val
    real, intent(inout) :: address
    real, value :: val
    end function
    attributes(device) pure double precision function atomicexchd(address, val)
  !dir$ ignore_tkr (rd) address, (d) val
    double precision, intent(inout) :: address
    double precision, value :: val
    end function
  end interface

  interface atomicxor
    attributes(device) pure integer function atomicxori(address, val)
  !dir$ ignore_tkr (rd) address, (d) val
    integer, intent(inout) :: address
    integer, value :: val
    end function
  end interface

  ! Time function

  interface
    attributes(device) integer function clock()
    end function
  end interface

  interface
    attributes(device) integer(8) function clock64()
    end function
  end interface

  interface
    attributes(device) integer(8) function globalTimer()
    end function
  end interface

  ! Warp Match Functions

  interface match_all_sync
    attributes(device) integer function match_all_syncjj(mask, val, pred)
  !dir$ ignore_tkr(d) mask, (d) val, (d) pred
    integer(4), value :: mask
    integer(4), value :: val
    integer(4)        :: pred
    end function
    attributes(device) integer function match_all_syncjx(mask, val, pred)
  !dir$ ignore_tkr(d) mask, (d) val, (d) pred
    integer(4), value :: mask
    integer(8), value :: val
    integer(4)        :: pred
    end function
    attributes(device) integer function match_all_syncjf(mask, val, pred)
  !dir$ ignore_tkr(d) mask, (d) val, (d) pred
    integer(4), value :: mask
    real(4), value    :: val
    integer(4)        :: pred
    end function
    attributes(device) integer function match_all_syncjd(mask, val, pred)
  !dir$ ignore_tkr(d) mask, (d) val, (d) pred
    integer(4), value :: mask
    real(8), value    :: val
    integer(4)        :: pred
    end function
  end interface

  interface match_any_sync
    attributes(device) integer function match_any_syncjj(mask, val)
  !dir$ ignore_tkr(d) mask, (d) val
    integer(4), value :: mask
    integer(4), value :: val
    end function
    attributes(device) integer function match_any_syncjx(mask, val)
  !dir$ ignore_tkr(d) mask, (d) val
    integer(4), value :: mask
    integer(8), value :: val
    end function
    attributes(device) integer function match_any_syncjf(mask, val)
  !dir$ ignore_tkr(d) mask, (d) val
    integer(4), value :: mask
    real(4), value    :: val
    end function
    attributes(device) integer function match_any_syncjd(mask, val)
  !dir$ ignore_tkr(d) mask, (d) val
    integer(4), value :: mask
    real(8), value    :: val
    end function
  end interface

  interface all_sync
    attributes(device) integer function all_sync(mask, pred)
      !dir$ ignore_tkr(d) mask, (td) pred
      integer, value :: mask, pred
    end function
  end interface

  interface any_sync
    attributes(device) integer function any_sync(mask, pred)
      !dir$ ignore_tkr(d) mask, (td) pred
      integer, value :: mask, pred
    end function
  end interface

  interface ballot_sync
    attributes(device) integer function ballot_sync(mask, pred)
      !dir$ ignore_tkr(d) mask, (td) pred
      integer, value :: mask, pred
    end function
  end interface

  ! LDCG
  interface __ldcg
    attributes(device) pure integer(4) function __ldcg_i4(x) bind(c)
      !dir$ ignore_tkr (d) x
      integer(4), intent(in) :: x
    end function
    attributes(device) pure integer(8) function __ldcg_i8(x) bind(c)
      !dir$ ignore_tkr (d) x
      integer(8), intent(in) :: x
    end function
    attributes(device) pure function __ldcg_cd(x) bind(c) result(y)
      import c_devptr
      !dir$ ignore_tkr (d) x
      type(c_devptr), intent(in) :: x
      type(c_devptr) :: y
    end function
    attributes(device) pure real(2) function __ldcg_r2(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(2), intent(in) :: x
    end function
    attributes(device) pure real(4) function __ldcg_r4(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(4), intent(in) :: x
    end function
    attributes(device) pure real(8) function __ldcg_r8(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(8), intent(in) :: x
    end function
    attributes(device) pure complex(4) function __ldcg_c4(x) &
        bind(c,name='__ldcg_c4x')
      !dir$ ignore_tkr (d) x
      complex(4), intent(in) :: x
    end function
    attributes(device) pure complex(8) function __ldcg_c8(x) &
        bind(c,name='__ldcg_c8x')
      !dir$ ignore_tkr (d) x
      complex(8), intent(in) :: x
    end function
    attributes(device) pure function __ldcg_i4x4(x) result(y)
      !dir$ ignore_tkr (d) x
      integer(4), dimension(4), intent(in) :: x
      integer(4), dimension(4) :: y
    end function
    attributes(device) pure function __ldcg_i8x2(x) result(y)
      !dir$ ignore_tkr (d) x
      integer(8), dimension(2), intent(in) :: x
      integer(8), dimension(2) :: y
    end function
    attributes(device) pure function __ldcg_r2x2(x) result(y)
      !dir$ ignore_tkr (d) x
      real(2), dimension(2), intent(in) :: x
      real(2), dimension(2) :: y
    end function
    attributes(device) pure function __ldcg_r4x4(x) result(y)
      !dir$ ignore_tkr (d) x
      real(4), dimension(4), intent(in) :: x
      real(4), dimension(4) :: y
    end function
    attributes(device) pure function __ldcg_r8x2(x) result(y)
      !dir$ ignore_tkr (d) x
      real(8), dimension(2), intent(in) :: x
      real(8), dimension(2) :: y
    end function
  end interface

  ! LDCA
  interface __ldca
    attributes(device) pure integer(4) function __ldca_i4(x) bind(c)
      !dir$ ignore_tkr (d) x
      integer(4), intent(in) :: x
    end function
    attributes(device) pure integer(8) function __ldca_i8(x) bind(c)
      !dir$ ignore_tkr (d) x
      integer(8), intent(in) :: x
    end function
    attributes(device) pure function __ldca_cd(x) bind(c) result(y)
      !dir$ ignore_tkr (d) x
      import c_devptr
      type(c_devptr), intent(in) :: x
      type(c_devptr) :: y
    end function
    attributes(device) pure real(2) function __ldca_r2(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(2), intent(in) :: x
    end function
    attributes(device) pure real(4) function __ldca_r4(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(4), intent(in) :: x
      end function
    attributes(device) pure real(8) function __ldca_r8(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(8), intent(in) :: x
    end function
    attributes(device) pure complex(4) function __ldca_c4(x) &
        bind(c,name='__ldca_c4x')
      !dir$ ignore_tkr (d) x
      complex(4), intent(in) :: x
    end function
    attributes(device) pure complex(8) function __ldca_c8(x) &
        bind(c,name='__ldca_c8x')
      !dir$ ignore_tkr (d) x
      complex(8), intent(in) :: x
    end function
    attributes(device) pure function __ldca_i4x4(x) result(y)
      !dir$ ignore_tkr (d) x
      integer(4), dimension(4), intent(in) :: x
      integer(4), dimension(4) :: y
    end function
    attributes(device) pure function __ldca_i8x2(x) result(y)
      !dir$ ignore_tkr (d) x
      integer(8), dimension(2), intent(in) :: x
      integer(8), dimension(2) :: y
    end function
    attributes(device) pure function __ldca_r2x2(x) result(y)
      !dir$ ignore_tkr (d) x
      real(2), dimension(2), intent(in) :: x
      real(2), dimension(2) :: y
    end function
    attributes(device) pure function __ldca_r4x4(x) result(y)
      !dir$ ignore_tkr (d) x
      real(4), dimension(4), intent(in) :: x
      real(4), dimension(4) :: y
    end function
    attributes(device) pure function __ldca_r8x2(x) result(y)
      !dir$ ignore_tkr (d) x
      real(8), dimension(2), intent(in) :: x
      real(8), dimension(2) :: y
    end function
  end interface

  ! LDCS
  interface __ldcs
    attributes(device) pure integer(4) function __ldcs_i4(x) bind(c)
      !dir$ ignore_tkr (d) x
      integer(4), intent(in) :: x
    end function
    attributes(device) pure integer(8) function __ldcs_i8(x) bind(c)
      !dir$ ignore_tkr (d) x
      integer(8), intent(in) :: x
    end function
    attributes(device) pure function __ldcs_cd(x) bind(c) result(y)
      import c_devptr
      !dir$ ignore_tkr (d) x
      type(c_devptr), intent(in) :: x
      type(c_devptr) :: y
    end function
    attributes(device) pure real(2) function __ldcs_r2(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(2), intent(in) :: x
    end function
    attributes(device) pure real(4) function __ldcs_r4(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(4), intent(in) :: x
    end function
    attributes(device) pure real(8) function __ldcs_r8(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(8), intent(in) :: x
    end function
    attributes(device) pure complex(4) function __ldcs_c4(x) &
        bind(c,name='__ldcs_c4x')
      !dir$ ignore_tkr (d) x
      complex(4), intent(in) :: x
    end function
    attributes(device) pure complex(8) function __ldcs_c8(x) &
        bind(c,name='__ldcs_c8x')
      !dir$ ignore_tkr (d) x
      complex(8), intent(in) :: x
    end function
    attributes(device) pure function __ldcs_i4x4(x) result(y)
      !dir$ ignore_tkr (d) x
      integer(4), dimension(4), intent(in) :: x
      integer(4), dimension(4) :: y
    end function
    attributes(device) pure function __ldcs_i8x2(x) result(y)
      !dir$ ignore_tkr (d) x
      integer(8), dimension(2), intent(in) :: x
      integer(8), dimension(2) :: y
    end function
    attributes(device) pure function __ldcs_r2x2(x) result(y)
      !dir$ ignore_tkr (d) x
      real(2), dimension(2), intent(in) :: x
      real(2), dimension(2) :: y
    end function
    attributes(device) pure function __ldcs_r4x4(x) result(y)
      !dir$ ignore_tkr (d) x
      real(4), dimension(4), intent(in) :: x
      real(4), dimension(4) :: y
    end function
    attributes(device) pure function __ldcs_r8x2(x) result(y)
      !dir$ ignore_tkr (d) x
      real(8), dimension(2), intent(in) :: x
      real(8), dimension(2) :: y
    end function
  end interface

  ! LDLU
  interface __ldlu
    attributes(device) pure integer(4) function __ldlu_i4(x) bind(c)
      !dir$ ignore_tkr (d) x
      integer(4), intent(in) :: x
    end function
    attributes(device) pure integer(8) function __ldlu_i8(x) bind(c)
      !dir$ ignore_tkr (d) x
      integer(8), intent(in) :: x
    end function
    attributes(device) pure function __ldlu_cd(x) bind(c) result(y)
      import c_devptr
      !dir$ ignore_tkr (d) x
      type(c_devptr), intent(in) :: x
      type(c_devptr) :: y
    end function
    attributes(device) pure real(2) function __ldlu_r2(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(2), intent(in) :: x
    end function
    attributes(device) pure real(4) function __ldlu_r4(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(4), intent(in) :: x
    end function
    attributes(device) pure real(8) function __ldlu_r8(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(8), intent(in) :: x
    end function
    attributes(device) pure complex(4) function __ldlu_c4(x) &
        bind(c,name='__ldlu_c4x')
      !dir$ ignore_tkr (d) x
      complex(4), intent(in) :: x
    end function
    attributes(device) pure complex(8) function __ldlu_c8(x) &
        bind(c,name='__ldlu_c8x')
      !dir$ ignore_tkr (d) x
      complex(8), intent(in) :: x
    end function
    attributes(device) pure function __ldlu_i4x4(x) result(y)
      !dir$ ignore_tkr (d) x
      integer(4), dimension(4), intent(in) :: x
      integer(4), dimension(4) :: y
    end function
    attributes(device) pure function __ldlu_i8x2(x) result(y)
      !dir$ ignore_tkr (d) x
      integer(8), dimension(2), intent(in) :: x
      integer(8), dimension(2) :: y
    end function
    attributes(device) pure function __ldlu_r2x2(x) result(y)
      !dir$ ignore_tkr (d) x
      real(2), dimension(2), intent(in) :: x
      real(2), dimension(2) :: y
    end function
    attributes(device) pure function __ldlu_r4x4(x) result(y)
      !dir$ ignore_tkr (d) x
      real(4), dimension(4), intent(in) :: x
      real(4), dimension(4) :: y
    end function
    attributes(device) pure function __ldlu_r8x2(x) result(y)
      !dir$ ignore_tkr (d) x
      real(8), dimension(2), intent(in) :: x
      real(8), dimension(2) :: y
    end function
  end interface

  ! LDCV
  interface __ldcv
    attributes(device) pure integer(4) function __ldcv_i4(x) bind(c)
      !dir$ ignore_tkr (d) x
      integer(4), intent(in) :: x
    end function
    attributes(device) pure integer(8) function __ldcv_i8(x) bind(c)
      !dir$ ignore_tkr (d) x
      integer(8), intent(in) :: x
    end function
    attributes(device) pure function __ldcv_cd(x) bind(c) result(y)
      import c_devptr
      !dir$ ignore_tkr (d) x
      type(c_devptr), intent(in) :: x
      type(c_devptr) :: y
    end function
    attributes(device) pure real(2) function __ldcv_r2(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(2), intent(in) :: x
    end function
    attributes(device) pure real(4) function __ldcv_r4(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(4), intent(in) :: x
    end function
    attributes(device) pure real(8) function __ldcv_r8(x) bind(c)
      !dir$ ignore_tkr (d) x
      real(8), intent(in) :: x
    end function
    attributes(device) pure complex(4) function __ldcv_c4(x) &
        bind(c,name='__ldcv_c4x')
      !dir$ ignore_tkr (d) x
      complex(4), intent(in) :: x
    end function
    attributes(device) pure complex(8) function __ldcv_c8(x) &
        bind(c,name='__ldcv_c8x')
      !dir$ ignore_tkr (d) x
      complex(8), intent(in) :: x
    end function
    attributes(device) pure function __ldcv_i4x4(x) result(y)
      !dir$ ignore_tkr (d) x
      integer(4), dimension(4), intent(in) :: x
      integer(4), dimension(4) :: y
      end function
    attributes(device) pure function __ldcv_i8x2(x) result(y)
      !dir$ ignore_tkr (d) x
      integer(8), dimension(2), intent(in) :: x
      integer(8), dimension(2) :: y
    end function
    attributes(device) pure function __ldcv_r2x2(x) result(y)
      !dir$ ignore_tkr (d) x
      real(2), dimension(2), intent(in) :: x
      real(2), dimension(2) :: y
    end function
    attributes(device) pure function __ldcv_r4x4(x) result(y)
      !dir$ ignore_tkr (d) x
      real(4), dimension(4), intent(in) :: x
      real(4), dimension(4) :: y
    end function
    attributes(device) pure function __ldcv_r8x2(x) result(y)
      !dir$ ignore_tkr (d) x
      real(8), dimension(2), intent(in) :: x
      real(8), dimension(2) :: y
    end function
  end interface

  ! STWB
  interface __stwb
    attributes(device) pure subroutine __stwb_i4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(4), value  :: x
      integer(4), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stwb_i8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(8), value  :: x
      integer(8), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stwb_cd(y, x) bind(c)
      import c_devptr
      !dir$ ignore_tkr (d) y, (d) x
      type(c_devptr), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwb_r2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(2), value :: x
      real(2), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stwb_r4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(4), value :: x
      real(4), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stwb_r8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(8), value :: x
      real(8), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stwb_c4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (rd) x
      complex(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwb_c8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      complex(8), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwb_i4x4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(4), dimension(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwb_i8x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(8), dimension(2), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwb_r2x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(2), dimension(2), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwb_r4x4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(4), dimension(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwb_r8x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(8), dimension(2), device, intent(in) :: y, x
    end subroutine
  end interface

  ! STCG
  interface __stcg
    attributes(device) pure subroutine __stcg_i4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(4), value  :: x
      integer(4), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stcg_i8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(8), value  :: x
      integer(8), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stcg_cd(y, x) bind(c)
      import c_devptr
      !dir$ ignore_tkr (d) y, (d) x
      type(c_devptr), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcg_r2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(2), value :: x
      real(2), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stcg_r4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(4), value :: x
      real(4), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stcg_r8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(8), value :: x
      real(8), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stcg_c4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (rd) x
      complex(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcg_c8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      complex(8), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcg_i4x4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(4), dimension(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcg_i8x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(8), dimension(2), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcg_r2x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(2), dimension(2), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcg_r4x4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(4), dimension(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcg_r8x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(8), dimension(2), device, intent(in) :: y, x
    end subroutine
  end interface

  ! STCS
  interface __stcs
    attributes(device) pure subroutine __stcs_i4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(4), value  :: x
      integer(4), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stcs_i8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(8), value  :: x
      integer(8), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stcs_cd(y, x) bind(c)
      import c_devptr
      !dir$ ignore_tkr (d) y, (d) x
      type(c_devptr), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcs_r2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(2), value :: x
      real(2), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stcs_r4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(4), value :: x
      real(4), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stcs_r8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(8), value :: x
      real(8), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stcs_c4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (rd) x
      complex(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcs_c8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      complex(8), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcs_i4x4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(4), dimension(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcs_i8x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(8), dimension(2), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcs_r2x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(2), dimension(2), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcs_r4x4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(4), dimension(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stcs_r8x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(8), dimension(2), device, intent(in) :: y, x
    end subroutine
  end interface

  ! STWT
  interface __stwt
    attributes(device) pure subroutine __stwt_i4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(4), value  :: x
      integer(4), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stwt_i8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(8), value  :: x
      integer(8), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stwt_cd(y, x) bind(c)
      import c_devptr
      !dir$ ignore_tkr (d) y, (d) x
      type(c_devptr), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwt_r2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(2), value :: x
      real(2), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stwt_r4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(4), value :: x
      real(4), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stwt_r8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(8), value :: x
      real(8), device, intent(in) :: y
    end subroutine
    attributes(device) pure subroutine __stwt_c4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (rd) x
      complex(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwt_c8(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      complex(8), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwt_i4x4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(4), dimension(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwt_i8x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      integer(8), dimension(2), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwt_r2x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(2), dimension(2), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwt_r4x4(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(4), dimension(4), device, intent(in) :: y, x
    end subroutine
    attributes(device) pure subroutine __stwt_r8x2(y, x) bind(c)
      !dir$ ignore_tkr (d) y, (d) x
      real(8), dimension(2), device, intent(in) :: y, x
    end subroutine
  end interface

  interface
    attributes(device,host) logical function on_device() bind(c)
    end function
  end interface

  ! TMA Operations

  interface barrier_arrive
    attributes(device) function barrier_arrive(barrier) result(token)
      integer(8), shared :: barrier
      integer(8) :: token
    end function
    attributes(device) function barrier_arrive_cnt(barrier, count) result(token)
      integer(8), shared :: barrier
      integer(4), value :: count
      integer(8) :: token
    end function
  end interface

  interface 
    attributes(device) subroutine barrier_init(barrier, count)
      integer(8), shared :: barrier
      integer(4), value :: count
    end subroutine
  end interface

  interface
    attributes(device) integer function barrier_try_wait(barrier, token)
      integer(8), shared :: barrier
      integer(8), value  :: token
    end function
  end interface
  
  interface
    attributes(device) integer function barrier_try_wait_sleep(barrier, token, ns)
      integer(8), shared :: barrier
      integer(8), value  :: token
      integer(4), value  :: ns
    end function
  end interface

  interface
    attributes(device) subroutine fence_proxy_async()
    end subroutine
  end interface

  interface
    attributes(device) subroutine tma_bulk_commit_group()
    end subroutine
  end interface

  interface
    attributes(device) subroutine tma_bulk_wait_group()
    end subroutine
  end interface

  ! --------------------
  ! Bulk load functions
  ! --------------------

  ! Generic load, count is in bytes
  ! -------------------------------

  interface
    attributes(device) subroutine tma_bulk_g2s(barrier, src, dst, nbytes)
      !dir$ ignore_tkr src, dst
      integer(8), shared :: barrier
      integer(4), device :: src(*)
      integer(4), shared :: dst(*)
      integer(4), value  :: nbytes
    end subroutine
  end interface

  ! Load specific types, count is in elements
  ! -----------------------------------------

  interface tma_bulk_load
    attributes(device) subroutine tma_bulk_ldc4(barrier, src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      integer(8), shared :: barrier
      complex(4), device :: src(*)
      complex(4), shared :: dst(*)
      integer(4), value :: nelems
    end subroutine

    attributes(device) subroutine tma_bulk_ldc8(barrier, src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      integer(8), shared :: barrier
      complex(8), device :: src(*)
      complex(8), shared :: dst(*)
      integer(4), value :: nelems
    end subroutine
  
    attributes(device) subroutine tma_bulk_ldi4(barrier, src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      integer(8), shared :: barrier
      integer(4), device :: src(*)
      integer(4), shared :: dst(*)
      integer(4), value :: nelems
    end subroutine

    attributes(device) subroutine tma_bulk_ldi8(barrier, src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      integer(8), shared :: barrier
      integer(8), device :: src(*)
      integer(8), shared :: dst(*)
      integer(4), value :: nelems
    end subroutine

    attributes(device) subroutine tma_bulk_ldr2(barrier, src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      integer(8), shared :: barrier
      real(2), device :: src(*)
      real(2), shared :: dst(*)
      integer(4), value :: nelems
    end subroutine

    attributes(device) subroutine tma_bulk_ldr4(barrier, src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      integer(8), shared :: barrier
      real(4), device :: src(*)
      real(4), shared :: dst(*)
      integer(4), value :: nelems
    end subroutine

    attributes(device) subroutine tma_bulk_ldr8(barrier, src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      integer(8), shared :: barrier
      real(8), device :: src(*)
      real(8), shared :: dst(*)
      integer(4), value :: nelems
    end subroutine
  end interface

  ! --------------------
  ! Bulk Store functions
  ! --------------------

  ! Generic store, count is in bytes
  ! --------------------------------

  interface
    attributes(device) subroutine tma_bulk_s2g(src, dst, nbytes)
      !dir$ ignore_tkr src, dst
      integer(4), shared  :: src(*)
      integer(4), device  :: dst(*)
      integer(4), value   :: nbytes
    end subroutine
  end interface

  ! Load specific types, count is in elements
  ! -----------------------------------------

  interface tma_bulk_store
    attributes(device) subroutine tma_bulk_store_c4(src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      complex(4), shared :: src(*)
      complex(4), device :: dst(*)
      integer(4), value :: nelems
    end subroutine

    attributes(device) subroutine tma_bulk_store_c8(src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      complex(8), shared :: src(*)
      complex(8), device :: dst(*)
      integer(4), value :: nelems
    end subroutine

    attributes(device) subroutine tma_bulk_store_i4(src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      integer(4), shared :: src(*)
      integer(4), device :: dst(*)
      integer(4), value :: nelems
    end subroutine

    attributes(device) subroutine tma_bulk_store_i8(src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      integer(8), shared :: src(*)
      integer(8), device :: dst(*)
      integer(4), value :: nelems
    end subroutine

    attributes(device) subroutine tma_bulk_store_r2(src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      real(2), shared :: src(*)
      real(2), device :: dst(*)
      integer(4), value :: nelems
    end subroutine

    attributes(device) subroutine tma_bulk_store_r4(src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      real(4), shared :: src(*)
      real(4), device :: dst(*)
      integer(4), value :: nelems
    end subroutine

    attributes(device) subroutine tma_bulk_store_r8(src, dst, nelems)
      !dir$ ignore_tkr (r) src, (r) dst
      real(8), shared :: src(*)
      real(8), device :: dst(*)
      integer(4), value :: nelems
    end subroutine
  end interface

contains

  attributes(device) subroutine syncthreads()
  end subroutine

end module
