1; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=SI -check-prefix=FUNC %s 2; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=VI -check-prefix=FUNC %s 3; RUN: llc -march=r600 -mcpu=cypress -verify-machineinstrs < %s | FileCheck -check-prefix=EG -check-prefix=FUNC %s 4 5; FUNC-LABEL: {{^}}sext_in_reg_i1_i32: 6; GCN: s_load_dword [[ARG:s[0-9]+]], 7; GCN: s_bfe_i32 [[SEXTRACT:s[0-9]+]], [[ARG]], 0x10000 8; GCN: v_mov_b32_e32 [[EXTRACT:v[0-9]+]], [[SEXTRACT]] 9; GCN: buffer_store_dword [[EXTRACT]], 10 11; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+\.[XYZW]]], [[ADDR:T[0-9]+.[XYZW]]] 12; EG: LSHR * [[ADDR]] 13; EG: BFE_INT * [[RES]], {{.*}}, 0.0, 1 14define void @sext_in_reg_i1_i32(i32 addrspace(1)* %out, i32 %in) #0 { 15 %shl = shl i32 %in, 31 16 %sext = ashr i32 %shl, 31 17 store i32 %sext, i32 addrspace(1)* %out 18 ret void 19} 20 21; FUNC-LABEL: {{^}}sext_in_reg_i8_to_i32: 22; GCN: s_add_i32 [[VAL:s[0-9]+]], 23; GCN: s_sext_i32_i8 [[EXTRACT:s[0-9]+]], [[VAL]] 24; GCN: v_mov_b32_e32 [[VEXTRACT:v[0-9]+]], [[EXTRACT]] 25; GCN: buffer_store_dword [[VEXTRACT]], 26 27; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+\.[XYZW]]], [[ADDR:T[0-9]+.[XYZW]]] 28; EG: ADD_INT 29; EG-NEXT: BFE_INT [[RES]], {{.*}}, 0.0, literal 30; EG-NEXT: LSHR * [[ADDR]] 31define void @sext_in_reg_i8_to_i32(i32 addrspace(1)* %out, i32 %a, i32 %b) #0 { 32 %c = add i32 %a, %b ; add to prevent folding into extload 33 %shl = shl i32 %c, 24 34 %ashr = ashr i32 %shl, 24 35 store i32 %ashr, i32 addrspace(1)* %out, align 4 36 ret void 37} 38 39; FUNC-LABEL: {{^}}sext_in_reg_i16_to_i32: 40; GCN: s_add_i32 [[VAL:s[0-9]+]], 41; GCN: s_sext_i32_i16 [[EXTRACT:s[0-9]+]], [[VAL]] 42; GCN: v_mov_b32_e32 [[VEXTRACT:v[0-9]+]], [[EXTRACT]] 43; GCN: buffer_store_dword [[VEXTRACT]], 44 45; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+\.[XYZW]]], [[ADDR:T[0-9]+.[XYZW]]] 46; EG: ADD_INT 47; EG-NEXT: BFE_INT [[RES]], {{.*}}, 0.0, literal 48; EG-NEXT: LSHR * [[ADDR]] 49define void @sext_in_reg_i16_to_i32(i32 addrspace(1)* %out, i32 %a, i32 %b) #0 { 50 %c = add i32 %a, %b ; add to prevent folding into extload 51 %shl = shl i32 %c, 16 52 %ashr = ashr i32 %shl, 16 53 store i32 %ashr, i32 addrspace(1)* %out, align 4 54 ret void 55} 56 57; FUNC-LABEL: {{^}}sext_in_reg_i8_to_v1i32: 58; GCN: s_add_i32 [[VAL:s[0-9]+]], 59; GCN: s_sext_i32_i8 [[EXTRACT:s[0-9]+]], [[VAL]] 60; GCN: v_mov_b32_e32 [[VEXTRACT:v[0-9]+]], [[EXTRACT]] 61; GCN: buffer_store_dword [[VEXTRACT]], 62 63; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+\.[XYZW]]], [[ADDR:T[0-9]+.[XYZW]]] 64; EG: ADD_INT 65; EG-NEXT: BFE_INT [[RES]], {{.*}}, 0.0, literal 66; EG-NEXT: LSHR * [[ADDR]] 67define void @sext_in_reg_i8_to_v1i32(<1 x i32> addrspace(1)* %out, <1 x i32> %a, <1 x i32> %b) #0 { 68 %c = add <1 x i32> %a, %b ; add to prevent folding into extload 69 %shl = shl <1 x i32> %c, <i32 24> 70 %ashr = ashr <1 x i32> %shl, <i32 24> 71 store <1 x i32> %ashr, <1 x i32> addrspace(1)* %out, align 4 72 ret void 73} 74 75; FUNC-LABEL: {{^}}sext_in_reg_i1_to_i64: 76; GCN: s_lshl_b64 [[VAL:s\[[0-9]+:[0-9]+\]]] 77; GCN-DAG: s_bfe_i64 s{{\[}}[[SLO:[0-9]+]]:[[SHI:[0-9]+]]{{\]}}, [[VAL]], 0x10000 78; GCN-DAG: v_mov_b32_e32 v[[VLO:[0-9]+]], s[[SLO]] 79; GCN-DAG: v_mov_b32_e32 v[[VHI:[0-9]+]], s[[SHI]] 80; GCN: buffer_store_dwordx2 v{{\[}}[[VLO]]:[[VHI]]{{\]}} 81define void @sext_in_reg_i1_to_i64(i64 addrspace(1)* %out, i64 %a, i64 %b) #0 { 82 %c = shl i64 %a, %b 83 %shl = shl i64 %c, 63 84 %ashr = ashr i64 %shl, 63 85 store i64 %ashr, i64 addrspace(1)* %out, align 8 86 ret void 87} 88 89; FUNC-LABEL: {{^}}sext_in_reg_i8_to_i64: 90; GCN: s_lshl_b64 [[VAL:s\[[0-9]+:[0-9]+\]]] 91; GCN-DAG: s_bfe_i64 s{{\[}}[[SLO:[0-9]+]]:[[SHI:[0-9]+]]{{\]}}, [[VAL]], 0x80000 92; GCN-DAG: v_mov_b32_e32 v[[VLO:[0-9]+]], s[[SLO]] 93; GCN-DAG: v_mov_b32_e32 v[[VHI:[0-9]+]], s[[SHI]] 94; GCN: buffer_store_dwordx2 v{{\[}}[[VLO]]:[[VHI]]{{\]}} 95define void @sext_in_reg_i8_to_i64(i64 addrspace(1)* %out, i64 %a, i64 %b) #0 { 96 %c = shl i64 %a, %b 97 %shl = shl i64 %c, 56 98 %ashr = ashr i64 %shl, 56 99 store i64 %ashr, i64 addrspace(1)* %out, align 8 100 ret void 101} 102 103; FUNC-LABEL: {{^}}sext_in_reg_i16_to_i64: 104; GCN: s_lshl_b64 [[VAL:s\[[0-9]+:[0-9]+\]]] 105; GCN-DAG: s_bfe_i64 s{{\[}}[[SLO:[0-9]+]]:[[SHI:[0-9]+]]{{\]}}, [[VAL]], 0x100000 106; GCN-DAG: v_mov_b32_e32 v[[VLO:[0-9]+]], s[[SLO]] 107; GCN-DAG: v_mov_b32_e32 v[[VHI:[0-9]+]], s[[SHI]] 108; GCN: buffer_store_dwordx2 v{{\[}}[[VLO]]:[[VHI]]{{\]}} 109 110define void @sext_in_reg_i16_to_i64(i64 addrspace(1)* %out, i64 %a, i64 %b) #0 { 111 %c = shl i64 %a, %b 112 %shl = shl i64 %c, 48 113 %ashr = ashr i64 %shl, 48 114 store i64 %ashr, i64 addrspace(1)* %out, align 8 115 ret void 116} 117 118; FUNC-LABEL: {{^}}sext_in_reg_i32_to_i64: 119; GCN: s_lshl_b64 [[VAL:s\[[0-9]+:[0-9]+\]]] 120; GCN-DAG: s_bfe_i64 s{{\[}}[[SLO:[0-9]+]]:[[SHI:[0-9]+]]{{\]}}, [[VAL]], 0x200000 121; GCN-DAG: v_mov_b32_e32 v[[VLO:[0-9]+]], s[[SLO]] 122; GCN-DAG: v_mov_b32_e32 v[[VHI:[0-9]+]], s[[SHI]] 123; GCN: buffer_store_dwordx2 v{{\[}}[[VLO]]:[[VHI]]{{\]}} 124define void @sext_in_reg_i32_to_i64(i64 addrspace(1)* %out, i64 %a, i64 %b) #0 { 125 %c = shl i64 %a, %b 126 %shl = shl i64 %c, 32 127 %ashr = ashr i64 %shl, 32 128 store i64 %ashr, i64 addrspace(1)* %out, align 8 129 ret void 130} 131 132; This is broken on Evergreen for some reason related to the <1 x i64> kernel arguments. 133; XFUNC-LABEL: {{^}}sext_in_reg_i8_to_v1i64: 134; XGCN: s_bfe_i32 [[EXTRACT:s[0-9]+]], {{s[0-9]+}}, 524288 135; XGCN: s_ashr_i32 {{v[0-9]+}}, [[EXTRACT]], 31 136; XGCN: buffer_store_dword 137; XEG: BFE_INT 138; XEG: ASHR 139; define void @sext_in_reg_i8_to_v1i64(<1 x i64> addrspace(1)* %out, <1 x i64> %a, <1 x i64> %b) #0 { 140; %c = add <1 x i64> %a, %b 141; %shl = shl <1 x i64> %c, <i64 56> 142; %ashr = ashr <1 x i64> %shl, <i64 56> 143; store <1 x i64> %ashr, <1 x i64> addrspace(1)* %out, align 8 144; ret void 145; } 146 147; FUNC-LABEL: {{^}}v_sext_in_reg_i1_to_i64: 148; SI: buffer_load_dwordx2 149; SI: v_lshl_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}} 150 151; VI: flat_load_dwordx2 152; VI: v_lshlrev_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}} 153 154; GCN: v_bfe_i32 v[[LO:[0-9]+]], v[[VAL_LO]], 0, 1 155; GCN: v_ashrrev_i32_e32 v[[HI:[0-9]+]], 31, v[[LO]] 156 157; SI: buffer_store_dwordx2 v{{\[}}[[LO]]:[[HI]]{{\]}} 158; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[LO]]:[[HI]]{{\]}} 159define void @v_sext_in_reg_i1_to_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr) #0 { 160 %tid = call i32 @llvm.r600.read.tidig.x() 161 %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 162 %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 163 %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid 164 %a = load i64, i64 addrspace(1)* %a.gep, align 8 165 %b = load i64, i64 addrspace(1)* %b.gep, align 8 166 167 %c = shl i64 %a, %b 168 %shl = shl i64 %c, 63 169 %ashr = ashr i64 %shl, 63 170 store i64 %ashr, i64 addrspace(1)* %out.gep, align 8 171 ret void 172} 173 174; FUNC-LABEL: {{^}}v_sext_in_reg_i8_to_i64: 175; SI: buffer_load_dwordx2 176; SI: v_lshl_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}} 177 178; VI: flat_load_dwordx2 179; VI: v_lshlrev_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}} 180 181; GCN: v_bfe_i32 v[[LO:[0-9]+]], v[[VAL_LO]], 0, 8 182; GCN: v_ashrrev_i32_e32 v[[HI:[0-9]+]], 31, v[[LO]] 183 184; SI: buffer_store_dwordx2 v{{\[}}[[LO]]:[[HI]]{{\]}} 185; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[LO]]:[[HI]]{{\]}} 186define void @v_sext_in_reg_i8_to_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr) #0 { 187 %tid = call i32 @llvm.r600.read.tidig.x() 188 %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 189 %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 190 %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid 191 %a = load i64, i64 addrspace(1)* %a.gep, align 8 192 %b = load i64, i64 addrspace(1)* %b.gep, align 8 193 194 %c = shl i64 %a, %b 195 %shl = shl i64 %c, 56 196 %ashr = ashr i64 %shl, 56 197 store i64 %ashr, i64 addrspace(1)* %out.gep, align 8 198 ret void 199} 200 201; FUNC-LABEL: {{^}}v_sext_in_reg_i16_to_i64: 202; SI: buffer_load_dwordx2 203; SI: v_lshl_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}} 204 205; VI: flat_load_dwordx2 206; VI: v_lshlrev_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}} 207 208; GCN: v_bfe_i32 v[[LO:[0-9]+]], v[[VAL_LO]], 0, 16 209; GCN: v_ashrrev_i32_e32 v[[HI:[0-9]+]], 31, v[[LO]] 210 211; SI: buffer_store_dwordx2 v{{\[}}[[LO]]:[[HI]]{{\]}} 212; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[LO]]:[[HI]]{{\]}} 213define void @v_sext_in_reg_i16_to_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr) #0 { 214 %tid = call i32 @llvm.r600.read.tidig.x() 215 %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 216 %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 217 %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid 218 %a = load i64, i64 addrspace(1)* %a.gep, align 8 219 %b = load i64, i64 addrspace(1)* %b.gep, align 8 220 221 %c = shl i64 %a, %b 222 %shl = shl i64 %c, 48 223 %ashr = ashr i64 %shl, 48 224 store i64 %ashr, i64 addrspace(1)* %out.gep, align 8 225 ret void 226} 227 228; FUNC-LABEL: {{^}}v_sext_in_reg_i32_to_i64: 229; SI: buffer_load_dwordx2 230; SI: v_lshl_b64 v{{\[}}[[LO:[0-9]+]]:[[HI:[0-9]+]]{{\]}}, 231 232; VI: flat_load_dwordx2 233; VI: v_lshlrev_b64 v{{\[}}[[LO:[0-9]+]]:[[HI:[0-9]+]]{{\]}}, 234 235; GCN: v_ashrrev_i32_e32 v[[SHR:[0-9]+]], 31, v[[LO]] 236; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[LO]]:[[SHR]]{{\]}} 237define void @v_sext_in_reg_i32_to_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr) #0 { 238 %tid = call i32 @llvm.r600.read.tidig.x() 239 %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 240 %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 241 %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid 242 %a = load i64, i64 addrspace(1)* %a.gep, align 8 243 %b = load i64, i64 addrspace(1)* %b.gep, align 8 244 245 %c = shl i64 %a, %b 246 %shl = shl i64 %c, 32 247 %ashr = ashr i64 %shl, 32 248 store i64 %ashr, i64 addrspace(1)* %out.gep, align 8 249 ret void 250} 251 252; FUNC-LABEL: {{^}}sext_in_reg_i1_in_i32_other_amount: 253; GCN-NOT: s_lshl 254; GCN-NOT: s_ashr 255; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x190001 256 257; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+\.[XYZW]]], [[ADDR:T[0-9]+.[XYZW]]] 258; EG-NOT: BFE 259; EG: ADD_INT 260; EG: LSHL 261; EG: ASHR [[RES]] 262; EG: LSHR {{\*?}} [[ADDR]] 263define void @sext_in_reg_i1_in_i32_other_amount(i32 addrspace(1)* %out, i32 %a, i32 %b) #0 { 264 %c = add i32 %a, %b 265 %x = shl i32 %c, 6 266 %y = ashr i32 %x, 7 267 store i32 %y, i32 addrspace(1)* %out 268 ret void 269} 270 271; FUNC-LABEL: {{^}}sext_in_reg_v2i1_in_v2i32_other_amount: 272; GCN-NOT: s_lshl 273; GCN-NOT: s_ashr 274; GCN-DAG: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x190001 275; GCN-DAG: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x190001 276; GCN: s_endpgm 277 278; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]] 279; EG-NOT: BFE 280; EG: ADD_INT 281; EG: LSHL 282; EG: ASHR [[RES]] 283; EG: LSHL 284; EG: ASHR [[RES]] 285; EG: LSHR {{\*?}} [[ADDR]] 286define void @sext_in_reg_v2i1_in_v2i32_other_amount(<2 x i32> addrspace(1)* %out, <2 x i32> %a, <2 x i32> %b) #0 { 287 %c = add <2 x i32> %a, %b 288 %x = shl <2 x i32> %c, <i32 6, i32 6> 289 %y = ashr <2 x i32> %x, <i32 7, i32 7> 290 store <2 x i32> %y, <2 x i32> addrspace(1)* %out 291 ret void 292} 293 294 295; FUNC-LABEL: {{^}}sext_in_reg_v2i1_to_v2i32: 296; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000 297; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000 298; GCN: buffer_store_dwordx2 299 300; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]] 301; EG: BFE_INT [[RES]] 302; EG: BFE_INT [[RES]] 303; EG: LSHR {{\*?}} [[ADDR]] 304define void @sext_in_reg_v2i1_to_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> %a, <2 x i32> %b) #0 { 305 %c = add <2 x i32> %a, %b ; add to prevent folding into extload 306 %shl = shl <2 x i32> %c, <i32 31, i32 31> 307 %ashr = ashr <2 x i32> %shl, <i32 31, i32 31> 308 store <2 x i32> %ashr, <2 x i32> addrspace(1)* %out, align 8 309 ret void 310} 311 312; FUNC-LABEL: {{^}}sext_in_reg_v4i1_to_v4i32: 313; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000 314; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000 315; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000 316; GCN: s_bfe_i32 {{s[0-9]+}}, {{s[0-9]+}}, 0x10000 317; GCN: buffer_store_dwordx4 318 319; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW][XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]] 320; EG: BFE_INT [[RES]] 321; EG: BFE_INT [[RES]] 322; EG: BFE_INT [[RES]] 323; EG: BFE_INT [[RES]] 324; EG: LSHR {{\*?}} [[ADDR]] 325define void @sext_in_reg_v4i1_to_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> %a, <4 x i32> %b) #0 { 326 %c = add <4 x i32> %a, %b ; add to prevent folding into extload 327 %shl = shl <4 x i32> %c, <i32 31, i32 31, i32 31, i32 31> 328 %ashr = ashr <4 x i32> %shl, <i32 31, i32 31, i32 31, i32 31> 329 store <4 x i32> %ashr, <4 x i32> addrspace(1)* %out, align 8 330 ret void 331} 332 333; FUNC-LABEL: {{^}}sext_in_reg_v2i8_to_v2i32: 334; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}} 335; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}} 336; GCN: buffer_store_dwordx2 337 338; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]] 339; EG: BFE_INT [[RES]] 340; EG: BFE_INT [[RES]] 341; EG: LSHR {{\*?}} [[ADDR]] 342define void @sext_in_reg_v2i8_to_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> %a, <2 x i32> %b) #0 { 343 %c = add <2 x i32> %a, %b ; add to prevent folding into extload 344 %shl = shl <2 x i32> %c, <i32 24, i32 24> 345 %ashr = ashr <2 x i32> %shl, <i32 24, i32 24> 346 store <2 x i32> %ashr, <2 x i32> addrspace(1)* %out, align 8 347 ret void 348} 349 350; FUNC-LABEL: {{^}}sext_in_reg_v4i8_to_v4i32: 351; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}} 352; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}} 353; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}} 354; GCN: s_sext_i32_i8 {{s[0-9]+}}, {{s[0-9]+}} 355; GCN: buffer_store_dwordx4 356 357; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW][XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]] 358; EG: BFE_INT [[RES]] 359; EG: BFE_INT [[RES]] 360; EG: BFE_INT [[RES]] 361; EG: BFE_INT [[RES]] 362; EG: LSHR {{\*?}} [[ADDR]] 363define void @sext_in_reg_v4i8_to_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> %a, <4 x i32> %b) #0 { 364 %c = add <4 x i32> %a, %b ; add to prevent folding into extload 365 %shl = shl <4 x i32> %c, <i32 24, i32 24, i32 24, i32 24> 366 %ashr = ashr <4 x i32> %shl, <i32 24, i32 24, i32 24, i32 24> 367 store <4 x i32> %ashr, <4 x i32> addrspace(1)* %out, align 8 368 ret void 369} 370 371; FUNC-LABEL: {{^}}sext_in_reg_v2i16_to_v2i32: 372; GCN: s_sext_i32_i16 {{s[0-9]+}}, {{s[0-9]+}} 373; GCN: s_sext_i32_i16 {{s[0-9]+}}, {{s[0-9]+}} 374; GCN: buffer_store_dwordx2 375 376; EG: MEM_{{.*}} STORE_{{.*}} [[RES:T[0-9]+]]{{\.[XYZW][XYZW]}}, [[ADDR:T[0-9]+.[XYZW]]] 377; EG: BFE_INT [[RES]] 378; EG: BFE_INT [[RES]] 379; EG: LSHR {{\*?}} [[ADDR]] 380define void @sext_in_reg_v2i16_to_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> %a, <2 x i32> %b) #0 { 381 %c = add <2 x i32> %a, %b ; add to prevent folding into extload 382 %shl = shl <2 x i32> %c, <i32 16, i32 16> 383 %ashr = ashr <2 x i32> %shl, <i32 16, i32 16> 384 store <2 x i32> %ashr, <2 x i32> addrspace(1)* %out, align 8 385 ret void 386} 387 388; FUNC-LABEL: {{^}}testcase: 389define void @testcase(i8 addrspace(1)* %out, i8 %a) #0 { 390 %and_a_1 = and i8 %a, 1 391 %cmp_eq = icmp eq i8 %and_a_1, 0 392 %cmp_slt = icmp slt i8 %a, 0 393 %sel0 = select i1 %cmp_slt, i8 0, i8 %a 394 %sel1 = select i1 %cmp_eq, i8 0, i8 %a 395 %xor = xor i8 %sel0, %sel1 396 store i8 %xor, i8 addrspace(1)* %out 397 ret void 398} 399 400; FUNC-LABEL: {{^}}testcase_3: 401define void @testcase_3(i8 addrspace(1)* %out, i8 %a) #0 { 402 %and_a_1 = and i8 %a, 1 403 %cmp_eq = icmp eq i8 %and_a_1, 0 404 %cmp_slt = icmp slt i8 %a, 0 405 %sel0 = select i1 %cmp_slt, i8 0, i8 %a 406 %sel1 = select i1 %cmp_eq, i8 0, i8 %a 407 %xor = xor i8 %sel0, %sel1 408 store i8 %xor, i8 addrspace(1)* %out 409 ret void 410} 411 412; FUNC-LABEL: {{^}}vgpr_sext_in_reg_v4i8_to_v4i32: 413; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 8 414; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 8 415; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 8 416; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 8 417define void @vgpr_sext_in_reg_v4i8_to_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %a, <4 x i32> addrspace(1)* %b) #0 { 418 %loada = load <4 x i32>, <4 x i32> addrspace(1)* %a, align 16 419 %loadb = load <4 x i32>, <4 x i32> addrspace(1)* %b, align 16 420 %c = add <4 x i32> %loada, %loadb ; add to prevent folding into extload 421 %shl = shl <4 x i32> %c, <i32 24, i32 24, i32 24, i32 24> 422 %ashr = ashr <4 x i32> %shl, <i32 24, i32 24, i32 24, i32 24> 423 store <4 x i32> %ashr, <4 x i32> addrspace(1)* %out, align 8 424 ret void 425} 426 427; FUNC-LABEL: {{^}}vgpr_sext_in_reg_v4i16_to_v4i32: 428; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 16 429; GCN: v_bfe_i32 [[EXTRACT:v[0-9]+]], {{v[0-9]+}}, 0, 16 430define void @vgpr_sext_in_reg_v4i16_to_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %a, <4 x i32> addrspace(1)* %b) #0 { 431 %loada = load <4 x i32>, <4 x i32> addrspace(1)* %a, align 16 432 %loadb = load <4 x i32>, <4 x i32> addrspace(1)* %b, align 16 433 %c = add <4 x i32> %loada, %loadb ; add to prevent folding into extload 434 %shl = shl <4 x i32> %c, <i32 16, i32 16, i32 16, i32 16> 435 %ashr = ashr <4 x i32> %shl, <i32 16, i32 16, i32 16, i32 16> 436 store <4 x i32> %ashr, <4 x i32> addrspace(1)* %out, align 8 437 ret void 438} 439 440; FUNC-LABEL: {{^}}sext_in_reg_to_illegal_type: 441; GCN: buffer_load_sbyte 442; GCN: v_max_i32 443; GCN-NOT: bfe 444; GCN: buffer_store_short 445define void @sext_in_reg_to_illegal_type(i16 addrspace(1)* nocapture %out, i8 addrspace(1)* nocapture %src) #0 { 446 %tmp5 = load i8, i8 addrspace(1)* %src, align 1 447 %tmp2 = sext i8 %tmp5 to i32 448 %tmp2.5 = icmp sgt i32 %tmp2, 0 449 %tmp3 = select i1 %tmp2.5, i32 %tmp2, i32 0 450 %tmp4 = trunc i32 %tmp3 to i8 451 %tmp6 = sext i8 %tmp4 to i16 452 store i16 %tmp6, i16 addrspace(1)* %out, align 2 453 ret void 454} 455 456declare i32 @llvm.AMDGPU.bfe.i32(i32, i32, i32) nounwind readnone 457 458; FUNC-LABEL: {{^}}bfe_0_width: 459; GCN-NOT: {{[^@]}}bfe 460; GCN: s_endpgm 461define void @bfe_0_width(i32 addrspace(1)* %out, i32 addrspace(1)* %ptr) #0 { 462 %load = load i32, i32 addrspace(1)* %ptr, align 4 463 %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %load, i32 8, i32 0) nounwind readnone 464 store i32 %bfe, i32 addrspace(1)* %out, align 4 465 ret void 466} 467 468; FUNC-LABEL: {{^}}bfe_8_bfe_8: 469; GCN: v_bfe_i32 470; GCN-NOT: {{[^@]}}bfe 471; GCN: s_endpgm 472define void @bfe_8_bfe_8(i32 addrspace(1)* %out, i32 addrspace(1)* %ptr) #0 { 473 %load = load i32, i32 addrspace(1)* %ptr, align 4 474 %bfe0 = call i32 @llvm.AMDGPU.bfe.i32(i32 %load, i32 0, i32 8) nounwind readnone 475 %bfe1 = call i32 @llvm.AMDGPU.bfe.i32(i32 %bfe0, i32 0, i32 8) nounwind readnone 476 store i32 %bfe1, i32 addrspace(1)* %out, align 4 477 ret void 478} 479 480; FUNC-LABEL: {{^}}bfe_8_bfe_16: 481; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 0, 8 482; GCN: s_endpgm 483define void @bfe_8_bfe_16(i32 addrspace(1)* %out, i32 addrspace(1)* %ptr) #0 { 484 %load = load i32, i32 addrspace(1)* %ptr, align 4 485 %bfe0 = call i32 @llvm.AMDGPU.bfe.i32(i32 %load, i32 0, i32 8) nounwind readnone 486 %bfe1 = call i32 @llvm.AMDGPU.bfe.i32(i32 %bfe0, i32 0, i32 16) nounwind readnone 487 store i32 %bfe1, i32 addrspace(1)* %out, align 4 488 ret void 489} 490 491; This really should be folded into 1 492; FUNC-LABEL: {{^}}bfe_16_bfe_8: 493; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 0, 8 494; GCN-NOT: {{[^@]}}bfe 495; GCN: s_endpgm 496define void @bfe_16_bfe_8(i32 addrspace(1)* %out, i32 addrspace(1)* %ptr) #0 { 497 %load = load i32, i32 addrspace(1)* %ptr, align 4 498 %bfe0 = call i32 @llvm.AMDGPU.bfe.i32(i32 %load, i32 0, i32 16) nounwind readnone 499 %bfe1 = call i32 @llvm.AMDGPU.bfe.i32(i32 %bfe0, i32 0, i32 8) nounwind readnone 500 store i32 %bfe1, i32 addrspace(1)* %out, align 4 501 ret void 502} 503 504; Make sure there isn't a redundant BFE 505; FUNC-LABEL: {{^}}sext_in_reg_i8_to_i32_bfe: 506; GCN: s_sext_i32_i8 s{{[0-9]+}}, s{{[0-9]+}} 507; GCN-NOT: {{[^@]}}bfe 508; GCN: s_endpgm 509define void @sext_in_reg_i8_to_i32_bfe(i32 addrspace(1)* %out, i32 %a, i32 %b) #0 { 510 %c = add i32 %a, %b ; add to prevent folding into extload 511 %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %c, i32 0, i32 8) nounwind readnone 512 %shl = shl i32 %bfe, 24 513 %ashr = ashr i32 %shl, 24 514 store i32 %ashr, i32 addrspace(1)* %out, align 4 515 ret void 516} 517 518; FUNC-LABEL: {{^}}sext_in_reg_i8_to_i32_bfe_wrong: 519define void @sext_in_reg_i8_to_i32_bfe_wrong(i32 addrspace(1)* %out, i32 %a, i32 %b) #0 { 520 %c = add i32 %a, %b ; add to prevent folding into extload 521 %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %c, i32 8, i32 0) nounwind readnone 522 %shl = shl i32 %bfe, 24 523 %ashr = ashr i32 %shl, 24 524 store i32 %ashr, i32 addrspace(1)* %out, align 4 525 ret void 526} 527 528; FUNC-LABEL: {{^}}sextload_i8_to_i32_bfe: 529; GCN: buffer_load_sbyte 530; GCN-NOT: {{[^@]}}bfe 531; GCN: s_endpgm 532define void @sextload_i8_to_i32_bfe(i32 addrspace(1)* %out, i8 addrspace(1)* %ptr) #0 { 533 %load = load i8, i8 addrspace(1)* %ptr, align 1 534 %sext = sext i8 %load to i32 535 %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %sext, i32 0, i32 8) nounwind readnone 536 %shl = shl i32 %bfe, 24 537 %ashr = ashr i32 %shl, 24 538 store i32 %ashr, i32 addrspace(1)* %out, align 4 539 ret void 540} 541 542; GCN: .text 543; FUNC-LABEL: {{^}}sextload_i8_to_i32_bfe_0:{{.*$}} 544; GCN-NOT: {{[^@]}}bfe 545; GCN: s_endpgm 546define void @sextload_i8_to_i32_bfe_0(i32 addrspace(1)* %out, i8 addrspace(1)* %ptr) #0 { 547 %load = load i8, i8 addrspace(1)* %ptr, align 1 548 %sext = sext i8 %load to i32 549 %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %sext, i32 8, i32 0) nounwind readnone 550 %shl = shl i32 %bfe, 24 551 %ashr = ashr i32 %shl, 24 552 store i32 %ashr, i32 addrspace(1)* %out, align 4 553 ret void 554} 555 556; FUNC-LABEL: {{^}}sext_in_reg_i1_bfe_offset_0: 557; GCN-NOT: shr 558; GCN-NOT: shl 559; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 0, 1 560; GCN: s_endpgm 561define void @sext_in_reg_i1_bfe_offset_0(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 { 562 %x = load i32, i32 addrspace(1)* %in, align 4 563 %shl = shl i32 %x, 31 564 %shr = ashr i32 %shl, 31 565 %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %shr, i32 0, i32 1) 566 store i32 %bfe, i32 addrspace(1)* %out, align 4 567 ret void 568} 569 570; FUNC-LABEL: {{^}}sext_in_reg_i1_bfe_offset_1: 571; GCN: buffer_load_dword 572; GCN-NOT: shl 573; GCN-NOT: shr 574; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 1, 1 575; GCN: s_endpgm 576define void @sext_in_reg_i1_bfe_offset_1(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 { 577 %x = load i32, i32 addrspace(1)* %in, align 4 578 %shl = shl i32 %x, 30 579 %shr = ashr i32 %shl, 30 580 %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %shr, i32 1, i32 1) 581 store i32 %bfe, i32 addrspace(1)* %out, align 4 582 ret void 583} 584 585; FUNC-LABEL: {{^}}sext_in_reg_i2_bfe_offset_1: 586; GCN: buffer_load_dword 587; GCN-NOT: v_lshl 588; GCN-NOT: v_ashr 589; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 0, 2 590; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 1, 2 591; GCN: s_endpgm 592define void @sext_in_reg_i2_bfe_offset_1(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 { 593 %x = load i32, i32 addrspace(1)* %in, align 4 594 %shl = shl i32 %x, 30 595 %shr = ashr i32 %shl, 30 596 %bfe = call i32 @llvm.AMDGPU.bfe.i32(i32 %shr, i32 1, i32 2) 597 store i32 %bfe, i32 addrspace(1)* %out, align 4 598 ret void 599} 600 601; Make sure we propagate the VALUness to users of a moved scalar BFE. 602 603; FUNC-LABEL: {{^}}v_sext_in_reg_i1_to_i64_move_use: 604; SI: buffer_load_dwordx2 605; SI: v_lshl_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}} 606 607; VI: flat_load_dwordx2 608; VI: v_lshlrev_b64 v{{\[}}[[VAL_LO:[0-9]+]]:[[VAL_HI:[0-9]+]]{{\]}} 609 610; GCN-DAG: v_bfe_i32 v[[LO:[0-9]+]], v[[VAL_LO]], 0, 1 611; GCN-DAG: v_ashrrev_i32_e32 v[[HI:[0-9]+]], 31, v[[LO]] 612; GCN-DAG: v_and_b32_e32 v[[RESULT_LO:[0-9]+]], s{{[0-9]+}}, v[[LO]] 613; GCN-DAG: v_and_b32_e32 v[[RESULT_HI:[0-9]+]], s{{[0-9]+}}, v[[HI]] 614; SI: buffer_store_dwordx2 v{{\[}}[[RESULT_LO]]:[[RESULT_HI]]{{\]}} 615; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[RESULT_LO]]:[[RESULT_HI]]{{\]}} 616define void @v_sext_in_reg_i1_to_i64_move_use(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr, i64 %s.val) #0 { 617 %tid = call i32 @llvm.r600.read.tidig.x() 618 %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 619 %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 620 %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid 621 %a = load i64, i64 addrspace(1)* %a.gep, align 8 622 %b = load i64, i64 addrspace(1)* %b.gep, align 8 623 624 %c = shl i64 %a, %b 625 %shl = shl i64 %c, 63 626 %ashr = ashr i64 %shl, 63 627 628 %and = and i64 %ashr, %s.val 629 store i64 %and, i64 addrspace(1)* %out.gep, align 8 630 ret void 631} 632 633; FUNC-LABEL: {{^}}v_sext_in_reg_i32_to_i64_move_use: 634; SI: buffer_load_dwordx2 635; SI: v_lshl_b64 v{{\[}}[[LO:[0-9]+]]:[[HI:[0-9]+]]{{\]}}, 636 637; VI: flat_load_dwordx2 638; VI: v_lshlrev_b64 v{{\[}}[[LO:[0-9]+]]:[[HI:[0-9]+]]{{\]}}, 639 640; GCN-DAG: v_ashrrev_i32_e32 v[[SHR:[0-9]+]], 31, v[[LO]] 641; GCN-DAG: v_and_b32_e32 v[[RESULT_LO:[0-9]+]], s{{[0-9]+}}, v[[LO]] 642; GCN-DAG: v_and_b32_e32 v[[RESULT_HI:[0-9]+]], s{{[0-9]+}}, v[[SHR]] 643 644; SI: buffer_store_dwordx2 v{{\[}}[[RESULT_LO]]:[[RESULT_HI]]{{\]}} 645; VI: flat_store_dwordx2 v{{\[[0-9]+:[0-9]+\]}}, v{{\[}}[[RESULT_LO]]:[[RESULT_HI]]{{\]}} 646define void @v_sext_in_reg_i32_to_i64_move_use(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr, i64 %s.val) #0 { 647 %tid = call i32 @llvm.r600.read.tidig.x() 648 %a.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 649 %b.gep = getelementptr i64, i64 addrspace(1)* %aptr, i32 %tid 650 %out.gep = getelementptr i64, i64 addrspace(1)* %out, i32 %tid 651 %a = load i64, i64 addrspace(1)* %a.gep, align 8 652 %b = load i64, i64 addrspace(1)* %b.gep, align 8 653 654 %c = shl i64 %a, %b 655 %shl = shl i64 %c, 32 656 %ashr = ashr i64 %shl, 32 657 %and = and i64 %ashr, %s.val 658 store i64 %and, i64 addrspace(1)* %out.gep, align 8 659 ret void 660} 661 662declare i32 @llvm.r600.read.tidig.x() #1 663 664attributes #0 = { nounwind } 665attributes #1 = { nounwind readnone } 666