523 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=x86_64-- < %s | FileCheck %s3 4declare i8 @llvm.fshl.i8(i8, i8, i8)5declare i32 @llvm.fshl.i32(i32, i32, i32)6declare i16 @llvm.fshr.i16(i16, i16, i16)7declare i64 @llvm.fshr.i64(i64, i64, i64)8declare <4 x i32> @llvm.fshl.v4i32(<4 x i32>, <4 x i32>, <4 x i32>)9declare void @use16(i16)10declare void @use32(i32)11 12define i1 @rotl_eq_0(i8 %x, i8 %y) nounwind {13; CHECK-LABEL: rotl_eq_0:14; CHECK: # %bb.0:15; CHECK-NEXT: testb %dil, %dil16; CHECK-NEXT: sete %al17; CHECK-NEXT: retq18 %rot = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %y)19 %r = icmp eq i8 %rot, 020 ret i1 %r21}22 23; Extra use is ok.24 25define i1 @rotl_ne_0(i32 %x, i32 %y) nounwind {26; CHECK-LABEL: rotl_ne_0:27; CHECK: # %bb.0:28; CHECK-NEXT: pushq %rbx29; CHECK-NEXT: movl %esi, %ecx30; CHECK-NEXT: movl %edi, %ebx31; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx32; CHECK-NEXT: roll %cl, %edi33; CHECK-NEXT: callq use32@PLT34; CHECK-NEXT: testl %ebx, %ebx35; CHECK-NEXT: setne %al36; CHECK-NEXT: popq %rbx37; CHECK-NEXT: retq38 %rot = tail call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %y)39 call void @use32(i32 %rot)40 %r = icmp ne i32 %rot, 041 ret i1 %r42}43 44define i1 @rotl_eq_n1(i8 %x, i8 %y) nounwind {45; CHECK-LABEL: rotl_eq_n1:46; CHECK: # %bb.0:47; CHECK-NEXT: cmpb $-1, %dil48; CHECK-NEXT: sete %al49; CHECK-NEXT: retq50 %rot = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %y)51 %r = icmp eq i8 %rot, -152 ret i1 %r53}54 55; Vectors work too.56 57define <4 x i1> @rotl_ne_n1(<4 x i32> %x, <4 x i32> %y) nounwind {58; CHECK-LABEL: rotl_ne_n1:59; CHECK: # %bb.0:60; CHECK-NEXT: pcmpeqd %xmm1, %xmm161; CHECK-NEXT: pcmpeqd %xmm1, %xmm062; CHECK-NEXT: pxor %xmm1, %xmm063; CHECK-NEXT: retq64 %rot = tail call <4 x i32> @llvm.fshl.v4i32(<4 x i32>%x, <4 x i32> %x, <4 x i32> %y)65 %r = icmp ne <4 x i32> %rot, <i32 -1, i32 -1, i32 -1, i32 -1>66 ret <4 x i1> %r67}68 69; Undef is ok to propagate.70 71define <4 x i1> @rotl_ne_n1_undef(<4 x i32> %x, <4 x i32> %y) nounwind {72; CHECK-LABEL: rotl_ne_n1_undef:73; CHECK: # %bb.0:74; CHECK-NEXT: pcmpeqd %xmm1, %xmm175; CHECK-NEXT: pcmpeqd %xmm1, %xmm076; CHECK-NEXT: pxor %xmm1, %xmm077; CHECK-NEXT: retq78 %rot = tail call <4 x i32> @llvm.fshl.v4i32(<4 x i32>%x, <4 x i32> %x, <4 x i32> %y)79 %r = icmp ne <4 x i32> %rot, <i32 -1, i32 undef, i32 -1, i32 -1>80 ret <4 x i1> %r81}82 83define i1 @rotr_eq_0(i16 %x, i16 %y) nounwind {84; CHECK-LABEL: rotr_eq_0:85; CHECK: # %bb.0:86; CHECK-NEXT: pushq %rbx87; CHECK-NEXT: movl %esi, %ecx88; CHECK-NEXT: movl %edi, %ebx89; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx90; CHECK-NEXT: rorw %cl, %di91; CHECK-NEXT: callq use16@PLT92; CHECK-NEXT: testw %bx, %bx93; CHECK-NEXT: sete %al94; CHECK-NEXT: popq %rbx95; CHECK-NEXT: retq96 %rot = tail call i16 @llvm.fshr.i16(i16 %x, i16 %x, i16 %y)97 call void @use16(i16 %rot)98 %r = icmp eq i16 %rot, 099 ret i1 %r100}101 102define i1 @rotr_ne_0(i64 %x, i64 %y) nounwind {103; CHECK-LABEL: rotr_ne_0:104; CHECK: # %bb.0:105; CHECK-NEXT: testq %rdi, %rdi106; CHECK-NEXT: setne %al107; CHECK-NEXT: retq108 %rot = tail call i64 @llvm.fshr.i64(i64 %x, i64 %x, i64 %y)109 %r = icmp ne i64 %rot, 0110 ret i1 %r111}112 113define i1 @rotr_eq_n1(i64 %x, i64 %y) nounwind {114; CHECK-LABEL: rotr_eq_n1:115; CHECK: # %bb.0:116; CHECK-NEXT: cmpq $-1, %rdi117; CHECK-NEXT: sete %al118; CHECK-NEXT: retq119 %rot = tail call i64 @llvm.fshr.i64(i64 %x, i64 %x, i64 %y)120 %r = icmp eq i64 %rot, -1121 ret i1 %r122}123 124define i1 @rotr_ne_n1(i16 %x, i16 %y) nounwind {125; CHECK-LABEL: rotr_ne_n1:126; CHECK: # %bb.0:127; CHECK-NEXT: cmpw $-1, %di128; CHECK-NEXT: setne %al129; CHECK-NEXT: retq130 %rot = tail call i16 @llvm.fshr.i16(i16 %x, i16 %x, i16 %y)131 %r = icmp ne i16 %rot, -1132 ret i1 %r133}134 135; negative test - wrong constant value136 137define i1 @rotr_ne_1(i64 %x, i64 %y) nounwind {138; CHECK-LABEL: rotr_ne_1:139; CHECK: # %bb.0:140; CHECK-NEXT: movq %rsi, %rcx141; CHECK-NEXT: # kill: def $cl killed $cl killed $rcx142; CHECK-NEXT: rorq %cl, %rdi143; CHECK-NEXT: cmpq $1, %rdi144; CHECK-NEXT: setne %al145; CHECK-NEXT: retq146 %rot = tail call i64 @llvm.fshr.i64(i64 %x, i64 %x, i64 %y)147 %r = icmp ne i64 %rot, 1148 ret i1 %r149}150 151; negative test - wrong predicate152 153define i1 @rotr_sgt_n1(i16 %x, i16 %y) nounwind {154; CHECK-LABEL: rotr_sgt_n1:155; CHECK: # %bb.0:156; CHECK-NEXT: movl %esi, %ecx157; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx158; CHECK-NEXT: rorw %cl, %di159; CHECK-NEXT: testw %di, %di160; CHECK-NEXT: setns %al161; CHECK-NEXT: retq162 %rot = tail call i16 @llvm.fshr.i16(i16 %x, i16 %x, i16 %y)163 %r = icmp sgt i16 %rot, -1164 ret i1 %r165}166 167; negative test - must be a rotate, not general funnel shift168 169define i1 @fshl_eq_n1(i8 %x, i8 %y, i8 %z) nounwind {170; CHECK-LABEL: fshl_eq_n1:171; CHECK: # %bb.0:172; CHECK-NEXT: movl %edx, %ecx173; CHECK-NEXT: shll $8, %edi174; CHECK-NEXT: movzbl %sil, %eax175; CHECK-NEXT: orl %edi, %eax176; CHECK-NEXT: andb $7, %cl177; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx178; CHECK-NEXT: shll %cl, %eax179; CHECK-NEXT: shrl $8, %eax180; CHECK-NEXT: cmpb $-1, %al181; CHECK-NEXT: sete %al182; CHECK-NEXT: retq183 %fsh = tail call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 %z)184 %r = icmp eq i8 %fsh, -1185 ret i1 %r186}187 188define i1 @or_rotl_eq_0(i8 %x, i8 %y, i8 %z) nounwind {189; CHECK-LABEL: or_rotl_eq_0:190; CHECK: # %bb.0:191; CHECK-NEXT: orb %sil, %dil192; CHECK-NEXT: sete %al193; CHECK-NEXT: retq194 %rot = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %z)195 %or = or i8 %rot, %y196 %r = icmp eq i8 %or, 0197 ret i1 %r198}199 200define i1 @or_rotr_ne_0(i64 %x, i64 %y, i64 %z) nounwind {201; CHECK-LABEL: or_rotr_ne_0:202; CHECK: # %bb.0:203; CHECK-NEXT: orq %rsi, %rdi204; CHECK-NEXT: setne %al205; CHECK-NEXT: retq206 %rot = tail call i64 @llvm.fshr.i64(i64 %x, i64 %x, i64 %z)207 %or = or i64 %y, %rot208 %r = icmp ne i64 %or, 0209 ret i1 %r210}211 212; negative test - wrong constant213 214define i1 @or_rotl_ne_n1(i32 %x, i32 %y, i32 %z) nounwind {215; CHECK-LABEL: or_rotl_ne_n1:216; CHECK: # %bb.0:217; CHECK-NEXT: movl %edx, %ecx218; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx219; CHECK-NEXT: roll %cl, %edi220; CHECK-NEXT: orl %esi, %edi221; CHECK-NEXT: cmpl $-1, %edi222; CHECK-NEXT: setne %al223; CHECK-NEXT: retq224 %rot = tail call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %z)225 %or = or i32 %y, %rot226 %r = icmp ne i32 %or, -1227 ret i1 %r228}229 230; negative test - extra use231 232define i1 @or_rotl_ne_0_use(i32 %x, i32 %y, i32 %z) nounwind {233; CHECK-LABEL: or_rotl_ne_0_use:234; CHECK: # %bb.0:235; CHECK-NEXT: pushq %rbx236; CHECK-NEXT: movl %edx, %ecx237; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx238; CHECK-NEXT: roll %cl, %edi239; CHECK-NEXT: orl %esi, %edi240; CHECK-NEXT: setne %bl241; CHECK-NEXT: callq use32@PLT242; CHECK-NEXT: movl %ebx, %eax243; CHECK-NEXT: popq %rbx244; CHECK-NEXT: retq245 %rot = tail call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %z)246 %or = or i32 %y, %rot247 call void @use32(i32 %or)248 %r = icmp ne i32 %or, 0249 ret i1 %r250}251 252define <4 x i1> @or_rotl_ne_eq0(<4 x i32> %x, <4 x i32> %y) nounwind {253; CHECK-LABEL: or_rotl_ne_eq0:254; CHECK: # %bb.0:255; CHECK-NEXT: pxor %xmm2, %xmm2256; CHECK-NEXT: por %xmm1, %xmm0257; CHECK-NEXT: pcmpeqd %xmm2, %xmm0258; CHECK-NEXT: retq259 %rot = tail call <4 x i32> @llvm.fshl.v4i32(<4 x i32>%x, <4 x i32> %x, <4 x i32> %y)260 %or = or <4 x i32> %y, %rot261 %r = icmp eq <4 x i32> %or, <i32 0, i32 0, i32 0, i32 poison>262 ret <4 x i1> %r263}264 265define i1 @fshl_or_eq_0(i32 %x, i32 %y) {266; CHECK-LABEL: fshl_or_eq_0:267; CHECK: # %bb.0:268; CHECK-NEXT: shll $5, %esi269; CHECK-NEXT: orl %edi, %esi270; CHECK-NEXT: sete %al271; CHECK-NEXT: retq272 %or = or i32 %x, %y273 %f = call i32 @llvm.fshl.i32(i32 %or, i32 %x, i32 5)274 %r = icmp eq i32 %f, 0275 ret i1 %r276}277 278define i1 @fshl_or_commute_eq_0(i32 %x, i32 %y) {279; CHECK-LABEL: fshl_or_commute_eq_0:280; CHECK: # %bb.0:281; CHECK-NEXT: shll $5, %esi282; CHECK-NEXT: orl %edi, %esi283; CHECK-NEXT: sete %al284; CHECK-NEXT: retq285 %or = or i32 %y, %x286 %f = call i32 @llvm.fshl.i32(i32 %or, i32 %x, i32 5)287 %r = icmp eq i32 %f, 0288 ret i1 %r289}290 291define <4 x i1> @fshl_or2_eq_0(<4 x i32> %x, <4 x i32> %y) {292; CHECK-LABEL: fshl_or2_eq_0:293; CHECK: # %bb.0:294; CHECK-NEXT: pxor %xmm2, %xmm2295; CHECK-NEXT: psrld $7, %xmm1296; CHECK-NEXT: por %xmm1, %xmm0297; CHECK-NEXT: pcmpeqd %xmm2, %xmm0298; CHECK-NEXT: retq299 %or = or <4 x i32> %x, %y300 %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %or, <4 x i32> <i32 25, i32 25, i32 25, i32 25>)301 %r = icmp eq <4 x i32> %f, zeroinitializer302 ret <4 x i1> %r303}304 305define <4 x i1> @fshl_or2_commute_eq_0(<4 x i32> %x, <4 x i32> %y) {306; CHECK-LABEL: fshl_or2_commute_eq_0:307; CHECK: # %bb.0:308; CHECK-NEXT: pxor %xmm2, %xmm2309; CHECK-NEXT: psrld $7, %xmm1310; CHECK-NEXT: por %xmm1, %xmm0311; CHECK-NEXT: pcmpeqd %xmm2, %xmm0312; CHECK-NEXT: retq313 %or = or <4 x i32> %y, %x314 %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %or, <4 x i32> <i32 25, i32 25, i32 25, i32 25>)315 %r = icmp eq <4 x i32> %f, zeroinitializer316 ret <4 x i1> %r317}318 319define i1 @fshr_or_eq_0(i16 %x, i16 %y) {320; CHECK-LABEL: fshr_or_eq_0:321; CHECK: # %bb.0:322; CHECK-NEXT: shll $8, %esi323; CHECK-NEXT: orw %di, %si324; CHECK-NEXT: sete %al325; CHECK-NEXT: retq326 %or = or i16 %x, %y327 %f = call i16 @llvm.fshr.i16(i16 %or, i16 %x, i16 8)328 %r = icmp eq i16 %f, 0329 ret i1 %r330}331 332define i1 @fshr_or_commute_eq_0(i16 %x, i16 %y) {333; CHECK-LABEL: fshr_or_commute_eq_0:334; CHECK: # %bb.0:335; CHECK-NEXT: shll $8, %esi336; CHECK-NEXT: orw %di, %si337; CHECK-NEXT: sete %al338; CHECK-NEXT: retq339 %or = or i16 %y, %x340 %f = call i16 @llvm.fshr.i16(i16 %or, i16 %x, i16 8)341 %r = icmp eq i16 %f, 0342 ret i1 %r343}344 345define i1 @fshr_or2_eq_0(i64 %x, i64 %y) {346; CHECK-LABEL: fshr_or2_eq_0:347; CHECK: # %bb.0:348; CHECK-NEXT: shrq $3, %rsi349; CHECK-NEXT: orq %rdi, %rsi350; CHECK-NEXT: sete %al351; CHECK-NEXT: retq352 %or = or i64 %x, %y353 %f = call i64 @llvm.fshr.i64(i64 %x, i64 %or, i64 3)354 %r = icmp eq i64 %f, 0355 ret i1 %r356}357 358define i1 @fshr_or2_commute_eq_0(i64 %x, i64 %y) {359; CHECK-LABEL: fshr_or2_commute_eq_0:360; CHECK: # %bb.0:361; CHECK-NEXT: shrq $3, %rsi362; CHECK-NEXT: orq %rdi, %rsi363; CHECK-NEXT: sete %al364; CHECK-NEXT: retq365 %or = or i64 %y, %x366 %f = call i64 @llvm.fshr.i64(i64 %x, i64 %or, i64 3)367 %r = icmp eq i64 %f, 0368 ret i1 %r369}370 371define i1 @fshl_or_ne_0(i32 %x, i32 %y) {372; CHECK-LABEL: fshl_or_ne_0:373; CHECK: # %bb.0:374; CHECK-NEXT: shll $7, %esi375; CHECK-NEXT: orl %edi, %esi376; CHECK-NEXT: setne %al377; CHECK-NEXT: retq378 %or = or i32 %x, %y379 %f = call i32 @llvm.fshl.i32(i32 %or, i32 %x, i32 7)380 %r = icmp ne i32 %f, 0381 ret i1 %r382}383 384define i1 @fshl_or_commute_ne_0(i32 %x, i32 %y) {385; CHECK-LABEL: fshl_or_commute_ne_0:386; CHECK: # %bb.0:387; CHECK-NEXT: shll $7, %esi388; CHECK-NEXT: orl %edi, %esi389; CHECK-NEXT: setne %al390; CHECK-NEXT: retq391 %or = or i32 %y, %x392 %f = call i32 @llvm.fshl.i32(i32 %or, i32 %x, i32 7)393 %r = icmp ne i32 %f, 0394 ret i1 %r395}396 397define <4 x i1> @fshl_or2_ne_0(<4 x i32> %x, <4 x i32> %y) {398; CHECK-LABEL: fshl_or2_ne_0:399; CHECK: # %bb.0:400; CHECK-NEXT: pxor %xmm2, %xmm2401; CHECK-NEXT: psrld $27, %xmm1402; CHECK-NEXT: por %xmm1, %xmm0403; CHECK-NEXT: pcmpeqd %xmm2, %xmm0404; CHECK-NEXT: pcmpeqd %xmm1, %xmm1405; CHECK-NEXT: pxor %xmm1, %xmm0406; CHECK-NEXT: retq407 %or = or <4 x i32> %x, %y408 %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %or, <4 x i32> <i32 5, i32 5, i32 5, i32 5>)409 %r = icmp ne <4 x i32> %f, zeroinitializer410 ret <4 x i1> %r411}412 413define <4 x i1> @fshl_or2_commute_ne_0(<4 x i32> %x, <4 x i32> %y) {414; CHECK-LABEL: fshl_or2_commute_ne_0:415; CHECK: # %bb.0:416; CHECK-NEXT: pxor %xmm2, %xmm2417; CHECK-NEXT: psrld $27, %xmm1418; CHECK-NEXT: por %xmm1, %xmm0419; CHECK-NEXT: pcmpeqd %xmm2, %xmm0420; CHECK-NEXT: pcmpeqd %xmm1, %xmm1421; CHECK-NEXT: pxor %xmm1, %xmm0422; CHECK-NEXT: retq423 %or = or <4 x i32> %y, %x424 %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %or, <4 x i32> <i32 5, i32 5, i32 5, i32 5>)425 %r = icmp ne <4 x i32> %f, zeroinitializer426 ret <4 x i1> %r427}428 429define i1 @fshr_or_ne_0(i64 %x, i64 %y) {430; CHECK-LABEL: fshr_or_ne_0:431; CHECK: # %bb.0:432; CHECK-NEXT: shlq $63, %rsi433; CHECK-NEXT: orq %rdi, %rsi434; CHECK-NEXT: setne %al435; CHECK-NEXT: retq436 %or = or i64 %x, %y437 %f = call i64 @llvm.fshr.i64(i64 %or, i64 %x, i64 1)438 %r = icmp ne i64 %f, 0439 ret i1 %r440}441 442define i1 @fshr_or_commute_ne_0(i64 %x, i64 %y) {443; CHECK-LABEL: fshr_or_commute_ne_0:444; CHECK: # %bb.0:445; CHECK-NEXT: shlq $63, %rsi446; CHECK-NEXT: orq %rdi, %rsi447; CHECK-NEXT: setne %al448; CHECK-NEXT: retq449 %or = or i64 %y, %x450 %f = call i64 @llvm.fshr.i64(i64 %or, i64 %x, i64 1)451 %r = icmp ne i64 %f, 0452 ret i1 %r453}454 455define i1 @fshr_or2_ne_0(i16 %x, i16 %y) {456; CHECK-LABEL: fshr_or2_ne_0:457; CHECK: # %bb.0:458; CHECK-NEXT: movzwl %si, %eax459; CHECK-NEXT: shrl $2, %eax460; CHECK-NEXT: orw %di, %ax461; CHECK-NEXT: setne %al462; CHECK-NEXT: retq463 %or = or i16 %x, %y464 %f = call i16 @llvm.fshr.i16(i16 %x, i16 %or, i16 2)465 %r = icmp ne i16 %f, 0466 ret i1 %r467}468 469define i1 @fshr_or2_commute_ne_0(i16 %x, i16 %y) {470; CHECK-LABEL: fshr_or2_commute_ne_0:471; CHECK: # %bb.0:472; CHECK-NEXT: movzwl %si, %eax473; CHECK-NEXT: shrl $2, %eax474; CHECK-NEXT: orw %di, %ax475; CHECK-NEXT: setne %al476; CHECK-NEXT: retq477 %or = or i16 %y, %x478 %f = call i16 @llvm.fshr.i16(i16 %x, i16 %or, i16 2)479 %r = icmp ne i16 %f, 0480 ret i1 %r481}482 483define i1 @fshl_xor_eq_0(i32 %x, i32 %y) {484; CHECK-LABEL: fshl_xor_eq_0:485; CHECK: # %bb.0:486; CHECK-NEXT: xorl %edi, %esi487; CHECK-NEXT: shldl $2, %edi, %esi488; CHECK-NEXT: sete %al489; CHECK-NEXT: retq490 %or = xor i32 %x, %y491 %f = call i32 @llvm.fshl.i32(i32 %or, i32 %x, i32 2)492 %r = icmp eq i32 %f, 0493 ret i1 %r494}495 496define i1 @fshl_or_sgt_0(i32 %x, i32 %y) {497; CHECK-LABEL: fshl_or_sgt_0:498; CHECK: # %bb.0:499; CHECK-NEXT: orl %edi, %esi500; CHECK-NEXT: shldl $2, %edi, %esi501; CHECK-NEXT: testl %esi, %esi502; CHECK-NEXT: setg %al503; CHECK-NEXT: retq504 %or = or i32 %x, %y505 %f = call i32 @llvm.fshl.i32(i32 %or, i32 %x, i32 2)506 %r = icmp sgt i32 %f, 0507 ret i1 %r508}509 510define i1 @fshl_or_ne_2(i32 %x, i32 %y) {511; CHECK-LABEL: fshl_or_ne_2:512; CHECK: # %bb.0:513; CHECK-NEXT: orl %edi, %esi514; CHECK-NEXT: shldl $2, %edi, %esi515; CHECK-NEXT: cmpl $2, %esi516; CHECK-NEXT: setne %al517; CHECK-NEXT: retq518 %or = or i32 %x, %y519 %f = call i32 @llvm.fshl.i32(i32 %or, i32 %x, i32 2)520 %r = icmp ne i32 %f, 2521 ret i1 %r522}523