1; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -amdgpu-lower-kernel-attributes -instcombine %s | FileCheck -enable-var-scope %s 2; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -passes=amdgpu-lower-kernel-attributes,instcombine %s | FileCheck -enable-var-scope %s 3 4target datalayout = "n32" 5 6; CHECK-LABEL: @invalid_reqd_work_group_size( 7; CHECK: load i16, 8define amdgpu_kernel void @invalid_reqd_work_group_size(i16 addrspace(1)* %out) #0 !reqd_work_group_size !1 { 9 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 10 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 11 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 12 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 13 store i16 %group.size.x, i16 addrspace(1)* %out 14 ret void 15} 16 17; CHECK-LABEL: @volatile_load_group_size_x( 18; CHECK: load volatile i16, 19define amdgpu_kernel void @volatile_load_group_size_x(i16 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 20 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 21 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 22 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 23 %group.size.x = load volatile i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 24 store i16 %group.size.x, i16 addrspace(1)* %out 25 ret void 26} 27 28; CHECK-LABEL: @load_group_size_x( 29; CHECK-NEXT: store i16 8, 30define amdgpu_kernel void @load_group_size_x(i16 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 31 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 32 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 33 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 34 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 35 store i16 %group.size.x, i16 addrspace(1)* %out 36 ret void 37} 38 39; CHECK-LABEL: @load_group_size_y( 40; CHECK-NEXT: store i16 16, 41define amdgpu_kernel void @load_group_size_y(i16 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 42 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 43 %gep.group.size.y = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 6 44 %gep.group.size.y.bc = bitcast i8 addrspace(4)* %gep.group.size.y to i16 addrspace(4)* 45 %group.size.y = load i16, i16 addrspace(4)* %gep.group.size.y.bc, align 4 46 store i16 %group.size.y, i16 addrspace(1)* %out 47 ret void 48} 49 50; CHECK-LABEL: @load_group_size_z( 51; CHECK-NEXT: store i16 2, 52define amdgpu_kernel void @load_group_size_z(i16 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 53 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 54 %gep.group.size.z = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 8 55 %gep.group.size.z.bc = bitcast i8 addrspace(4)* %gep.group.size.z to i16 addrspace(4)* 56 %group.size.z = load i16, i16 addrspace(4)* %gep.group.size.z.bc, align 4 57 store i16 %group.size.z, i16 addrspace(1)* %out 58 ret void 59} 60 61; Metadata uses i64 instead of i32 62; CHECK-LABEL: @load_group_size_x_reqd_work_group_size_i64( 63; CHECK-NEXT: store i16 8, 64define amdgpu_kernel void @load_group_size_x_reqd_work_group_size_i64(i16 addrspace(1)* %out) #0 !reqd_work_group_size !2 { 65 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 66 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 67 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 68 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 69 store i16 %group.size.x, i16 addrspace(1)* %out 70 ret void 71} 72 73; Metadata uses i16 instead of i32 74; CHECK-LABEL: @load_group_size_x_reqd_work_group_size_i16( 75; CHECK-NEXT: store i16 8, 76define amdgpu_kernel void @load_group_size_x_reqd_work_group_size_i16(i16 addrspace(1)* %out) #0 !reqd_work_group_size !3 { 77 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 78 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 79 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 80 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 81 store i16 %group.size.x, i16 addrspace(1)* %out 82 ret void 83} 84 85; CHECK-LABEL: @use_local_size_x_8_16_2( 86; CHECK-NEXT: store i64 8, 87define amdgpu_kernel void @use_local_size_x_8_16_2(i64 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 88 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 89 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 90 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 91 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 92 %gep.grid.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 12 93 %gep.grid.size.x.bc = bitcast i8 addrspace(4)* %gep.grid.size.x to i32 addrspace(4)* 94 %grid.size.x = load i32, i32 addrspace(4)* %gep.grid.size.x.bc, align 4 95 %group.id = tail call i32 @llvm.amdgcn.workgroup.id.x() 96 %group.size.x.zext = zext i16 %group.size.x to i32 97 %group.id_x_group.size.x = mul i32 %group.id, %group.size.x.zext 98 %sub = sub i32 %grid.size.x, %group.id_x_group.size.x 99 %cmp = icmp ult i32 %sub, %group.size.x.zext 100 %select = select i1 %cmp, i32 %sub, i32 %group.size.x.zext 101 %zext = zext i32 %select to i64 102 store i64 %zext, i64 addrspace(1)* %out 103 ret void 104} 105 106; CHECK-LABEL: @use_local_size_y_8_16_2( 107; CHECK-NEXT: store i64 16, 108define amdgpu_kernel void @use_local_size_y_8_16_2(i64 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 109 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 110 %gep.group.size.y = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 6 111 %gep.group.size.y.bc = bitcast i8 addrspace(4)* %gep.group.size.y to i16 addrspace(4)* 112 %group.size.y = load i16, i16 addrspace(4)* %gep.group.size.y.bc, align 4 113 %gep.grid.size.y = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 16 114 %gep.grid.size.y.bc = bitcast i8 addrspace(4)* %gep.grid.size.y to i32 addrspace(4)* 115 %grid.size.y = load i32, i32 addrspace(4)* %gep.grid.size.y.bc, align 4 116 %group.id = tail call i32 @llvm.amdgcn.workgroup.id.y() 117 %group.size.y.zext = zext i16 %group.size.y to i32 118 %group.id_x_group.size.y = mul i32 %group.id, %group.size.y.zext 119 %sub = sub i32 %grid.size.y, %group.id_x_group.size.y 120 %cmp = icmp ult i32 %sub, %group.size.y.zext 121 %select = select i1 %cmp, i32 %sub, i32 %group.size.y.zext 122 %zext = zext i32 %select to i64 123 store i64 %zext, i64 addrspace(1)* %out 124 ret void 125} 126 127; CHECK-LABEL: @use_local_size_z_8_16_2( 128; CHECK-NEXT: store i64 2, 129define amdgpu_kernel void @use_local_size_z_8_16_2(i64 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 130 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 131 %gep.group.size.z = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 8 132 %gep.group.size.z.bc = bitcast i8 addrspace(4)* %gep.group.size.z to i16 addrspace(4)* 133 %group.size.z = load i16, i16 addrspace(4)* %gep.group.size.z.bc, align 4 134 %gep.grid.size.z = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 20 135 %gep.grid.size.z.bc = bitcast i8 addrspace(4)* %gep.grid.size.z to i32 addrspace(4)* 136 %grid.size.z = load i32, i32 addrspace(4)* %gep.grid.size.z.bc, align 4 137 %group.id = tail call i32 @llvm.amdgcn.workgroup.id.z() 138 %group.size.z.zext = zext i16 %group.size.z to i32 139 %group.id_x_group.size.z = mul i32 %group.id, %group.size.z.zext 140 %sub = sub i32 %grid.size.z, %group.id_x_group.size.z 141 %cmp = icmp ult i32 %sub, %group.size.z.zext 142 %select = select i1 %cmp, i32 %sub, i32 %group.size.z.zext 143 %zext = zext i32 %select to i64 144 store i64 %zext, i64 addrspace(1)* %out 145 ret void 146} 147 148; Simplification on select is invalid, but we can still eliminate the 149; load of the group size. 150 151; CHECK-LABEL: @local_size_x_8_16_2_wrong_group_id( 152; CHECK: %group.id = tail call i32 @llvm.amdgcn.workgroup.id.y() 153; CHECK: %group.id_x_group.size.x.neg = mul i32 %group.id, -8 154define amdgpu_kernel void @local_size_x_8_16_2_wrong_group_id(i64 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 155 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 156 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 157 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 158 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 159 %gep.grid.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 12 160 %gep.grid.size.x.bc = bitcast i8 addrspace(4)* %gep.grid.size.x to i32 addrspace(4)* 161 %grid.size.x = load i32, i32 addrspace(4)* %gep.grid.size.x.bc, align 4 162 %group.id = tail call i32 @llvm.amdgcn.workgroup.id.y() 163 %group.size.x.zext = zext i16 %group.size.x to i32 164 %group.id_x_group.size.x = mul i32 %group.id, %group.size.x.zext 165 %sub = sub i32 %grid.size.x, %group.id_x_group.size.x 166 %cmp = icmp ult i32 %sub, %group.size.x.zext 167 %select = select i1 %cmp, i32 %sub, i32 %group.size.x.zext 168 %zext = zext i32 %select to i64 169 store i64 %zext, i64 addrspace(1)* %out 170 ret void 171} 172 173; CHECK-LABEL: @local_size_x_8_16_2_wrong_grid_size( 174; CHECK: %grid.size.x = load i32, i32 addrspace(4)* %gep.grid.size.x.bc, align 4 175; CHECK: %group.id = tail call i32 @llvm.amdgcn.workgroup.id.x() 176; CHECK: %group.id_x_group.size.x.neg = mul i32 %group.id, -8 177 define amdgpu_kernel void @local_size_x_8_16_2_wrong_grid_size(i64 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 178 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 179 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 180 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 181 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 182 %gep.grid.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 16 183 %gep.grid.size.x.bc = bitcast i8 addrspace(4)* %gep.grid.size.x to i32 addrspace(4)* 184 %grid.size.x = load i32, i32 addrspace(4)* %gep.grid.size.x.bc, align 4 185 %group.id = tail call i32 @llvm.amdgcn.workgroup.id.x() 186 %group.size.x.zext = zext i16 %group.size.x to i32 187 %group.id_x_group.size.x = mul i32 %group.id, %group.size.x.zext 188 %sub = sub i32 %grid.size.x, %group.id_x_group.size.x 189 %cmp = icmp ult i32 %sub, %group.size.x.zext 190 %select = select i1 %cmp, i32 %sub, i32 %group.size.x.zext 191 %zext = zext i32 %select to i64 192 store i64 %zext, i64 addrspace(1)* %out 193 ret void 194} 195 196; CHECK-LABEL: @local_size_x_8_16_2_wrong_cmp_type( 197; CHECK: %grid.size.x = load i32, i32 addrspace(4)* %gep.grid.size.x.bc, align 4 198; CHECK: %group.id = tail call i32 @llvm.amdgcn.workgroup.id.x() 199; CHECK: %group.id_x_group.size.x.neg = mul i32 %group.id, -8 200; CHECK: %sub = add i32 %group.id_x_group.size.x.neg, %grid.size.x 201; CHECK: %1 = call i32 @llvm.smin.i32(i32 %sub, i32 8) 202define amdgpu_kernel void @local_size_x_8_16_2_wrong_cmp_type(i64 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 203 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 204 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 205 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 206 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 207 %gep.grid.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 12 208 %gep.grid.size.x.bc = bitcast i8 addrspace(4)* %gep.grid.size.x to i32 addrspace(4)* 209 %grid.size.x = load i32, i32 addrspace(4)* %gep.grid.size.x.bc, align 4 210 %group.id = tail call i32 @llvm.amdgcn.workgroup.id.x() 211 %group.size.x.zext = zext i16 %group.size.x to i32 212 %group.id_x_group.size.x = mul i32 %group.id, %group.size.x.zext 213 %sub = sub i32 %grid.size.x, %group.id_x_group.size.x 214 %cmp = icmp slt i32 %sub, %group.size.x.zext 215 %select = select i1 %cmp, i32 %sub, i32 %group.size.x.zext 216 %zext = zext i32 %select to i64 217 store i64 %zext, i64 addrspace(1)* %out 218 ret void 219} 220 221; CHECK-LABEL: @local_size_x_8_16_2_wrong_select( 222; CHECK: %group.id_x_group.size.x.neg = mul i32 %group.id, -8 223; CHECK: %sub = add i32 %group.id_x_group.size.x.neg, %grid.size.x 224; CHECK: %1 = call i32 @llvm.umax.i32(i32 %sub, i32 8) 225; CHECK: %zext = zext i32 %1 to i64 226define amdgpu_kernel void @local_size_x_8_16_2_wrong_select(i64 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 227 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 228 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 229 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 230 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 231 %gep.grid.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 12 232 %gep.grid.size.x.bc = bitcast i8 addrspace(4)* %gep.grid.size.x to i32 addrspace(4)* 233 %grid.size.x = load i32, i32 addrspace(4)* %gep.grid.size.x.bc, align 4 234 %group.id = tail call i32 @llvm.amdgcn.workgroup.id.x() 235 %group.size.x.zext = zext i16 %group.size.x to i32 236 %group.id_x_group.size.x = mul i32 %group.id, %group.size.x.zext 237 %sub = sub i32 %grid.size.x, %group.id_x_group.size.x 238 %cmp = icmp ult i32 %sub, %group.size.x.zext 239 %select = select i1 %cmp, i32 %group.size.x.zext, i32 %sub 240 %zext = zext i32 %select to i64 241 store i64 %zext, i64 addrspace(1)* %out 242 ret void 243} 244 245; CHECK-LABEL: @use_local_size_x_8_16_2_wrong_grid_load_size( 246; CHECK: %grid.size.x = load i16, i16 addrspace(4)* %gep.grid.size.x.bc, align 4 247; CHECK: %grid.size.x.zext = zext i16 %grid.size.x to i32 248; CHECK: %group.id = tail call i32 @llvm.amdgcn.workgroup.id.x() 249; CHECK: %group.id_x_group.size.x.neg = mul i32 %group.id, -8 250; CHECK: %sub = add i32 %group.id_x_group.size.x.neg, %grid.size.x.zext 251define amdgpu_kernel void @use_local_size_x_8_16_2_wrong_grid_load_size(i64 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 252 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 253 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 254 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 255 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 256 %gep.grid.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 12 257 %gep.grid.size.x.bc = bitcast i8 addrspace(4)* %gep.grid.size.x to i16 addrspace(4)* 258 %grid.size.x = load i16, i16 addrspace(4)* %gep.grid.size.x.bc, align 4 259 %grid.size.x.zext = zext i16 %grid.size.x to i32 260 %group.id = tail call i32 @llvm.amdgcn.workgroup.id.x() 261 %group.size.x.zext = zext i16 %group.size.x to i32 262 %group.id_x_group.size.x = mul i32 %group.id, %group.size.x.zext 263 %sub = sub i32 %grid.size.x.zext, %group.id_x_group.size.x 264 %cmp = icmp ult i32 %sub, %group.size.x.zext 265 %select = select i1 %cmp, i32 %sub, i32 %group.size.x.zext 266 %zext = zext i32 %select to i64 267 store i64 %zext, i64 addrspace(1)* %out 268 ret void 269} 270 271; CHECK-LABEL: @func_group_size_x( 272; CHECK-NEXT: ret i32 8 273define i32 @func_group_size_x(i16 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 274 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 275 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 276 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 277 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 278 %zext = zext i16 %group.size.x to i32 279 ret i32 %zext 280} 281 282; CHECK-LABEL: @__ockl_get_local_size_reqd_size( 283; CHECK: %group.size = phi i32 [ 2, %bb17 ], [ 16, %bb9 ], [ 8, %bb1 ], [ 1, %bb ] 284define i64 @__ockl_get_local_size_reqd_size(i32 %arg) #1 !reqd_work_group_size !0 { 285bb: 286 %tmp = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() #2 287 switch i32 %arg, label %bb25 [ 288 i32 0, label %bb1 289 i32 1, label %bb9 290 i32 2, label %bb17 291 ] 292 293bb1: ; preds = %bb 294 %tmp2 = tail call i32 @llvm.amdgcn.workgroup.id.x() 295 %tmp3 = getelementptr inbounds i8, i8 addrspace(4)* %tmp, i64 12 296 %tmp4 = bitcast i8 addrspace(4)* %tmp3 to i32 addrspace(4)* 297 %tmp5 = load i32, i32 addrspace(4)* %tmp4, align 4 298 %tmp6 = getelementptr inbounds i8, i8 addrspace(4)* %tmp, i64 4 299 %tmp7 = bitcast i8 addrspace(4)* %tmp6 to i16 addrspace(4)* 300 %tmp8 = load i16, i16 addrspace(4)* %tmp7, align 4 301 br label %bb25 302 303bb9: ; preds = %bb 304 %tmp10 = tail call i32 @llvm.amdgcn.workgroup.id.y() 305 %tmp11 = getelementptr inbounds i8, i8 addrspace(4)* %tmp, i64 16 306 %tmp12 = bitcast i8 addrspace(4)* %tmp11 to i32 addrspace(4)* 307 %tmp13 = load i32, i32 addrspace(4)* %tmp12, align 8 308 %tmp14 = getelementptr inbounds i8, i8 addrspace(4)* %tmp, i64 6 309 %tmp15 = bitcast i8 addrspace(4)* %tmp14 to i16 addrspace(4)* 310 %tmp16 = load i16, i16 addrspace(4)* %tmp15, align 2 311 br label %bb25 312 313bb17: ; preds = %bb 314 %tmp18 = tail call i32 @llvm.amdgcn.workgroup.id.z() 315 %tmp19 = getelementptr inbounds i8, i8 addrspace(4)* %tmp, i64 20 316 %tmp20 = bitcast i8 addrspace(4)* %tmp19 to i32 addrspace(4)* 317 %tmp21 = load i32, i32 addrspace(4)* %tmp20, align 4 318 %tmp22 = getelementptr inbounds i8, i8 addrspace(4)* %tmp, i64 8 319 %tmp23 = bitcast i8 addrspace(4)* %tmp22 to i16 addrspace(4)* 320 %tmp24 = load i16, i16 addrspace(4)* %tmp23, align 8 321 br label %bb25 322 323bb25: ; preds = %bb17, %bb9, %bb1, %bb 324 %tmp26 = phi i32 [ %tmp21, %bb17 ], [ %tmp13, %bb9 ], [ %tmp5, %bb1 ], [ 0, %bb ] 325 %group.size = phi i16 [ %tmp24, %bb17 ], [ %tmp16, %bb9 ], [ %tmp8, %bb1 ], [ 1, %bb ] 326 %tmp28 = phi i32 [ %tmp18, %bb17 ], [ %tmp10, %bb9 ], [ %tmp2, %bb1 ], [ 0, %bb ] 327 %tmp29 = zext i16 %group.size to i32 328 %tmp30 = mul i32 %tmp28, %tmp29 329 %tmp31 = sub i32 %tmp26, %tmp30 330 %tmp32 = icmp ult i32 %tmp31, %tmp29 331 %tmp33 = select i1 %tmp32, i32 %tmp31, i32 %tmp29 332 %tmp34 = zext i32 %tmp33 to i64 333 ret i64 %tmp34 334} 335 336; CHECK-LABEL: @all_local_size( 337; CHECK-NEXT: store volatile i64 8, i64 addrspace(1)* %out, align 4 338; CHECK-NEXT: store volatile i64 16, i64 addrspace(1)* %out, align 4 339; CHECK-NEXT: store volatile i64 2, i64 addrspace(1)* %out, align 4 340define amdgpu_kernel void @all_local_size(i64 addrspace(1)* nocapture readnone %out) #0 !reqd_work_group_size !0 { 341 %tmp.i = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() #0 342 %tmp2.i = tail call i32 @llvm.amdgcn.workgroup.id.x() #0 343 %tmp3.i = getelementptr inbounds i8, i8 addrspace(4)* %tmp.i, i64 12 344 %tmp4.i = bitcast i8 addrspace(4)* %tmp3.i to i32 addrspace(4)* 345 %tmp5.i = load i32, i32 addrspace(4)* %tmp4.i, align 4 346 %tmp6.i = getelementptr inbounds i8, i8 addrspace(4)* %tmp.i, i64 4 347 %tmp7.i = bitcast i8 addrspace(4)* %tmp6.i to i16 addrspace(4)* 348 %tmp8.i = load i16, i16 addrspace(4)* %tmp7.i, align 4 349 %tmp29.i = zext i16 %tmp8.i to i32 350 %tmp30.i = mul i32 %tmp2.i, %tmp29.i 351 %tmp31.i = sub i32 %tmp5.i, %tmp30.i 352 %tmp32.i = icmp ult i32 %tmp31.i, %tmp29.i 353 %tmp33.i = select i1 %tmp32.i, i32 %tmp31.i, i32 %tmp29.i 354 %tmp34.i = zext i32 %tmp33.i to i64 355 %tmp10.i = tail call i32 @llvm.amdgcn.workgroup.id.y() #0 356 %tmp11.i = getelementptr inbounds i8, i8 addrspace(4)* %tmp.i, i64 16 357 %tmp12.i = bitcast i8 addrspace(4)* %tmp11.i to i32 addrspace(4)* 358 %tmp13.i = load i32, i32 addrspace(4)* %tmp12.i, align 8 359 %tmp14.i = getelementptr inbounds i8, i8 addrspace(4)* %tmp.i, i64 6 360 %tmp15.i = bitcast i8 addrspace(4)* %tmp14.i to i16 addrspace(4)* 361 %tmp16.i = load i16, i16 addrspace(4)* %tmp15.i, align 2 362 %tmp29.i9 = zext i16 %tmp16.i to i32 363 %tmp30.i10 = mul i32 %tmp10.i, %tmp29.i9 364 %tmp31.i11 = sub i32 %tmp13.i, %tmp30.i10 365 %tmp32.i12 = icmp ult i32 %tmp31.i11, %tmp29.i9 366 %tmp33.i13 = select i1 %tmp32.i12, i32 %tmp31.i11, i32 %tmp29.i9 367 %tmp34.i14 = zext i32 %tmp33.i13 to i64 368 %tmp18.i = tail call i32 @llvm.amdgcn.workgroup.id.z() #0 369 %tmp19.i = getelementptr inbounds i8, i8 addrspace(4)* %tmp.i, i64 20 370 %tmp20.i = bitcast i8 addrspace(4)* %tmp19.i to i32 addrspace(4)* 371 %tmp21.i = load i32, i32 addrspace(4)* %tmp20.i, align 4 372 %tmp22.i = getelementptr inbounds i8, i8 addrspace(4)* %tmp.i, i64 8 373 %tmp23.i = bitcast i8 addrspace(4)* %tmp22.i to i16 addrspace(4)* 374 %tmp24.i = load i16, i16 addrspace(4)* %tmp23.i, align 8 375 %tmp29.i2 = zext i16 %tmp24.i to i32 376 %tmp30.i3 = mul i32 %tmp18.i, %tmp29.i2 377 %tmp31.i4 = sub i32 %tmp21.i, %tmp30.i3 378 %tmp32.i5 = icmp ult i32 %tmp31.i4, %tmp29.i2 379 %tmp33.i6 = select i1 %tmp32.i5, i32 %tmp31.i4, i32 %tmp29.i2 380 %tmp34.i7 = zext i32 %tmp33.i6 to i64 381 store volatile i64 %tmp34.i, i64 addrspace(1)* %out, align 4 382 store volatile i64 %tmp34.i14, i64 addrspace(1)* %out, align 4 383 store volatile i64 %tmp34.i7, i64 addrspace(1)* %out, align 4 384 ret void 385} 386 387; TODO: Should be able to handle this, but not much reason to. 388; CHECK-LABEL: @partial_load_group_size_x( 389; CHECK-NEXT: %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 390; CHECK-NEXT: %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 391; CHECK-NEXT: %group.size.x.lo = load i8, i8 addrspace(4)* %gep.group.size.x, align 4 392; CHECK-NEXT: store i8 %group.size.x.lo, i8 addrspace(1)* %out, align 1 393define amdgpu_kernel void @partial_load_group_size_x(i8 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 394 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 395 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 396 %group.size.x.lo = load i8, i8 addrspace(4)* %gep.group.size.x, align 1 397 store i8 %group.size.x.lo, i8 addrspace(1)* %out 398 ret void 399} 400 401; CHECK-LABEL: @partial_load_group_size_x_explicit_callsite_align( 402; CHECK-NEXT: %dispatch.ptr = tail call align 2 i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 403; CHECK-NEXT: %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 404; CHECK-NEXT: %group.size.x.lo = load i8, i8 addrspace(4)* %gep.group.size.x, align 2 405; CHECK-NEXT: store i8 %group.size.x.lo, i8 addrspace(1)* %out, align 1 406define amdgpu_kernel void @partial_load_group_size_x_explicit_callsite_align(i8 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 407 %dispatch.ptr = tail call align 2 i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 408 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 409 %group.size.x.lo = load i8, i8 addrspace(4)* %gep.group.size.x, align 1 410 store i8 %group.size.x.lo, i8 addrspace(1)* %out 411 ret void 412} 413 414; TODO: Should be able to handle this 415; CHECK-LABEL: @load_group_size_xy_i32( 416; CHECK: %group.size.xy = load i32, 417; CHECK: store i32 %group.size.xy 418define amdgpu_kernel void @load_group_size_xy_i32(i32 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 419 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 420 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 421 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i32 addrspace(4)* 422 %group.size.xy = load i32, i32 addrspace(4)* %gep.group.size.x.bc, align 4 423 store i32 %group.size.xy, i32 addrspace(1)* %out 424 ret void 425} 426 427; CHECK-LABEL: @load_group_size_x_y_multiple_dispatch_ptr( 428; CHECK-NEXT: store volatile i16 8, i16 addrspace(1)* %out, align 2 429; CHECK-NEXT: store volatile i16 16, i16 addrspace(1)* %out, align 2 430define amdgpu_kernel void @load_group_size_x_y_multiple_dispatch_ptr(i16 addrspace(1)* %out) #0 !reqd_work_group_size !0 { 431 %dispatch.ptr0 = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 432 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr0, i64 4 433 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 434 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 435 store volatile i16 %group.size.x, i16 addrspace(1)* %out 436 437 %dispatch.ptr1 = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 438 %gep.group.size.y = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr1, i64 6 439 %gep.group.size.y.bc = bitcast i8 addrspace(4)* %gep.group.size.y to i16 addrspace(4)* 440 %group.size.y = load i16, i16 addrspace(4)* %gep.group.size.y.bc, align 4 441 store volatile i16 %group.size.y, i16 addrspace(1)* %out 442 443 ret void 444} 445 446; CHECK-LABEL: @use_local_size_x_uniform_work_group_size( 447; CHECK-NEXT: %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 448; CHECK-NEXT: %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 449; CHECK-NEXT: %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 450; CHECK-NEXT: %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 451; CHECK-NEXT: %zext = zext i16 %group.size.x to i64 452; CHECK-NEXT: store i64 %zext, i64 addrspace(1)* %out, align 4 453define amdgpu_kernel void @use_local_size_x_uniform_work_group_size(i64 addrspace(1)* %out) #2 { 454 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 455 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 456 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 457 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 458 %gep.grid.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 12 459 %gep.grid.size.x.bc = bitcast i8 addrspace(4)* %gep.grid.size.x to i32 addrspace(4)* 460 %grid.size.x = load i32, i32 addrspace(4)* %gep.grid.size.x.bc, align 4 461 %group.id = tail call i32 @llvm.amdgcn.workgroup.id.x() 462 %group.size.x.zext = zext i16 %group.size.x to i32 463 %group.id_x_group.size.x = mul i32 %group.id, %group.size.x.zext 464 %sub = sub i32 %grid.size.x, %group.id_x_group.size.x 465 %cmp = icmp ult i32 %sub, %group.size.x.zext 466 %select = select i1 %cmp, i32 %sub, i32 %group.size.x.zext 467 %zext = zext i32 %select to i64 468 store i64 %zext, i64 addrspace(1)* %out 469 ret void 470} 471 472; CHECK-LABEL: @use_local_size_x_uniform_work_group_size_false( 473; CHECK: call i32 @llvm.umin 474define amdgpu_kernel void @use_local_size_x_uniform_work_group_size_false(i64 addrspace(1)* %out) #3 { 475 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 476 %gep.group.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 4 477 %gep.group.size.x.bc = bitcast i8 addrspace(4)* %gep.group.size.x to i16 addrspace(4)* 478 %group.size.x = load i16, i16 addrspace(4)* %gep.group.size.x.bc, align 4 479 %gep.grid.size.x = getelementptr inbounds i8, i8 addrspace(4)* %dispatch.ptr, i64 12 480 %gep.grid.size.x.bc = bitcast i8 addrspace(4)* %gep.grid.size.x to i32 addrspace(4)* 481 %grid.size.x = load i32, i32 addrspace(4)* %gep.grid.size.x.bc, align 4 482 %group.id = tail call i32 @llvm.amdgcn.workgroup.id.x() 483 %group.size.x.zext = zext i16 %group.size.x to i32 484 %group.id_x_group.size.x = mul i32 %group.id, %group.size.x.zext 485 %sub = sub i32 %grid.size.x, %group.id_x_group.size.x 486 %cmp = icmp ult i32 %sub, %group.size.x.zext 487 %select = select i1 %cmp, i32 %sub, i32 %group.size.x.zext 488 %zext = zext i32 %select to i64 489 store i64 %zext, i64 addrspace(1)* %out 490 ret void 491} 492 493; CHECK-LABEL: @no_use_dispatch_ptr( 494; CHECK-NEXT: ret void 495define amdgpu_kernel void @no_use_dispatch_ptr() { 496 %dispatch.ptr = tail call i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() 497 ret void 498} 499 500declare i8 addrspace(4)* @llvm.amdgcn.dispatch.ptr() #1 501declare i32 @llvm.amdgcn.workgroup.id.x() #1 502declare i32 @llvm.amdgcn.workgroup.id.y() #1 503declare i32 @llvm.amdgcn.workgroup.id.z() #1 504 505attributes #0 = { nounwind "uniform-work-group-size"="true" } 506attributes #1 = { nounwind readnone speculatable } 507attributes #2 = { nounwind "uniform-work-group-size"="true" } 508attributes #3 = { nounwind "uniform-work-group-size"="false" } 509 510!0 = !{i32 8, i32 16, i32 2} 511!1 = !{i32 8, i32 16} 512!2 = !{i64 8, i64 16, i64 2} 513!3 = !{i16 8, i16 16, i16 2} 514