548 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=i686-unknown | FileCheck %s --check-prefix=X863; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s --check-prefix=X644 5; Shift i64 integers on 32-bit target6 7define i64 @test1(i64 %X, i8 %C) nounwind {8; X86-LABEL: test1:9; X86: # %bb.0:10; X86-NEXT: pushl %esi11; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx12; X86-NEXT: movl {{[0-9]+}}(%esp), %esi13; X86-NEXT: movl {{[0-9]+}}(%esp), %edx14; X86-NEXT: movl %esi, %eax15; X86-NEXT: shll %cl, %eax16; X86-NEXT: shldl %cl, %esi, %edx17; X86-NEXT: testb $32, %cl18; X86-NEXT: je .LBB0_219; X86-NEXT: # %bb.1:20; X86-NEXT: movl %eax, %edx21; X86-NEXT: xorl %eax, %eax22; X86-NEXT: .LBB0_2:23; X86-NEXT: popl %esi24; X86-NEXT: retl25;26; X64-LABEL: test1:27; X64: # %bb.0:28; X64-NEXT: movl %esi, %ecx29; X64-NEXT: movq %rdi, %rax30; X64-NEXT: # kill: def $cl killed $cl killed $ecx31; X64-NEXT: shlq %cl, %rax32; X64-NEXT: retq33 %shift.upgrd.1 = zext i8 %C to i64 ; <i64> [#uses=1]34 %Y = shl i64 %X, %shift.upgrd.1 ; <i64> [#uses=1]35 ret i64 %Y36}37 38define i64 @test2(i64 %X, i8 %C) nounwind {39; X86-LABEL: test2:40; X86: # %bb.0:41; X86-NEXT: pushl %esi42; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx43; X86-NEXT: movl {{[0-9]+}}(%esp), %eax44; X86-NEXT: movl {{[0-9]+}}(%esp), %esi45; X86-NEXT: movl %esi, %edx46; X86-NEXT: sarl %cl, %edx47; X86-NEXT: shrdl %cl, %esi, %eax48; X86-NEXT: testb $32, %cl49; X86-NEXT: je .LBB1_250; X86-NEXT: # %bb.1:51; X86-NEXT: sarl $31, %esi52; X86-NEXT: movl %edx, %eax53; X86-NEXT: movl %esi, %edx54; X86-NEXT: .LBB1_2:55; X86-NEXT: popl %esi56; X86-NEXT: retl57;58; X64-LABEL: test2:59; X64: # %bb.0:60; X64-NEXT: movl %esi, %ecx61; X64-NEXT: movq %rdi, %rax62; X64-NEXT: # kill: def $cl killed $cl killed $ecx63; X64-NEXT: sarq %cl, %rax64; X64-NEXT: retq65 %shift.upgrd.2 = zext i8 %C to i64 ; <i64> [#uses=1]66 %Y = ashr i64 %X, %shift.upgrd.2 ; <i64> [#uses=1]67 ret i64 %Y68}69 70define i64 @test3(i64 %X, i8 %C) nounwind {71; X86-LABEL: test3:72; X86: # %bb.0:73; X86-NEXT: pushl %esi74; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx75; X86-NEXT: movl {{[0-9]+}}(%esp), %eax76; X86-NEXT: movl {{[0-9]+}}(%esp), %esi77; X86-NEXT: movl %esi, %edx78; X86-NEXT: shrl %cl, %edx79; X86-NEXT: shrdl %cl, %esi, %eax80; X86-NEXT: testb $32, %cl81; X86-NEXT: je .LBB2_282; X86-NEXT: # %bb.1:83; X86-NEXT: movl %edx, %eax84; X86-NEXT: xorl %edx, %edx85; X86-NEXT: .LBB2_2:86; X86-NEXT: popl %esi87; X86-NEXT: retl88;89; X64-LABEL: test3:90; X64: # %bb.0:91; X64-NEXT: movl %esi, %ecx92; X64-NEXT: movq %rdi, %rax93; X64-NEXT: # kill: def $cl killed $cl killed $ecx94; X64-NEXT: shrq %cl, %rax95; X64-NEXT: retq96 %shift.upgrd.3 = zext i8 %C to i64 ; <i64> [#uses=1]97 %Y = lshr i64 %X, %shift.upgrd.3 ; <i64> [#uses=1]98 ret i64 %Y99}100 101; Combine 2xi32/2xi16 shifts into SHLD102 103define i32 @test4(i32 %A, i32 %B, i8 %C) nounwind {104; X86-LABEL: test4:105; X86: # %bb.0:106; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx107; X86-NEXT: movl {{[0-9]+}}(%esp), %edx108; X86-NEXT: movl {{[0-9]+}}(%esp), %eax109; X86-NEXT: shldl %cl, %edx, %eax110; X86-NEXT: retl111;112; X64-LABEL: test4:113; X64: # %bb.0:114; X64-NEXT: movl %edx, %ecx115; X64-NEXT: movl %edi, %eax116; X64-NEXT: # kill: def $cl killed $cl killed $ecx117; X64-NEXT: shldl %cl, %esi, %eax118; X64-NEXT: retq119 %shift.upgrd.4 = zext i8 %C to i32 ; <i32> [#uses=1]120 %X = shl i32 %A, %shift.upgrd.4 ; <i32> [#uses=1]121 %Cv = sub i8 32, %C ; <i8> [#uses=1]122 %shift.upgrd.5 = zext i8 %Cv to i32 ; <i32> [#uses=1]123 %Y = lshr i32 %B, %shift.upgrd.5 ; <i32> [#uses=1]124 %Z = or i32 %Y, %X ; <i32> [#uses=1]125 ret i32 %Z126}127 128define i16 @test5(i16 %A, i16 %B, i8 %C) nounwind {129; X86-LABEL: test5:130; X86: # %bb.0:131; X86-NEXT: movzwl {{[0-9]+}}(%esp), %edx132; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax133; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx134; X86-NEXT: andb $15, %cl135; X86-NEXT: shldw %cl, %dx, %ax136; X86-NEXT: retl137;138; X64-LABEL: test5:139; X64: # %bb.0:140; X64-NEXT: movl %edx, %ecx141; X64-NEXT: movl %edi, %eax142; X64-NEXT: andb $15, %cl143; X64-NEXT: # kill: def $cl killed $cl killed $ecx144; X64-NEXT: shldw %cl, %si, %ax145; X64-NEXT: # kill: def $ax killed $ax killed $eax146; X64-NEXT: retq147 %shift.upgrd.6 = zext i8 %C to i16 ; <i16> [#uses=1]148 %X = shl i16 %A, %shift.upgrd.6 ; <i16> [#uses=1]149 %Cv = sub i8 16, %C ; <i8> [#uses=1]150 %shift.upgrd.7 = zext i8 %Cv to i16 ; <i16> [#uses=1]151 %Y = lshr i16 %B, %shift.upgrd.7 ; <i16> [#uses=1]152 %Z = or i16 %Y, %X ; <i16> [#uses=1]153 ret i16 %Z154}155 156; Combine 2xi32/2xi16 shifts into SHRD157 158define i32 @test6(i32 %A, i32 %B, i8 %C) nounwind {159; X86-LABEL: test6:160; X86: # %bb.0:161; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx162; X86-NEXT: movl {{[0-9]+}}(%esp), %edx163; X86-NEXT: movl {{[0-9]+}}(%esp), %eax164; X86-NEXT: shrdl %cl, %edx, %eax165; X86-NEXT: retl166;167; X64-LABEL: test6:168; X64: # %bb.0:169; X64-NEXT: movl %edx, %ecx170; X64-NEXT: movl %edi, %eax171; X64-NEXT: # kill: def $cl killed $cl killed $ecx172; X64-NEXT: shrdl %cl, %esi, %eax173; X64-NEXT: retq174 %shift.upgrd.4 = zext i8 %C to i32 ; <i32> [#uses=1]175 %X = lshr i32 %A, %shift.upgrd.4 ; <i32> [#uses=1]176 %Cv = sub i8 32, %C ; <i8> [#uses=1]177 %shift.upgrd.5 = zext i8 %Cv to i32 ; <i32> [#uses=1]178 %Y = shl i32 %B, %shift.upgrd.5 ; <i32> [#uses=1]179 %Z = or i32 %Y, %X ; <i32> [#uses=1]180 ret i32 %Z181}182 183define i16 @test7(i16 %A, i16 %B, i8 %C) nounwind {184; X86-LABEL: test7:185; X86: # %bb.0:186; X86-NEXT: movzwl {{[0-9]+}}(%esp), %edx187; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax188; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx189; X86-NEXT: andb $15, %cl190; X86-NEXT: shrdw %cl, %dx, %ax191; X86-NEXT: retl192;193; X64-LABEL: test7:194; X64: # %bb.0:195; X64-NEXT: movl %edx, %ecx196; X64-NEXT: movl %edi, %eax197; X64-NEXT: andb $15, %cl198; X64-NEXT: # kill: def $cl killed $cl killed $ecx199; X64-NEXT: shrdw %cl, %si, %ax200; X64-NEXT: # kill: def $ax killed $ax killed $eax201; X64-NEXT: retq202 %shift.upgrd.6 = zext i8 %C to i16 ; <i16> [#uses=1]203 %X = lshr i16 %A, %shift.upgrd.6 ; <i16> [#uses=1]204 %Cv = sub i8 16, %C ; <i8> [#uses=1]205 %shift.upgrd.7 = zext i8 %Cv to i16 ; <i16> [#uses=1]206 %Y = shl i16 %B, %shift.upgrd.7 ; <i16> [#uses=1]207 %Z = or i16 %Y, %X ; <i16> [#uses=1]208 ret i16 %Z209}210 211; Shift i64 integers on 32-bit target by shift value less then 32 (PR14593)212 213define i64 @test8(i64 %val, i32 %bits) nounwind {214; X86-LABEL: test8:215; X86: # %bb.0:216; X86-NEXT: pushl %esi217; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx218; X86-NEXT: movl {{[0-9]+}}(%esp), %esi219; X86-NEXT: movl {{[0-9]+}}(%esp), %edx220; X86-NEXT: movl %esi, %eax221; X86-NEXT: shll %cl, %eax222; X86-NEXT: shldl %cl, %esi, %edx223; X86-NEXT: popl %esi224; X86-NEXT: retl225;226; X64-LABEL: test8:227; X64: # %bb.0:228; X64-NEXT: movl %esi, %ecx229; X64-NEXT: movq %rdi, %rax230; X64-NEXT: andb $31, %cl231; X64-NEXT: # kill: def $cl killed $cl killed $ecx232; X64-NEXT: shlq %cl, %rax233; X64-NEXT: retq234 %and = and i32 %bits, 31235 %sh_prom = zext i32 %and to i64236 %shl = shl i64 %val, %sh_prom237 ret i64 %shl238}239 240define i64 @test9(i64 %val, i32 %bits) nounwind {241; X86-LABEL: test9:242; X86: # %bb.0:243; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx244; X86-NEXT: movl {{[0-9]+}}(%esp), %eax245; X86-NEXT: movl {{[0-9]+}}(%esp), %edx246; X86-NEXT: shrdl %cl, %edx, %eax247; X86-NEXT: sarl %cl, %edx248; X86-NEXT: retl249;250; X64-LABEL: test9:251; X64: # %bb.0:252; X64-NEXT: movl %esi, %ecx253; X64-NEXT: movq %rdi, %rax254; X64-NEXT: andb $31, %cl255; X64-NEXT: # kill: def $cl killed $cl killed $ecx256; X64-NEXT: sarq %cl, %rax257; X64-NEXT: retq258 %and = and i32 %bits, 31259 %sh_prom = zext i32 %and to i64260 %ashr = ashr i64 %val, %sh_prom261 ret i64 %ashr262}263 264define i64 @test10(i64 %val, i32 %bits) nounwind {265; X86-LABEL: test10:266; X86: # %bb.0:267; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx268; X86-NEXT: movl {{[0-9]+}}(%esp), %eax269; X86-NEXT: movl {{[0-9]+}}(%esp), %edx270; X86-NEXT: shrdl %cl, %edx, %eax271; X86-NEXT: shrl %cl, %edx272; X86-NEXT: retl273;274; X64-LABEL: test10:275; X64: # %bb.0:276; X64-NEXT: movl %esi, %ecx277; X64-NEXT: movq %rdi, %rax278; X64-NEXT: andb $31, %cl279; X64-NEXT: # kill: def $cl killed $cl killed $ecx280; X64-NEXT: shrq %cl, %rax281; X64-NEXT: retq282 %and = and i32 %bits, 31283 %sh_prom = zext i32 %and to i64284 %lshr = lshr i64 %val, %sh_prom285 ret i64 %lshr286}287 288; SHLD/SHRD manual shifts289 290define i32 @test11(i32 %hi, i32 %lo, i32 %bits) nounwind {291; X86-LABEL: test11:292; X86: # %bb.0:293; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx294; X86-NEXT: movl {{[0-9]+}}(%esp), %edx295; X86-NEXT: movl {{[0-9]+}}(%esp), %eax296; X86-NEXT: shldl %cl, %edx, %eax297; X86-NEXT: retl298;299; X64-LABEL: test11:300; X64: # %bb.0:301; X64-NEXT: movl %edx, %ecx302; X64-NEXT: movl %edi, %eax303; X64-NEXT: # kill: def $cl killed $cl killed $ecx304; X64-NEXT: shldl %cl, %esi, %eax305; X64-NEXT: retq306 %and = and i32 %bits, 31307 %and32 = sub i32 32, %and308 %sh_lo = lshr i32 %lo, %and32309 %sh_hi = shl i32 %hi, %and310 %sh = or i32 %sh_lo, %sh_hi311 ret i32 %sh312}313 314define i32 @test12(i32 %hi, i32 %lo, i32 %bits) nounwind {315; X86-LABEL: test12:316; X86: # %bb.0:317; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx318; X86-NEXT: movl {{[0-9]+}}(%esp), %edx319; X86-NEXT: movl {{[0-9]+}}(%esp), %eax320; X86-NEXT: shrdl %cl, %edx, %eax321; X86-NEXT: retl322;323; X64-LABEL: test12:324; X64: # %bb.0:325; X64-NEXT: movl %edx, %ecx326; X64-NEXT: movl %esi, %eax327; X64-NEXT: # kill: def $cl killed $cl killed $ecx328; X64-NEXT: shrdl %cl, %edi, %eax329; X64-NEXT: retq330 %and = and i32 %bits, 31331 %and32 = sub i32 32, %and332 %sh_lo = shl i32 %hi, %and32333 %sh_hi = lshr i32 %lo, %and334 %sh = or i32 %sh_lo, %sh_hi335 ret i32 %sh336}337 338define i32 @test13(i32 %hi, i32 %lo, i32 %bits) nounwind {339; X86-LABEL: test13:340; X86: # %bb.0:341; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx342; X86-NEXT: movl {{[0-9]+}}(%esp), %edx343; X86-NEXT: movl {{[0-9]+}}(%esp), %eax344; X86-NEXT: shldl %cl, %edx, %eax345; X86-NEXT: retl346;347; X64-LABEL: test13:348; X64: # %bb.0:349; X64-NEXT: movl %edx, %ecx350; X64-NEXT: movl %edi, %eax351; X64-NEXT: # kill: def $cl killed $cl killed $ecx352; X64-NEXT: shldl %cl, %esi, %eax353; X64-NEXT: retq354 %bits32 = sub i32 32, %bits355 %sh_lo = lshr i32 %lo, %bits32356 %sh_hi = shl i32 %hi, %bits357 %sh = or i32 %sh_lo, %sh_hi358 ret i32 %sh359}360 361define i32 @test14(i32 %hi, i32 %lo, i32 %bits) nounwind {362; X86-LABEL: test14:363; X86: # %bb.0:364; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx365; X86-NEXT: movl {{[0-9]+}}(%esp), %edx366; X86-NEXT: movl {{[0-9]+}}(%esp), %eax367; X86-NEXT: shrdl %cl, %edx, %eax368; X86-NEXT: retl369;370; X64-LABEL: test14:371; X64: # %bb.0:372; X64-NEXT: movl %edx, %ecx373; X64-NEXT: movl %esi, %eax374; X64-NEXT: # kill: def $cl killed $cl killed $ecx375; X64-NEXT: shrdl %cl, %edi, %eax376; X64-NEXT: retq377 %bits32 = sub i32 32, %bits378 %sh_lo = shl i32 %hi, %bits32379 %sh_hi = lshr i32 %lo, %bits380 %sh = or i32 %sh_lo, %sh_hi381 ret i32 %sh382}383 384define i32 @test15(i32 %hi, i32 %lo, i32 %bits) nounwind {385; X86-LABEL: test15:386; X86: # %bb.0:387; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx388; X86-NEXT: movl {{[0-9]+}}(%esp), %edx389; X86-NEXT: movl {{[0-9]+}}(%esp), %eax390; X86-NEXT: shldl %cl, %edx, %eax391; X86-NEXT: retl392;393; X64-LABEL: test15:394; X64: # %bb.0:395; X64-NEXT: movl %edx, %ecx396; X64-NEXT: movl %edi, %eax397; X64-NEXT: # kill: def $cl killed $cl killed $ecx398; X64-NEXT: shldl %cl, %esi, %eax399; X64-NEXT: retq400 %bits32 = xor i32 %bits, 31401 %lo2 = lshr i32 %lo, 1402 %sh_lo = lshr i32 %lo2, %bits32403 %sh_hi = shl i32 %hi, %bits404 %sh = or i32 %sh_lo, %sh_hi405 ret i32 %sh406}407 408define i32 @test16(i32 %hi, i32 %lo, i32 %bits) nounwind {409; X86-LABEL: test16:410; X86: # %bb.0:411; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx412; X86-NEXT: movl {{[0-9]+}}(%esp), %edx413; X86-NEXT: movl {{[0-9]+}}(%esp), %eax414; X86-NEXT: shrdl %cl, %edx, %eax415; X86-NEXT: retl416;417; X64-LABEL: test16:418; X64: # %bb.0:419; X64-NEXT: movl %edx, %ecx420; X64-NEXT: movl %edi, %eax421; X64-NEXT: # kill: def $cl killed $cl killed $ecx422; X64-NEXT: shrdl %cl, %esi, %eax423; X64-NEXT: retq424 %bits32 = xor i32 %bits, 31425 %lo2 = shl i32 %lo, 1426 %sh_lo = shl i32 %lo2, %bits32427 %sh_hi = lshr i32 %hi, %bits428 %sh = or i32 %sh_lo, %sh_hi429 ret i32 %sh430}431 432define i32 @test17(i32 %hi, i32 %lo, i32 %bits) nounwind {433; X86-LABEL: test17:434; X86: # %bb.0:435; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx436; X86-NEXT: movl {{[0-9]+}}(%esp), %edx437; X86-NEXT: movl {{[0-9]+}}(%esp), %eax438; X86-NEXT: shrdl %cl, %edx, %eax439; X86-NEXT: retl440;441; X64-LABEL: test17:442; X64: # %bb.0:443; X64-NEXT: movl %edx, %ecx444; X64-NEXT: movl %edi, %eax445; X64-NEXT: # kill: def $cl killed $cl killed $ecx446; X64-NEXT: shrdl %cl, %esi, %eax447; X64-NEXT: retq448 %bits32 = xor i32 %bits, 31449 %lo2 = add i32 %lo, %lo450 %sh_lo = shl i32 %lo2, %bits32451 %sh_hi = lshr i32 %hi, %bits452 %sh = or i32 %sh_lo, %sh_hi453 ret i32 %sh454}455 456define i32 @test18(i32 %hi, i32 %lo, i32 %bits) nounwind {457; X86-LABEL: test18:458; X86: # %bb.0:459; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx460; X86-NEXT: movl {{[0-9]+}}(%esp), %edx461; X86-NEXT: movl {{[0-9]+}}(%esp), %eax462; X86-NEXT: shldl %cl, %edx, %eax463; X86-NEXT: retl464;465; X64-LABEL: test18:466; X64: # %bb.0:467; X64-NEXT: movl %edx, %ecx468; X64-NEXT: movl %edi, %eax469; X64-NEXT: # kill: def $cl killed $cl killed $ecx470; X64-NEXT: shldl %cl, %esi, %eax471; X64-NEXT: retq472 %tbits = trunc i32 %bits to i8473 %tand = and i8 %tbits, 31474 %tand64 = sub i8 32, %tand475 %and = zext i8 %tand to i32476 %and64 = zext i8 %tand64 to i32477 %sh_lo = lshr i32 %lo, %and64478 %sh_hi = shl i32 %hi, %and479 %sh = or i32 %sh_lo, %sh_hi480 ret i32 %sh481}482 483; These are not valid shld/shrd patterns. When the shift amount modulo484; the bitwidth is zero, the result should be an OR of both operands not a485; shift.486 487define i32 @not_shld_i32(i32, i32, i32) {488; X86-LABEL: not_shld_i32:489; X86: # %bb.0:490; X86-NEXT: movl {{[0-9]+}}(%esp), %eax491; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx492; X86-NEXT: movl {{[0-9]+}}(%esp), %edx493; X86-NEXT: shll %cl, %edx494; X86-NEXT: negb %cl495; X86-NEXT: shrl %cl, %eax496; X86-NEXT: orl %edx, %eax497; X86-NEXT: retl498;499; X64-LABEL: not_shld_i32:500; X64: # %bb.0:501; X64-NEXT: movl %edx, %ecx502; X64-NEXT: movl %esi, %eax503; X64-NEXT: shll %cl, %edi504; X64-NEXT: negb %cl505; X64-NEXT: # kill: def $cl killed $cl killed $ecx506; X64-NEXT: shrl %cl, %eax507; X64-NEXT: orl %edi, %eax508; X64-NEXT: retq509 %4 = and i32 %2, 31510 %5 = shl i32 %0, %4511 %6 = sub i32 0, %2512 %7 = and i32 %6, 31513 %8 = lshr i32 %1, %7514 %9 = or i32 %5, %8515 ret i32 %9516}517 518define i32 @not_shrd_i32(i32, i32, i32) {519; X86-LABEL: not_shrd_i32:520; X86: # %bb.0:521; X86-NEXT: movl {{[0-9]+}}(%esp), %eax522; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx523; X86-NEXT: movl {{[0-9]+}}(%esp), %edx524; X86-NEXT: shrl %cl, %edx525; X86-NEXT: negb %cl526; X86-NEXT: shll %cl, %eax527; X86-NEXT: orl %edx, %eax528; X86-NEXT: retl529;530; X64-LABEL: not_shrd_i32:531; X64: # %bb.0:532; X64-NEXT: movl %edx, %ecx533; X64-NEXT: movl %esi, %eax534; X64-NEXT: shrl %cl, %edi535; X64-NEXT: negb %cl536; X64-NEXT: # kill: def $cl killed $cl killed $ecx537; X64-NEXT: shll %cl, %eax538; X64-NEXT: orl %edi, %eax539; X64-NEXT: retq540 %4 = and i32 %2, 31541 %5 = lshr i32 %0, %4542 %6 = sub i32 0, %2543 %7 = and i32 %6, 31544 %8 = shl i32 %1, %7545 %9 = or i32 %5, %8546 ret i32 %9547}548