1; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds < %s | FileCheck --check-prefixes=CHECK,SUPER-ALIGN_ON %s
2; RUN: opt -S -mtriple=amdgcn-- -passes=amdgpu-lower-module-lds < %s | FileCheck --check-prefixes=CHECK,SUPER-ALIGN_ON %s
3; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds --amdgpu-super-align-lds-globals=false < %s | FileCheck --check-prefixes=CHECK,SUPER-ALIGN_OFF %s
4; RUN: opt -S -mtriple=amdgcn-- -passes=amdgpu-lower-module-lds --amdgpu-super-align-lds-globals=false < %s | FileCheck --check-prefixes=CHECK,SUPER-ALIGN_OFF %s
5
6; CHECK: %llvm.amdgcn.kernel.k1.lds.t = type { [32 x i8] }
7; CHECK: %llvm.amdgcn.kernel.k2.lds.t = type { i16, [2 x i8], i16 }
8; CHECK: %llvm.amdgcn.kernel.k3.lds.t = type { [32 x i64], [32 x i32] }
9; CHECK: %llvm.amdgcn.kernel.k4.lds.t = type { [2 x i32 addrspace(3)*] }
10
11; CHECK-NOT: @lds.1
12@lds.1 = internal unnamed_addr addrspace(3) global [32 x i8] undef, align 1
13
14; SUPER-ALIGN_ON: @llvm.amdgcn.kernel.k1.lds = internal addrspace(3) global %llvm.amdgcn.kernel.k1.lds.t undef, align 16
15; SUPER-ALIGN_OFF: @llvm.amdgcn.kernel.k1.lds = internal addrspace(3) global %llvm.amdgcn.kernel.k1.lds.t undef, align 1
16
17; CHECK: @llvm.amdgcn.kernel.k2.lds = internal addrspace(3) global %llvm.amdgcn.kernel.k2.lds.t undef, align 4
18; SUPER-ALIGN_ON:  @llvm.amdgcn.kernel.k3.lds = internal addrspace(3) global %llvm.amdgcn.kernel.k3.lds.t undef, align 16
19; SUPER-ALIGN_OFF: @llvm.amdgcn.kernel.k3.lds = internal addrspace(3) global %llvm.amdgcn.kernel.k3.lds.t undef, align 8
20
21; SUPER-ALIGN_ON:  @llvm.amdgcn.kernel.k4.lds = internal addrspace(3) global %llvm.amdgcn.kernel.k4.lds.t undef, align 16
22; SUPER-ALIGN_OFF: @llvm.amdgcn.kernel.k4.lds = internal addrspace(3) global %llvm.amdgcn.kernel.k4.lds.t undef, align 4
23
24; CHECK-LABEL: @k1
25; CHECK:  %1 = getelementptr inbounds [32 x i8], [32 x i8] addrspace(3)* getelementptr inbounds (%llvm.amdgcn.kernel.k1.lds.t, %llvm.amdgcn.kernel.k1.lds.t addrspace(3)* @llvm.amdgcn.kernel.k1.lds, i32 0, i32 0), i32 0, i32 0
26; CHECK:  %2 = addrspacecast i8 addrspace(3)* %1 to i8*
27; CHECK:  %ptr = getelementptr inbounds i8, i8* %2, i64 %x
28; CHECK:  store i8 1, i8* %ptr, align 1
29define amdgpu_kernel void @k1(i64 %x) {
30  %ptr = getelementptr inbounds i8, i8* addrspacecast ([32 x i8] addrspace(3)* @lds.1 to i8*), i64 %x
31  store i8 1, i8 addrspace(0)* %ptr, align 1
32  ret void
33}
34
35@lds.2 = internal unnamed_addr addrspace(3) global i16 undef, align 4
36@lds.3 = internal unnamed_addr addrspace(3) global i16 undef, align 4
37
38; Check that alignment is propagated to uses for scalar variables.
39
40; CHECK-LABEL: @k2
41; CHECK: store i16 1, i16 addrspace(3)* getelementptr inbounds (%llvm.amdgcn.kernel.k2.lds.t, %llvm.amdgcn.kernel.k2.lds.t addrspace(3)* @llvm.amdgcn.kernel.k2.lds, i32 0, i32 0), align 4
42; CHECK: store i16 2, i16 addrspace(3)* getelementptr inbounds (%llvm.amdgcn.kernel.k2.lds.t, %llvm.amdgcn.kernel.k2.lds.t addrspace(3)* @llvm.amdgcn.kernel.k2.lds, i32 0, i32 2), align 4
43define amdgpu_kernel void @k2() {
44  store i16 1, i16 addrspace(3)* @lds.2, align 2
45  store i16 2, i16 addrspace(3)* @lds.3, align 2
46  ret void
47}
48
49@lds.4 = internal unnamed_addr addrspace(3) global [32 x i64] undef, align 8
50@lds.5 = internal unnamed_addr addrspace(3) global [32 x i32] undef, align 4
51
52; Check that alignment is propagated to uses for arrays.
53
54; CHECK-LABEL: @k3
55; CHECK:  store i32 1, i32 addrspace(3)* %ptr1, align 8
56; CHECK:  store i32 2, i32 addrspace(3)* %ptr2, align 4
57; SUPER-ALIGN_ON:  store i32 3, i32 addrspace(3)* %ptr3, align 16
58; SUPER-ALIGN_OFF: store i32 3, i32 addrspace(3)* %ptr3, align 8
59; CHECK:  store i32 4, i32 addrspace(3)* %ptr4, align 4
60; CHECK:  store i32 5, i32 addrspace(3)* %ptr5, align 4
61; CHECK:  %load1 = load i32, i32 addrspace(3)* %ptr1, align 8
62; CHECK:  %load2 = load i32, i32 addrspace(3)* %ptr2, align 4
63; SUPER-ALIGN_ON:   %load3 = load i32, i32 addrspace(3)* %ptr3, align 16
64; SUPER-ALIGN_OFF:  %load3 = load i32, i32 addrspace(3)* %ptr3, align 8
65; CHECK:  %load4 = load i32, i32 addrspace(3)* %ptr4, align 4
66; CHECK:  %load5 = load i32, i32 addrspace(3)* %ptr5, align 4
67; CHECK:  %val1 = atomicrmw volatile add i32 addrspace(3)* %ptr1, i32 1 monotonic, align 8
68; CHECK:  %val2 = cmpxchg volatile i32 addrspace(3)* %ptr1, i32 1, i32 2 monotonic monotonic, align 8
69; CHECK:  %ptr1.bc = bitcast i32 addrspace(3)* %ptr1 to i16 addrspace(3)*
70; CHECK:  %ptr2.bc = bitcast i32 addrspace(3)* %ptr2 to i16 addrspace(3)*
71; CHECK:  %ptr3.bc = bitcast i32 addrspace(3)* %ptr3 to i16 addrspace(3)*
72; CHECK:  %ptr4.bc = bitcast i32 addrspace(3)* %ptr4 to i16 addrspace(3)*
73; CHECK:  store i16 11, i16 addrspace(3)* %ptr1.bc, align 8
74; CHECK:  store i16 12, i16 addrspace(3)* %ptr2.bc, align 4
75; SUPER-ALIGN_ON:   store i16 13, i16 addrspace(3)* %ptr3.bc, align 16
76; SUPER-ALIGN_OFF:  store i16 13, i16 addrspace(3)* %ptr3.bc, align 8
77; CHECK:  store i16 14, i16 addrspace(3)* %ptr4.bc, align 4
78; CHECK:  %ptr1.ac = addrspacecast i32 addrspace(3)* %ptr1 to i32*
79; CHECK:  %ptr2.ac = addrspacecast i32 addrspace(3)* %ptr2 to i32*
80; CHECK:  %ptr3.ac = addrspacecast i32 addrspace(3)* %ptr3 to i32*
81; CHECK:  %ptr4.ac = addrspacecast i32 addrspace(3)* %ptr4 to i32*
82; CHECK:  store i32 21, i32* %ptr1.ac, align 8
83; CHECK:  store i32 22, i32* %ptr2.ac, align 4
84; SUPER-ALIGN_ON:   store i32 23, i32* %ptr3.ac, align 16
85; SUPER-ALIGN_OFF:  store i32 23, i32* %ptr3.ac, align 8
86; CHECK:  store i32 24, i32* %ptr4.ac, align 4
87define amdgpu_kernel void @k3(i64 %x) {
88  %ptr0 = getelementptr inbounds i64, i64 addrspace(3)* bitcast ([32 x i64] addrspace(3)* @lds.4 to i64 addrspace(3)*), i64 0
89  store i64 0, i64 addrspace(3)* %ptr0, align 8
90
91  %ptr1 = getelementptr inbounds i32, i32 addrspace(3)* bitcast ([32 x i32] addrspace(3)* @lds.5 to i32 addrspace(3)*), i64 2
92  %ptr2 = getelementptr inbounds i32, i32 addrspace(3)* bitcast ([32 x i32] addrspace(3)* @lds.5 to i32 addrspace(3)*), i64 3
93  %ptr3 = getelementptr inbounds i32, i32 addrspace(3)* bitcast ([32 x i32] addrspace(3)* @lds.5 to i32 addrspace(3)*), i64 4
94  %ptr4 = getelementptr inbounds i32, i32 addrspace(3)* bitcast ([32 x i32] addrspace(3)* @lds.5 to i32 addrspace(3)*), i64 5
95  %ptr5 = getelementptr inbounds i32, i32 addrspace(3)* bitcast ([32 x i32] addrspace(3)* @lds.5 to i32 addrspace(3)*), i64 %x
96
97  store i32 1, i32 addrspace(3)* %ptr1, align 4
98  store i32 2, i32 addrspace(3)* %ptr2, align 4
99  store i32 3, i32 addrspace(3)* %ptr3, align 4
100  store i32 4, i32 addrspace(3)* %ptr4, align 4
101  store i32 5, i32 addrspace(3)* %ptr5, align 4
102
103  %load1 = load i32, i32 addrspace(3)* %ptr1, align 4
104  %load2 = load i32, i32 addrspace(3)* %ptr2, align 4
105  %load3 = load i32, i32 addrspace(3)* %ptr3, align 4
106  %load4 = load i32, i32 addrspace(3)* %ptr4, align 4
107  %load5 = load i32, i32 addrspace(3)* %ptr5, align 4
108
109  %val1 = atomicrmw volatile add i32 addrspace(3)* %ptr1, i32 1 monotonic, align 4
110  %val2 = cmpxchg volatile i32 addrspace(3)* %ptr1, i32 1, i32 2 monotonic monotonic, align 4
111
112  %ptr1.bc = bitcast i32 addrspace(3)* %ptr1 to i16 addrspace(3)*
113  %ptr2.bc = bitcast i32 addrspace(3)* %ptr2 to i16 addrspace(3)*
114  %ptr3.bc = bitcast i32 addrspace(3)* %ptr3 to i16 addrspace(3)*
115  %ptr4.bc = bitcast i32 addrspace(3)* %ptr4 to i16 addrspace(3)*
116
117  store i16 11, i16 addrspace(3)* %ptr1.bc, align 2
118  store i16 12, i16 addrspace(3)* %ptr2.bc, align 2
119  store i16 13, i16 addrspace(3)* %ptr3.bc, align 2
120  store i16 14, i16 addrspace(3)* %ptr4.bc, align 2
121
122  %ptr1.ac = addrspacecast i32 addrspace(3)* %ptr1 to i32*
123  %ptr2.ac = addrspacecast i32 addrspace(3)* %ptr2 to i32*
124  %ptr3.ac = addrspacecast i32 addrspace(3)* %ptr3 to i32*
125  %ptr4.ac = addrspacecast i32 addrspace(3)* %ptr4 to i32*
126
127  store i32 21, i32* %ptr1.ac, align 4
128  store i32 22, i32* %ptr2.ac, align 4
129  store i32 23, i32* %ptr3.ac, align 4
130  store i32 24, i32* %ptr4.ac, align 4
131
132  ret void
133}
134
135@lds.6 = internal unnamed_addr addrspace(3) global [2 x i32 addrspace(3)*] undef, align 4
136
137; Check that aligment is not propagated if use is not a pointer operand.
138
139; CHECK-LABEL: @k4
140; SUPER-ALIGN_ON:  store i32 undef, i32 addrspace(3)* %ptr, align 8
141; SUPER-ALIGN_OFF: store i32 undef, i32 addrspace(3)* %ptr, align 4
142; CHECK:           store i32 addrspace(3)* %ptr, i32 addrspace(3)** undef, align 4
143; SUPER-ALIGN_ON:  %val1 = cmpxchg volatile i32 addrspace(3)* %ptr, i32 1, i32 2 monotonic monotonic, align 8
144; SUPER-ALIGN_OFF: %val1 = cmpxchg volatile i32 addrspace(3)* %ptr, i32 1, i32 2 monotonic monotonic, align 4
145; CHECK:           %val2 = cmpxchg volatile i32 addrspace(3)** undef, i32 addrspace(3)* %ptr, i32 addrspace(3)* undef monotonic monotonic, align 4
146define amdgpu_kernel void @k4() {
147  %gep = getelementptr inbounds i32 addrspace(3)*, i32 addrspace(3)* addrspace(3)* bitcast ([2 x i32 addrspace(3)*] addrspace(3)* @lds.6 to i32 addrspace(3)* addrspace(3)*), i64 1
148  %ptr = bitcast i32 addrspace(3)* addrspace(3)* %gep to i32 addrspace(3)*
149  store i32 undef, i32 addrspace(3)* %ptr, align 4
150  store i32 addrspace(3)* %ptr, i32 addrspace(3)** undef, align 4
151  %val1 = cmpxchg volatile i32 addrspace(3)* %ptr, i32 1, i32 2 monotonic monotonic, align 4
152  %val2 = cmpxchg volatile i32 addrspace(3)** undef, i32 addrspace(3)* %ptr, i32 addrspace(3)* undef monotonic monotonic, align 4
153  ret void
154}
155