1; RUN: opt -S -mtriple=amdgcn-- -codegenprepare < %s | FileCheck -check-prefix=OPT %s 2; RUN: opt -S -mtriple=amdgcn-- -mcpu=tonga -codegenprepare < %s | FileCheck -check-prefix=OPT %s 3; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=SI %s 4; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=VI %s 5 6; This particular case will actually be worse in terms of code size 7; from sinking into both. 8 9; OPT-LABEL: @sink_ubfe_i32( 10; OPT: entry: 11; OPT-NEXT: br i1 12 13; OPT: bb0: 14; OPT: %0 = lshr i32 %arg1, 8 15; OPT-NEXT: %val0 = and i32 %0, 255 16; OPT: br label 17 18; OPT: bb1: 19; OPT: %1 = lshr i32 %arg1, 8 20; OPT-NEXT: %val1 = and i32 %1, 127 21; OPT: br label 22 23; OPT: ret: 24; OPT: store 25; OPT: ret 26 27 28; GCN-LABEL: {{^}}sink_ubfe_i32: 29; GCN-NOT: lshr 30; GCN: s_cbranch_vccnz 31 32; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x80008 33; GCN: BB0_2: 34; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x70008 35 36; GCN: BB0_3: 37; GCN: buffer_store_dword 38; GCN: s_endpgm 39define void @sink_ubfe_i32(i32 addrspace(1)* %out, i32 %arg1) #0 { 40entry: 41 %shr = lshr i32 %arg1, 8 42 br i1 undef, label %bb0, label %bb1 43 44bb0: 45 %val0 = and i32 %shr, 255 46 store volatile i32 0, i32 addrspace(1)* undef 47 br label %ret 48 49bb1: 50 %val1 = and i32 %shr, 127 51 store volatile i32 0, i32 addrspace(1)* undef 52 br label %ret 53 54ret: 55 %phi = phi i32 [ %val0, %bb0 ], [ %val1, %bb1 ] 56 store i32 %phi, i32 addrspace(1)* %out 57 ret void 58} 59 60; OPT-LABEL: @sink_sbfe_i32( 61; OPT: entry: 62; OPT-NEXT: br i1 63 64; OPT: bb0: 65; OPT: %0 = ashr i32 %arg1, 8 66; OPT-NEXT: %val0 = and i32 %0, 255 67; OPT: br label 68 69; OPT: bb1: 70; OPT: %1 = ashr i32 %arg1, 8 71; OPT-NEXT: %val1 = and i32 %1, 127 72; OPT: br label 73 74; OPT: ret: 75; OPT: store 76; OPT: ret 77 78; GCN-LABEL: {{^}}sink_sbfe_i32: 79define void @sink_sbfe_i32(i32 addrspace(1)* %out, i32 %arg1) #0 { 80entry: 81 %shr = ashr i32 %arg1, 8 82 br i1 undef, label %bb0, label %bb1 83 84bb0: 85 %val0 = and i32 %shr, 255 86 store volatile i32 0, i32 addrspace(1)* undef 87 br label %ret 88 89bb1: 90 %val1 = and i32 %shr, 127 91 store volatile i32 0, i32 addrspace(1)* undef 92 br label %ret 93 94ret: 95 %phi = phi i32 [ %val0, %bb0 ], [ %val1, %bb1 ] 96 store i32 %phi, i32 addrspace(1)* %out 97 ret void 98} 99 100 101; OPT-LABEL: @sink_ubfe_i16( 102; OPT: entry: 103; OPT-NEXT: br i1 104 105; OPT: bb0: 106; OPT: %0 = lshr i16 %arg1, 4 107; OPT-NEXT: %val0 = and i16 %0, 255 108; OPT: br label 109 110; OPT: bb1: 111; OPT: %1 = lshr i16 %arg1, 4 112; OPT-NEXT: %val1 = and i16 %1, 127 113; OPT: br label 114 115; OPT: ret: 116; OPT: store 117; OPT: ret 118 119; For GFX8: since i16 is legal type, we cannot sink lshr into BBs. 120 121; GCN-LABEL: {{^}}sink_ubfe_i16: 122; GCN-NOT: lshr 123; VI: s_bfe_u32 s0, s0, 0xc0004 124; GCN: s_cbranch_vccnz 125 126; SI: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x80004 127; VI: s_and_b32 s0, s0, 0xff 128 129; GCN: BB2_2: 130; SI: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x70004 131; VI: s_and_b32 s0, s0, 0x7f 132 133; GCN: BB2_3: 134; GCN: buffer_store_short 135; GCN: s_endpgm 136define void @sink_ubfe_i16(i16 addrspace(1)* %out, i16 %arg1) #0 { 137entry: 138 %shr = lshr i16 %arg1, 4 139 br i1 undef, label %bb0, label %bb1 140 141bb0: 142 %val0 = and i16 %shr, 255 143 store volatile i16 0, i16 addrspace(1)* undef 144 br label %ret 145 146bb1: 147 %val1 = and i16 %shr, 127 148 store volatile i16 0, i16 addrspace(1)* undef 149 br label %ret 150 151ret: 152 %phi = phi i16 [ %val0, %bb0 ], [ %val1, %bb1 ] 153 store i16 %phi, i16 addrspace(1)* %out 154 ret void 155} 156 157; We don't really want to sink this one since it isn't reducible to a 158; 32-bit BFE on one half of the integer. 159 160; OPT-LABEL: @sink_ubfe_i64_span_midpoint( 161; OPT: entry: 162; OPT-NOT: lshr 163; OPT: br i1 164 165; OPT: bb0: 166; OPT: %0 = lshr i64 %arg1, 30 167; OPT-NEXT: %val0 = and i64 %0, 255 168 169; OPT: bb1: 170; OPT: %1 = lshr i64 %arg1, 30 171; OPT-NEXT: %val1 = and i64 %1, 127 172 173; OPT: ret: 174; OPT: store 175; OPT: ret 176 177; GCN-LABEL: {{^}}sink_ubfe_i64_span_midpoint: 178; GCN: s_lshr_b64 s{{\[}}[[LO:[0-9]+]]:{{[0-9]+}}], s{{\[[0-9]+:[0-9]+\]}}, 30 179; GCN: s_cbranch_vccnz BB3_2 180 181; GCN: s_and_b32 s{{[0-9]+}}, s[[LO]], 0xff 182 183; GCN: BB3_2: 184; GCN: s_and_b32 s{{[0-9]+}}, s[[LO]], 0x7f 185 186; GCN: BB3_3: 187; GCN: buffer_store_dwordx2 188define void @sink_ubfe_i64_span_midpoint(i64 addrspace(1)* %out, i64 %arg1) #0 { 189entry: 190 %shr = lshr i64 %arg1, 30 191 br i1 undef, label %bb0, label %bb1 192 193bb0: 194 %val0 = and i64 %shr, 255 195 store volatile i32 0, i32 addrspace(1)* undef 196 br label %ret 197 198bb1: 199 %val1 = and i64 %shr, 127 200 store volatile i32 0, i32 addrspace(1)* undef 201 br label %ret 202 203ret: 204 %phi = phi i64 [ %val0, %bb0 ], [ %val1, %bb1 ] 205 store i64 %phi, i64 addrspace(1)* %out 206 ret void 207} 208 209; OPT-LABEL: @sink_ubfe_i64_low32( 210; OPT: entry: 211; OPT-NOT: lshr 212; OPT: br i1 213 214; OPT: bb0: 215; OPT: %0 = lshr i64 %arg1, 15 216; OPT-NEXT: %val0 = and i64 %0, 255 217 218; OPT: bb1: 219; OPT: %1 = lshr i64 %arg1, 15 220; OPT-NEXT: %val1 = and i64 %1, 127 221 222; OPT: ret: 223; OPT: store 224; OPT: ret 225 226; GCN-LABEL: {{^}}sink_ubfe_i64_low32: 227 228; GCN: s_cbranch_vccnz BB4_2 229 230; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x8000f 231 232; GCN: BB4_2: 233; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x7000f 234 235; GCN: BB4_3: 236; GCN: buffer_store_dwordx2 237define void @sink_ubfe_i64_low32(i64 addrspace(1)* %out, i64 %arg1) #0 { 238entry: 239 %shr = lshr i64 %arg1, 15 240 br i1 undef, label %bb0, label %bb1 241 242bb0: 243 %val0 = and i64 %shr, 255 244 store volatile i32 0, i32 addrspace(1)* undef 245 br label %ret 246 247bb1: 248 %val1 = and i64 %shr, 127 249 store volatile i32 0, i32 addrspace(1)* undef 250 br label %ret 251 252ret: 253 %phi = phi i64 [ %val0, %bb0 ], [ %val1, %bb1 ] 254 store i64 %phi, i64 addrspace(1)* %out 255 ret void 256} 257 258; OPT-LABEL: @sink_ubfe_i64_high32( 259; OPT: entry: 260; OPT-NOT: lshr 261; OPT: br i1 262 263; OPT: bb0: 264; OPT: %0 = lshr i64 %arg1, 35 265; OPT-NEXT: %val0 = and i64 %0, 255 266 267; OPT: bb1: 268; OPT: %1 = lshr i64 %arg1, 35 269; OPT-NEXT: %val1 = and i64 %1, 127 270 271; OPT: ret: 272; OPT: store 273; OPT: ret 274 275; GCN-LABEL: {{^}}sink_ubfe_i64_high32: 276; GCN: s_cbranch_vccnz BB5_2 277; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x80003 278 279; GCN: BB5_2: 280; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x70003 281 282; GCN: BB5_3: 283; GCN: buffer_store_dwordx2 284define void @sink_ubfe_i64_high32(i64 addrspace(1)* %out, i64 %arg1) #0 { 285entry: 286 %shr = lshr i64 %arg1, 35 287 br i1 undef, label %bb0, label %bb1 288 289bb0: 290 %val0 = and i64 %shr, 255 291 store volatile i32 0, i32 addrspace(1)* undef 292 br label %ret 293 294bb1: 295 %val1 = and i64 %shr, 127 296 store volatile i32 0, i32 addrspace(1)* undef 297 br label %ret 298 299ret: 300 %phi = phi i64 [ %val0, %bb0 ], [ %val1, %bb1 ] 301 store i64 %phi, i64 addrspace(1)* %out 302 ret void 303} 304 305attributes #0 = { nounwind } 306