323 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=i686-- < %s | FileCheck %s --check-prefix=X863; RUN: llc -mtriple=x86_64-- < %s | FileCheck %s --check-prefix=X644 5; Optimize expanded SRL/SHL used as an input of6; SETCC comparing it with zero by removing rotation.7;8; See https://bugs.llvm.org/show_bug.cgi?id=501979define i128 @opt_setcc_lt_power_of_2(i128 %a) nounwind {10; X86-LABEL: opt_setcc_lt_power_of_2:11; X86: # %bb.0:12; X86-NEXT: pushl %ebp13; X86-NEXT: movl %esp, %ebp14; X86-NEXT: pushl %ebx15; X86-NEXT: pushl %edi16; X86-NEXT: pushl %esi17; X86-NEXT: andl $-16, %esp18; X86-NEXT: subl $16, %esp19; X86-NEXT: movl 36(%ebp), %ecx20; X86-NEXT: movl 32(%ebp), %edx21; X86-NEXT: movl 28(%ebp), %edi22; X86-NEXT: movl 24(%ebp), %esi23; X86-NEXT: .p2align 424; X86-NEXT: .LBB0_1: # %loop25; X86-NEXT: # =>This Inner Loop Header: Depth=126; X86-NEXT: addl $1, %esi27; X86-NEXT: adcl $0, %edi28; X86-NEXT: adcl $0, %edx29; X86-NEXT: adcl $0, %ecx30; X86-NEXT: movl %edx, %ebx31; X86-NEXT: orl %ecx, %ebx32; X86-NEXT: movl %esi, %eax33; X86-NEXT: movl %edi, %esi34; X86-NEXT: orl %edx, %esi35; X86-NEXT: orl %ecx, %esi36; X86-NEXT: shrdl $28, %ebx, %esi37; X86-NEXT: movl %eax, %esi38; X86-NEXT: jne .LBB0_139; X86-NEXT: # %bb.2: # %exit40; X86-NEXT: movl 8(%ebp), %eax41; X86-NEXT: movl %esi, (%eax)42; X86-NEXT: movl %edi, 4(%eax)43; X86-NEXT: movl %edx, 8(%eax)44; X86-NEXT: movl %ecx, 12(%eax)45; X86-NEXT: leal -12(%ebp), %esp46; X86-NEXT: popl %esi47; X86-NEXT: popl %edi48; X86-NEXT: popl %ebx49; X86-NEXT: popl %ebp50; X86-NEXT: retl $451;52; X64-LABEL: opt_setcc_lt_power_of_2:53; X64: # %bb.0:54; X64-NEXT: movq %rsi, %rdx55; X64-NEXT: movq %rdi, %rax56; X64-NEXT: .p2align 457; X64-NEXT: .LBB0_1: # %loop58; X64-NEXT: # =>This Inner Loop Header: Depth=159; X64-NEXT: addq $1, %rax60; X64-NEXT: adcq $0, %rdx61; X64-NEXT: movq %rax, %rcx62; X64-NEXT: shrq $60, %rcx63; X64-NEXT: orq %rdx, %rcx64; X64-NEXT: jne .LBB0_165; X64-NEXT: # %bb.2: # %exit66; X64-NEXT: retq67 br label %loop68 69loop:70 %phi.a = phi i128 [ %a, %0 ], [ %inc, %loop ]71 %inc = add i128 %phi.a, 172 %cmp = icmp ult i128 %inc, 115292150460684697673 br i1 %cmp, label %exit, label %loop74 75exit:76 ret i128 %inc77}78 79define i1 @opt_setcc_srl_eq_zero(i128 %a) nounwind {80; X86-LABEL: opt_setcc_srl_eq_zero:81; X86: # %bb.0:82; X86-NEXT: pushl %ebp83; X86-NEXT: movl %esp, %ebp84; X86-NEXT: andl $-16, %esp85; X86-NEXT: subl $16, %esp86; X86-NEXT: movl 16(%ebp), %eax87; X86-NEXT: movl 12(%ebp), %ecx88; X86-NEXT: orl 20(%ebp), %ecx89; X86-NEXT: movl 8(%ebp), %edx90; X86-NEXT: orl %eax, %edx91; X86-NEXT: orl %ecx, %edx92; X86-NEXT: orl %eax, %ecx93; X86-NEXT: shldl $15, %edx, %ecx94; X86-NEXT: sete %al95; X86-NEXT: movl %ebp, %esp96; X86-NEXT: popl %ebp97; X86-NEXT: retl98;99; X64-LABEL: opt_setcc_srl_eq_zero:100; X64: # %bb.0:101; X64-NEXT: shrq $17, %rdi102; X64-NEXT: orq %rsi, %rdi103; X64-NEXT: sete %al104; X64-NEXT: retq105 %srl = lshr i128 %a, 17106 %cmp = icmp eq i128 %srl, 0107 ret i1 %cmp108}109 110define i1 @opt_setcc_srl_ne_zero(i128 %a) nounwind {111; X86-LABEL: opt_setcc_srl_ne_zero:112; X86: # %bb.0:113; X86-NEXT: pushl %ebp114; X86-NEXT: movl %esp, %ebp115; X86-NEXT: andl $-16, %esp116; X86-NEXT: subl $16, %esp117; X86-NEXT: movl 16(%ebp), %eax118; X86-NEXT: movl 12(%ebp), %ecx119; X86-NEXT: orl 20(%ebp), %ecx120; X86-NEXT: movl 8(%ebp), %edx121; X86-NEXT: orl %eax, %edx122; X86-NEXT: orl %ecx, %edx123; X86-NEXT: orl %eax, %ecx124; X86-NEXT: shldl $15, %edx, %ecx125; X86-NEXT: setne %al126; X86-NEXT: movl %ebp, %esp127; X86-NEXT: popl %ebp128; X86-NEXT: retl129;130; X64-LABEL: opt_setcc_srl_ne_zero:131; X64: # %bb.0:132; X64-NEXT: shrq $17, %rdi133; X64-NEXT: orq %rsi, %rdi134; X64-NEXT: setne %al135; X64-NEXT: retq136 %srl = lshr i128 %a, 17137 %cmp = icmp ne i128 %srl, 0138 ret i1 %cmp139}140 141define i1 @opt_setcc_shl_eq_zero(i128 %a) nounwind {142; X86-LABEL: opt_setcc_shl_eq_zero:143; X86: # %bb.0:144; X86-NEXT: pushl %ebp145; X86-NEXT: movl %esp, %ebp146; X86-NEXT: andl $-16, %esp147; X86-NEXT: subl $16, %esp148; X86-NEXT: movl 16(%ebp), %eax149; X86-NEXT: movl 20(%ebp), %ecx150; X86-NEXT: shll $17, %ecx151; X86-NEXT: orl 8(%ebp), %eax152; X86-NEXT: orl 12(%ebp), %eax153; X86-NEXT: orl %ecx, %eax154; X86-NEXT: sete %al155; X86-NEXT: movl %ebp, %esp156; X86-NEXT: popl %ebp157; X86-NEXT: retl158;159; X64-LABEL: opt_setcc_shl_eq_zero:160; X64: # %bb.0:161; X64-NEXT: shlq $17, %rsi162; X64-NEXT: orq %rdi, %rsi163; X64-NEXT: sete %al164; X64-NEXT: retq165 %shl = shl i128 %a, 17166 %cmp = icmp eq i128 %shl, 0167 ret i1 %cmp168}169 170define i1 @opt_setcc_shl_ne_zero(i128 %a) nounwind {171; X86-LABEL: opt_setcc_shl_ne_zero:172; X86: # %bb.0:173; X86-NEXT: pushl %ebp174; X86-NEXT: movl %esp, %ebp175; X86-NEXT: andl $-16, %esp176; X86-NEXT: subl $16, %esp177; X86-NEXT: movl 16(%ebp), %eax178; X86-NEXT: movl 20(%ebp), %ecx179; X86-NEXT: shll $17, %ecx180; X86-NEXT: orl 8(%ebp), %eax181; X86-NEXT: orl 12(%ebp), %eax182; X86-NEXT: orl %ecx, %eax183; X86-NEXT: setne %al184; X86-NEXT: movl %ebp, %esp185; X86-NEXT: popl %ebp186; X86-NEXT: retl187;188; X64-LABEL: opt_setcc_shl_ne_zero:189; X64: # %bb.0:190; X64-NEXT: shlq $17, %rsi191; X64-NEXT: orq %rdi, %rsi192; X64-NEXT: setne %al193; X64-NEXT: retq194 %shl = shl i128 %a, 17195 %cmp = icmp ne i128 %shl, 0196 ret i1 %cmp197}198 199; Negative test: optimization should not be applied if shift has multiple users.200define i1 @opt_setcc_shl_eq_zero_multiple_shl_users(i128 %a) nounwind {201; X86-LABEL: opt_setcc_shl_eq_zero_multiple_shl_users:202; X86: # %bb.0:203; X86-NEXT: pushl %ebp204; X86-NEXT: movl %esp, %ebp205; X86-NEXT: pushl %ebx206; X86-NEXT: pushl %edi207; X86-NEXT: pushl %esi208; X86-NEXT: andl $-16, %esp209; X86-NEXT: subl $16, %esp210; X86-NEXT: movl 8(%ebp), %eax211; X86-NEXT: movl 12(%ebp), %ecx212; X86-NEXT: movl 16(%ebp), %edx213; X86-NEXT: movl 20(%ebp), %esi214; X86-NEXT: shldl $17, %edx, %esi215; X86-NEXT: shldl $17, %ecx, %edx216; X86-NEXT: shldl $17, %eax, %ecx217; X86-NEXT: shll $17, %eax218; X86-NEXT: movl %ecx, %edi219; X86-NEXT: orl %esi, %edi220; X86-NEXT: movl %eax, %ebx221; X86-NEXT: orl %edx, %ebx222; X86-NEXT: orl %edi, %ebx223; X86-NEXT: sete %bl224; X86-NEXT: pushl %esi225; X86-NEXT: pushl %edx226; X86-NEXT: pushl %ecx227; X86-NEXT: pushl %eax228; X86-NEXT: calll use@PLT229; X86-NEXT: addl $16, %esp230; X86-NEXT: movl %ebx, %eax231; X86-NEXT: leal -12(%ebp), %esp232; X86-NEXT: popl %esi233; X86-NEXT: popl %edi234; X86-NEXT: popl %ebx235; X86-NEXT: popl %ebp236; X86-NEXT: retl237;238; X64-LABEL: opt_setcc_shl_eq_zero_multiple_shl_users:239; X64: # %bb.0:240; X64-NEXT: pushq %rbx241; X64-NEXT: shldq $17, %rdi, %rsi242; X64-NEXT: shlq $17, %rdi243; X64-NEXT: movq %rdi, %rax244; X64-NEXT: orq %rsi, %rax245; X64-NEXT: sete %bl246; X64-NEXT: callq use@PLT247; X64-NEXT: movl %ebx, %eax248; X64-NEXT: popq %rbx249; X64-NEXT: retq250 %shl = shl i128 %a, 17251 %cmp = icmp eq i128 %shl, 0252 call void @use(i128 %shl)253 ret i1 %cmp254}255 256; Check that optimization is applied to DAG having appropriate shape257; even if there were no actual shift's expansion.258define i1 @opt_setcc_expanded_shl_correct_shifts(i64 %a, i64 %b) nounwind {259; X86-LABEL: opt_setcc_expanded_shl_correct_shifts:260; X86: # %bb.0:261; X86-NEXT: movl {{[0-9]+}}(%esp), %eax262; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx263; X86-NEXT: orl {{[0-9]+}}(%esp), %eax264; X86-NEXT: shll $17, %ecx265; X86-NEXT: orl {{[0-9]+}}(%esp), %eax266; X86-NEXT: orl %ecx, %eax267; X86-NEXT: sete %al268; X86-NEXT: retl269;270; X64-LABEL: opt_setcc_expanded_shl_correct_shifts:271; X64: # %bb.0:272; X64-NEXT: shlq $17, %rdi273; X64-NEXT: orq %rsi, %rdi274; X64-NEXT: sete %al275; X64-NEXT: retq276 %shl.a = shl i64 %a, 17277 %srl.b = lshr i64 %b, 47278 %or.0 = or i64 %shl.a, %srl.b279 %shl.b = shl i64 %b, 17280 %or.1 = or i64 %or.0, %shl.b281 %cmp = icmp eq i64 %or.1, 0282 ret i1 %cmp283}284 285; Negative test: optimization should not be applied as286; constants used in shifts do not match.287define i1 @opt_setcc_expanded_shl_wrong_shifts(i64 %a, i64 %b) nounwind {288; X86-LABEL: opt_setcc_expanded_shl_wrong_shifts:289; X86: # %bb.0:290; X86-NEXT: pushl %esi291; X86-NEXT: movl {{[0-9]+}}(%esp), %eax292; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx293; X86-NEXT: movl {{[0-9]+}}(%esp), %edx294; X86-NEXT: movl {{[0-9]+}}(%esp), %esi295; X86-NEXT: shldl $17, %edx, %esi296; X86-NEXT: shldl $17, %ecx, %edx297; X86-NEXT: shldl $18, %eax, %ecx298; X86-NEXT: shll $18, %eax299; X86-NEXT: orl %edx, %eax300; X86-NEXT: orl %esi, %ecx301; X86-NEXT: orl %eax, %ecx302; X86-NEXT: sete %al303; X86-NEXT: popl %esi304; X86-NEXT: retl305;306; X64-LABEL: opt_setcc_expanded_shl_wrong_shifts:307; X64: # %bb.0:308; X64-NEXT: shldq $17, %rsi, %rdi309; X64-NEXT: shlq $18, %rsi310; X64-NEXT: orq %rdi, %rsi311; X64-NEXT: sete %al312; X64-NEXT: retq313 %shl.a = shl i64 %a, 17314 %srl.b = lshr i64 %b, 47315 %or.0 = or i64 %shl.a, %srl.b316 %shl.b = shl i64 %b, 18317 %or.1 = or i64 %or.0, %shl.b318 %cmp = icmp eq i64 %or.1, 0319 ret i1 %cmp320}321 322declare void @use(i128 %a)323