1*532dc62bSNikita Popov // RUN: %clang_cc1 -no-opaque-pointers -x hip -emit-llvm -std=c++11 %s -o - \
2cd95338eSYaxun (Sam) Liu // RUN:   -triple x86_64-linux-gnu \
3cd95338eSYaxun (Sam) Liu // RUN:   | FileCheck -check-prefix=HOST %s
4*532dc62bSNikita Popov // RUN: %clang_cc1 -no-opaque-pointers -x hip -emit-llvm -std=c++11 %s -o - \
5cd95338eSYaxun (Sam) Liu // RUN:   -triple amdgcn-amd-amdhsa -fcuda-is-device \
6cd95338eSYaxun (Sam) Liu // RUN:   | FileCheck -check-prefix=DEV %s
7cd95338eSYaxun (Sam) Liu 
8cd95338eSYaxun (Sam) Liu #include "Inputs/cuda.h"
9cd95338eSYaxun (Sam) Liu 
10cd95338eSYaxun (Sam) Liu // HOST: %[[T1:.*]] = type <{ i32*, i32, [4 x i8] }>
11cd95338eSYaxun (Sam) Liu // HOST: %[[T2:.*]] = type { i32*, i32** }
12cd95338eSYaxun (Sam) Liu // HOST: %[[T3:.*]] = type <{ i32*, i32, [4 x i8] }>
13cd95338eSYaxun (Sam) Liu // DEV: %[[T1:.*]] = type { i32* }
14cd95338eSYaxun (Sam) Liu // DEV: %[[T2:.*]] = type { i32** }
15cd95338eSYaxun (Sam) Liu // DEV: %[[T3:.*]] = type <{ i32*, i32, [4 x i8] }>
16cd95338eSYaxun (Sam) Liu int global_host_var;
17cd95338eSYaxun (Sam) Liu __device__ int global_device_var;
18cd95338eSYaxun (Sam) Liu 
19cd95338eSYaxun (Sam) Liu template<class F>
kern(F f)20cd95338eSYaxun (Sam) Liu __global__ void kern(F f) { f(); }
21cd95338eSYaxun (Sam) Liu 
22cd95338eSYaxun (Sam) Liu // DEV-LABEL: @_ZZ27dev_capture_dev_ref_by_copyPiENKUlvE_clEv(
23cd95338eSYaxun (Sam) Liu // DEV: %[[VAL:.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @global_device_var to i32*)
24cd95338eSYaxun (Sam) Liu // DEV: store i32 %[[VAL]]
dev_capture_dev_ref_by_copy(int * out)25cd95338eSYaxun (Sam) Liu __device__ void dev_capture_dev_ref_by_copy(int *out) {
26cd95338eSYaxun (Sam) Liu   int &ref = global_device_var;
27cd95338eSYaxun (Sam) Liu   [=](){ *out = ref;}();
28cd95338eSYaxun (Sam) Liu }
29cd95338eSYaxun (Sam) Liu 
303a781b91SYaxun (Sam) Liu // DEV-LABEL: @_ZZ28dev_capture_dev_rval_by_copyPiENKUlvE_clEv(
313a781b91SYaxun (Sam) Liu // DEV: store i32 3
dev_capture_dev_rval_by_copy(int * out)323a781b91SYaxun (Sam) Liu __device__ void dev_capture_dev_rval_by_copy(int *out) {
333a781b91SYaxun (Sam) Liu   constexpr int a = 1;
343a781b91SYaxun (Sam) Liu   constexpr int b = 2;
353a781b91SYaxun (Sam) Liu   constexpr int c = a + b;
363a781b91SYaxun (Sam) Liu   [=](){ *out = c;}();
373a781b91SYaxun (Sam) Liu }
383a781b91SYaxun (Sam) Liu 
39cd95338eSYaxun (Sam) Liu // DEV-LABEL: @_ZZ26dev_capture_dev_ref_by_refPiENKUlvE_clEv(
40cd95338eSYaxun (Sam) Liu // DEV: %[[VAL:.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @global_device_var to i32*)
41cd95338eSYaxun (Sam) Liu // DEV: %[[VAL2:.*]] = add nsw i32 %[[VAL]], 1
42cd95338eSYaxun (Sam) Liu // DEV: store i32 %[[VAL2]], i32* addrspacecast (i32 addrspace(1)* @global_device_var to i32*)
43cd95338eSYaxun (Sam) Liu // DEV: %[[VAL:.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @global_device_var to i32*)
44cd95338eSYaxun (Sam) Liu // DEV: store i32 %[[VAL]]
dev_capture_dev_ref_by_ref(int * out)45cd95338eSYaxun (Sam) Liu __device__ void dev_capture_dev_ref_by_ref(int *out) {
46cd95338eSYaxun (Sam) Liu   int &ref = global_device_var;
47cd95338eSYaxun (Sam) Liu   [&](){ ref++; *out = ref;}();
48cd95338eSYaxun (Sam) Liu }
49cd95338eSYaxun (Sam) Liu 
50219d00e0SFangrui Song // DEV-LABEL: define{{.*}} void @_Z7dev_refPi(
51cd95338eSYaxun (Sam) Liu // DEV: %[[VAL:.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @global_device_var to i32*)
52cd95338eSYaxun (Sam) Liu // DEV: %[[VAL2:.*]] = add nsw i32 %[[VAL]], 1
53cd95338eSYaxun (Sam) Liu // DEV: store i32 %[[VAL2]], i32* addrspacecast (i32 addrspace(1)* @global_device_var to i32*)
54cd95338eSYaxun (Sam) Liu // DEV: %[[VAL:.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @global_device_var to i32*)
55cd95338eSYaxun (Sam) Liu // DEV: store i32 %[[VAL]]
dev_ref(int * out)56cd95338eSYaxun (Sam) Liu __device__ void dev_ref(int *out) {
57cd95338eSYaxun (Sam) Liu   int &ref = global_device_var;
58cd95338eSYaxun (Sam) Liu   ref++;
59cd95338eSYaxun (Sam) Liu   *out = ref;
60cd95338eSYaxun (Sam) Liu }
61cd95338eSYaxun (Sam) Liu 
62cd95338eSYaxun (Sam) Liu // DEV-LABEL: @_ZZ14dev_lambda_refPiENKUlvE_clEv(
63cd95338eSYaxun (Sam) Liu // DEV: %[[VAL:.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @global_device_var to i32*)
64cd95338eSYaxun (Sam) Liu // DEV: %[[VAL2:.*]] = add nsw i32 %[[VAL]], 1
65cd95338eSYaxun (Sam) Liu // DEV: store i32 %[[VAL2]], i32* addrspacecast (i32 addrspace(1)* @global_device_var to i32*)
66cd95338eSYaxun (Sam) Liu // DEV: %[[VAL:.*]] = load i32, i32* addrspacecast (i32 addrspace(1)* @global_device_var to i32*)
67cd95338eSYaxun (Sam) Liu // DEV: store i32 %[[VAL]]
dev_lambda_ref(int * out)68cd95338eSYaxun (Sam) Liu __device__ void dev_lambda_ref(int *out) {
69cd95338eSYaxun (Sam) Liu   [=](){
70cd95338eSYaxun (Sam) Liu     int &ref = global_device_var;
71cd95338eSYaxun (Sam) Liu     ref++;
72cd95338eSYaxun (Sam) Liu     *out = ref;
73cd95338eSYaxun (Sam) Liu   }();
74cd95338eSYaxun (Sam) Liu }
75cd95338eSYaxun (Sam) Liu 
76cd95338eSYaxun (Sam) Liu // HOST-LABEL: @_ZZ29host_capture_host_ref_by_copyPiENKUlvE_clEv(
77cd95338eSYaxun (Sam) Liu // HOST: %[[VAL:.*]] = load i32, i32* @global_host_var
78cd95338eSYaxun (Sam) Liu // HOST: store i32 %[[VAL]]
host_capture_host_ref_by_copy(int * out)79cd95338eSYaxun (Sam) Liu void host_capture_host_ref_by_copy(int *out) {
80cd95338eSYaxun (Sam) Liu   int &ref = global_host_var;
81cd95338eSYaxun (Sam) Liu   [=](){ *out = ref;}();
82cd95338eSYaxun (Sam) Liu }
83cd95338eSYaxun (Sam) Liu 
84cd95338eSYaxun (Sam) Liu // HOST-LABEL: @_ZZ28host_capture_host_ref_by_refPiENKUlvE_clEv(
85cd95338eSYaxun (Sam) Liu // HOST: %[[CAP:.*]] = getelementptr inbounds %[[T2]], %[[T2]]* %this1, i32 0, i32 0
86cd95338eSYaxun (Sam) Liu // HOST: %[[REF:.*]] = load i32*, i32** %[[CAP]]
87cd95338eSYaxun (Sam) Liu // HOST: %[[VAL:.*]] = load i32, i32* %[[REF]]
88cd95338eSYaxun (Sam) Liu // HOST: %[[VAL2:.*]] = add nsw i32 %[[VAL]], 1
89cd95338eSYaxun (Sam) Liu // HOST: store i32 %[[VAL2]], i32* %[[REF]]
90cd95338eSYaxun (Sam) Liu // HOST: %[[VAL:.*]] = load i32, i32* @global_host_var
91cd95338eSYaxun (Sam) Liu // HOST: store i32 %[[VAL]]
host_capture_host_ref_by_ref(int * out)92cd95338eSYaxun (Sam) Liu void host_capture_host_ref_by_ref(int *out) {
93cd95338eSYaxun (Sam) Liu   int &ref = global_host_var;
94cd95338eSYaxun (Sam) Liu   [&](){ ref++; *out = ref;}();
95cd95338eSYaxun (Sam) Liu }
96cd95338eSYaxun (Sam) Liu 
97219d00e0SFangrui Song // HOST-LABEL: define{{.*}} void @_Z8host_refPi(
98cd95338eSYaxun (Sam) Liu // HOST: %[[VAL:.*]] = load i32, i32* @global_host_var
99cd95338eSYaxun (Sam) Liu // HOST: %[[VAL2:.*]] = add nsw i32 %[[VAL]], 1
100cd95338eSYaxun (Sam) Liu // HOST: store i32 %[[VAL2]], i32* @global_host_var
101cd95338eSYaxun (Sam) Liu // HOST: %[[VAL:.*]] = load i32, i32* @global_host_var
102cd95338eSYaxun (Sam) Liu // HOST: store i32 %[[VAL]]
host_ref(int * out)103cd95338eSYaxun (Sam) Liu void host_ref(int *out) {
104cd95338eSYaxun (Sam) Liu   int &ref = global_host_var;
105cd95338eSYaxun (Sam) Liu   ref++;
106cd95338eSYaxun (Sam) Liu   *out = ref;
107cd95338eSYaxun (Sam) Liu }
108cd95338eSYaxun (Sam) Liu 
109cd95338eSYaxun (Sam) Liu // HOST-LABEL: @_ZZ15host_lambda_refPiENKUlvE_clEv(
110cd95338eSYaxun (Sam) Liu // HOST: %[[VAL:.*]] = load i32, i32* @global_host_var
111cd95338eSYaxun (Sam) Liu // HOST: %[[VAL2:.*]] = add nsw i32 %[[VAL]], 1
112cd95338eSYaxun (Sam) Liu // HOST: store i32 %[[VAL2]], i32* @global_host_var
113cd95338eSYaxun (Sam) Liu // HOST: %[[VAL:.*]] = load i32, i32* @global_host_var
114cd95338eSYaxun (Sam) Liu // HOST: store i32 %[[VAL]]
host_lambda_ref(int * out)115cd95338eSYaxun (Sam) Liu void host_lambda_ref(int *out) {
116cd95338eSYaxun (Sam) Liu   [=](){
117cd95338eSYaxun (Sam) Liu     int &ref = global_host_var;
118cd95338eSYaxun (Sam) Liu     ref++;
119cd95338eSYaxun (Sam) Liu     *out = ref;
120cd95338eSYaxun (Sam) Liu   }();
121cd95338eSYaxun (Sam) Liu }
122cd95338eSYaxun (Sam) Liu 
123219d00e0SFangrui Song // HOST-LABEL: define{{.*}} void @_Z28dev_capture_host_ref_by_copyPi(
124cd95338eSYaxun (Sam) Liu // HOST: %[[CAP:.*]] = getelementptr inbounds %[[T3]], %[[T3]]* %{{.*}}, i32 0, i32 1
125cd95338eSYaxun (Sam) Liu // HOST: %[[VAL:.*]] = load i32, i32* @global_host_var
126cd95338eSYaxun (Sam) Liu // HOST: store i32 %[[VAL]], i32* %[[CAP]]
127cd95338eSYaxun (Sam) Liu // DEV-LABEL: define internal void @_ZZ28dev_capture_host_ref_by_copyPiENKUlvE_clEv(
128cd95338eSYaxun (Sam) Liu // DEV: %[[CAP:.*]] = getelementptr inbounds %[[T3]], %[[T3]]* %this1, i32 0, i32 1
129cd95338eSYaxun (Sam) Liu // DEV: %[[VAL:.*]] = load i32, i32* %[[CAP]]
130cd95338eSYaxun (Sam) Liu // DEV: store i32 %[[VAL]]
dev_capture_host_ref_by_copy(int * out)131cd95338eSYaxun (Sam) Liu void dev_capture_host_ref_by_copy(int *out) {
132cd95338eSYaxun (Sam) Liu   int &ref = global_host_var;
133cd95338eSYaxun (Sam) Liu   kern<<<1, 1>>>([=]__device__() { *out = ref;});
134cd95338eSYaxun (Sam) Liu }
135cd95338eSYaxun (Sam) Liu 
136