866 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 52; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+cmov,+sse2,+bmi | FileCheck %s --check-prefixes=X863; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+cmov,+sse2,+bmi,+bmi2 | FileCheck %s --check-prefixes=X864; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefixes=X645; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+bmi2 | FileCheck %s --check-prefixes=X646 7; PR1315878define i32 @and_select_neg_to_blsi1(i1 %a0, i32 inreg %a1) nounwind {9; X86-LABEL: and_select_neg_to_blsi1:10; X86: # %bb.0:11; X86-NEXT: blsil %eax, %ecx12; X86-NEXT: testb $1, {{[0-9]+}}(%esp)13; X86-NEXT: cmovnel %ecx, %eax14; X86-NEXT: retl15;16; X64-LABEL: and_select_neg_to_blsi1:17; X64: # %bb.0:18; X64-NEXT: blsil %esi, %eax19; X64-NEXT: testb $1, %dil20; X64-NEXT: cmovel %esi, %eax21; X64-NEXT: retq22 %sub = sub i32 0, %a123 %bls = select i1 %a0, i32 %sub, i32 -124 %ret = and i32 %a1, %bls25 ret i32 %ret26}27 28; PR13158729define i32 @and_select_neg_to_blsi2(i1 %a0, i32 inreg %a1) nounwind {30; X86-LABEL: and_select_neg_to_blsi2:31; X86: # %bb.0:32; X86-NEXT: blsil %eax, %ecx33; X86-NEXT: testb $1, {{[0-9]+}}(%esp)34; X86-NEXT: cmovnel %ecx, %eax35; X86-NEXT: retl36;37; X64-LABEL: and_select_neg_to_blsi2:38; X64: # %bb.0:39; X64-NEXT: blsil %esi, %eax40; X64-NEXT: testb $1, %dil41; X64-NEXT: cmovel %esi, %eax42; X64-NEXT: retq43 %sub = sub i32 0, %a144 %bls = select i1 %a0, i32 %sub, i32 -145 %ret = and i32 %bls, %a146 ret i32 %ret47}48 49; PR13158750define i32 @and_select_neg_to_blsi3(i1 %a0, i32 inreg %a1) nounwind {51; X86-LABEL: and_select_neg_to_blsi3:52; X86: # %bb.0:53; X86-NEXT: blsil %eax, %ecx54; X86-NEXT: testb $1, {{[0-9]+}}(%esp)55; X86-NEXT: cmovel %ecx, %eax56; X86-NEXT: retl57;58; X64-LABEL: and_select_neg_to_blsi3:59; X64: # %bb.0:60; X64-NEXT: blsil %esi, %eax61; X64-NEXT: testb $1, %dil62; X64-NEXT: cmovnel %esi, %eax63; X64-NEXT: retq64 %sub = sub i32 0, %a165 %bls = select i1 %a0, i32 -1, i32 %sub66 %ret = and i32 %a1, %bls67 ret i32 %ret68}69 70; PR13158771define i64 @and_select_neg_to_blsi_i64(i1 %a0, i64 %a1) nounwind {72; X86-LABEL: and_select_neg_to_blsi_i64:73; X86: # %bb.0:74; X86-NEXT: pushl %esi75; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx76; X86-NEXT: movl {{[0-9]+}}(%esp), %esi77; X86-NEXT: xorl %edx, %edx78; X86-NEXT: movl %ecx, %eax79; X86-NEXT: negl %eax80; X86-NEXT: sbbl %esi, %edx81; X86-NEXT: andl %esi, %edx82; X86-NEXT: andl %ecx, %eax83; X86-NEXT: testb $1, {{[0-9]+}}(%esp)84; X86-NEXT: cmovel %esi, %edx85; X86-NEXT: cmovel %ecx, %eax86; X86-NEXT: popl %esi87; X86-NEXT: retl88;89; X64-LABEL: and_select_neg_to_blsi_i64:90; X64: # %bb.0:91; X64-NEXT: blsiq %rsi, %rax92; X64-NEXT: testb $1, %dil93; X64-NEXT: cmoveq %rsi, %rax94; X64-NEXT: retq95 %sub = sub i64 0, %a196 %bls = select i1 %a0, i64 %sub, i64 -197 %ret = and i64 %a1, %bls98 ret i64 %ret99}100 101; The transformation also applies to the following test although we do not emit a BLSI instruction102; here because the negation instruction is used more than once.103define i32 @and_neg_select_pos_i32(i1 %a0, i32 inreg %a1) nounwind {104; X86-LABEL: and_neg_select_pos_i32:105; X86: # %bb.0:106; X86-NEXT: movl %eax, %ecx107; X86-NEXT: negl %ecx108; X86-NEXT: andl %ecx, %eax109; X86-NEXT: testb $1, {{[0-9]+}}(%esp)110; X86-NEXT: cmovel %ecx, %eax111; X86-NEXT: retl112;113; X64-LABEL: and_neg_select_pos_i32:114; X64: # %bb.0:115; X64-NEXT: movl %esi, %eax116; X64-NEXT: negl %eax117; X64-NEXT: andl %eax, %esi118; X64-NEXT: testb $1, %dil119; X64-NEXT: cmovnel %esi, %eax120; X64-NEXT: retq121 %sub = sub i32 0, %a1122 %bls = select i1 %a0, i32 %a1, i32 -1123 %ret = and i32 %sub, %bls124 ret i32 %ret125}126 127; Negative test128define i16 @and_select_neg_i16(i1 %a0, i16 %a1) nounwind {129; X86-LABEL: and_select_neg_i16:130; X86: # %bb.0:131; X86-NEXT: pushl %esi132; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx133; X86-NEXT: andb $1, %cl134; X86-NEXT: movl {{[0-9]+}}(%esp), %edx135; X86-NEXT: movl %edx, %esi136; X86-NEXT: negl %esi137; X86-NEXT: xorl %eax, %eax138; X86-NEXT: cmpb $1, %cl139; X86-NEXT: sbbl %eax, %eax140; X86-NEXT: orl %esi, %eax141; X86-NEXT: andl %edx, %eax142; X86-NEXT: # kill: def $ax killed $ax killed $eax143; X86-NEXT: popl %esi144; X86-NEXT: retl145;146; X64-LABEL: and_select_neg_i16:147; X64: # %bb.0:148; X64-NEXT: andb $1, %dil149; X64-NEXT: movl %esi, %ecx150; X64-NEXT: negl %ecx151; X64-NEXT: xorl %eax, %eax152; X64-NEXT: cmpb $1, %dil153; X64-NEXT: sbbl %eax, %eax154; X64-NEXT: orl %ecx, %eax155; X64-NEXT: andl %esi, %eax156; X64-NEXT: # kill: def $ax killed $ax killed $eax157; X64-NEXT: retq158 %sub = sub i16 0, %a1159 %bls = select i1 %a0, i16 %sub, i16 -1160 %ret = and i16 %a1, %bls161 ret i16 %ret162}163 164; Negative test165define <4 x i32> @and_select_neg_v4xi32(i1 %a0, <4 x i32> %a1) nounwind {166; X86-LABEL: and_select_neg_v4xi32:167; X86: # %bb.0:168; X86-NEXT: testb $1, {{[0-9]+}}(%esp)169; X86-NEXT: jne .LBB6_1170; X86-NEXT: # %bb.2:171; X86-NEXT: pcmpeqd %xmm1, %xmm1172; X86-NEXT: pand %xmm1, %xmm0173; X86-NEXT: retl174; X86-NEXT: .LBB6_1:175; X86-NEXT: pxor %xmm1, %xmm1176; X86-NEXT: psubd %xmm0, %xmm1177; X86-NEXT: pand %xmm1, %xmm0178; X86-NEXT: retl179;180; X64-LABEL: and_select_neg_v4xi32:181; X64: # %bb.0:182; X64-NEXT: testb $1, %dil183; X64-NEXT: jne .LBB6_1184; X64-NEXT: # %bb.2:185; X64-NEXT: pcmpeqd %xmm1, %xmm1186; X64-NEXT: pand %xmm1, %xmm0187; X64-NEXT: retq188; X64-NEXT: .LBB6_1:189; X64-NEXT: pxor %xmm1, %xmm1190; X64-NEXT: psubd %xmm0, %xmm1191; X64-NEXT: pand %xmm1, %xmm0192; X64-NEXT: retq193 %sub = sub <4 x i32> zeroinitializer, %a1194 %bls = select i1 %a0, <4 x i32> %sub, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>195 %ret = and <4 x i32> %a1, %bls196 ret <4 x i32> %ret197}198 199; Negative test200define i32 @and_select_no_neg(i1 %a0, i32 inreg %a1) nounwind {201; X86-LABEL: and_select_no_neg:202; X86: # %bb.0:203; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx204; X86-NEXT: andb $1, %cl205; X86-NEXT: xorl %edx, %edx206; X86-NEXT: cmpb $1, %cl207; X86-NEXT: sbbl %edx, %edx208; X86-NEXT: orl %eax, %edx209; X86-NEXT: andl %edx, %eax210; X86-NEXT: retl211;212; X64-LABEL: and_select_no_neg:213; X64: # %bb.0:214; X64-NEXT: andb $1, %dil215; X64-NEXT: xorl %eax, %eax216; X64-NEXT: cmpb $1, %dil217; X64-NEXT: sbbl %eax, %eax218; X64-NEXT: orl %esi, %eax219; X64-NEXT: andl %esi, %eax220; X64-NEXT: retq221 %sub = sub i32 %a1, 0222 %bls = select i1 %a0, i32 %sub, i32 -1223 %ret = and i32 %a1, %bls224 ret i32 %ret225}226 227; Negative test228define i32 @and_select_neg_wrong_const(i1 %a0, i32 inreg %a1) nounwind {229; X86-LABEL: and_select_neg_wrong_const:230; X86: # %bb.0:231; X86-NEXT: movl %eax, %ecx232; X86-NEXT: negl %ecx233; X86-NEXT: testb $1, {{[0-9]+}}(%esp)234; X86-NEXT: movl $1, %edx235; X86-NEXT: cmovnel %ecx, %edx236; X86-NEXT: andl %edx, %eax237; X86-NEXT: retl238;239; X64-LABEL: and_select_neg_wrong_const:240; X64: # %bb.0:241; X64-NEXT: movl %esi, %ecx242; X64-NEXT: negl %ecx243; X64-NEXT: testb $1, %dil244; X64-NEXT: movl $1, %eax245; X64-NEXT: cmovnel %ecx, %eax246; X64-NEXT: andl %esi, %eax247; X64-NEXT: retq248 %sub = sub i32 0, %a1249 %bls = select i1 %a0, i32 %sub, i32 1250 %ret = and i32 %a1, %bls251 ret i32 %ret252}253 254; Negative test255define i32 @and_select_neg_different_op(i1 %a0, i32 inreg %a1, i32 inreg %a2) nounwind {256; X86-LABEL: and_select_neg_different_op:257; X86: # %bb.0:258; X86-NEXT: pushl %esi259; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx260; X86-NEXT: andb $1, %cl261; X86-NEXT: negl %edx262; X86-NEXT: xorl %esi, %esi263; X86-NEXT: cmpb $1, %cl264; X86-NEXT: sbbl %esi, %esi265; X86-NEXT: orl %edx, %esi266; X86-NEXT: andl %esi, %eax267; X86-NEXT: popl %esi268; X86-NEXT: retl269;270; X64-LABEL: and_select_neg_different_op:271; X64: # %bb.0:272; X64-NEXT: andb $1, %dil273; X64-NEXT: negl %edx274; X64-NEXT: xorl %eax, %eax275; X64-NEXT: cmpb $1, %dil276; X64-NEXT: sbbl %eax, %eax277; X64-NEXT: orl %edx, %eax278; X64-NEXT: andl %esi, %eax279; X64-NEXT: retq280 %sub = sub i32 0, %a2281 %bls = select i1 %a0, i32 %sub, i32 -1282 %ret = and i32 %a1, %bls283 ret i32 %ret284}285 286; PR133848287define i32 @and_select_sub_1_to_blsr1(i1 %a0, i32 inreg %a1) nounwind {288; X86-LABEL: and_select_sub_1_to_blsr1:289; X86: # %bb.0:290; X86-NEXT: blsrl %eax, %ecx291; X86-NEXT: testb $1, {{[0-9]+}}(%esp)292; X86-NEXT: cmovnel %ecx, %eax293; X86-NEXT: retl294;295; X64-LABEL: and_select_sub_1_to_blsr1:296; X64: # %bb.0:297; X64-NEXT: blsrl %esi, %eax298; X64-NEXT: testb $1, %dil299; X64-NEXT: cmovel %esi, %eax300; X64-NEXT: retq301 %sub = add i32 %a1, -1302 %bls = select i1 %a0, i32 %sub, i32 -1303 %ret = and i32 %a1, %bls304 ret i32 %ret305}306 307; PR133848308define i32 @and_select_sub_1_to_blsr2(i1 %a0, i32 inreg %a1) nounwind {309; X86-LABEL: and_select_sub_1_to_blsr2:310; X86: # %bb.0:311; X86-NEXT: blsrl %eax, %ecx312; X86-NEXT: testb $1, {{[0-9]+}}(%esp)313; X86-NEXT: cmovnel %ecx, %eax314; X86-NEXT: retl315;316; X64-LABEL: and_select_sub_1_to_blsr2:317; X64: # %bb.0:318; X64-NEXT: blsrl %esi, %eax319; X64-NEXT: testb $1, %dil320; X64-NEXT: cmovel %esi, %eax321; X64-NEXT: retq322 %sub = add i32 %a1, -1323 %bls = select i1 %a0, i32 %sub, i32 -1324 %ret = and i32 %bls, %a1325 ret i32 %ret326}327 328; PR133848329define i32 @and_select_sub_1_to_blsr3(i1 %a0, i32 inreg %a1) nounwind {330; X86-LABEL: and_select_sub_1_to_blsr3:331; X86: # %bb.0:332; X86-NEXT: blsrl %eax, %ecx333; X86-NEXT: testb $1, {{[0-9]+}}(%esp)334; X86-NEXT: cmovel %ecx, %eax335; X86-NEXT: retl336;337; X64-LABEL: and_select_sub_1_to_blsr3:338; X64: # %bb.0:339; X64-NEXT: blsrl %esi, %eax340; X64-NEXT: testb $1, %dil341; X64-NEXT: cmovnel %esi, %eax342; X64-NEXT: retq343 %sub = add i32 %a1, -1344 %bls = select i1 %a0, i32 -1, i32 %sub345 %ret = and i32 %a1, %bls346 ret i32 %ret347}348 349; PR133848350define i32 @and_select_sub_1_to_blsr4(i1 %a0, i32 inreg %a1) nounwind {351; X86-LABEL: and_select_sub_1_to_blsr4:352; X86: # %bb.0:353; X86-NEXT: blsrl %eax, %ecx354; X86-NEXT: testb $1, {{[0-9]+}}(%esp)355; X86-NEXT: cmovnel %ecx, %eax356; X86-NEXT: retl357;358; X64-LABEL: and_select_sub_1_to_blsr4:359; X64: # %bb.0:360; X64-NEXT: blsrl %esi, %eax361; X64-NEXT: testb $1, %dil362; X64-NEXT: cmovel %esi, %eax363; X64-NEXT: retq364 %sub = sub i32 %a1, 1365 %bls = select i1 %a0, i32 %sub, i32 -1366 %ret = and i32 %a1, %bls367 ret i32 %ret368}369 370; The transformation also applies to the following test although we do not emit a BLSR instruction371; here because the subtraction instruction is used more than once.372define i32 @and_sub_1_select_orig(i1 %a0, i32 inreg %a1) nounwind {373; X86-LABEL: and_sub_1_select_orig:374; X86: # %bb.0:375; X86-NEXT: leal -1(%eax), %ecx376; X86-NEXT: andl %ecx, %eax377; X86-NEXT: testb $1, {{[0-9]+}}(%esp)378; X86-NEXT: cmovel %ecx, %eax379; X86-NEXT: retl380;381; X64-LABEL: and_sub_1_select_orig:382; X64: # %bb.0:383; X64-NEXT: # kill: def $esi killed $esi def $rsi384; X64-NEXT: leal -1(%rsi), %eax385; X64-NEXT: andl %eax, %esi386; X64-NEXT: testb $1, %dil387; X64-NEXT: cmovnel %esi, %eax388; X64-NEXT: retq389 %sub = add i32 %a1, -1390 %bls = select i1 %a0, i32 %a1, i32 -1391 %ret = and i32 %sub, %bls392 ret i32 %ret393}394 395; PR133848396define i64 @and_select_sub_1_to_blsr_i64(i1 %a0, i64 %a1) nounwind {397; X86-LABEL: and_select_sub_1_to_blsr_i64:398; X86: # %bb.0:399; X86-NEXT: pushl %esi400; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx401; X86-NEXT: movl {{[0-9]+}}(%esp), %esi402; X86-NEXT: movl %ecx, %eax403; X86-NEXT: addl $-1, %eax404; X86-NEXT: movl %esi, %edx405; X86-NEXT: adcl $-1, %edx406; X86-NEXT: andl %esi, %edx407; X86-NEXT: andl %ecx, %eax408; X86-NEXT: testb $1, {{[0-9]+}}(%esp)409; X86-NEXT: cmovel %ecx, %eax410; X86-NEXT: cmovel %esi, %edx411; X86-NEXT: popl %esi412; X86-NEXT: retl413;414; X64-LABEL: and_select_sub_1_to_blsr_i64:415; X64: # %bb.0:416; X64-NEXT: blsrq %rsi, %rax417; X64-NEXT: testb $1, %dil418; X64-NEXT: cmoveq %rsi, %rax419; X64-NEXT: retq420 %sub = add i64 %a1, -1421 %bls = select i1 %a0, i64 %sub, i64 -1422 %ret = and i64 %a1, %bls423 ret i64 %ret424}425 426; Negative test427define i16 @and_select_sub_1_i16(i1 %a0, i16 %a1) nounwind {428; X86-LABEL: and_select_sub_1_i16:429; X86: # %bb.0:430; X86-NEXT: pushl %esi431; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx432; X86-NEXT: andb $1, %cl433; X86-NEXT: movl {{[0-9]+}}(%esp), %edx434; X86-NEXT: leal -1(%edx), %esi435; X86-NEXT: xorl %eax, %eax436; X86-NEXT: cmpb $1, %cl437; X86-NEXT: sbbl %eax, %eax438; X86-NEXT: orl %esi, %eax439; X86-NEXT: andl %edx, %eax440; X86-NEXT: # kill: def $ax killed $ax killed $eax441; X86-NEXT: popl %esi442; X86-NEXT: retl443;444; X64-LABEL: and_select_sub_1_i16:445; X64: # %bb.0:446; X64-NEXT: # kill: def $esi killed $esi def $rsi447; X64-NEXT: andb $1, %dil448; X64-NEXT: leal -1(%rsi), %ecx449; X64-NEXT: xorl %eax, %eax450; X64-NEXT: cmpb $1, %dil451; X64-NEXT: sbbl %eax, %eax452; X64-NEXT: orl %ecx, %eax453; X64-NEXT: andl %esi, %eax454; X64-NEXT: # kill: def $ax killed $ax killed $eax455; X64-NEXT: retq456 %sub = add i16 %a1, -1457 %bls = select i1 %a0, i16 %sub, i16 -1458 %ret = and i16 %a1, %bls459 ret i16 %ret460}461 462; Negative test463define <4 x i32> @and_select_sub_1_v4xi32(i1 %a0, <4 x i32> %a1) nounwind {464; X86-LABEL: and_select_sub_1_v4xi32:465; X86: # %bb.0:466; X86-NEXT: pcmpeqd %xmm1, %xmm1467; X86-NEXT: testb $1, {{[0-9]+}}(%esp)468; X86-NEXT: je .LBB17_2469; X86-NEXT: # %bb.1:470; X86-NEXT: paddd %xmm0, %xmm1471; X86-NEXT: .LBB17_2:472; X86-NEXT: pand %xmm1, %xmm0473; X86-NEXT: retl474;475; X64-LABEL: and_select_sub_1_v4xi32:476; X64: # %bb.0:477; X64-NEXT: pcmpeqd %xmm1, %xmm1478; X64-NEXT: testb $1, %dil479; X64-NEXT: je .LBB17_2480; X64-NEXT: # %bb.1:481; X64-NEXT: paddd %xmm0, %xmm1482; X64-NEXT: .LBB17_2:483; X64-NEXT: pand %xmm1, %xmm0484; X64-NEXT: retq485 %sub = add <4 x i32> %a1, <i32 -1, i32 -1, i32 -1, i32 -1>486 %bls = select i1 %a0, <4 x i32> %sub, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>487 %ret = and <4 x i32> %a1, %bls488 ret <4 x i32> %ret489}490 491; Negative test492define i32 @and_select_no_sub_1(i1 %a0, i32 inreg %a1) nounwind {493; X86-LABEL: and_select_no_sub_1:494; X86: # %bb.0:495; X86-NEXT: pushl %esi496; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx497; X86-NEXT: andb $1, %cl498; X86-NEXT: leal -2(%eax), %edx499; X86-NEXT: xorl %esi, %esi500; X86-NEXT: cmpb $1, %cl501; X86-NEXT: sbbl %esi, %esi502; X86-NEXT: orl %edx, %esi503; X86-NEXT: andl %esi, %eax504; X86-NEXT: popl %esi505; X86-NEXT: retl506;507; X64-LABEL: and_select_no_sub_1:508; X64: # %bb.0:509; X64-NEXT: # kill: def $esi killed $esi def $rsi510; X64-NEXT: andb $1, %dil511; X64-NEXT: leal -2(%rsi), %ecx512; X64-NEXT: xorl %eax, %eax513; X64-NEXT: cmpb $1, %dil514; X64-NEXT: sbbl %eax, %eax515; X64-NEXT: orl %ecx, %eax516; X64-NEXT: andl %esi, %eax517; X64-NEXT: retq518 %sub = add i32 %a1, -2519 %bls = select i1 %a0, i32 %sub, i32 -1520 %ret = and i32 %a1, %bls521 ret i32 %ret522}523 524; Negative test525define i32 @and_select_sub_1_wrong_const(i1 %a0, i32 inreg %a1) nounwind {526; X86-LABEL: and_select_sub_1_wrong_const:527; X86: # %bb.0:528; X86-NEXT: leal -1(%eax), %ecx529; X86-NEXT: testb $1, {{[0-9]+}}(%esp)530; X86-NEXT: movl $1, %edx531; X86-NEXT: cmovnel %ecx, %edx532; X86-NEXT: andl %edx, %eax533; X86-NEXT: retl534;535; X64-LABEL: and_select_sub_1_wrong_const:536; X64: # %bb.0:537; X64-NEXT: # kill: def $esi killed $esi def $rsi538; X64-NEXT: leal -1(%rsi), %ecx539; X64-NEXT: testb $1, %dil540; X64-NEXT: movl $1, %eax541; X64-NEXT: cmovnel %ecx, %eax542; X64-NEXT: andl %esi, %eax543; X64-NEXT: retq544 %sub = add i32 %a1, -1545 %bls = select i1 %a0, i32 %sub, i32 1546 %ret = and i32 %a1, %bls547 ret i32 %ret548}549 550; Negative test551define i32 @and_select_sub_1_different_op(i1 %a0, i32 inreg %a1, i32 inreg %a2) nounwind {552; X86-LABEL: and_select_sub_1_different_op:553; X86: # %bb.0:554; X86-NEXT: pushl %esi555; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx556; X86-NEXT: andb $1, %cl557; X86-NEXT: decl %edx558; X86-NEXT: xorl %esi, %esi559; X86-NEXT: cmpb $1, %cl560; X86-NEXT: sbbl %esi, %esi561; X86-NEXT: orl %edx, %esi562; X86-NEXT: andl %esi, %eax563; X86-NEXT: popl %esi564; X86-NEXT: retl565;566; X64-LABEL: and_select_sub_1_different_op:567; X64: # %bb.0:568; X64-NEXT: # kill: def $edx killed $edx def $rdx569; X64-NEXT: andb $1, %dil570; X64-NEXT: leal -1(%rdx), %ecx571; X64-NEXT: xorl %eax, %eax572; X64-NEXT: cmpb $1, %dil573; X64-NEXT: sbbl %eax, %eax574; X64-NEXT: orl %ecx, %eax575; X64-NEXT: andl %esi, %eax576; X64-NEXT: retq577 %sub = add i32 %a2, -1578 %bls = select i1 %a0, i32 %sub, i32 -1579 %ret = and i32 %a1, %bls580 ret i32 %ret581}582 583define i32 @xor_select_sub_1_to_blsmsk1(i1 %a0, i32 inreg %a1) nounwind {584; X86-LABEL: xor_select_sub_1_to_blsmsk1:585; X86: # %bb.0:586; X86-NEXT: blsmskl %eax, %ecx587; X86-NEXT: testb $1, {{[0-9]+}}(%esp)588; X86-NEXT: cmovnel %ecx, %eax589; X86-NEXT: retl590;591; X64-LABEL: xor_select_sub_1_to_blsmsk1:592; X64: # %bb.0:593; X64-NEXT: blsmskl %esi, %eax594; X64-NEXT: testb $1, %dil595; X64-NEXT: cmovel %esi, %eax596; X64-NEXT: retq597 %sub = add i32 %a1, -1598 %bls = select i1 %a0, i32 %sub, i32 0599 %ret = xor i32 %a1, %bls600 ret i32 %ret601}602 603define i32 @xor_select_sub_1_to_blsmsk2(i1 %a0, i32 inreg %a1) nounwind {604; X86-LABEL: xor_select_sub_1_to_blsmsk2:605; X86: # %bb.0:606; X86-NEXT: blsmskl %eax, %ecx607; X86-NEXT: testb $1, {{[0-9]+}}(%esp)608; X86-NEXT: cmovnel %ecx, %eax609; X86-NEXT: retl610;611; X64-LABEL: xor_select_sub_1_to_blsmsk2:612; X64: # %bb.0:613; X64-NEXT: blsmskl %esi, %eax614; X64-NEXT: testb $1, %dil615; X64-NEXT: cmovel %esi, %eax616; X64-NEXT: retq617 %sub = add i32 %a1, -1618 %bls = select i1 %a0, i32 %sub, i32 0619 %ret = xor i32 %bls, %a1620 ret i32 %ret621}622 623define i32 @xor_select_sub_1_to_blsmsk3(i1 %a0, i32 inreg %a1) nounwind {624; X86-LABEL: xor_select_sub_1_to_blsmsk3:625; X86: # %bb.0:626; X86-NEXT: blsmskl %eax, %ecx627; X86-NEXT: testb $1, {{[0-9]+}}(%esp)628; X86-NEXT: cmovel %ecx, %eax629; X86-NEXT: retl630;631; X64-LABEL: xor_select_sub_1_to_blsmsk3:632; X64: # %bb.0:633; X64-NEXT: blsmskl %esi, %eax634; X64-NEXT: testb $1, %dil635; X64-NEXT: cmovnel %esi, %eax636; X64-NEXT: retq637 %sub = add i32 %a1, -1638 %bls = select i1 %a0, i32 0, i32 %sub639 %ret = xor i32 %a1, %bls640 ret i32 %ret641}642 643define i32 @xor_select_sub_1_to_blsmsk4(i1 %a0, i32 inreg %a1) nounwind {644; X86-LABEL: xor_select_sub_1_to_blsmsk4:645; X86: # %bb.0:646; X86-NEXT: blsmskl %eax, %ecx647; X86-NEXT: testb $1, {{[0-9]+}}(%esp)648; X86-NEXT: cmovnel %ecx, %eax649; X86-NEXT: retl650;651; X64-LABEL: xor_select_sub_1_to_blsmsk4:652; X64: # %bb.0:653; X64-NEXT: blsmskl %esi, %eax654; X64-NEXT: testb $1, %dil655; X64-NEXT: cmovel %esi, %eax656; X64-NEXT: retq657 %sub = sub i32 %a1, 1658 %bls = select i1 %a0, i32 %sub, i32 0659 %ret = xor i32 %a1, %bls660 ret i32 %ret661}662 663; The transformation also applies to the following test although we do not emit a BLSMSK instruction664; here because the subtraction instruction is used more than once.665define i32 @xor_sub_1_select_orig(i1 %a0, i32 inreg %a1) nounwind {666; X86-LABEL: xor_sub_1_select_orig:667; X86: # %bb.0:668; X86-NEXT: leal -1(%eax), %ecx669; X86-NEXT: xorl %ecx, %eax670; X86-NEXT: testb $1, {{[0-9]+}}(%esp)671; X86-NEXT: cmovel %ecx, %eax672; X86-NEXT: retl673;674; X64-LABEL: xor_sub_1_select_orig:675; X64: # %bb.0:676; X64-NEXT: # kill: def $esi killed $esi def $rsi677; X64-NEXT: leal -1(%rsi), %eax678; X64-NEXT: xorl %eax, %esi679; X64-NEXT: testb $1, %dil680; X64-NEXT: cmovnel %esi, %eax681; X64-NEXT: retq682 %sub = add i32 %a1, -1683 %bls = select i1 %a0, i32 %a1, i32 0684 %ret = xor i32 %sub, %bls685 ret i32 %ret686}687 688define i64 @xor_select_sub_1_to_blsmsk_i64(i1 %a0, i64 %a1) nounwind {689; X86-LABEL: xor_select_sub_1_to_blsmsk_i64:690; X86: # %bb.0:691; X86-NEXT: pushl %esi692; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx693; X86-NEXT: movl {{[0-9]+}}(%esp), %esi694; X86-NEXT: movl %ecx, %eax695; X86-NEXT: addl $-1, %eax696; X86-NEXT: movl %esi, %edx697; X86-NEXT: adcl $-1, %edx698; X86-NEXT: xorl %esi, %edx699; X86-NEXT: xorl %ecx, %eax700; X86-NEXT: testb $1, {{[0-9]+}}(%esp)701; X86-NEXT: cmovel %ecx, %eax702; X86-NEXT: cmovel %esi, %edx703; X86-NEXT: popl %esi704; X86-NEXT: retl705;706; X64-LABEL: xor_select_sub_1_to_blsmsk_i64:707; X64: # %bb.0:708; X64-NEXT: blsmskq %rsi, %rax709; X64-NEXT: testb $1, %dil710; X64-NEXT: cmoveq %rsi, %rax711; X64-NEXT: retq712 %sub = add i64 %a1, -1713 %bls = select i1 %a0, i64 %sub, i64 0714 %ret = xor i64 %a1, %bls715 ret i64 %ret716}717 718; Negative test719define i16 @xor_select_sub_1_i16(i1 %a0, i16 %a1) nounwind {720; X86-LABEL: xor_select_sub_1_i16:721; X86: # %bb.0:722; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx723; X86-NEXT: leal -1(%ecx), %edx724; X86-NEXT: xorl %eax, %eax725; X86-NEXT: testb $1, {{[0-9]+}}(%esp)726; X86-NEXT: cmovnel %edx, %eax727; X86-NEXT: xorl %ecx, %eax728; X86-NEXT: # kill: def $ax killed $ax killed $eax729; X86-NEXT: retl730;731; X64-LABEL: xor_select_sub_1_i16:732; X64: # %bb.0:733; X64-NEXT: # kill: def $esi killed $esi def $rsi734; X64-NEXT: leal -1(%rsi), %ecx735; X64-NEXT: xorl %eax, %eax736; X64-NEXT: testb $1, %dil737; X64-NEXT: cmovnel %ecx, %eax738; X64-NEXT: xorl %esi, %eax739; X64-NEXT: # kill: def $ax killed $ax killed $eax740; X64-NEXT: retq741 %sub = add i16 %a1, -1742 %bls = select i1 %a0, i16 %sub, i16 0743 %ret = xor i16 %a1, %bls744 ret i16 %ret745}746 747; Negative test748define <4 x i32> @xor_select_sub_1_v4xi32(i1 %a0, <4 x i32> %a1) nounwind {749; X86-LABEL: xor_select_sub_1_v4xi32:750; X86: # %bb.0:751; X86-NEXT: testb $1, {{[0-9]+}}(%esp)752; X86-NEXT: jne .LBB28_1753; X86-NEXT: # %bb.2:754; X86-NEXT: xorps %xmm1, %xmm1755; X86-NEXT: xorps %xmm1, %xmm0756; X86-NEXT: retl757; X86-NEXT: .LBB28_1:758; X86-NEXT: pcmpeqd %xmm1, %xmm1759; X86-NEXT: paddd %xmm0, %xmm1760; X86-NEXT: pxor %xmm1, %xmm0761; X86-NEXT: retl762;763; X64-LABEL: xor_select_sub_1_v4xi32:764; X64: # %bb.0:765; X64-NEXT: testb $1, %dil766; X64-NEXT: jne .LBB28_1767; X64-NEXT: # %bb.2:768; X64-NEXT: xorps %xmm1, %xmm1769; X64-NEXT: xorps %xmm1, %xmm0770; X64-NEXT: retq771; X64-NEXT: .LBB28_1:772; X64-NEXT: pcmpeqd %xmm1, %xmm1773; X64-NEXT: paddd %xmm0, %xmm1774; X64-NEXT: pxor %xmm1, %xmm0775; X64-NEXT: retq776 %sub = add <4 x i32> %a1, <i32 -1, i32 -1, i32 -1, i32 -1>777 %bls = select i1 %a0, <4 x i32> %sub, <4 x i32> zeroinitializer778 %ret = xor <4 x i32> %a1, %bls779 ret <4 x i32> %ret780}781 782; Negative test783define i32 @xor_select_no_sub_1(i1 %a0, i32 inreg %a1) nounwind {784; X86-LABEL: xor_select_no_sub_1:785; X86: # %bb.0:786; X86-NEXT: leal 1(%eax), %ecx787; X86-NEXT: xorl %edx, %edx788; X86-NEXT: testb $1, {{[0-9]+}}(%esp)789; X86-NEXT: cmovnel %ecx, %edx790; X86-NEXT: xorl %edx, %eax791; X86-NEXT: retl792;793; X64-LABEL: xor_select_no_sub_1:794; X64: # %bb.0:795; X64-NEXT: # kill: def $esi killed $esi def $rsi796; X64-NEXT: leal 1(%rsi), %ecx797; X64-NEXT: xorl %eax, %eax798; X64-NEXT: testb $1, %dil799; X64-NEXT: cmovnel %ecx, %eax800; X64-NEXT: xorl %esi, %eax801; X64-NEXT: retq802 %sub = add i32 %a1, 1803 %bls = select i1 %a0, i32 %sub, i32 0804 %ret = xor i32 %a1, %bls805 ret i32 %ret806}807 808; Negative test809define i32 @xor_select_sub_1_wrong_const(i1 %a0, i32 inreg %a1) nounwind {810; X86-LABEL: xor_select_sub_1_wrong_const:811; X86: # %bb.0:812; X86-NEXT: pushl %esi813; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx814; X86-NEXT: andb $1, %cl815; X86-NEXT: leal -1(%eax), %edx816; X86-NEXT: xorl %esi, %esi817; X86-NEXT: cmpb $1, %cl818; X86-NEXT: sbbl %esi, %esi819; X86-NEXT: orl %edx, %esi820; X86-NEXT: xorl %esi, %eax821; X86-NEXT: popl %esi822; X86-NEXT: retl823;824; X64-LABEL: xor_select_sub_1_wrong_const:825; X64: # %bb.0:826; X64-NEXT: # kill: def $esi killed $esi def $rsi827; X64-NEXT: andb $1, %dil828; X64-NEXT: leal -1(%rsi), %ecx829; X64-NEXT: xorl %eax, %eax830; X64-NEXT: cmpb $1, %dil831; X64-NEXT: sbbl %eax, %eax832; X64-NEXT: orl %ecx, %eax833; X64-NEXT: xorl %esi, %eax834; X64-NEXT: retq835 %sub = add i32 %a1, -1836 %bls = select i1 %a0, i32 %sub, i32 -1837 %ret = xor i32 %a1, %bls838 ret i32 %ret839}840 841; Negative test842define i32 @xor_select_sub_1_different_op(i1 %a0, i32 inreg %a1, i32 inreg %a2) nounwind {843; X86-LABEL: xor_select_sub_1_different_op:844; X86: # %bb.0:845; X86-NEXT: leal -1(%edx), %ecx846; X86-NEXT: xorl %edx, %edx847; X86-NEXT: testb $1, {{[0-9]+}}(%esp)848; X86-NEXT: cmovnel %ecx, %edx849; X86-NEXT: xorl %edx, %eax850; X86-NEXT: retl851;852; X64-LABEL: xor_select_sub_1_different_op:853; X64: # %bb.0:854; X64-NEXT: # kill: def $edx killed $edx def $rdx855; X64-NEXT: leal -1(%rdx), %ecx856; X64-NEXT: xorl %eax, %eax857; X64-NEXT: testb $1, %dil858; X64-NEXT: cmovnel %ecx, %eax859; X64-NEXT: xorl %esi, %eax860; X64-NEXT: retq861 %sub = add i32 %a2, -1862 %bls = select i1 %a0, i32 %sub, i32 0863 %ret = xor i32 %a1, %bls864 ret i32 %ret865}866