1337 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 42; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefixes=X86,X86-NOCMOV3; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+cmov | FileCheck %s --check-prefixes=X86,X86-CMOV4; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X645; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X86-CLZ6; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X64-CLZ7; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt,+fast-lzcnt | FileCheck %s --check-prefix=X64-FASTLZCNT8; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi,+lzcnt,+fast-lzcnt | FileCheck %s --check-prefix=X86-FASTLZCNT9 10declare i8 @llvm.ctlz.i8(i8, i1)11declare i16 @llvm.ctlz.i16(i16, i1)12declare i32 @llvm.ctlz.i32(i32, i1)13declare i64 @llvm.ctlz.i64(i64, i1)14 15define i8 @ctlz_i8(i8 %x) {16; X86-LABEL: ctlz_i8:17; X86: # %bb.0:18; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax19; X86-NEXT: bsrl %eax, %eax20; X86-NEXT: xorl $7, %eax21; X86-NEXT: # kill: def $al killed $al killed $eax22; X86-NEXT: retl23;24; X64-LABEL: ctlz_i8:25; X64: # %bb.0:26; X64-NEXT: movzbl %dil, %eax27; X64-NEXT: bsrl %eax, %eax28; X64-NEXT: xorl $7, %eax29; X64-NEXT: # kill: def $al killed $al killed $eax30; X64-NEXT: retq31;32; X86-CLZ-LABEL: ctlz_i8:33; X86-CLZ: # %bb.0:34; X86-CLZ-NEXT: movl {{[0-9]+}}(%esp), %eax35; X86-CLZ-NEXT: shll $24, %eax36; X86-CLZ-NEXT: lzcntl %eax, %eax37; X86-CLZ-NEXT: # kill: def $al killed $al killed $eax38; X86-CLZ-NEXT: retl39;40; X64-CLZ-LABEL: ctlz_i8:41; X64-CLZ: # %bb.0:42; X64-CLZ-NEXT: shll $24, %edi43; X64-CLZ-NEXT: lzcntl %edi, %eax44; X64-CLZ-NEXT: # kill: def $al killed $al killed $eax45; X64-CLZ-NEXT: retq46;47; X64-FASTLZCNT-LABEL: ctlz_i8:48; X64-FASTLZCNT: # %bb.0:49; X64-FASTLZCNT-NEXT: shll $24, %edi50; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax51; X64-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax52; X64-FASTLZCNT-NEXT: retq53;54; X86-FASTLZCNT-LABEL: ctlz_i8:55; X86-FASTLZCNT: # %bb.0:56; X86-FASTLZCNT-NEXT: movl {{[0-9]+}}(%esp), %eax57; X86-FASTLZCNT-NEXT: shll $24, %eax58; X86-FASTLZCNT-NEXT: lzcntl %eax, %eax59; X86-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax60; X86-FASTLZCNT-NEXT: retl61 %tmp2 = call i8 @llvm.ctlz.i8( i8 %x, i1 true )62 ret i8 %tmp263}64 65define i16 @ctlz_i16(i16 %x) {66; X86-LABEL: ctlz_i16:67; X86: # %bb.0:68; X86-NEXT: bsrw {{[0-9]+}}(%esp), %ax69; X86-NEXT: xorl $15, %eax70; X86-NEXT: # kill: def $ax killed $ax killed $eax71; X86-NEXT: retl72;73; X64-LABEL: ctlz_i16:74; X64: # %bb.0:75; X64-NEXT: bsrw %di, %ax76; X64-NEXT: xorl $15, %eax77; X64-NEXT: # kill: def $ax killed $ax killed $eax78; X64-NEXT: retq79;80; X86-CLZ-LABEL: ctlz_i16:81; X86-CLZ: # %bb.0:82; X86-CLZ-NEXT: lzcntw {{[0-9]+}}(%esp), %ax83; X86-CLZ-NEXT: retl84;85; X64-CLZ-LABEL: ctlz_i16:86; X64-CLZ: # %bb.0:87; X64-CLZ-NEXT: lzcntw %di, %ax88; X64-CLZ-NEXT: retq89;90; X64-FASTLZCNT-LABEL: ctlz_i16:91; X64-FASTLZCNT: # %bb.0:92; X64-FASTLZCNT-NEXT: lzcntw %di, %ax93; X64-FASTLZCNT-NEXT: retq94;95; X86-FASTLZCNT-LABEL: ctlz_i16:96; X86-FASTLZCNT: # %bb.0:97; X86-FASTLZCNT-NEXT: lzcntw {{[0-9]+}}(%esp), %ax98; X86-FASTLZCNT-NEXT: retl99 %tmp2 = call i16 @llvm.ctlz.i16( i16 %x, i1 true )100 ret i16 %tmp2101}102 103define i32 @ctlz_i32(i32 %x) {104; X86-LABEL: ctlz_i32:105; X86: # %bb.0:106; X86-NEXT: bsrl {{[0-9]+}}(%esp), %eax107; X86-NEXT: xorl $31, %eax108; X86-NEXT: retl109;110; X64-LABEL: ctlz_i32:111; X64: # %bb.0:112; X64-NEXT: bsrl %edi, %eax113; X64-NEXT: xorl $31, %eax114; X64-NEXT: retq115;116; X86-CLZ-LABEL: ctlz_i32:117; X86-CLZ: # %bb.0:118; X86-CLZ-NEXT: lzcntl {{[0-9]+}}(%esp), %eax119; X86-CLZ-NEXT: retl120;121; X64-CLZ-LABEL: ctlz_i32:122; X64-CLZ: # %bb.0:123; X64-CLZ-NEXT: lzcntl %edi, %eax124; X64-CLZ-NEXT: retq125;126; X64-FASTLZCNT-LABEL: ctlz_i32:127; X64-FASTLZCNT: # %bb.0:128; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax129; X64-FASTLZCNT-NEXT: retq130;131; X86-FASTLZCNT-LABEL: ctlz_i32:132; X86-FASTLZCNT: # %bb.0:133; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax134; X86-FASTLZCNT-NEXT: retl135 %tmp = call i32 @llvm.ctlz.i32( i32 %x, i1 true )136 ret i32 %tmp137}138 139define i64 @ctlz_i64(i64 %x) {140; X86-NOCMOV-LABEL: ctlz_i64:141; X86-NOCMOV: # %bb.0:142; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %eax143; X86-NOCMOV-NEXT: testl %eax, %eax144; X86-NOCMOV-NEXT: jne .LBB3_1145; X86-NOCMOV-NEXT: # %bb.2:146; X86-NOCMOV-NEXT: bsrl {{[0-9]+}}(%esp), %eax147; X86-NOCMOV-NEXT: xorl $31, %eax148; X86-NOCMOV-NEXT: orl $32, %eax149; X86-NOCMOV-NEXT: xorl %edx, %edx150; X86-NOCMOV-NEXT: retl151; X86-NOCMOV-NEXT: .LBB3_1:152; X86-NOCMOV-NEXT: bsrl %eax, %eax153; X86-NOCMOV-NEXT: xorl $31, %eax154; X86-NOCMOV-NEXT: xorl %edx, %edx155; X86-NOCMOV-NEXT: retl156;157; X86-CMOV-LABEL: ctlz_i64:158; X86-CMOV: # %bb.0:159; X86-CMOV-NEXT: movl {{[0-9]+}}(%esp), %ecx160; X86-CMOV-NEXT: bsrl %ecx, %edx161; X86-CMOV-NEXT: xorl $31, %edx162; X86-CMOV-NEXT: bsrl {{[0-9]+}}(%esp), %eax163; X86-CMOV-NEXT: xorl $31, %eax164; X86-CMOV-NEXT: orl $32, %eax165; X86-CMOV-NEXT: testl %ecx, %ecx166; X86-CMOV-NEXT: cmovnel %edx, %eax167; X86-CMOV-NEXT: xorl %edx, %edx168; X86-CMOV-NEXT: retl169;170; X64-LABEL: ctlz_i64:171; X64: # %bb.0:172; X64-NEXT: bsrq %rdi, %rax173; X64-NEXT: xorq $63, %rax174; X64-NEXT: retq175;176; X86-CLZ-LABEL: ctlz_i64:177; X86-CLZ: # %bb.0:178; X86-CLZ-NEXT: movl {{[0-9]+}}(%esp), %eax179; X86-CLZ-NEXT: testl %eax, %eax180; X86-CLZ-NEXT: jne .LBB3_1181; X86-CLZ-NEXT: # %bb.2:182; X86-CLZ-NEXT: lzcntl {{[0-9]+}}(%esp), %eax183; X86-CLZ-NEXT: addl $32, %eax184; X86-CLZ-NEXT: xorl %edx, %edx185; X86-CLZ-NEXT: retl186; X86-CLZ-NEXT: .LBB3_1:187; X86-CLZ-NEXT: lzcntl %eax, %eax188; X86-CLZ-NEXT: xorl %edx, %edx189; X86-CLZ-NEXT: retl190;191; X64-CLZ-LABEL: ctlz_i64:192; X64-CLZ: # %bb.0:193; X64-CLZ-NEXT: lzcntq %rdi, %rax194; X64-CLZ-NEXT: retq195;196; X64-FASTLZCNT-LABEL: ctlz_i64:197; X64-FASTLZCNT: # %bb.0:198; X64-FASTLZCNT-NEXT: lzcntq %rdi, %rax199; X64-FASTLZCNT-NEXT: retq200;201; X86-FASTLZCNT-LABEL: ctlz_i64:202; X86-FASTLZCNT: # %bb.0:203; X86-FASTLZCNT-NEXT: movl {{[0-9]+}}(%esp), %eax204; X86-FASTLZCNT-NEXT: testl %eax, %eax205; X86-FASTLZCNT-NEXT: jne .LBB3_1206; X86-FASTLZCNT-NEXT: # %bb.2:207; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax208; X86-FASTLZCNT-NEXT: addl $32, %eax209; X86-FASTLZCNT-NEXT: xorl %edx, %edx210; X86-FASTLZCNT-NEXT: retl211; X86-FASTLZCNT-NEXT: .LBB3_1:212; X86-FASTLZCNT-NEXT: lzcntl %eax, %eax213; X86-FASTLZCNT-NEXT: xorl %edx, %edx214; X86-FASTLZCNT-NEXT: retl215 %tmp = call i64 @llvm.ctlz.i64( i64 %x, i1 true )216 ret i64 %tmp217}218 219; Generate a test and branch to handle zero inputs because bsr/bsf are very slow.220define i8 @ctlz_i8_zero_test(i8 %n) {221; X86-NOCMOV-LABEL: ctlz_i8_zero_test:222; X86-NOCMOV: # %bb.0:223; X86-NOCMOV-NEXT: movzbl {{[0-9]+}}(%esp), %eax224; X86-NOCMOV-NEXT: testb %al, %al225; X86-NOCMOV-NEXT: je .LBB4_1226; X86-NOCMOV-NEXT: # %bb.2: # %cond.false227; X86-NOCMOV-NEXT: movzbl %al, %eax228; X86-NOCMOV-NEXT: bsrl %eax, %eax229; X86-NOCMOV-NEXT: xorl $7, %eax230; X86-NOCMOV-NEXT: # kill: def $al killed $al killed $eax231; X86-NOCMOV-NEXT: retl232; X86-NOCMOV-NEXT: .LBB4_1:233; X86-NOCMOV-NEXT: movb $8, %al234; X86-NOCMOV-NEXT: # kill: def $al killed $al killed $eax235; X86-NOCMOV-NEXT: retl236;237; X86-CMOV-LABEL: ctlz_i8_zero_test:238; X86-CMOV: # %bb.0:239; X86-CMOV-NEXT: movzbl {{[0-9]+}}(%esp), %eax240; X86-CMOV-NEXT: bsrl %eax, %ecx241; X86-CMOV-NEXT: movl $15, %eax242; X86-CMOV-NEXT: cmovnel %ecx, %eax243; X86-CMOV-NEXT: xorl $7, %eax244; X86-CMOV-NEXT: # kill: def $al killed $al killed $eax245; X86-CMOV-NEXT: retl246;247; X64-LABEL: ctlz_i8_zero_test:248; X64: # %bb.0:249; X64-NEXT: movzbl %dil, %ecx250; X64-NEXT: movl $15, %eax251; X64-NEXT: bsrl %ecx, %eax252; X64-NEXT: xorl $7, %eax253; X64-NEXT: # kill: def $al killed $al killed $eax254; X64-NEXT: retq255;256; X86-CLZ-LABEL: ctlz_i8_zero_test:257; X86-CLZ: # %bb.0:258; X86-CLZ-NEXT: movzbl {{[0-9]+}}(%esp), %eax259; X86-CLZ-NEXT: lzcntl %eax, %eax260; X86-CLZ-NEXT: addl $-24, %eax261; X86-CLZ-NEXT: # kill: def $al killed $al killed $eax262; X86-CLZ-NEXT: retl263;264; X64-CLZ-LABEL: ctlz_i8_zero_test:265; X64-CLZ: # %bb.0:266; X64-CLZ-NEXT: movzbl %dil, %eax267; X64-CLZ-NEXT: lzcntl %eax, %eax268; X64-CLZ-NEXT: addl $-24, %eax269; X64-CLZ-NEXT: # kill: def $al killed $al killed $eax270; X64-CLZ-NEXT: retq271;272; X64-FASTLZCNT-LABEL: ctlz_i8_zero_test:273; X64-FASTLZCNT: # %bb.0:274; X64-FASTLZCNT-NEXT: movzbl %dil, %eax275; X64-FASTLZCNT-NEXT: lzcntl %eax, %eax276; X64-FASTLZCNT-NEXT: addl $-24, %eax277; X64-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax278; X64-FASTLZCNT-NEXT: retq279;280; X86-FASTLZCNT-LABEL: ctlz_i8_zero_test:281; X86-FASTLZCNT: # %bb.0:282; X86-FASTLZCNT-NEXT: movzbl {{[0-9]+}}(%esp), %eax283; X86-FASTLZCNT-NEXT: lzcntl %eax, %eax284; X86-FASTLZCNT-NEXT: addl $-24, %eax285; X86-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax286; X86-FASTLZCNT-NEXT: retl287 %tmp1 = call i8 @llvm.ctlz.i8(i8 %n, i1 false)288 ret i8 %tmp1289}290 291; Generate a test and branch to handle zero inputs because bsr/bsf are very slow.292define i16 @ctlz_i16_zero_test(i16 %n) {293; X86-NOCMOV-LABEL: ctlz_i16_zero_test:294; X86-NOCMOV: # %bb.0:295; X86-NOCMOV-NEXT: movzwl {{[0-9]+}}(%esp), %eax296; X86-NOCMOV-NEXT: testw %ax, %ax297; X86-NOCMOV-NEXT: je .LBB5_1298; X86-NOCMOV-NEXT: # %bb.2: # %cond.false299; X86-NOCMOV-NEXT: bsrw %ax, %ax300; X86-NOCMOV-NEXT: xorl $15, %eax301; X86-NOCMOV-NEXT: # kill: def $ax killed $ax killed $eax302; X86-NOCMOV-NEXT: retl303; X86-NOCMOV-NEXT: .LBB5_1:304; X86-NOCMOV-NEXT: movw $16, %ax305; X86-NOCMOV-NEXT: # kill: def $ax killed $ax killed $eax306; X86-NOCMOV-NEXT: retl307;308; X86-CMOV-LABEL: ctlz_i16_zero_test:309; X86-CMOV: # %bb.0:310; X86-CMOV-NEXT: bsrw {{[0-9]+}}(%esp), %cx311; X86-CMOV-NEXT: movw $31, %ax312; X86-CMOV-NEXT: cmovnew %cx, %ax313; X86-CMOV-NEXT: xorl $15, %eax314; X86-CMOV-NEXT: # kill: def $ax killed $ax killed $eax315; X86-CMOV-NEXT: retl316;317; X64-LABEL: ctlz_i16_zero_test:318; X64: # %bb.0:319; X64-NEXT: movw $31, %ax320; X64-NEXT: bsrw %di, %ax321; X64-NEXT: xorl $15, %eax322; X64-NEXT: # kill: def $ax killed $ax killed $eax323; X64-NEXT: retq324;325; X86-CLZ-LABEL: ctlz_i16_zero_test:326; X86-CLZ: # %bb.0:327; X86-CLZ-NEXT: lzcntw {{[0-9]+}}(%esp), %ax328; X86-CLZ-NEXT: retl329;330; X64-CLZ-LABEL: ctlz_i16_zero_test:331; X64-CLZ: # %bb.0:332; X64-CLZ-NEXT: lzcntw %di, %ax333; X64-CLZ-NEXT: retq334;335; X64-FASTLZCNT-LABEL: ctlz_i16_zero_test:336; X64-FASTLZCNT: # %bb.0:337; X64-FASTLZCNT-NEXT: lzcntw %di, %ax338; X64-FASTLZCNT-NEXT: retq339;340; X86-FASTLZCNT-LABEL: ctlz_i16_zero_test:341; X86-FASTLZCNT: # %bb.0:342; X86-FASTLZCNT-NEXT: lzcntw {{[0-9]+}}(%esp), %ax343; X86-FASTLZCNT-NEXT: retl344 %tmp1 = call i16 @llvm.ctlz.i16(i16 %n, i1 false)345 ret i16 %tmp1346}347 348; Generate a test and branch to handle zero inputs because bsr/bsf are very slow.349define i32 @ctlz_i32_zero_test(i32 %n) {350; X86-NOCMOV-LABEL: ctlz_i32_zero_test:351; X86-NOCMOV: # %bb.0:352; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %eax353; X86-NOCMOV-NEXT: testl %eax, %eax354; X86-NOCMOV-NEXT: je .LBB6_1355; X86-NOCMOV-NEXT: # %bb.2: # %cond.false356; X86-NOCMOV-NEXT: bsrl %eax, %eax357; X86-NOCMOV-NEXT: xorl $31, %eax358; X86-NOCMOV-NEXT: retl359; X86-NOCMOV-NEXT: .LBB6_1:360; X86-NOCMOV-NEXT: movl $32, %eax361; X86-NOCMOV-NEXT: retl362;363; X86-CMOV-LABEL: ctlz_i32_zero_test:364; X86-CMOV: # %bb.0:365; X86-CMOV-NEXT: bsrl {{[0-9]+}}(%esp), %ecx366; X86-CMOV-NEXT: movl $63, %eax367; X86-CMOV-NEXT: cmovnel %ecx, %eax368; X86-CMOV-NEXT: xorl $31, %eax369; X86-CMOV-NEXT: retl370;371; X64-LABEL: ctlz_i32_zero_test:372; X64: # %bb.0:373; X64-NEXT: movl $63, %eax374; X64-NEXT: bsrl %edi, %eax375; X64-NEXT: xorl $31, %eax376; X64-NEXT: retq377;378; X86-CLZ-LABEL: ctlz_i32_zero_test:379; X86-CLZ: # %bb.0:380; X86-CLZ-NEXT: lzcntl {{[0-9]+}}(%esp), %eax381; X86-CLZ-NEXT: retl382;383; X64-CLZ-LABEL: ctlz_i32_zero_test:384; X64-CLZ: # %bb.0:385; X64-CLZ-NEXT: lzcntl %edi, %eax386; X64-CLZ-NEXT: retq387;388; X64-FASTLZCNT-LABEL: ctlz_i32_zero_test:389; X64-FASTLZCNT: # %bb.0:390; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax391; X64-FASTLZCNT-NEXT: retq392;393; X86-FASTLZCNT-LABEL: ctlz_i32_zero_test:394; X86-FASTLZCNT: # %bb.0:395; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax396; X86-FASTLZCNT-NEXT: retl397 %tmp1 = call i32 @llvm.ctlz.i32(i32 %n, i1 false)398 ret i32 %tmp1399}400 401; Generate a test and branch to handle zero inputs because bsr/bsf are very slow.402define i64 @ctlz_i64_zero_test(i64 %n) nounwind {403; X86-NOCMOV-LABEL: ctlz_i64_zero_test:404; X86-NOCMOV: # %bb.0:405; X86-NOCMOV-NEXT: pushl %esi406; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %eax407; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %ecx408; X86-NOCMOV-NEXT: xorl %edx, %edx409; X86-NOCMOV-NEXT: movl %ecx, %esi410; X86-NOCMOV-NEXT: orl %eax, %esi411; X86-NOCMOV-NEXT: je .LBB7_1412; X86-NOCMOV-NEXT: # %bb.2: # %cond.false413; X86-NOCMOV-NEXT: testl %eax, %eax414; X86-NOCMOV-NEXT: jne .LBB7_3415; X86-NOCMOV-NEXT: # %bb.4: # %cond.false416; X86-NOCMOV-NEXT: bsrl %ecx, %eax417; X86-NOCMOV-NEXT: xorl $31, %eax418; X86-NOCMOV-NEXT: orl $32, %eax419; X86-NOCMOV-NEXT: popl %esi420; X86-NOCMOV-NEXT: retl421; X86-NOCMOV-NEXT: .LBB7_1:422; X86-NOCMOV-NEXT: movl $64, %eax423; X86-NOCMOV-NEXT: popl %esi424; X86-NOCMOV-NEXT: retl425; X86-NOCMOV-NEXT: .LBB7_3:426; X86-NOCMOV-NEXT: bsrl %eax, %eax427; X86-NOCMOV-NEXT: xorl $31, %eax428; X86-NOCMOV-NEXT: popl %esi429; X86-NOCMOV-NEXT: retl430;431; X86-CMOV-LABEL: ctlz_i64_zero_test:432; X86-CMOV: # %bb.0:433; X86-CMOV-NEXT: movl {{[0-9]+}}(%esp), %ecx434; X86-CMOV-NEXT: bsrl {{[0-9]+}}(%esp), %eax435; X86-CMOV-NEXT: movl $63, %edx436; X86-CMOV-NEXT: cmovnel %eax, %edx437; X86-CMOV-NEXT: xorl $31, %edx438; X86-CMOV-NEXT: addl $32, %edx439; X86-CMOV-NEXT: bsrl %ecx, %eax440; X86-CMOV-NEXT: xorl $31, %eax441; X86-CMOV-NEXT: testl %ecx, %ecx442; X86-CMOV-NEXT: cmovel %edx, %eax443; X86-CMOV-NEXT: xorl %edx, %edx444; X86-CMOV-NEXT: retl445;446; X64-LABEL: ctlz_i64_zero_test:447; X64: # %bb.0:448; X64-NEXT: movl $127, %eax449; X64-NEXT: bsrq %rdi, %rax450; X64-NEXT: xorq $63, %rax451; X64-NEXT: retq452;453; X86-CLZ-LABEL: ctlz_i64_zero_test:454; X86-CLZ: # %bb.0:455; X86-CLZ-NEXT: movl {{[0-9]+}}(%esp), %eax456; X86-CLZ-NEXT: testl %eax, %eax457; X86-CLZ-NEXT: jne .LBB7_1458; X86-CLZ-NEXT: # %bb.2:459; X86-CLZ-NEXT: lzcntl {{[0-9]+}}(%esp), %eax460; X86-CLZ-NEXT: addl $32, %eax461; X86-CLZ-NEXT: xorl %edx, %edx462; X86-CLZ-NEXT: retl463; X86-CLZ-NEXT: .LBB7_1:464; X86-CLZ-NEXT: lzcntl %eax, %eax465; X86-CLZ-NEXT: xorl %edx, %edx466; X86-CLZ-NEXT: retl467;468; X64-CLZ-LABEL: ctlz_i64_zero_test:469; X64-CLZ: # %bb.0:470; X64-CLZ-NEXT: lzcntq %rdi, %rax471; X64-CLZ-NEXT: retq472;473; X64-FASTLZCNT-LABEL: ctlz_i64_zero_test:474; X64-FASTLZCNT: # %bb.0:475; X64-FASTLZCNT-NEXT: lzcntq %rdi, %rax476; X64-FASTLZCNT-NEXT: retq477;478; X86-FASTLZCNT-LABEL: ctlz_i64_zero_test:479; X86-FASTLZCNT: # %bb.0:480; X86-FASTLZCNT-NEXT: movl {{[0-9]+}}(%esp), %eax481; X86-FASTLZCNT-NEXT: testl %eax, %eax482; X86-FASTLZCNT-NEXT: jne .LBB7_1483; X86-FASTLZCNT-NEXT: # %bb.2:484; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax485; X86-FASTLZCNT-NEXT: addl $32, %eax486; X86-FASTLZCNT-NEXT: xorl %edx, %edx487; X86-FASTLZCNT-NEXT: retl488; X86-FASTLZCNT-NEXT: .LBB7_1:489; X86-FASTLZCNT-NEXT: lzcntl %eax, %eax490; X86-FASTLZCNT-NEXT: xorl %edx, %edx491; X86-FASTLZCNT-NEXT: retl492 %tmp1 = call i64 @llvm.ctlz.i64(i64 %n, i1 false)493 ret i64 %tmp1494}495 496; Don't generate the cmovne when the source is known non-zero (and bsr would497; not set ZF).498; rdar://9490949499define i32 @ctlz_i32_fold_cmov(i32 %n) {500; X86-LABEL: ctlz_i32_fold_cmov:501; X86: # %bb.0:502; X86-NEXT: movl {{[0-9]+}}(%esp), %eax503; X86-NEXT: orl $1, %eax504; X86-NEXT: bsrl %eax, %eax505; X86-NEXT: xorl $31, %eax506; X86-NEXT: retl507;508; X64-LABEL: ctlz_i32_fold_cmov:509; X64: # %bb.0:510; X64-NEXT: orl $1, %edi511; X64-NEXT: bsrl %edi, %eax512; X64-NEXT: xorl $31, %eax513; X64-NEXT: retq514;515; X86-CLZ-LABEL: ctlz_i32_fold_cmov:516; X86-CLZ: # %bb.0:517; X86-CLZ-NEXT: movl {{[0-9]+}}(%esp), %eax518; X86-CLZ-NEXT: orl $1, %eax519; X86-CLZ-NEXT: lzcntl %eax, %eax520; X86-CLZ-NEXT: retl521;522; X64-CLZ-LABEL: ctlz_i32_fold_cmov:523; X64-CLZ: # %bb.0:524; X64-CLZ-NEXT: orl $1, %edi525; X64-CLZ-NEXT: lzcntl %edi, %eax526; X64-CLZ-NEXT: retq527;528; X64-FASTLZCNT-LABEL: ctlz_i32_fold_cmov:529; X64-FASTLZCNT: # %bb.0:530; X64-FASTLZCNT-NEXT: orl $1, %edi531; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax532; X64-FASTLZCNT-NEXT: retq533;534; X86-FASTLZCNT-LABEL: ctlz_i32_fold_cmov:535; X86-FASTLZCNT: # %bb.0:536; X86-FASTLZCNT-NEXT: movl {{[0-9]+}}(%esp), %eax537; X86-FASTLZCNT-NEXT: orl $1, %eax538; X86-FASTLZCNT-NEXT: lzcntl %eax, %eax539; X86-FASTLZCNT-NEXT: retl540 %or = or i32 %n, 1541 %tmp1 = call i32 @llvm.ctlz.i32(i32 %or, i1 false)542 ret i32 %tmp1543}544 545; Don't generate any xors when a 'ctlz' intrinsic is actually used to compute546; the most significant bit, which is what 'bsr' does natively.547; NOTE: We intentionally don't select `bsr` when `fast-lzcnt` is548; available. This is 1) because `bsr` has some drawbacks including a549; dependency on dst, 2) very poor performance on some of the550; `fast-lzcnt` processors, and 3) `lzcnt` runs at ALU latency/throughput551; so `lzcnt` + `xor` has better throughput than even the 1-uop552; (1c latency, 1c throughput) `bsr`.553define i32 @ctlz_bsr(i32 %n) {554; X86-LABEL: ctlz_bsr:555; X86: # %bb.0:556; X86-NEXT: bsrl {{[0-9]+}}(%esp), %eax557; X86-NEXT: retl558;559; X64-LABEL: ctlz_bsr:560; X64: # %bb.0:561; X64-NEXT: bsrl %edi, %eax562; X64-NEXT: retq563;564; X86-CLZ-LABEL: ctlz_bsr:565; X86-CLZ: # %bb.0:566; X86-CLZ-NEXT: bsrl {{[0-9]+}}(%esp), %eax567; X86-CLZ-NEXT: retl568;569; X64-CLZ-LABEL: ctlz_bsr:570; X64-CLZ: # %bb.0:571; X64-CLZ-NEXT: bsrl %edi, %eax572; X64-CLZ-NEXT: retq573;574; X64-FASTLZCNT-LABEL: ctlz_bsr:575; X64-FASTLZCNT: # %bb.0:576; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax577; X64-FASTLZCNT-NEXT: xorl $31, %eax578; X64-FASTLZCNT-NEXT: retq579;580; X86-FASTLZCNT-LABEL: ctlz_bsr:581; X86-FASTLZCNT: # %bb.0:582; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax583; X86-FASTLZCNT-NEXT: xorl $31, %eax584; X86-FASTLZCNT-NEXT: retl585 %ctlz = call i32 @llvm.ctlz.i32(i32 %n, i1 true)586 %bsr = xor i32 %ctlz, 31587 ret i32 %bsr588}589 590; Generate a test and branch to handle zero inputs because bsr/bsf are very slow.591; FIXME: The compare and branch are produced late in IR (by CodeGenPrepare), and592; codegen doesn't know how to combine the $32 and $31 into $63.593define i32 @ctlz_bsr_zero_test(i32 %n) {594; X86-NOCMOV-LABEL: ctlz_bsr_zero_test:595; X86-NOCMOV: # %bb.0:596; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %eax597; X86-NOCMOV-NEXT: testl %eax, %eax598; X86-NOCMOV-NEXT: je .LBB10_1599; X86-NOCMOV-NEXT: # %bb.2: # %cond.false600; X86-NOCMOV-NEXT: bsrl %eax, %eax601; X86-NOCMOV-NEXT: xorl $31, %eax602; X86-NOCMOV-NEXT: xorl $31, %eax603; X86-NOCMOV-NEXT: retl604; X86-NOCMOV-NEXT: .LBB10_1:605; X86-NOCMOV-NEXT: movl $32, %eax606; X86-NOCMOV-NEXT: xorl $31, %eax607; X86-NOCMOV-NEXT: retl608;609; X86-CMOV-LABEL: ctlz_bsr_zero_test:610; X86-CMOV: # %bb.0:611; X86-CMOV-NEXT: bsrl {{[0-9]+}}(%esp), %ecx612; X86-CMOV-NEXT: movl $63, %eax613; X86-CMOV-NEXT: cmovnel %ecx, %eax614; X86-CMOV-NEXT: retl615;616; X64-LABEL: ctlz_bsr_zero_test:617; X64: # %bb.0:618; X64-NEXT: movl $63, %eax619; X64-NEXT: bsrl %edi, %eax620; X64-NEXT: retq621;622; X86-CLZ-LABEL: ctlz_bsr_zero_test:623; X86-CLZ: # %bb.0:624; X86-CLZ-NEXT: lzcntl {{[0-9]+}}(%esp), %eax625; X86-CLZ-NEXT: xorl $31, %eax626; X86-CLZ-NEXT: retl627;628; X64-CLZ-LABEL: ctlz_bsr_zero_test:629; X64-CLZ: # %bb.0:630; X64-CLZ-NEXT: lzcntl %edi, %eax631; X64-CLZ-NEXT: xorl $31, %eax632; X64-CLZ-NEXT: retq633;634; X64-FASTLZCNT-LABEL: ctlz_bsr_zero_test:635; X64-FASTLZCNT: # %bb.0:636; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax637; X64-FASTLZCNT-NEXT: xorl $31, %eax638; X64-FASTLZCNT-NEXT: retq639;640; X86-FASTLZCNT-LABEL: ctlz_bsr_zero_test:641; X86-FASTLZCNT: # %bb.0:642; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax643; X86-FASTLZCNT-NEXT: xorl $31, %eax644; X86-FASTLZCNT-NEXT: retl645 %ctlz = call i32 @llvm.ctlz.i32(i32 %n, i1 false)646 %bsr = xor i32 %ctlz, 31647 ret i32 %bsr648}649 650define i8 @ctlz_i8_knownbits(i8 %x) {651; X86-LABEL: ctlz_i8_knownbits:652; X86: # %bb.0:653; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax654; X86-NEXT: orb $64, %al655; X86-NEXT: movzbl %al, %eax656; X86-NEXT: bsrl %eax, %eax657; X86-NEXT: xorl $7, %eax658; X86-NEXT: # kill: def $al killed $al killed $eax659; X86-NEXT: retl660;661; X64-LABEL: ctlz_i8_knownbits:662; X64: # %bb.0:663; X64-NEXT: orb $64, %dil664; X64-NEXT: movzbl %dil, %eax665; X64-NEXT: bsrl %eax, %eax666; X64-NEXT: xorl $7, %eax667; X64-NEXT: # kill: def $al killed $al killed $eax668; X64-NEXT: retq669;670; X86-CLZ-LABEL: ctlz_i8_knownbits:671; X86-CLZ: # %bb.0:672; X86-CLZ-NEXT: movzbl {{[0-9]+}}(%esp), %eax673; X86-CLZ-NEXT: orb $64, %al674; X86-CLZ-NEXT: movzbl %al, %eax675; X86-CLZ-NEXT: shll $24, %eax676; X86-CLZ-NEXT: lzcntl %eax, %eax677; X86-CLZ-NEXT: # kill: def $al killed $al killed $eax678; X86-CLZ-NEXT: retl679;680; X64-CLZ-LABEL: ctlz_i8_knownbits:681; X64-CLZ: # %bb.0:682; X64-CLZ-NEXT: orb $64, %dil683; X64-CLZ-NEXT: movzbl %dil, %eax684; X64-CLZ-NEXT: shll $24, %eax685; X64-CLZ-NEXT: lzcntl %eax, %eax686; X64-CLZ-NEXT: # kill: def $al killed $al killed $eax687; X64-CLZ-NEXT: retq688;689; X64-FASTLZCNT-LABEL: ctlz_i8_knownbits:690; X64-FASTLZCNT: # %bb.0:691; X64-FASTLZCNT-NEXT: orb $64, %dil692; X64-FASTLZCNT-NEXT: movzbl %dil, %eax693; X64-FASTLZCNT-NEXT: shll $24, %eax694; X64-FASTLZCNT-NEXT: lzcntl %eax, %eax695; X64-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax696; X64-FASTLZCNT-NEXT: retq697;698; X86-FASTLZCNT-LABEL: ctlz_i8_knownbits:699; X86-FASTLZCNT: # %bb.0:700; X86-FASTLZCNT-NEXT: movzbl {{[0-9]+}}(%esp), %eax701; X86-FASTLZCNT-NEXT: orb $64, %al702; X86-FASTLZCNT-NEXT: movzbl %al, %eax703; X86-FASTLZCNT-NEXT: shll $24, %eax704; X86-FASTLZCNT-NEXT: lzcntl %eax, %eax705; X86-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax706; X86-FASTLZCNT-NEXT: retl707 708 %x2 = or i8 %x, 64709 %tmp = call i8 @llvm.ctlz.i8(i8 %x2, i1 true )710 %tmp2 = and i8 %tmp, 1711 ret i8 %tmp2712}713 714; Make sure we can detect that the input is non-zero and avoid cmov after BSR715; This is relevant for 32-bit mode without lzcnt716define i64 @ctlz_i64_zero_test_knownneverzero(i64 %n) {717; X86-NOCMOV-LABEL: ctlz_i64_zero_test_knownneverzero:718; X86-NOCMOV: # %bb.0:719; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %eax720; X86-NOCMOV-NEXT: testl %eax, %eax721; X86-NOCMOV-NEXT: jne .LBB12_1722; X86-NOCMOV-NEXT: # %bb.2:723; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %eax724; X86-NOCMOV-NEXT: orl $1, %eax725; X86-NOCMOV-NEXT: bsrl %eax, %eax726; X86-NOCMOV-NEXT: xorl $31, %eax727; X86-NOCMOV-NEXT: orl $32, %eax728; X86-NOCMOV-NEXT: xorl %edx, %edx729; X86-NOCMOV-NEXT: retl730; X86-NOCMOV-NEXT: .LBB12_1:731; X86-NOCMOV-NEXT: bsrl %eax, %eax732; X86-NOCMOV-NEXT: xorl $31, %eax733; X86-NOCMOV-NEXT: xorl %edx, %edx734; X86-NOCMOV-NEXT: retl735;736; X86-CMOV-LABEL: ctlz_i64_zero_test_knownneverzero:737; X86-CMOV: # %bb.0:738; X86-CMOV-NEXT: movl {{[0-9]+}}(%esp), %eax739; X86-CMOV-NEXT: movl {{[0-9]+}}(%esp), %ecx740; X86-CMOV-NEXT: orl $1, %eax741; X86-CMOV-NEXT: bsrl %ecx, %edx742; X86-CMOV-NEXT: xorl $31, %edx743; X86-CMOV-NEXT: bsrl %eax, %eax744; X86-CMOV-NEXT: xorl $31, %eax745; X86-CMOV-NEXT: orl $32, %eax746; X86-CMOV-NEXT: testl %ecx, %ecx747; X86-CMOV-NEXT: cmovnel %edx, %eax748; X86-CMOV-NEXT: xorl %edx, %edx749; X86-CMOV-NEXT: retl750;751; X64-LABEL: ctlz_i64_zero_test_knownneverzero:752; X64: # %bb.0:753; X64-NEXT: orq $1, %rdi754; X64-NEXT: bsrq %rdi, %rax755; X64-NEXT: xorq $63, %rax756; X64-NEXT: retq757;758; X86-CLZ-LABEL: ctlz_i64_zero_test_knownneverzero:759; X86-CLZ: # %bb.0:760; X86-CLZ-NEXT: movl {{[0-9]+}}(%esp), %eax761; X86-CLZ-NEXT: testl %eax, %eax762; X86-CLZ-NEXT: jne .LBB12_1763; X86-CLZ-NEXT: # %bb.2:764; X86-CLZ-NEXT: movl {{[0-9]+}}(%esp), %eax765; X86-CLZ-NEXT: orl $1, %eax766; X86-CLZ-NEXT: lzcntl %eax, %eax767; X86-CLZ-NEXT: orl $32, %eax768; X86-CLZ-NEXT: xorl %edx, %edx769; X86-CLZ-NEXT: retl770; X86-CLZ-NEXT: .LBB12_1:771; X86-CLZ-NEXT: lzcntl %eax, %eax772; X86-CLZ-NEXT: xorl %edx, %edx773; X86-CLZ-NEXT: retl774;775; X64-CLZ-LABEL: ctlz_i64_zero_test_knownneverzero:776; X64-CLZ: # %bb.0:777; X64-CLZ-NEXT: orq $1, %rdi778; X64-CLZ-NEXT: lzcntq %rdi, %rax779; X64-CLZ-NEXT: retq780;781; X64-FASTLZCNT-LABEL: ctlz_i64_zero_test_knownneverzero:782; X64-FASTLZCNT: # %bb.0:783; X64-FASTLZCNT-NEXT: orq $1, %rdi784; X64-FASTLZCNT-NEXT: lzcntq %rdi, %rax785; X64-FASTLZCNT-NEXT: retq786;787; X86-FASTLZCNT-LABEL: ctlz_i64_zero_test_knownneverzero:788; X86-FASTLZCNT: # %bb.0:789; X86-FASTLZCNT-NEXT: movl {{[0-9]+}}(%esp), %eax790; X86-FASTLZCNT-NEXT: testl %eax, %eax791; X86-FASTLZCNT-NEXT: jne .LBB12_1792; X86-FASTLZCNT-NEXT: # %bb.2:793; X86-FASTLZCNT-NEXT: movl {{[0-9]+}}(%esp), %eax794; X86-FASTLZCNT-NEXT: orl $1, %eax795; X86-FASTLZCNT-NEXT: lzcntl %eax, %eax796; X86-FASTLZCNT-NEXT: orl $32, %eax797; X86-FASTLZCNT-NEXT: xorl %edx, %edx798; X86-FASTLZCNT-NEXT: retl799; X86-FASTLZCNT-NEXT: .LBB12_1:800; X86-FASTLZCNT-NEXT: lzcntl %eax, %eax801; X86-FASTLZCNT-NEXT: xorl %edx, %edx802; X86-FASTLZCNT-NEXT: retl803 %o = or i64 %n, 1804 %tmp1 = call i64 @llvm.ctlz.i64(i64 %o, i1 false)805 ret i64 %tmp1806}807 808; Ensure we fold away the XOR(TRUNC(XOR(BSR(X),31)),31).809define i8 @PR47603_trunc(i32 %0) {810; X86-LABEL: PR47603_trunc:811; X86: # %bb.0:812; X86-NEXT: bsrl {{[0-9]+}}(%esp), %eax813; X86-NEXT: # kill: def $al killed $al killed $eax814; X86-NEXT: retl815;816; X64-LABEL: PR47603_trunc:817; X64: # %bb.0:818; X64-NEXT: bsrl %edi, %eax819; X64-NEXT: # kill: def $al killed $al killed $eax820; X64-NEXT: retq821;822; X86-CLZ-LABEL: PR47603_trunc:823; X86-CLZ: # %bb.0:824; X86-CLZ-NEXT: lzcntl {{[0-9]+}}(%esp), %eax825; X86-CLZ-NEXT: xorb $31, %al826; X86-CLZ-NEXT: # kill: def $al killed $al killed $eax827; X86-CLZ-NEXT: retl828;829; X64-CLZ-LABEL: PR47603_trunc:830; X64-CLZ: # %bb.0:831; X64-CLZ-NEXT: lzcntl %edi, %eax832; X64-CLZ-NEXT: xorb $31, %al833; X64-CLZ-NEXT: # kill: def $al killed $al killed $eax834; X64-CLZ-NEXT: retq835;836; X64-FASTLZCNT-LABEL: PR47603_trunc:837; X64-FASTLZCNT: # %bb.0:838; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax839; X64-FASTLZCNT-NEXT: xorb $31, %al840; X64-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax841; X64-FASTLZCNT-NEXT: retq842;843; X86-FASTLZCNT-LABEL: PR47603_trunc:844; X86-FASTLZCNT: # %bb.0:845; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax846; X86-FASTLZCNT-NEXT: xorb $31, %al847; X86-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax848; X86-FASTLZCNT-NEXT: retl849 %2 = call i32 @llvm.ctlz.i32(i32 %0, i1 true)850 %3 = xor i32 %2, 31851 %4 = trunc i32 %3 to i8852 ret i8 %4853}854 855; Ensure we fold away the XOR(ZEXT(XOR(BSR(X),31)),31).856define i32 @PR47603_zext(i32 %a0, ptr %a1) {857; X86-LABEL: PR47603_zext:858; X86: # %bb.0:859; X86-NEXT: movl {{[0-9]+}}(%esp), %eax860; X86-NEXT: bsrl {{[0-9]+}}(%esp), %ecx861; X86-NEXT: movsbl (%eax,%ecx), %eax862; X86-NEXT: retl863;864; X64-LABEL: PR47603_zext:865; X64: # %bb.0:866; X64-NEXT: bsrl %edi, %eax867; X64-NEXT: movsbl (%rsi,%rax), %eax868; X64-NEXT: retq869;870; X86-CLZ-LABEL: PR47603_zext:871; X86-CLZ: # %bb.0:872; X86-CLZ-NEXT: movl {{[0-9]+}}(%esp), %eax873; X86-CLZ-NEXT: bsrl {{[0-9]+}}(%esp), %ecx874; X86-CLZ-NEXT: movsbl (%eax,%ecx), %eax875; X86-CLZ-NEXT: retl876;877; X64-CLZ-LABEL: PR47603_zext:878; X64-CLZ: # %bb.0:879; X64-CLZ-NEXT: lzcntl %edi, %eax880; X64-CLZ-NEXT: xorq $31, %rax881; X64-CLZ-NEXT: movsbl (%rsi,%rax), %eax882; X64-CLZ-NEXT: retq883;884; X64-FASTLZCNT-LABEL: PR47603_zext:885; X64-FASTLZCNT: # %bb.0:886; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax887; X64-FASTLZCNT-NEXT: xorq $31, %rax888; X64-FASTLZCNT-NEXT: movsbl (%rsi,%rax), %eax889; X64-FASTLZCNT-NEXT: retq890;891; X86-FASTLZCNT-LABEL: PR47603_zext:892; X86-FASTLZCNT: # %bb.0:893; X86-FASTLZCNT-NEXT: movl {{[0-9]+}}(%esp), %eax894; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %ecx895; X86-FASTLZCNT-NEXT: xorl $31, %ecx896; X86-FASTLZCNT-NEXT: movsbl (%eax,%ecx), %eax897; X86-FASTLZCNT-NEXT: retl898 %ctlz = tail call i32 @llvm.ctlz.i32(i32 %a0, i1 true)899 %xor = xor i32 %ctlz, 31900 %zext = zext i32 %xor to i64901 %gep = getelementptr inbounds [32 x i8], ptr %a1, i64 0, i64 %zext902 %load = load i8, ptr %gep, align 1903 %sext = sext i8 %load to i32904 ret i32 %sext905}906 907define i8 @ctlz_xor7_i8_true(i8 %x) {908; X86-LABEL: ctlz_xor7_i8_true:909; X86: # %bb.0:910; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax911; X86-NEXT: bsrl %eax, %eax912; X86-NEXT: # kill: def $al killed $al killed $eax913; X86-NEXT: retl914;915; X64-LABEL: ctlz_xor7_i8_true:916; X64: # %bb.0:917; X64-NEXT: movzbl %dil, %eax918; X64-NEXT: bsrl %eax, %eax919; X64-NEXT: # kill: def $al killed $al killed $eax920; X64-NEXT: retq921;922; X86-CLZ-LABEL: ctlz_xor7_i8_true:923; X86-CLZ: # %bb.0:924; X86-CLZ-NEXT: movzbl {{[0-9]+}}(%esp), %eax925; X86-CLZ-NEXT: bsrl %eax, %eax926; X86-CLZ-NEXT: # kill: def $al killed $al killed $eax927; X86-CLZ-NEXT: retl928;929; X64-CLZ-LABEL: ctlz_xor7_i8_true:930; X64-CLZ: # %bb.0:931; X64-CLZ-NEXT: movzbl %dil, %eax932; X64-CLZ-NEXT: bsrl %eax, %eax933; X64-CLZ-NEXT: # kill: def $al killed $al killed $eax934; X64-CLZ-NEXT: retq935;936; X64-FASTLZCNT-LABEL: ctlz_xor7_i8_true:937; X64-FASTLZCNT: # %bb.0:938; X64-FASTLZCNT-NEXT: shll $24, %edi939; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax940; X64-FASTLZCNT-NEXT: xorb $7, %al941; X64-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax942; X64-FASTLZCNT-NEXT: retq943;944; X86-FASTLZCNT-LABEL: ctlz_xor7_i8_true:945; X86-FASTLZCNT: # %bb.0:946; X86-FASTLZCNT-NEXT: movl {{[0-9]+}}(%esp), %eax947; X86-FASTLZCNT-NEXT: shll $24, %eax948; X86-FASTLZCNT-NEXT: lzcntl %eax, %eax949; X86-FASTLZCNT-NEXT: xorb $7, %al950; X86-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax951; X86-FASTLZCNT-NEXT: retl952 %clz = call i8 @llvm.ctlz.i8(i8 %x, i1 true)953 %res = xor i8 %clz, 7954 ret i8 %res955}956 957define i8 @ctlz_xor7_i8_false(i8 %x) {958; X86-NOCMOV-LABEL: ctlz_xor7_i8_false:959; X86-NOCMOV: # %bb.0:960; X86-NOCMOV-NEXT: movzbl {{[0-9]+}}(%esp), %eax961; X86-NOCMOV-NEXT: testb %al, %al962; X86-NOCMOV-NEXT: je .LBB16_1963; X86-NOCMOV-NEXT: # %bb.2: # %cond.false964; X86-NOCMOV-NEXT: movzbl %al, %eax965; X86-NOCMOV-NEXT: bsrl %eax, %eax966; X86-NOCMOV-NEXT: xorl $7, %eax967; X86-NOCMOV-NEXT: xorb $7, %al968; X86-NOCMOV-NEXT: # kill: def $al killed $al killed $eax969; X86-NOCMOV-NEXT: retl970; X86-NOCMOV-NEXT: .LBB16_1:971; X86-NOCMOV-NEXT: movb $8, %al972; X86-NOCMOV-NEXT: xorb $7, %al973; X86-NOCMOV-NEXT: # kill: def $al killed $al killed $eax974; X86-NOCMOV-NEXT: retl975;976; X86-CMOV-LABEL: ctlz_xor7_i8_false:977; X86-CMOV: # %bb.0:978; X86-CMOV-NEXT: movzbl {{[0-9]+}}(%esp), %eax979; X86-CMOV-NEXT: bsrl %eax, %ecx980; X86-CMOV-NEXT: movl $15, %eax981; X86-CMOV-NEXT: cmovnel %ecx, %eax982; X86-CMOV-NEXT: # kill: def $al killed $al killed $eax983; X86-CMOV-NEXT: retl984;985; X64-LABEL: ctlz_xor7_i8_false:986; X64: # %bb.0:987; X64-NEXT: movzbl %dil, %ecx988; X64-NEXT: movl $15, %eax989; X64-NEXT: bsrl %ecx, %eax990; X64-NEXT: # kill: def $al killed $al killed $eax991; X64-NEXT: retq992;993; X86-CLZ-LABEL: ctlz_xor7_i8_false:994; X86-CLZ: # %bb.0:995; X86-CLZ-NEXT: movzbl {{[0-9]+}}(%esp), %eax996; X86-CLZ-NEXT: lzcntl %eax, %eax997; X86-CLZ-NEXT: addl $-24, %eax998; X86-CLZ-NEXT: xorb $7, %al999; X86-CLZ-NEXT: # kill: def $al killed $al killed $eax1000; X86-CLZ-NEXT: retl1001;1002; X64-CLZ-LABEL: ctlz_xor7_i8_false:1003; X64-CLZ: # %bb.0:1004; X64-CLZ-NEXT: movzbl %dil, %eax1005; X64-CLZ-NEXT: lzcntl %eax, %eax1006; X64-CLZ-NEXT: addl $-24, %eax1007; X64-CLZ-NEXT: xorb $7, %al1008; X64-CLZ-NEXT: # kill: def $al killed $al killed $eax1009; X64-CLZ-NEXT: retq1010;1011; X64-FASTLZCNT-LABEL: ctlz_xor7_i8_false:1012; X64-FASTLZCNT: # %bb.0:1013; X64-FASTLZCNT-NEXT: movzbl %dil, %eax1014; X64-FASTLZCNT-NEXT: lzcntl %eax, %eax1015; X64-FASTLZCNT-NEXT: addl $-24, %eax1016; X64-FASTLZCNT-NEXT: xorb $7, %al1017; X64-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax1018; X64-FASTLZCNT-NEXT: retq1019;1020; X86-FASTLZCNT-LABEL: ctlz_xor7_i8_false:1021; X86-FASTLZCNT: # %bb.0:1022; X86-FASTLZCNT-NEXT: movzbl {{[0-9]+}}(%esp), %eax1023; X86-FASTLZCNT-NEXT: lzcntl %eax, %eax1024; X86-FASTLZCNT-NEXT: addl $-24, %eax1025; X86-FASTLZCNT-NEXT: xorb $7, %al1026; X86-FASTLZCNT-NEXT: # kill: def $al killed $al killed $eax1027; X86-FASTLZCNT-NEXT: retl1028 %clz = call i8 @llvm.ctlz.i8(i8 %x, i1 false)1029 %res = xor i8 %clz, 71030 ret i8 %res1031}1032 1033define i16 @ctlz_xor15_i16_true(i16 %x) {1034; X86-LABEL: ctlz_xor15_i16_true:1035; X86: # %bb.0:1036; X86-NEXT: bsrw {{[0-9]+}}(%esp), %ax1037; X86-NEXT: retl1038;1039; X64-LABEL: ctlz_xor15_i16_true:1040; X64: # %bb.0:1041; X64-NEXT: bsrw %di, %ax1042; X64-NEXT: retq1043;1044; X86-CLZ-LABEL: ctlz_xor15_i16_true:1045; X86-CLZ: # %bb.0:1046; X86-CLZ-NEXT: bsrw {{[0-9]+}}(%esp), %ax1047; X86-CLZ-NEXT: retl1048;1049; X64-CLZ-LABEL: ctlz_xor15_i16_true:1050; X64-CLZ: # %bb.0:1051; X64-CLZ-NEXT: bsrw %di, %ax1052; X64-CLZ-NEXT: retq1053;1054; X64-FASTLZCNT-LABEL: ctlz_xor15_i16_true:1055; X64-FASTLZCNT: # %bb.0:1056; X64-FASTLZCNT-NEXT: lzcntw %di, %ax1057; X64-FASTLZCNT-NEXT: xorl $15, %eax1058; X64-FASTLZCNT-NEXT: # kill: def $ax killed $ax killed $eax1059; X64-FASTLZCNT-NEXT: retq1060;1061; X86-FASTLZCNT-LABEL: ctlz_xor15_i16_true:1062; X86-FASTLZCNT: # %bb.0:1063; X86-FASTLZCNT-NEXT: lzcntw {{[0-9]+}}(%esp), %ax1064; X86-FASTLZCNT-NEXT: xorl $15, %eax1065; X86-FASTLZCNT-NEXT: # kill: def $ax killed $ax killed $eax1066; X86-FASTLZCNT-NEXT: retl1067 %clz = call i16 @llvm.ctlz.i16(i16 %x, i1 true)1068 %res = xor i16 %clz, 151069 ret i16 %res1070}1071 1072define i32 @ctlz_xor31_i32_false(i32 %x) {1073; X86-NOCMOV-LABEL: ctlz_xor31_i32_false:1074; X86-NOCMOV: # %bb.0:1075; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %eax1076; X86-NOCMOV-NEXT: testl %eax, %eax1077; X86-NOCMOV-NEXT: je .LBB18_11078; X86-NOCMOV-NEXT: # %bb.2: # %cond.false1079; X86-NOCMOV-NEXT: bsrl %eax, %eax1080; X86-NOCMOV-NEXT: xorl $31, %eax1081; X86-NOCMOV-NEXT: xorl $31, %eax1082; X86-NOCMOV-NEXT: retl1083; X86-NOCMOV-NEXT: .LBB18_1:1084; X86-NOCMOV-NEXT: movl $32, %eax1085; X86-NOCMOV-NEXT: xorl $31, %eax1086; X86-NOCMOV-NEXT: retl1087;1088; X86-CMOV-LABEL: ctlz_xor31_i32_false:1089; X86-CMOV: # %bb.0:1090; X86-CMOV-NEXT: bsrl {{[0-9]+}}(%esp), %ecx1091; X86-CMOV-NEXT: movl $63, %eax1092; X86-CMOV-NEXT: cmovnel %ecx, %eax1093; X86-CMOV-NEXT: retl1094;1095; X64-LABEL: ctlz_xor31_i32_false:1096; X64: # %bb.0:1097; X64-NEXT: movl $63, %eax1098; X64-NEXT: bsrl %edi, %eax1099; X64-NEXT: retq1100;1101; X86-CLZ-LABEL: ctlz_xor31_i32_false:1102; X86-CLZ: # %bb.0:1103; X86-CLZ-NEXT: lzcntl {{[0-9]+}}(%esp), %eax1104; X86-CLZ-NEXT: xorl $31, %eax1105; X86-CLZ-NEXT: retl1106;1107; X64-CLZ-LABEL: ctlz_xor31_i32_false:1108; X64-CLZ: # %bb.0:1109; X64-CLZ-NEXT: lzcntl %edi, %eax1110; X64-CLZ-NEXT: xorl $31, %eax1111; X64-CLZ-NEXT: retq1112;1113; X64-FASTLZCNT-LABEL: ctlz_xor31_i32_false:1114; X64-FASTLZCNT: # %bb.0:1115; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax1116; X64-FASTLZCNT-NEXT: xorl $31, %eax1117; X64-FASTLZCNT-NEXT: retq1118;1119; X86-FASTLZCNT-LABEL: ctlz_xor31_i32_false:1120; X86-FASTLZCNT: # %bb.0:1121; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax1122; X86-FASTLZCNT-NEXT: xorl $31, %eax1123; X86-FASTLZCNT-NEXT: retl1124 %clz = call i32 @llvm.ctlz.i32(i32 %x, i1 false)1125 %res = xor i32 %clz, 311126 ret i32 %res1127}1128 1129define i64 @ctlz_xor63_i64_true(i64 %x) {1130; X86-NOCMOV-LABEL: ctlz_xor63_i64_true:1131; X86-NOCMOV: # %bb.0:1132; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %eax1133; X86-NOCMOV-NEXT: testl %eax, %eax1134; X86-NOCMOV-NEXT: jne .LBB19_11135; X86-NOCMOV-NEXT: # %bb.2:1136; X86-NOCMOV-NEXT: bsrl {{[0-9]+}}(%esp), %eax1137; X86-NOCMOV-NEXT: xorl $31, %eax1138; X86-NOCMOV-NEXT: orl $32, %eax1139; X86-NOCMOV-NEXT: jmp .LBB19_31140; X86-NOCMOV-NEXT: .LBB19_1:1141; X86-NOCMOV-NEXT: bsrl %eax, %eax1142; X86-NOCMOV-NEXT: xorl $31, %eax1143; X86-NOCMOV-NEXT: .LBB19_3:1144; X86-NOCMOV-NEXT: xorl $63, %eax1145; X86-NOCMOV-NEXT: xorl %edx, %edx1146; X86-NOCMOV-NEXT: retl1147;1148; X86-CMOV-LABEL: ctlz_xor63_i64_true:1149; X86-CMOV: # %bb.0:1150; X86-CMOV-NEXT: movl {{[0-9]+}}(%esp), %ecx1151; X86-CMOV-NEXT: bsrl %ecx, %edx1152; X86-CMOV-NEXT: xorl $31, %edx1153; X86-CMOV-NEXT: bsrl {{[0-9]+}}(%esp), %eax1154; X86-CMOV-NEXT: xorl $31, %eax1155; X86-CMOV-NEXT: orl $32, %eax1156; X86-CMOV-NEXT: testl %ecx, %ecx1157; X86-CMOV-NEXT: cmovnel %edx, %eax1158; X86-CMOV-NEXT: xorl $63, %eax1159; X86-CMOV-NEXT: xorl %edx, %edx1160; X86-CMOV-NEXT: retl1161;1162; X64-LABEL: ctlz_xor63_i64_true:1163; X64: # %bb.0:1164; X64-NEXT: bsrq %rdi, %rax1165; X64-NEXT: retq1166;1167; X86-CLZ-LABEL: ctlz_xor63_i64_true:1168; X86-CLZ: # %bb.0:1169; X86-CLZ-NEXT: movl {{[0-9]+}}(%esp), %eax1170; X86-CLZ-NEXT: testl %eax, %eax1171; X86-CLZ-NEXT: jne .LBB19_11172; X86-CLZ-NEXT: # %bb.2:1173; X86-CLZ-NEXT: lzcntl {{[0-9]+}}(%esp), %eax1174; X86-CLZ-NEXT: addl $32, %eax1175; X86-CLZ-NEXT: jmp .LBB19_31176; X86-CLZ-NEXT: .LBB19_1:1177; X86-CLZ-NEXT: lzcntl %eax, %eax1178; X86-CLZ-NEXT: .LBB19_3:1179; X86-CLZ-NEXT: xorl $63, %eax1180; X86-CLZ-NEXT: xorl %edx, %edx1181; X86-CLZ-NEXT: retl1182;1183; X64-CLZ-LABEL: ctlz_xor63_i64_true:1184; X64-CLZ: # %bb.0:1185; X64-CLZ-NEXT: bsrq %rdi, %rax1186; X64-CLZ-NEXT: retq1187;1188; X64-FASTLZCNT-LABEL: ctlz_xor63_i64_true:1189; X64-FASTLZCNT: # %bb.0:1190; X64-FASTLZCNT-NEXT: lzcntq %rdi, %rax1191; X64-FASTLZCNT-NEXT: xorq $63, %rax1192; X64-FASTLZCNT-NEXT: retq1193;1194; X86-FASTLZCNT-LABEL: ctlz_xor63_i64_true:1195; X86-FASTLZCNT: # %bb.0:1196; X86-FASTLZCNT-NEXT: movl {{[0-9]+}}(%esp), %eax1197; X86-FASTLZCNT-NEXT: testl %eax, %eax1198; X86-FASTLZCNT-NEXT: jne .LBB19_11199; X86-FASTLZCNT-NEXT: # %bb.2:1200; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax1201; X86-FASTLZCNT-NEXT: addl $32, %eax1202; X86-FASTLZCNT-NEXT: jmp .LBB19_31203; X86-FASTLZCNT-NEXT: .LBB19_1:1204; X86-FASTLZCNT-NEXT: lzcntl %eax, %eax1205; X86-FASTLZCNT-NEXT: .LBB19_3:1206; X86-FASTLZCNT-NEXT: xorl $63, %eax1207; X86-FASTLZCNT-NEXT: xorl %edx, %edx1208; X86-FASTLZCNT-NEXT: retl1209 %clz = call i64 @llvm.ctlz.i64(i64 %x, i1 true)1210 %res = xor i64 %clz, 631211 ret i64 %res1212}1213 1214define i64 @ctlz_i32_sext(i32 %x) {1215; X86-NOCMOV-LABEL: ctlz_i32_sext:1216; X86-NOCMOV: # %bb.0:1217; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %eax1218; X86-NOCMOV-NEXT: testl %eax, %eax1219; X86-NOCMOV-NEXT: je .LBB20_11220; X86-NOCMOV-NEXT: # %bb.2: # %cond.false1221; X86-NOCMOV-NEXT: bsrl %eax, %eax1222; X86-NOCMOV-NEXT: xorl $31, %eax1223; X86-NOCMOV-NEXT: jmp .LBB20_31224; X86-NOCMOV-NEXT: .LBB20_1:1225; X86-NOCMOV-NEXT: movl $32, %eax1226; X86-NOCMOV-NEXT: .LBB20_3: # %cond.end1227; X86-NOCMOV-NEXT: xorl $31, %eax1228; X86-NOCMOV-NEXT: xorl %edx, %edx1229; X86-NOCMOV-NEXT: retl1230;1231; X86-CMOV-LABEL: ctlz_i32_sext:1232; X86-CMOV: # %bb.0:1233; X86-CMOV-NEXT: bsrl {{[0-9]+}}(%esp), %ecx1234; X86-CMOV-NEXT: movl $63, %eax1235; X86-CMOV-NEXT: cmovnel %ecx, %eax1236; X86-CMOV-NEXT: xorl %edx, %edx1237; X86-CMOV-NEXT: retl1238;1239; X64-LABEL: ctlz_i32_sext:1240; X64: # %bb.0:1241; X64-NEXT: movl $63, %eax1242; X64-NEXT: bsrl %edi, %eax1243; X64-NEXT: retq1244;1245; X86-CLZ-LABEL: ctlz_i32_sext:1246; X86-CLZ: # %bb.0:1247; X86-CLZ-NEXT: lzcntl {{[0-9]+}}(%esp), %eax1248; X86-CLZ-NEXT: xorl $31, %eax1249; X86-CLZ-NEXT: xorl %edx, %edx1250; X86-CLZ-NEXT: retl1251;1252; X64-CLZ-LABEL: ctlz_i32_sext:1253; X64-CLZ: # %bb.0:1254; X64-CLZ-NEXT: lzcntl %edi, %eax1255; X64-CLZ-NEXT: xorl $31, %eax1256; X64-CLZ-NEXT: retq1257;1258; X64-FASTLZCNT-LABEL: ctlz_i32_sext:1259; X64-FASTLZCNT: # %bb.0:1260; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax1261; X64-FASTLZCNT-NEXT: xorl $31, %eax1262; X64-FASTLZCNT-NEXT: retq1263;1264; X86-FASTLZCNT-LABEL: ctlz_i32_sext:1265; X86-FASTLZCNT: # %bb.0:1266; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax1267; X86-FASTLZCNT-NEXT: xorl $31, %eax1268; X86-FASTLZCNT-NEXT: xorl %edx, %edx1269; X86-FASTLZCNT-NEXT: retl1270 %tmp = call i32 @llvm.ctlz.i32( i32 %x, i1 false)1271 %xor = xor i32 %tmp, 311272 %ext = sext i32 %xor to i641273 ret i64 %ext1274}1275 1276define i64 @ctlz_i32_zext(i32 %x) {1277; X86-NOCMOV-LABEL: ctlz_i32_zext:1278; X86-NOCMOV: # %bb.0:1279; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %eax1280; X86-NOCMOV-NEXT: testl %eax, %eax1281; X86-NOCMOV-NEXT: je .LBB21_11282; X86-NOCMOV-NEXT: # %bb.2: # %cond.false1283; X86-NOCMOV-NEXT: bsrl %eax, %eax1284; X86-NOCMOV-NEXT: xorl $31, %eax1285; X86-NOCMOV-NEXT: jmp .LBB21_31286; X86-NOCMOV-NEXT: .LBB21_1:1287; X86-NOCMOV-NEXT: movl $32, %eax1288; X86-NOCMOV-NEXT: .LBB21_3: # %cond.end1289; X86-NOCMOV-NEXT: xorl $31, %eax1290; X86-NOCMOV-NEXT: xorl %edx, %edx1291; X86-NOCMOV-NEXT: retl1292;1293; X86-CMOV-LABEL: ctlz_i32_zext:1294; X86-CMOV: # %bb.0:1295; X86-CMOV-NEXT: bsrl {{[0-9]+}}(%esp), %ecx1296; X86-CMOV-NEXT: movl $63, %eax1297; X86-CMOV-NEXT: cmovnel %ecx, %eax1298; X86-CMOV-NEXT: xorl %edx, %edx1299; X86-CMOV-NEXT: retl1300;1301; X64-LABEL: ctlz_i32_zext:1302; X64: # %bb.0:1303; X64-NEXT: movl $63, %eax1304; X64-NEXT: bsrl %edi, %eax1305; X64-NEXT: retq1306;1307; X86-CLZ-LABEL: ctlz_i32_zext:1308; X86-CLZ: # %bb.0:1309; X86-CLZ-NEXT: lzcntl {{[0-9]+}}(%esp), %eax1310; X86-CLZ-NEXT: xorl $31, %eax1311; X86-CLZ-NEXT: xorl %edx, %edx1312; X86-CLZ-NEXT: retl1313;1314; X64-CLZ-LABEL: ctlz_i32_zext:1315; X64-CLZ: # %bb.0:1316; X64-CLZ-NEXT: lzcntl %edi, %eax1317; X64-CLZ-NEXT: xorl $31, %eax1318; X64-CLZ-NEXT: retq1319;1320; X64-FASTLZCNT-LABEL: ctlz_i32_zext:1321; X64-FASTLZCNT: # %bb.0:1322; X64-FASTLZCNT-NEXT: lzcntl %edi, %eax1323; X64-FASTLZCNT-NEXT: xorl $31, %eax1324; X64-FASTLZCNT-NEXT: retq1325;1326; X86-FASTLZCNT-LABEL: ctlz_i32_zext:1327; X86-FASTLZCNT: # %bb.0:1328; X86-FASTLZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax1329; X86-FASTLZCNT-NEXT: xorl $31, %eax1330; X86-FASTLZCNT-NEXT: xorl %edx, %edx1331; X86-FASTLZCNT-NEXT: retl1332 %tmp = call i32 @llvm.ctlz.i32( i32 %x, i1 false)1333 %xor = xor i32 %tmp, 311334 %ext = zext i32 %xor to i641335 ret i64 %ext1336}1337