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 120; GCN-LABEL: {{^}}sink_ubfe_i16: 121; GCN-NOT: lshr 122; GCN: s_cbranch_vccnz 123 124; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x80004 125; GCN: BB2_2: 126; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x70004 127 128; GCN: BB2_3: 129; GCN: buffer_store_short 130; GCN: s_endpgm 131define void @sink_ubfe_i16(i16 addrspace(1)* %out, i16 %arg1) #0 { 132entry: 133 %shr = lshr i16 %arg1, 4 134 br i1 undef, label %bb0, label %bb1 135 136bb0: 137 %val0 = and i16 %shr, 255 138 store volatile i16 0, i16 addrspace(1)* undef 139 br label %ret 140 141bb1: 142 %val1 = and i16 %shr, 127 143 store volatile i16 0, i16 addrspace(1)* undef 144 br label %ret 145 146ret: 147 %phi = phi i16 [ %val0, %bb0 ], [ %val1, %bb1 ] 148 store i16 %phi, i16 addrspace(1)* %out 149 ret void 150} 151 152; We don't really want to sink this one since it isn't reducible to a 153; 32-bit BFE on one half of the integer. 154 155; OPT-LABEL: @sink_ubfe_i64_span_midpoint( 156; OPT: entry: 157; OPT-NOT: lshr 158; OPT: br i1 159 160; OPT: bb0: 161; OPT: %0 = lshr i64 %arg1, 30 162; OPT-NEXT: %val0 = and i64 %0, 255 163 164; OPT: bb1: 165; OPT: %1 = lshr i64 %arg1, 30 166; OPT-NEXT: %val1 = and i64 %1, 127 167 168; OPT: ret: 169; OPT: store 170; OPT: ret 171 172; GCN-LABEL: {{^}}sink_ubfe_i64_span_midpoint: 173; GCN: s_cbranch_vccnz BB3_2 174 175; GCN: s_lshr_b64 s{{\[}}[[LO:[0-9]+]]:{{[0-9]+}}], s{{\[[0-9]+:[0-9]+\]}}, 30 176; GCN: s_and_b32 s{{[0-9]+}}, s[[LO]], 0xff 177 178; GCN: BB3_2: 179; GCN: s_lshr_b64 s{{\[}}[[LO:[0-9]+]]:{{[0-9]+}}], s{{\[[0-9]+:[0-9]+\]}}, 30 180; GCN: s_and_b32 s{{[0-9]+}}, s[[LO]], 0x7f 181 182; GCN: BB3_3: 183; GCN: buffer_store_dwordx2 184define void @sink_ubfe_i64_span_midpoint(i64 addrspace(1)* %out, i64 %arg1) #0 { 185entry: 186 %shr = lshr i64 %arg1, 30 187 br i1 undef, label %bb0, label %bb1 188 189bb0: 190 %val0 = and i64 %shr, 255 191 store volatile i32 0, i32 addrspace(1)* undef 192 br label %ret 193 194bb1: 195 %val1 = and i64 %shr, 127 196 store volatile i32 0, i32 addrspace(1)* undef 197 br label %ret 198 199ret: 200 %phi = phi i64 [ %val0, %bb0 ], [ %val1, %bb1 ] 201 store i64 %phi, i64 addrspace(1)* %out 202 ret void 203} 204 205; OPT-LABEL: @sink_ubfe_i64_low32( 206; OPT: entry: 207; OPT-NOT: lshr 208; OPT: br i1 209 210; OPT: bb0: 211; OPT: %0 = lshr i64 %arg1, 15 212; OPT-NEXT: %val0 = and i64 %0, 255 213 214; OPT: bb1: 215; OPT: %1 = lshr i64 %arg1, 15 216; OPT-NEXT: %val1 = and i64 %1, 127 217 218; OPT: ret: 219; OPT: store 220; OPT: ret 221 222; GCN-LABEL: {{^}}sink_ubfe_i64_low32: 223 224; GCN: s_cbranch_vccnz BB4_2 225 226; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x8000f 227 228; GCN: BB4_2: 229; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x7000f 230 231; GCN: BB4_3: 232; GCN: buffer_store_dwordx2 233define void @sink_ubfe_i64_low32(i64 addrspace(1)* %out, i64 %arg1) #0 { 234entry: 235 %shr = lshr i64 %arg1, 15 236 br i1 undef, label %bb0, label %bb1 237 238bb0: 239 %val0 = and i64 %shr, 255 240 store volatile i32 0, i32 addrspace(1)* undef 241 br label %ret 242 243bb1: 244 %val1 = and i64 %shr, 127 245 store volatile i32 0, i32 addrspace(1)* undef 246 br label %ret 247 248ret: 249 %phi = phi i64 [ %val0, %bb0 ], [ %val1, %bb1 ] 250 store i64 %phi, i64 addrspace(1)* %out 251 ret void 252} 253 254; OPT-LABEL: @sink_ubfe_i64_high32( 255; OPT: entry: 256; OPT-NOT: lshr 257; OPT: br i1 258 259; OPT: bb0: 260; OPT: %0 = lshr i64 %arg1, 35 261; OPT-NEXT: %val0 = and i64 %0, 255 262 263; OPT: bb1: 264; OPT: %1 = lshr i64 %arg1, 35 265; OPT-NEXT: %val1 = and i64 %1, 127 266 267; OPT: ret: 268; OPT: store 269; OPT: ret 270 271; GCN-LABEL: {{^}}sink_ubfe_i64_high32: 272; GCN: s_cbranch_vccnz BB5_2 273; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x80003 274 275; GCN: BB5_2: 276; GCN: s_bfe_u32 s{{[0-9]+}}, s{{[0-9]+}}, 0x70003 277 278; GCN: BB5_3: 279; GCN: buffer_store_dwordx2 280define void @sink_ubfe_i64_high32(i64 addrspace(1)* %out, i64 %arg1) #0 { 281entry: 282 %shr = lshr i64 %arg1, 35 283 br i1 undef, label %bb0, label %bb1 284 285bb0: 286 %val0 = and i64 %shr, 255 287 store volatile i32 0, i32 addrspace(1)* undef 288 br label %ret 289 290bb1: 291 %val1 = and i64 %shr, 127 292 store volatile i32 0, i32 addrspace(1)* undef 293 br label %ret 294 295ret: 296 %phi = phi i64 [ %val0, %bb0 ], [ %val1, %bb1 ] 297 store i64 %phi, i64 addrspace(1)* %out 298 ret void 299} 300 301attributes #0 = { nounwind } 302