1; RUN: llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=tahiti -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,MOVREL,PREGFX9 %s 2; RUN: llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,MOVREL,PREGFX9 %s 3; RUN: llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -amdgpu-vgpr-index-mode -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,IDXMODE,PREGFX9 %s 4; RUN: llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=gfx900 -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,IDXMODE,GFX9 %s 5 6; Tests for indirect addressing on SI, which is implemented using dynamic 7; indexing of vectors. 8 9; GCN-LABEL: {{^}}extract_w_offset: 10; GCN-DAG: s_load_dword [[IN:s[0-9]+]] 11; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, 4.0 12; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, 0x40400000 13; GCN-DAG: v_mov_b32_e32 [[BASEREG:v[0-9]+]], 2.0 14; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, 1.0 15 16; MOVREL-DAG: s_mov_b32 m0, [[IN]] 17; MOVREL: v_movrels_b32_e32 v{{[0-9]+}}, [[BASEREG]] 18 19; IDXMODE: s_set_gpr_idx_on [[IN]], src0{{$}} 20; IDXMODE-NEXT: v_mov_b32_e32 v{{[0-9]+}}, [[BASEREG]] 21; IDXMODE-NEXT: s_set_gpr_idx_off 22define amdgpu_kernel void @extract_w_offset(float addrspace(1)* %out, i32 %in) { 23entry: 24 %idx = add i32 %in, 1 25 %elt = extractelement <16 x float> <float 1.0, float 2.0, float 3.0, float 4.0, float 5.0, float 6.0, float 7.0, float 8.0, float 9.0, float 10.0, float 11.0, float 12.0, float 13.0, float 14.0, float 15.0, float 16.0>, i32 %idx 26 store float %elt, float addrspace(1)* %out 27 ret void 28} 29 30; XXX: Could do v_or_b32 directly 31; GCN-LABEL: {{^}}extract_w_offset_salu_use_vector: 32; MOVREL: s_mov_b32 m0 33; GCN-DAG: s_or_b32 34; GCN-DAG: s_or_b32 35; GCN-DAG: s_or_b32 36; GCN-DAG: s_or_b32 37; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, s{{[0-9]+}} 38; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, s{{[0-9]+}} 39; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, s{{[0-9]+}} 40; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, s{{[0-9]+}} 41 42; MOVREL: v_movrels_b32_e32 43 44; IDXMODE: s_set_gpr_idx_on s{{[0-9]+}}, src0{{$}} 45; IDXMODE-NEXT: v_mov_b32_e32 v{{[0-9]+}}, v{{[0-9]+}} 46; IDXMODE-NEXT: s_set_gpr_idx_off 47define amdgpu_kernel void @extract_w_offset_salu_use_vector(i32 addrspace(1)* %out, i32 %in, <16 x i32> %or.val) { 48entry: 49 %idx = add i32 %in, 1 50 %vec = or <16 x i32> %or.val, <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16> 51 %elt = extractelement <16 x i32> %vec, i32 %idx 52 store i32 %elt, i32 addrspace(1)* %out 53 ret void 54} 55 56; GCN-LABEL: {{^}}extract_wo_offset: 57; GCN-DAG: s_load_dword [[IN:s[0-9]+]] 58; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, 4.0 59; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, 0x40400000 60; GCN-DAG: v_mov_b32_e32 v{{[0-9]+}}, 2.0 61; GCN-DAG: v_mov_b32_e32 [[BASEREG:v[0-9]+]], 1.0 62 63; MOVREL-DAG: s_mov_b32 m0, [[IN]] 64; MOVREL: v_movrels_b32_e32 v{{[0-9]+}}, [[BASEREG]] 65 66; IDXMODE: s_set_gpr_idx_on [[IN]], src0{{$}} 67; IDXMODE-NEXT: v_mov_b32_e32 v{{[0-9]+}}, [[BASEREG]] 68; IDXMODE-NEXT: s_set_gpr_idx_off 69define amdgpu_kernel void @extract_wo_offset(float addrspace(1)* %out, i32 %in) { 70entry: 71 %elt = extractelement <16 x float> <float 1.0, float 2.0, float 3.0, float 4.0, float 5.0, float 6.0, float 7.0, float 8.0, float 9.0, float 10.0, float 11.0, float 12.0, float 13.0, float 14.0, float 15.0, float 16.0>, i32 %in 72 store float %elt, float addrspace(1)* %out 73 ret void 74} 75 76; GCN-LABEL: {{^}}extract_neg_offset_sgpr: 77; The offset depends on the register that holds the first element of the vector. 78; MOVREL: s_add_i32 m0, s{{[0-9]+}}, 0xfffffe{{[0-9a-z]+}} 79; MOVREL: v_movrels_b32_e32 v{{[0-9]}}, v0 80 81; IDXMODE: s_addk_i32 [[ADD_IDX:s[0-9]+]], 0xfe00{{$}} 82; IDXMODE: v_mov_b32_e32 v14, 15 83; IDXMODE: v_mov_b32_e32 v15, 16 84; IDXMODE-NEXT: s_set_gpr_idx_on [[ADD_IDX]], src0{{$}} 85; IDXMODE-NEXT: v_mov_b32_e32 v{{[0-9]+}}, v{{[0-9]+}} 86; IDXMODE-NEXT: s_set_gpr_idx_off 87define amdgpu_kernel void @extract_neg_offset_sgpr(i32 addrspace(1)* %out, i32 %offset) { 88entry: 89 %index = add i32 %offset, -512 90 %value = extractelement <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>, i32 %index 91 store i32 %value, i32 addrspace(1)* %out 92 ret void 93} 94 95; GCN-LABEL: {{^}}extract_neg_offset_sgpr_loaded: 96; The offset depends on the register that holds the first element of the vector. 97; MOVREL: s_add_i32 m0, s{{[0-9]+}}, 0xfffffe{{[0-9a-z]+}} 98; MOVREL: v_movrels_b32_e32 v{{[0-9]}}, v0 99 100; IDXMODE: s_addk_i32 [[ADD_IDX:s[0-9]+]], 0xfe00{{$}} 101; IDXMODE: v_mov_b32_e32 v0, 102; IDXMODE: v_mov_b32_e32 v1, 103; IDXMODE: v_mov_b32_e32 v2, 104; IDXMODE: v_mov_b32_e32 v3, 105; IDXMODE: v_mov_b32_e32 v4, 106; IDXMODE: v_mov_b32_e32 v5, 107; IDXMODE: v_mov_b32_e32 v6, 108; IDXMODE: v_mov_b32_e32 v7, 109; IDXMODE: v_mov_b32_e32 v8, 110; IDXMODE: v_mov_b32_e32 v9, 111; IDXMODE: v_mov_b32_e32 v10, 112; IDXMODE: v_mov_b32_e32 v11, 113; IDXMODE: v_mov_b32_e32 v12, 114; IDXMODE: v_mov_b32_e32 v13, 115; IDXMODE: v_mov_b32_e32 v14, 116; IDXMODE: v_mov_b32_e32 v15, 117; IDXMODE-NEXT: s_set_gpr_idx_on [[ADD_IDX]], src0{{$}} 118; IDXMODE-NEXT: v_mov_b32_e32 v{{[0-9]+}}, v{{[0-9]+}} 119; IDXMODE-NEXT: s_set_gpr_idx_off 120define amdgpu_kernel void @extract_neg_offset_sgpr_loaded(i32 addrspace(1)* %out, <16 x i32> %vec0, <16 x i32> %vec1, i32 %offset) { 121entry: 122 %index = add i32 %offset, -512 123 %or = or <16 x i32> %vec0, %vec1 124 %value = extractelement <16 x i32> %or, i32 %index 125 store i32 %value, i32 addrspace(1)* %out 126 ret void 127} 128 129; GCN-LABEL: {{^}}extract_neg_offset_vgpr: 130; The offset depends on the register that holds the first element of the vector. 131 132; FIXME: The waitcnt for the argument load can go after the loop 133; GCN: s_mov_b64 s{{\[[0-9]+:[0-9]+\]}}, exec 134; GCN: [[LOOPBB:BB[0-9]+_[0-9]+]]: 135; GCN: v_readfirstlane_b32 [[READLANE:s[0-9]+]], v{{[0-9]+}} 136; GCN: s_and_saveexec_b64 vcc, vcc 137 138; MOVREL: s_add_i32 m0, [[READLANE]], 0xfffffe0 139; MOVREL: v_movrels_b32_e32 [[RESULT:v[0-9]+]], v1 140 141; IDXMODE: s_addk_i32 [[ADD_IDX:s[0-9]+]], 0xfe00 142; IDXMODE: s_set_gpr_idx_on [[ADD_IDX]], src0 143; IDXMODE: v_mov_b32_e32 [[RESULT:v[0-9]+]], v1 144; IDXMODE: s_set_gpr_idx_off 145 146; GCN: s_cbranch_execnz 147 148; GCN: buffer_store_dword [[RESULT]] 149define amdgpu_kernel void @extract_neg_offset_vgpr(i32 addrspace(1)* %out) { 150entry: 151 %id = call i32 @llvm.amdgcn.workitem.id.x() #1 152 %index = add i32 %id, -512 153 %value = extractelement <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>, i32 %index 154 store i32 %value, i32 addrspace(1)* %out 155 ret void 156} 157 158; GCN-LABEL: {{^}}extract_undef_offset_sgpr: 159; undefined behavior, but shouldn't crash compiler 160define amdgpu_kernel void @extract_undef_offset_sgpr(i32 addrspace(1)* %out, <4 x i32> addrspace(1)* %in) { 161entry: 162 %ld = load volatile <4 x i32>, <4 x i32> addrspace(1)* %in 163 %value = extractelement <4 x i32> %ld, i32 undef 164 store i32 %value, i32 addrspace(1)* %out 165 ret void 166} 167 168; GCN-LABEL: {{^}}insert_undef_offset_sgpr_vector_src: 169; undefined behavior, but shouldn't crash compiler 170define amdgpu_kernel void @insert_undef_offset_sgpr_vector_src(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %in) { 171entry: 172 %ld = load <4 x i32>, <4 x i32> addrspace(1)* %in 173 %value = insertelement <4 x i32> %ld, i32 5, i32 undef 174 store <4 x i32> %value, <4 x i32> addrspace(1)* %out 175 ret void 176} 177 178; GCN-LABEL: {{^}}insert_w_offset: 179; GCN-DAG: s_load_dword [[IN:s[0-9]+]] 180; MOVREL-DAG: s_mov_b32 m0, [[IN]] 181; GCN-DAG: v_mov_b32_e32 v[[ELT0:[0-9]+]], 1.0 182; GCN-DAG: v_mov_b32_e32 v[[ELT1:[0-9]+]], 2.0 183; GCN-DAG: v_mov_b32_e32 v[[ELT2:[0-9]+]], 0x40400000 184; GCN-DAG: v_mov_b32_e32 v[[ELT3:[0-9]+]], 4.0 185; GCN-DAG: v_mov_b32_e32 v[[ELT15:[0-9]+]], 0x41800000 186; GCN-DAG: v_mov_b32_e32 v[[INS:[0-9]+]], 0x41880000 187 188; MOVREL: v_movreld_b32_e32 v[[ELT1]], v[[INS]] 189; MOVREL: buffer_store_dwordx4 v{{\[}}[[ELT0]]:[[ELT3]]{{\]}} 190define amdgpu_kernel void @insert_w_offset(<16 x float> addrspace(1)* %out, i32 %in) { 191entry: 192 %add = add i32 %in, 1 193 %ins = insertelement <16 x float> <float 1.0, float 2.0, float 3.0, float 4.0, float 5.0, float 6.0, float 7.0, float 8.0, float 9.0, float 10.0, float 11.0, float 12.0, float 13.0, float 14.0, float 15.0, float 16.0>, float 17.0, i32 %add 194 store <16 x float> %ins, <16 x float> addrspace(1)* %out 195 ret void 196} 197 198; GCN-LABEL: {{^}}insert_wo_offset: 199; GCN: s_load_dword [[IN:s[0-9]+]] 200 201; MOVREL: s_mov_b32 m0, [[IN]] 202; MOVREL: v_movreld_b32_e32 v[[ELT0:[0-9]+]] 203 204; IDXMODE: s_set_gpr_idx_on [[IN]], dst 205; IDXMODE-NEXT: v_mov_b32_e32 v[[ELT0:[0-9]+]], v{{[0-9]+}} 206; IDXMODE-NEXT: s_set_gpr_idx_off 207 208; GCN: buffer_store_dwordx4 v{{\[}}[[ELT0]]: 209define amdgpu_kernel void @insert_wo_offset(<16 x float> addrspace(1)* %out, i32 %in) { 210entry: 211 %ins = insertelement <16 x float> <float 1.0, float 2.0, float 3.0, float 4.0, float 5.0, float 6.0, float 7.0, float 8.0, float 9.0, float 10.0, float 11.0, float 12.0, float 13.0, float 14.0, float 15.0, float 16.0>, float 17.0, i32 %in 212 store <16 x float> %ins, <16 x float> addrspace(1)* %out 213 ret void 214} 215 216; GCN-LABEL: {{^}}insert_neg_offset_sgpr: 217; The offset depends on the register that holds the first element of the vector. 218; MOVREL: s_add_i32 m0, s{{[0-9]+}}, 0xfffffe{{[0-9a-z]+}} 219; MOVREL: v_movreld_b32_e32 v0, 16 220 221; IDXMODE: s_addk_i32 [[ADD_IDX:s[0-9]+]], 0xfe00{{$}} 222; IDXMODE: s_set_gpr_idx_on [[ADD_IDX]], dst 223; IDXMODE-NEXT: v_mov_b32_e32 v0, 16 224; IDXMODE-NEXT: s_set_gpr_idx_off 225define amdgpu_kernel void @insert_neg_offset_sgpr(i32 addrspace(1)* %in, <16 x i32> addrspace(1)* %out, i32 %offset) { 226entry: 227 %index = add i32 %offset, -512 228 %value = insertelement <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>, i32 16, i32 %index 229 store <16 x i32> %value, <16 x i32> addrspace(1)* %out 230 ret void 231} 232 233; The vector indexed into is originally loaded into an SGPR rather 234; than built with a reg_sequence 235 236; GCN-LABEL: {{^}}insert_neg_offset_sgpr_loadreg: 237; The offset depends on the register that holds the first element of the vector. 238; MOVREL: s_add_i32 m0, s{{[0-9]+}}, 0xfffffe{{[0-9a-z]+}} 239; MOVREL: v_movreld_b32_e32 v0, 5 240 241; IDXMODE: s_addk_i32 [[ADD_IDX:s[0-9]+]], 0xfe00{{$}} 242; IDXMODE: s_set_gpr_idx_on [[ADD_IDX]], dst 243; IDXMODE-NEXT: v_mov_b32_e32 v0, 5 244; IDXMODE-NEXT: s_set_gpr_idx_off 245define amdgpu_kernel void @insert_neg_offset_sgpr_loadreg(i32 addrspace(1)* %in, <16 x i32> addrspace(1)* %out, <16 x i32> %vec, i32 %offset) { 246entry: 247 %index = add i32 %offset, -512 248 %value = insertelement <16 x i32> %vec, i32 5, i32 %index 249 store <16 x i32> %value, <16 x i32> addrspace(1)* %out 250 ret void 251} 252 253; GCN-LABEL: {{^}}insert_neg_offset_vgpr: 254; The offset depends on the register that holds the first element of the vector. 255 256; GCN-DAG: v_mov_b32_e32 [[VEC_ELT0:v[0-9]+]], 1{{$}} 257; GCN-DAG: v_mov_b32_e32 [[VEC_ELT1:v[0-9]+]], 2{{$}} 258; GCN-DAG: v_mov_b32_e32 [[VEC_ELT2:v[0-9]+]], 3{{$}} 259; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 4{{$}} 260; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 5{{$}} 261; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 6{{$}} 262; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 7{{$}} 263; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 8{{$}} 264; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 9{{$}} 265; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 10{{$}} 266; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 11{{$}} 267; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 12{{$}} 268; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 13{{$}} 269; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 14{{$}} 270; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 15{{$}} 271; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 16{{$}} 272 273; GCN: s_mov_b64 [[SAVEEXEC:s\[[0-9]+:[0-9]+\]]], exec 274; GCN: [[LOOPBB:BB[0-9]+_[0-9]+]]: 275; GCN: v_readfirstlane_b32 [[READLANE:s[0-9]+]] 276; GCN: s_and_saveexec_b64 vcc, vcc 277 278; MOVREL: s_add_i32 m0, [[READLANE]], 0xfffffe00 279; MOVREL: v_movreld_b32_e32 [[VEC_ELT0]], 33 280 281; IDXMODE: s_addk_i32 [[ADD_IDX:s[0-9]+]], 0xfe00{{$}} 282; IDXMODE: s_set_gpr_idx_on [[ADD_IDX]], dst 283; IDXMODE: v_mov_b32_e32 v{{[0-9]+}}, 33 284; IDXMODE: s_set_gpr_idx_off 285 286; GCN: s_cbranch_execnz [[LOOPBB]] 287; GCN: s_mov_b64 exec, [[SAVEEXEC]] 288 289; GCN: buffer_store_dword 290define amdgpu_kernel void @insert_neg_offset_vgpr(i32 addrspace(1)* %in, <16 x i32> addrspace(1)* %out) { 291entry: 292 %id = call i32 @llvm.amdgcn.workitem.id.x() #1 293 %index = add i32 %id, -512 294 %value = insertelement <16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>, i32 33, i32 %index 295 store <16 x i32> %value, <16 x i32> addrspace(1)* %out 296 ret void 297} 298 299; GCN-LABEL: {{^}}insert_neg_inline_offset_vgpr: 300 301; GCN-DAG: v_mov_b32_e32 [[VEC_ELT0:v[0-9]+]], 1{{$}} 302; GCN-DAG: v_mov_b32_e32 [[VEC_ELT1:v[0-9]+]], 2{{$}} 303; GCN-DAG: v_mov_b32_e32 [[VEC_ELT2:v[0-9]+]], 3{{$}} 304; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 4{{$}} 305; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 5{{$}} 306; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 6{{$}} 307; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 7{{$}} 308; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 8{{$}} 309; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 9{{$}} 310; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 10{{$}} 311; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 11{{$}} 312; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 12{{$}} 313; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 13{{$}} 314; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 14{{$}} 315; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 15{{$}} 316; GCN-DAG: v_mov_b32_e32 [[VEC_ELT3:v[0-9]+]], 16{{$}} 317; GCN-DAG: v_mov_b32_e32 [[VAL:v[0-9]+]], 0x1f4{{$}} 318 319; GCN: s_mov_b64 [[SAVEEXEC:s\[[0-9]+:[0-9]+\]]], exec 320 321; The offset depends on the register that holds the first element of the vector. 322; GCN: v_readfirstlane_b32 [[READLANE:s[0-9]+]] 323 324; MOVREL: s_add_i32 m0, [[READLANE]], -16 325; MOVREL: v_movreld_b32_e32 [[VEC_ELT0]], [[VAL]] 326 327; IDXMODE: s_add_i32 [[ADD_IDX:s[0-9]+]], [[READLANE]], -16 328; IDXMODE: s_set_gpr_idx_on [[ADD_IDX]], dst 329; IDXMODE: v_mov_b32_e32 [[VEC_ELT0]], [[VAL]] 330; IDXMODE: s_set_gpr_idx_off 331 332; GCN: s_cbranch_execnz 333define amdgpu_kernel void @insert_neg_inline_offset_vgpr(i32 addrspace(1)* %in, <16 x i32> addrspace(1)* %out) { 334entry: 335 %id = call i32 @llvm.amdgcn.workitem.id.x() #1 336 %index = add i32 %id, -16 337 %value = insertelement <16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>, i32 500, i32 %index 338 store <16 x i32> %value, <16 x i32> addrspace(1)* %out 339 ret void 340} 341 342; When the block is split to insert the loop, make sure any other 343; places that need to be expanded in the same block are also handled. 344 345; GCN-LABEL: {{^}}extract_vgpr_offset_multiple_in_block: 346 347; FIXME: Why is vector copied in between? 348 349; GCN-DAG: {{buffer|flat|global}}_load_dword [[IDX0:v[0-9]+]] 350; GCN-DAG: s_mov_b32 [[S_ELT1:s[0-9]+]], 9 351; GCN-DAG: s_mov_b32 [[S_ELT0:s[0-9]+]], 7 352; GCN-DAG: v_mov_b32_e32 [[VEC_ELT0:v[0-9]+]], [[S_ELT0]] 353; GCN-DAG: v_mov_b32_e32 [[VEC_ELT1:v[0-9]+]], [[S_ELT1]] 354 355; GCN: s_mov_b64 [[MASK:s\[[0-9]+:[0-9]+\]]], exec 356 357; GCN: [[LOOP0:BB[0-9]+_[0-9]+]]: 358; GCN-NEXT: s_waitcnt vmcnt(0) 359; GCN-NEXT: v_readfirstlane_b32 [[READLANE:s[0-9]+]], [[IDX0]] 360; GCN: v_cmp_eq_u32_e32 vcc, [[READLANE]], [[IDX0]] 361; GCN: s_and_saveexec_b64 vcc, vcc 362 363; MOVREL: s_mov_b32 m0, [[READLANE]] 364; MOVREL: v_movrels_b32_e32 [[MOVREL0:v[0-9]+]], [[VEC_ELT0]] 365 366; IDXMODE: s_set_gpr_idx_on [[READLANE]], src0 367; IDXMODE: v_mov_b32_e32 [[MOVREL0:v[0-9]+]], [[VEC_ELT0]] 368; IDXMODE: s_set_gpr_idx_off 369 370; GCN-NEXT: s_xor_b64 exec, exec, vcc 371; GCN-NEXT: s_cbranch_execnz [[LOOP0]] 372 373; FIXME: Redundant copy 374; GCN: s_mov_b64 exec, [[MASK]] 375 376; GCN: v_mov_b32_e32 [[VEC_ELT1_2:v[0-9]+]], [[S_ELT1]] 377 378; GCN: s_mov_b64 [[MASK2:s\[[0-9]+:[0-9]+\]]], exec 379 380; GCN: [[LOOP1:BB[0-9]+_[0-9]+]]: 381; GCN-NEXT: v_readfirstlane_b32 [[READLANE:s[0-9]+]], [[IDX0]] 382; GCN: v_cmp_eq_u32_e32 vcc, [[READLANE]], [[IDX0]] 383; GCN: s_and_saveexec_b64 vcc, vcc 384 385; MOVREL: s_mov_b32 m0, [[READLANE]] 386; MOVREL-NEXT: v_movrels_b32_e32 [[MOVREL1:v[0-9]+]], [[VEC_ELT1_2]] 387 388; IDXMODE: s_set_gpr_idx_on [[READLANE]], src0 389; IDXMODE-NEXT: v_mov_b32_e32 [[MOVREL1:v[0-9]+]], [[VEC_ELT1_2]] 390; IDXMODE: s_set_gpr_idx_off 391 392; GCN-NEXT: s_xor_b64 exec, exec, vcc 393; GCN: s_cbranch_execnz [[LOOP1]] 394 395; GCN: buffer_store_dword [[MOVREL0]] 396; GCN: buffer_store_dword [[MOVREL1]] 397define amdgpu_kernel void @extract_vgpr_offset_multiple_in_block(i32 addrspace(1)* %out0, i32 addrspace(1)* %out1, i32 addrspace(1)* %in) #0 { 398entry: 399 %id = call i32 @llvm.amdgcn.workitem.id.x() #1 400 %id.ext = zext i32 %id to i64 401 %gep = getelementptr inbounds i32, i32 addrspace(1)* %in, i64 %id.ext 402 %idx0 = load volatile i32, i32 addrspace(1)* %gep 403 %idx1 = add i32 %idx0, 1 404 %val0 = extractelement <16 x i32> <i32 7, i32 9, i32 11, i32 13, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>, i32 %idx0 405 %live.out.reg = call i32 asm sideeffect "s_mov_b32 $0, 17", "={s4}" () 406 %val1 = extractelement <16 x i32> <i32 7, i32 9, i32 11, i32 13, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>, i32 %idx1 407 store volatile i32 %val0, i32 addrspace(1)* %out0 408 store volatile i32 %val1, i32 addrspace(1)* %out0 409 %cmp = icmp eq i32 %id, 0 410 br i1 %cmp, label %bb1, label %bb2 411 412bb1: 413 store volatile i32 %live.out.reg, i32 addrspace(1)* undef 414 br label %bb2 415 416bb2: 417 ret void 418} 419 420; Moved subtest for insert_vgpr_offset_multiple_in_block to separate file to 421; avoid very different schedule induced isses with gfx9. 422; test/CodeGen/AMDGPU/indirect-addressing-si-pregfx9.ll 423 424 425; GCN-LABEL: {{^}}insert_adjacent_blocks: 426define amdgpu_kernel void @insert_adjacent_blocks(i32 %arg, float %val0) #0 { 427bb: 428 %tmp = icmp eq i32 %arg, 0 429 br i1 %tmp, label %bb1, label %bb4 430 431bb1: ; preds = %bb 432 %tmp2 = load volatile <4 x float>, <4 x float> addrspace(1)* undef 433 %tmp3 = insertelement <4 x float> %tmp2, float %val0, i32 undef 434 call void asm sideeffect "; reg use $0", "v"(<4 x float> %tmp3) #0 ; Prevent block optimize out 435 br label %bb7 436 437bb4: ; preds = %bb 438 %tmp5 = load volatile <4 x float>, <4 x float> addrspace(1)* undef 439 %tmp6 = insertelement <4 x float> %tmp5, float %val0, i32 undef 440 call void asm sideeffect "; reg use $0", "v"(<4 x float> %tmp6) #0 ; Prevent block optimize out 441 br label %bb7 442 443bb7: ; preds = %bb4, %bb1 444 %tmp8 = phi <4 x float> [ %tmp3, %bb1 ], [ %tmp6, %bb4 ] 445 store volatile <4 x float> %tmp8, <4 x float> addrspace(1)* undef 446 ret void 447} 448 449; FIXME: Should be able to fold zero input to movreld to inline imm? 450 451; GCN-LABEL: {{^}}multi_same_block: 452 453; GCN: s_load_dword [[ARG:s[0-9]+]] 454 455; MOVREL: v_mov_b32_e32 v{{[0-9]+}}, 0x41900000 456; MOVREL: s_waitcnt 457; MOVREL: s_add_i32 m0, [[ARG]], -16 458; MOVREL: v_movreld_b32_e32 v{{[0-9]+}}, 4.0 459; MOVREL: v_mov_b32_e32 v{{[0-9]+}}, 0x41b0cccd 460; MOVREL: v_movreld_b32_e32 v{{[0-9]+}}, -4.0 461; MOVREL: s_mov_b32 m0, -1 462 463 464; IDXMODE: v_mov_b32_e32 v{{[0-9]+}}, 0x41900000 465; IDXMODE: s_waitcnt 466; IDXMODE: s_add_i32 [[ARG]], [[ARG]], -16 467; IDXMODE: s_set_gpr_idx_on [[ARG]], dst 468; IDXMODE: v_mov_b32_e32 v{{[0-9]+}}, 4.0 469; IDXMODE: s_set_gpr_idx_off 470; IDXMODE: v_mov_b32_e32 v{{[0-9]+}}, 0x41b0cccd 471; IDXMODE: s_set_gpr_idx_on [[ARG]], dst 472; IDXMODE: v_mov_b32_e32 v{{[0-9]+}}, -4.0 473; IDXMODE: s_set_gpr_idx_off 474 475; GCN: ds_write_b32 476; GCN: ds_write_b32 477; GCN: s_endpgm 478define amdgpu_kernel void @multi_same_block(i32 %arg) #0 { 479bb: 480 %tmp1 = add i32 %arg, -16 481 %tmp2 = insertelement <9 x float> <float 1.700000e+01, float 1.800000e+01, float 1.900000e+01, float 2.000000e+01, float 2.100000e+01, float 2.200000e+01, float 2.300000e+01, float 2.400000e+01, float 2.500000e+01>, float 4.000000e+00, i32 %tmp1 482 %tmp3 = add i32 %arg, -16 483 %tmp4 = insertelement <9 x float> <float 0x40311999A0000000, float 0x40321999A0000000, float 0x40331999A0000000, float 0x40341999A0000000, float 0x40351999A0000000, float 0x40361999A0000000, float 0x40371999A0000000, float 0x40381999A0000000, float 0x40391999A0000000>, float -4.0, i32 %tmp3 484 %tmp5 = bitcast <9 x float> %tmp2 to <9 x i32> 485 %tmp6 = extractelement <9 x i32> %tmp5, i32 1 486 %tmp7 = bitcast <9 x float> %tmp4 to <9 x i32> 487 %tmp8 = extractelement <9 x i32> %tmp7, i32 5 488 store volatile i32 %tmp6, i32 addrspace(3)* undef, align 4 489 store volatile i32 %tmp8, i32 addrspace(3)* undef, align 4 490 ret void 491} 492 493; offset puts outside of superegister bounaries, so clamp to 1st element. 494; GCN-LABEL: {{^}}extract_largest_inbounds_offset: 495; GCN-DAG: buffer_load_dwordx4 v{{\[}}[[LO_ELT:[0-9]+]]:[[HI_ELT:[0-9]+]]{{\].* offset:48}} 496; GCN-DAG: s_load_dword [[IDX:s[0-9]+]] 497; MOVREL: s_mov_b32 m0, [[IDX]] 498; MOVREL: v_movrels_b32_e32 [[EXTRACT:v[0-9]+]], v[[HI_ELT]] 499 500; IDXMODE: s_set_gpr_idx_on [[IDX]], src0 501; IDXMODE: v_mov_b32_e32 [[EXTRACT:v[0-9]+]], v[[HI_ELT]] 502; IDXMODE: s_set_gpr_idx_off 503 504; GCN: buffer_store_dword [[EXTRACT]] 505define amdgpu_kernel void @extract_largest_inbounds_offset(i32 addrspace(1)* %out, <16 x i32> addrspace(1)* %in, i32 %idx) { 506entry: 507 %ld = load volatile <16 x i32>, <16 x i32> addrspace(1)* %in 508 %offset = add i32 %idx, 15 509 %value = extractelement <16 x i32> %ld, i32 %offset 510 store i32 %value, i32 addrspace(1)* %out 511 ret void 512} 513 514; GCN-LABEL: {{^}}extract_out_of_bounds_offset: 515; GCN-DAG: buffer_load_dwordx4 v{{\[}}[[LO_ELT:[0-9]+]]:[[HI_ELT:[0-9]+]]{{\]}} 516; GCN-DAG: s_load_dword [[IDX:s[0-9]+]] 517; MOVREL: s_add_i32 m0, [[IDX]], 16 518; MOVREL: v_movrels_b32_e32 [[EXTRACT:v[0-9]+]], v[[LO_ELT]] 519 520; IDXMODE: s_add_i32 [[ADD_IDX:s[0-9]+]], [[IDX]], 16 521; IDXMODE: s_set_gpr_idx_on [[ADD_IDX]], src0 522; IDXMODE: v_mov_b32_e32 [[EXTRACT:v[0-9]+]], v[[LO_ELT]] 523; IDXMODE: s_set_gpr_idx_off 524 525; GCN: buffer_store_dword [[EXTRACT]] 526define amdgpu_kernel void @extract_out_of_bounds_offset(i32 addrspace(1)* %out, <16 x i32> addrspace(1)* %in, i32 %idx) { 527entry: 528 %ld = load volatile <16 x i32>, <16 x i32> addrspace(1)* %in 529 %offset = add i32 %idx, 16 530 %value = extractelement <16 x i32> %ld, i32 %offset 531 store i32 %value, i32 addrspace(1)* %out 532 ret void 533} 534 535; Test that the or is folded into the base address register instead of 536; added to m0 537 538; GCN-LABEL: {{^}}extractelement_v16i32_or_index: 539; GCN: s_load_dword [[IDX_IN:s[0-9]+]] 540; GCN: s_lshl_b32 [[IDX_SHL:s[0-9]+]], [[IDX_IN]] 541; GCN-NOT: [[IDX_SHL]] 542 543; MOVREL: s_mov_b32 m0, [[IDX_SHL]] 544; MOVREL: v_movrels_b32_e32 v{{[0-9]+}}, v{{[0-9]+}} 545 546; IDXMODE: s_set_gpr_idx_on [[IDX_SHL]], src0 547; IDXMODE: v_mov_b32_e32 v{{[0-9]+}}, v{{[0-9]+}} 548; IDXMODE: s_set_gpr_idx_off 549define amdgpu_kernel void @extractelement_v16i32_or_index(i32 addrspace(1)* %out, <16 x i32> addrspace(1)* %in, i32 %idx.in) { 550entry: 551 %ld = load volatile <16 x i32>, <16 x i32> addrspace(1)* %in 552 %idx.shl = shl i32 %idx.in, 2 553 %idx = or i32 %idx.shl, 1 554 %value = extractelement <16 x i32> %ld, i32 %idx 555 store i32 %value, i32 addrspace(1)* %out 556 ret void 557} 558 559; GCN-LABEL: {{^}}insertelement_v16f32_or_index: 560; GCN: s_load_dword [[IDX_IN:s[0-9]+]] 561; GCN: s_lshl_b32 [[IDX_SHL:s[0-9]+]], [[IDX_IN]] 562; GCN-NOT: [[IDX_SHL]] 563 564; MOVREL: s_mov_b32 m0, [[IDX_SHL]] 565; MOVREL: v_movreld_b32_e32 v{{[0-9]+}}, v{{[0-9]+}} 566 567; IDXMODE: s_set_gpr_idx_on [[IDX_SHL]], dst 568; IDXMODE: v_mov_b32_e32 v{{[0-9]+}}, v{{[0-9]+}} 569; IDXMODE: s_set_gpr_idx_off 570define amdgpu_kernel void @insertelement_v16f32_or_index(<16 x float> addrspace(1)* %out, <16 x float> %a, i32 %idx.in) nounwind { 571 %idx.shl = shl i32 %idx.in, 2 572 %idx = or i32 %idx.shl, 1 573 %vecins = insertelement <16 x float> %a, float 5.000000e+00, i32 %idx 574 store <16 x float> %vecins, <16 x float> addrspace(1)* %out, align 64 575 ret void 576} 577 578; GCN-LABEL: {{^}}broken_phi_bb: 579; GCN: v_mov_b32_e32 [[PHIREG:v[0-9]+]], 8 580 581; GCN: s_branch [[BB2:BB[0-9]+_[0-9]+]] 582 583; GCN: {{^BB[0-9]+_[0-9]+}}: 584; GCN: s_mov_b64 exec, 585 586; GCN: [[BB2]]: 587; GCN: v_cmp_le_i32_e32 vcc, s{{[0-9]+}}, [[PHIREG]] 588; GCN: buffer_load_dword 589 590; GCN: [[REGLOOP:BB[0-9]+_[0-9]+]]: 591; MOVREL: v_movreld_b32_e32 592 593; IDXMODE: s_set_gpr_idx_on 594; IDXMODE: v_mov_b32_e32 595; IDXMODE: s_set_gpr_idx_off 596 597; GCN: s_cbranch_execnz [[REGLOOP]] 598define amdgpu_kernel void @broken_phi_bb(i32 %arg, i32 %arg1) #0 { 599bb: 600 br label %bb2 601 602bb2: ; preds = %bb4, %bb 603 %tmp = phi i32 [ 8, %bb ], [ %tmp7, %bb4 ] 604 %tmp3 = icmp slt i32 %tmp, %arg 605 br i1 %tmp3, label %bb4, label %bb8 606 607bb4: ; preds = %bb2 608 %vgpr = load volatile i32, i32 addrspace(1)* undef 609 %tmp5 = insertelement <16 x i32> undef, i32 undef, i32 %vgpr 610 %tmp6 = insertelement <16 x i32> %tmp5, i32 %arg1, i32 %vgpr 611 %tmp7 = extractelement <16 x i32> %tmp6, i32 0 612 br label %bb2 613 614bb8: ; preds = %bb2 615 ret void 616} 617 618declare i32 @llvm.amdgcn.workitem.id.x() #1 619declare void @llvm.amdgcn.s.barrier() #2 620 621attributes #0 = { nounwind } 622attributes #1 = { nounwind readnone } 623attributes #2 = { nounwind convergent } 624