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 39 define void @sink_ubfe_i32(i32 addrspace(1)* %out, i32 %arg1) #0 { 40 entry: 41 %shr = lshr i32 %arg1, 8 42 br i1 undef, label %bb0, label %bb1 43 44 bb0: 45 %val0 = and i32 %shr, 255 46 store volatile i32 0, i32 addrspace(1)* undef 47 br label %ret 48 49 bb1: 50 %val1 = and i32 %shr, 127 51 store volatile i32 0, i32 addrspace(1)* undef 52 br label %ret 53 54 ret: 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: 79 define void @sink_sbfe_i32(i32 addrspace(1)* %out, i32 %arg1) #0 { 80 entry: 81 %shr = ashr i32 %arg1, 8 82 br i1 undef, label %bb0, label %bb1 83 84 bb0: 85 %val0 = and i32 %shr, 255 86 store volatile i32 0, i32 addrspace(1)* undef 87 br label %ret 88 89 bb1: 90 %val1 = and i32 %shr, 127 91 store volatile i32 0, i32 addrspace(1)* undef 92 br label %ret 93 94 ret: 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 131 define void @sink_ubfe_i16(i16 addrspace(1)* %out, i16 %arg1) #0 { 132 entry: 133 %shr = lshr i16 %arg1, 4 134 br i1 undef, label %bb0, label %bb1 135 136 bb0: 137 %val0 = and i16 %shr, 255 138 store volatile i16 0, i16 addrspace(1)* undef 139 br label %ret 140 141 bb1: 142 %val1 = and i16 %shr, 127 143 store volatile i16 0, i16 addrspace(1)* undef 144 br label %ret 145 146 ret: 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 184 define void @sink_ubfe_i64_span_midpoint(i64 addrspace(1)* %out, i64 %arg1) #0 { 185 entry: 186 %shr = lshr i64 %arg1, 30 187 br i1 undef, label %bb0, label %bb1 188 189 bb0: 190 %val0 = and i64 %shr, 255 191 store volatile i32 0, i32 addrspace(1)* undef 192 br label %ret 193 194 bb1: 195 %val1 = and i64 %shr, 127 196 store volatile i32 0, i32 addrspace(1)* undef 197 br label %ret 198 199 ret: 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 233 define void @sink_ubfe_i64_low32(i64 addrspace(1)* %out, i64 %arg1) #0 { 234 entry: 235 %shr = lshr i64 %arg1, 15 236 br i1 undef, label %bb0, label %bb1 237 238 bb0: 239 %val0 = and i64 %shr, 255 240 store volatile i32 0, i32 addrspace(1)* undef 241 br label %ret 242 243 bb1: 244 %val1 = and i64 %shr, 127 245 store volatile i32 0, i32 addrspace(1)* undef 246 br label %ret 247 248 ret: 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 280 define void @sink_ubfe_i64_high32(i64 addrspace(1)* %out, i64 %arg1) #0 { 281 entry: 282 %shr = lshr i64 %arg1, 35 283 br i1 undef, label %bb0, label %bb1 284 285 bb0: 286 %val0 = and i64 %shr, 255 287 store volatile i32 0, i32 addrspace(1)* undef 288 br label %ret 289 290 bb1: 291 %val1 = and i64 %shr, 127 292 store volatile i32 0, i32 addrspace(1)* undef 293 br label %ret 294 295 ret: 296 %phi = phi i64 [ %val0, %bb0 ], [ %val1, %bb1 ] 297 store i64 %phi, i64 addrspace(1)* %out 298 ret void 299 } 300 301 attributes #0 = { nounwind } 302