1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc < %s -mtriple=i686-unknown | FileCheck %s --check-prefix=X86 3 ; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s --check-prefix=X64 4 5 ; Shift i64 integers on 32-bit target 6 7 define i64 @test1(i64 %X, i8 %C) nounwind { 8 ; X86-LABEL: test1: 9 ; X86: # %bb.0: 10 ; X86-NEXT: pushl %esi 11 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 12 ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi 13 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 14 ; X86-NEXT: movl %esi, %eax 15 ; X86-NEXT: shll %cl, %eax 16 ; X86-NEXT: shldl %cl, %esi, %edx 17 ; X86-NEXT: testb $32, %cl 18 ; X86-NEXT: je .LBB0_2 19 ; X86-NEXT: # %bb.1: 20 ; X86-NEXT: movl %eax, %edx 21 ; X86-NEXT: xorl %eax, %eax 22 ; X86-NEXT: .LBB0_2: 23 ; X86-NEXT: popl %esi 24 ; X86-NEXT: retl 25 ; 26 ; X64-LABEL: test1: 27 ; X64: # %bb.0: 28 ; X64-NEXT: movl %esi, %ecx 29 ; X64-NEXT: shlq %cl, %rdi 30 ; X64-NEXT: movq %rdi, %rax 31 ; X64-NEXT: retq 32 %shift.upgrd.1 = zext i8 %C to i64 ; <i64> [#uses=1] 33 %Y = shl i64 %X, %shift.upgrd.1 ; <i64> [#uses=1] 34 ret i64 %Y 35 } 36 37 define i64 @test2(i64 %X, i8 %C) nounwind { 38 ; X86-LABEL: test2: 39 ; X86: # %bb.0: 40 ; X86-NEXT: pushl %esi 41 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 42 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 43 ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi 44 ; X86-NEXT: movl %esi, %edx 45 ; X86-NEXT: sarl %cl, %edx 46 ; X86-NEXT: shrdl %cl, %esi, %eax 47 ; X86-NEXT: testb $32, %cl 48 ; X86-NEXT: je .LBB1_2 49 ; X86-NEXT: # %bb.1: 50 ; X86-NEXT: sarl $31, %esi 51 ; X86-NEXT: movl %edx, %eax 52 ; X86-NEXT: movl %esi, %edx 53 ; X86-NEXT: .LBB1_2: 54 ; X86-NEXT: popl %esi 55 ; X86-NEXT: retl 56 ; 57 ; X64-LABEL: test2: 58 ; X64: # %bb.0: 59 ; X64-NEXT: movl %esi, %ecx 60 ; X64-NEXT: sarq %cl, %rdi 61 ; X64-NEXT: movq %rdi, %rax 62 ; X64-NEXT: retq 63 %shift.upgrd.2 = zext i8 %C to i64 ; <i64> [#uses=1] 64 %Y = ashr i64 %X, %shift.upgrd.2 ; <i64> [#uses=1] 65 ret i64 %Y 66 } 67 68 define i64 @test3(i64 %X, i8 %C) nounwind { 69 ; X86-LABEL: test3: 70 ; X86: # %bb.0: 71 ; X86-NEXT: pushl %esi 72 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 73 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 74 ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi 75 ; X86-NEXT: movl %esi, %edx 76 ; X86-NEXT: shrl %cl, %edx 77 ; X86-NEXT: shrdl %cl, %esi, %eax 78 ; X86-NEXT: testb $32, %cl 79 ; X86-NEXT: je .LBB2_2 80 ; X86-NEXT: # %bb.1: 81 ; X86-NEXT: movl %edx, %eax 82 ; X86-NEXT: xorl %edx, %edx 83 ; X86-NEXT: .LBB2_2: 84 ; X86-NEXT: popl %esi 85 ; X86-NEXT: retl 86 ; 87 ; X64-LABEL: test3: 88 ; X64: # %bb.0: 89 ; X64-NEXT: movl %esi, %ecx 90 ; X64-NEXT: shrq %cl, %rdi 91 ; X64-NEXT: movq %rdi, %rax 92 ; X64-NEXT: retq 93 %shift.upgrd.3 = zext i8 %C to i64 ; <i64> [#uses=1] 94 %Y = lshr i64 %X, %shift.upgrd.3 ; <i64> [#uses=1] 95 ret i64 %Y 96 } 97 98 ; Combine 2xi32/2xi16 shifts into SHLD 99 100 define i32 @test4(i32 %A, i32 %B, i8 %C) nounwind { 101 ; X86-LABEL: test4: 102 ; X86: # %bb.0: 103 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 104 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 105 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 106 ; X86-NEXT: shldl %cl, %edx, %eax 107 ; X86-NEXT: retl 108 ; 109 ; X64-LABEL: test4: 110 ; X64: # %bb.0: 111 ; X64-NEXT: movl %edx, %ecx 112 ; X64-NEXT: shldl %cl, %esi, %edi 113 ; X64-NEXT: movl %edi, %eax 114 ; X64-NEXT: retq 115 %shift.upgrd.4 = zext i8 %C to i32 ; <i32> [#uses=1] 116 %X = shl i32 %A, %shift.upgrd.4 ; <i32> [#uses=1] 117 %Cv = sub i8 32, %C ; <i8> [#uses=1] 118 %shift.upgrd.5 = zext i8 %Cv to i32 ; <i32> [#uses=1] 119 %Y = lshr i32 %B, %shift.upgrd.5 ; <i32> [#uses=1] 120 %Z = or i32 %Y, %X ; <i32> [#uses=1] 121 ret i32 %Z 122 } 123 124 define i16 @test5(i16 %A, i16 %B, i8 %C) nounwind { 125 ; X86-LABEL: test5: 126 ; X86: # %bb.0: 127 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 128 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %edx 129 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax 130 ; X86-NEXT: shldw %cl, %dx, %ax 131 ; X86-NEXT: retl 132 ; 133 ; X64-LABEL: test5: 134 ; X64: # %bb.0: 135 ; X64-NEXT: movl %edx, %ecx 136 ; X64-NEXT: shldw %cl, %si, %di 137 ; X64-NEXT: movl %edi, %eax 138 ; X64-NEXT: retq 139 %shift.upgrd.6 = zext i8 %C to i16 ; <i16> [#uses=1] 140 %X = shl i16 %A, %shift.upgrd.6 ; <i16> [#uses=1] 141 %Cv = sub i8 16, %C ; <i8> [#uses=1] 142 %shift.upgrd.7 = zext i8 %Cv to i16 ; <i16> [#uses=1] 143 %Y = lshr i16 %B, %shift.upgrd.7 ; <i16> [#uses=1] 144 %Z = or i16 %Y, %X ; <i16> [#uses=1] 145 ret i16 %Z 146 } 147 148 ; Combine 2xi32/2xi16 shifts into SHRD 149 150 define i32 @test6(i32 %A, i32 %B, i8 %C) nounwind { 151 ; X86-LABEL: test6: 152 ; X86: # %bb.0: 153 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 154 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 155 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 156 ; X86-NEXT: shrdl %cl, %edx, %eax 157 ; X86-NEXT: retl 158 ; 159 ; X64-LABEL: test6: 160 ; X64: # %bb.0: 161 ; X64-NEXT: movl %edx, %ecx 162 ; X64-NEXT: shrdl %cl, %esi, %edi 163 ; X64-NEXT: movl %edi, %eax 164 ; X64-NEXT: retq 165 %shift.upgrd.4 = zext i8 %C to i32 ; <i32> [#uses=1] 166 %X = lshr i32 %A, %shift.upgrd.4 ; <i32> [#uses=1] 167 %Cv = sub i8 32, %C ; <i8> [#uses=1] 168 %shift.upgrd.5 = zext i8 %Cv to i32 ; <i32> [#uses=1] 169 %Y = shl i32 %B, %shift.upgrd.5 ; <i32> [#uses=1] 170 %Z = or i32 %Y, %X ; <i32> [#uses=1] 171 ret i32 %Z 172 } 173 174 define i16 @test7(i16 %A, i16 %B, i8 %C) nounwind { 175 ; X86-LABEL: test7: 176 ; X86: # %bb.0: 177 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 178 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %edx 179 ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax 180 ; X86-NEXT: shrdw %cl, %dx, %ax 181 ; X86-NEXT: retl 182 ; 183 ; X64-LABEL: test7: 184 ; X64: # %bb.0: 185 ; X64-NEXT: movl %edx, %ecx 186 ; X64-NEXT: shrdw %cl, %si, %di 187 ; X64-NEXT: movl %edi, %eax 188 ; X64-NEXT: retq 189 %shift.upgrd.6 = zext i8 %C to i16 ; <i16> [#uses=1] 190 %X = lshr i16 %A, %shift.upgrd.6 ; <i16> [#uses=1] 191 %Cv = sub i8 16, %C ; <i8> [#uses=1] 192 %shift.upgrd.7 = zext i8 %Cv to i16 ; <i16> [#uses=1] 193 %Y = shl i16 %B, %shift.upgrd.7 ; <i16> [#uses=1] 194 %Z = or i16 %Y, %X ; <i16> [#uses=1] 195 ret i16 %Z 196 } 197 198 ; Shift i64 integers on 32-bit target by shift value less then 32 (PR14593) 199 200 define i64 @test8(i64 %val, i32 %bits) nounwind { 201 ; X86-LABEL: test8: 202 ; X86: # %bb.0: 203 ; X86-NEXT: pushl %esi 204 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 205 ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi 206 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 207 ; X86-NEXT: movl %esi, %eax 208 ; X86-NEXT: shll %cl, %eax 209 ; X86-NEXT: shldl %cl, %esi, %edx 210 ; X86-NEXT: popl %esi 211 ; X86-NEXT: retl 212 ; 213 ; X64-LABEL: test8: 214 ; X64: # %bb.0: 215 ; X64-NEXT: andb $31, %sil 216 ; X64-NEXT: movl %esi, %ecx 217 ; X64-NEXT: shlq %cl, %rdi 218 ; X64-NEXT: movq %rdi, %rax 219 ; X64-NEXT: retq 220 %and = and i32 %bits, 31 221 %sh_prom = zext i32 %and to i64 222 %shl = shl i64 %val, %sh_prom 223 ret i64 %shl 224 } 225 226 define i64 @test9(i64 %val, i32 %bits) nounwind { 227 ; X86-LABEL: test9: 228 ; X86: # %bb.0: 229 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 230 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 231 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 232 ; X86-NEXT: shrdl %cl, %edx, %eax 233 ; X86-NEXT: sarl %cl, %edx 234 ; X86-NEXT: retl 235 ; 236 ; X64-LABEL: test9: 237 ; X64: # %bb.0: 238 ; X64-NEXT: andb $31, %sil 239 ; X64-NEXT: movl %esi, %ecx 240 ; X64-NEXT: sarq %cl, %rdi 241 ; X64-NEXT: movq %rdi, %rax 242 ; X64-NEXT: retq 243 %and = and i32 %bits, 31 244 %sh_prom = zext i32 %and to i64 245 %ashr = ashr i64 %val, %sh_prom 246 ret i64 %ashr 247 } 248 249 define i64 @test10(i64 %val, i32 %bits) nounwind { 250 ; X86-LABEL: test10: 251 ; X86: # %bb.0: 252 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 253 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 254 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 255 ; X86-NEXT: shrdl %cl, %edx, %eax 256 ; X86-NEXT: shrl %cl, %edx 257 ; X86-NEXT: retl 258 ; 259 ; X64-LABEL: test10: 260 ; X64: # %bb.0: 261 ; X64-NEXT: andb $31, %sil 262 ; X64-NEXT: movl %esi, %ecx 263 ; X64-NEXT: shrq %cl, %rdi 264 ; X64-NEXT: movq %rdi, %rax 265 ; X64-NEXT: retq 266 %and = and i32 %bits, 31 267 %sh_prom = zext i32 %and to i64 268 %lshr = lshr i64 %val, %sh_prom 269 ret i64 %lshr 270 } 271 272 ; SHLD/SHRD manual shifts 273 274 define i32 @test11(i32 %hi, i32 %lo, i32 %bits) nounwind { 275 ; X86-LABEL: test11: 276 ; X86: # %bb.0: 277 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 278 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 279 ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 280 ; X86-NEXT: andl $31, %ecx 281 ; X86-NEXT: # kill: def $cl killed $cl killed $ecx 282 ; X86-NEXT: shldl %cl, %edx, %eax 283 ; X86-NEXT: retl 284 ; 285 ; X64-LABEL: test11: 286 ; X64: # %bb.0: 287 ; X64-NEXT: andl $31, %edx 288 ; X64-NEXT: movl %edx, %ecx 289 ; X64-NEXT: shldl %cl, %esi, %edi 290 ; X64-NEXT: movl %edi, %eax 291 ; X64-NEXT: retq 292 %and = and i32 %bits, 31 293 %and32 = sub i32 32, %and 294 %sh_lo = lshr i32 %lo, %and32 295 %sh_hi = shl i32 %hi, %and 296 %sh = or i32 %sh_lo, %sh_hi 297 ret i32 %sh 298 } 299 300 define i32 @test12(i32 %hi, i32 %lo, i32 %bits) nounwind { 301 ; X86-LABEL: test12: 302 ; X86: # %bb.0: 303 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 304 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 305 ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 306 ; X86-NEXT: andl $31, %ecx 307 ; X86-NEXT: # kill: def $cl killed $cl killed $ecx 308 ; X86-NEXT: shrdl %cl, %edx, %eax 309 ; X86-NEXT: retl 310 ; 311 ; X64-LABEL: test12: 312 ; X64: # %bb.0: 313 ; X64-NEXT: andl $31, %edx 314 ; X64-NEXT: movl %edx, %ecx 315 ; X64-NEXT: shrdl %cl, %edi, %esi 316 ; X64-NEXT: movl %esi, %eax 317 ; X64-NEXT: retq 318 %and = and i32 %bits, 31 319 %and32 = sub i32 32, %and 320 %sh_lo = shl i32 %hi, %and32 321 %sh_hi = lshr i32 %lo, %and 322 %sh = or i32 %sh_lo, %sh_hi 323 ret i32 %sh 324 } 325 326 define i32 @test13(i32 %hi, i32 %lo, i32 %bits) nounwind { 327 ; X86-LABEL: test13: 328 ; X86: # %bb.0: 329 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 330 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 331 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 332 ; X86-NEXT: shldl %cl, %edx, %eax 333 ; X86-NEXT: retl 334 ; 335 ; X64-LABEL: test13: 336 ; X64: # %bb.0: 337 ; X64-NEXT: movl %edx, %ecx 338 ; X64-NEXT: shldl %cl, %esi, %edi 339 ; X64-NEXT: movl %edi, %eax 340 ; X64-NEXT: retq 341 %bits32 = sub i32 32, %bits 342 %sh_lo = lshr i32 %lo, %bits32 343 %sh_hi = shl i32 %hi, %bits 344 %sh = or i32 %sh_lo, %sh_hi 345 ret i32 %sh 346 } 347 348 define i32 @test14(i32 %hi, i32 %lo, i32 %bits) nounwind { 349 ; X86-LABEL: test14: 350 ; X86: # %bb.0: 351 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 352 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 353 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 354 ; X86-NEXT: shrdl %cl, %edx, %eax 355 ; X86-NEXT: retl 356 ; 357 ; X64-LABEL: test14: 358 ; X64: # %bb.0: 359 ; X64-NEXT: movl %edx, %ecx 360 ; X64-NEXT: shrdl %cl, %edi, %esi 361 ; X64-NEXT: movl %esi, %eax 362 ; X64-NEXT: retq 363 %bits32 = sub i32 32, %bits 364 %sh_lo = shl i32 %hi, %bits32 365 %sh_hi = lshr i32 %lo, %bits 366 %sh = or i32 %sh_lo, %sh_hi 367 ret i32 %sh 368 } 369 370 define i32 @test15(i32 %hi, i32 %lo, i32 %bits) nounwind { 371 ; X86-LABEL: test15: 372 ; X86: # %bb.0: 373 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 374 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 375 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 376 ; X86-NEXT: shldl %cl, %edx, %eax 377 ; X86-NEXT: retl 378 ; 379 ; X64-LABEL: test15: 380 ; X64: # %bb.0: 381 ; X64-NEXT: movl %edx, %ecx 382 ; X64-NEXT: shldl %cl, %esi, %edi 383 ; X64-NEXT: movl %edi, %eax 384 ; X64-NEXT: retq 385 %bits32 = xor i32 %bits, 31 386 %lo2 = lshr i32 %lo, 1 387 %sh_lo = lshr i32 %lo2, %bits32 388 %sh_hi = shl i32 %hi, %bits 389 %sh = or i32 %sh_lo, %sh_hi 390 ret i32 %sh 391 } 392 393 define i32 @test16(i32 %hi, i32 %lo, i32 %bits) nounwind { 394 ; X86-LABEL: test16: 395 ; X86: # %bb.0: 396 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 397 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 398 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 399 ; X86-NEXT: shrdl %cl, %edx, %eax 400 ; X86-NEXT: retl 401 ; 402 ; X64-LABEL: test16: 403 ; X64: # %bb.0: 404 ; X64-NEXT: movl %edx, %ecx 405 ; X64-NEXT: shrdl %cl, %esi, %edi 406 ; X64-NEXT: movl %edi, %eax 407 ; X64-NEXT: retq 408 %bits32 = xor i32 %bits, 31 409 %lo2 = shl i32 %lo, 1 410 %sh_lo = shl i32 %lo2, %bits32 411 %sh_hi = lshr i32 %hi, %bits 412 %sh = or i32 %sh_lo, %sh_hi 413 ret i32 %sh 414 } 415 416 define i32 @test17(i32 %hi, i32 %lo, i32 %bits) nounwind { 417 ; X86-LABEL: test17: 418 ; X86: # %bb.0: 419 ; X86-NEXT: movb {{[0-9]+}}(%esp), %cl 420 ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 421 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 422 ; X86-NEXT: shrdl %cl, %edx, %eax 423 ; X86-NEXT: retl 424 ; 425 ; X64-LABEL: test17: 426 ; X64: # %bb.0: 427 ; X64-NEXT: movl %edx, %ecx 428 ; X64-NEXT: shrdl %cl, %esi, %edi 429 ; X64-NEXT: movl %edi, %eax 430 ; X64-NEXT: retq 431 %bits32 = xor i32 %bits, 31 432 %lo2 = add i32 %lo, %lo 433 %sh_lo = shl i32 %lo2, %bits32 434 %sh_hi = lshr i32 %hi, %bits 435 %sh = or i32 %sh_lo, %sh_hi 436 ret i32 %sh 437 } 438