320 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefix=X863; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X644 5; Check that under certain conditions we can factor out a rotate6; from the following idioms:7; (a*c0) >> s1 | (a*c1)8; (a/c0) << s1 | (a/c1)9; This targets cases where instcombine has folded a shl/srl/mul/udiv10; with one of the shifts from the rotate idiom11 12define i64 @rolq_extract_shl(i64 %i) nounwind {13; X86-LABEL: rolq_extract_shl:14; X86: # %bb.0:15; X86-NEXT: movl {{[0-9]+}}(%esp), %edx16; X86-NEXT: movl {{[0-9]+}}(%esp), %eax17; X86-NEXT: movl %eax, %ecx18; X86-NEXT: shldl $3, %edx, %ecx19; X86-NEXT: shll $3, %eax20; X86-NEXT: shll $3, %edx21; X86-NEXT: shrdl $25, %edx, %eax22; X86-NEXT: shrdl $25, %ecx, %edx23; X86-NEXT: retl24;25; X64-LABEL: rolq_extract_shl:26; X64: # %bb.0:27; X64-NEXT: leaq (,%rdi,8), %rax28; X64-NEXT: rolq $7, %rax29; X64-NEXT: retq30 %lhs_mul = shl i64 %i, 331 %rhs_mul = shl i64 %i, 1032 %lhs_shift = lshr i64 %lhs_mul, 5733 %out = or i64 %lhs_shift, %rhs_mul34 ret i64 %out35}36 37define i16 @rolw_extract_shrl(i16 %i) nounwind {38; X86-LABEL: rolw_extract_shrl:39; X86: # %bb.0:40; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax41; X86-NEXT: shrl $3, %eax42; X86-NEXT: rolw $12, %ax43; X86-NEXT: # kill: def $ax killed $ax killed $eax44; X86-NEXT: retl45;46; X64-LABEL: rolw_extract_shrl:47; X64: # %bb.0:48; X64-NEXT: movzwl %di, %eax49; X64-NEXT: shrl $3, %eax50; X64-NEXT: rolw $12, %ax51; X64-NEXT: # kill: def $ax killed $ax killed $eax52; X64-NEXT: retq53 %lhs_div = lshr i16 %i, 754 %rhs_div = lshr i16 %i, 355 %rhs_shift = shl i16 %rhs_div, 1256 %out = or i16 %lhs_div, %rhs_shift57 ret i16 %out58}59 60define i32 @roll_extract_mul(i32 %i) nounwind {61; X86-LABEL: roll_extract_mul:62; X86: # %bb.0:63; X86-NEXT: movl {{[0-9]+}}(%esp), %eax64; X86-NEXT: leal (%eax,%eax,8), %eax65; X86-NEXT: roll $7, %eax66; X86-NEXT: retl67;68; X64-LABEL: roll_extract_mul:69; X64: # %bb.0:70; X64-NEXT: # kill: def $edi killed $edi def $rdi71; X64-NEXT: leal (%rdi,%rdi,8), %eax72; X64-NEXT: roll $7, %eax73; X64-NEXT: retq74 %lhs_mul = mul i32 %i, 975 %rhs_mul = mul i32 %i, 115276 %lhs_shift = lshr i32 %lhs_mul, 2577 %out = or i32 %lhs_shift, %rhs_mul78 ret i32 %out79}80 81define i8 @rolb_extract_udiv(i8 %i) nounwind {82; X86-LABEL: rolb_extract_udiv:83; X86: # %bb.0:84; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax85; X86-NEXT: imull $171, %eax, %eax86; X86-NEXT: shrl $9, %eax87; X86-NEXT: rolb $4, %al88; X86-NEXT: # kill: def $al killed $al killed $eax89; X86-NEXT: retl90;91; X64-LABEL: rolb_extract_udiv:92; X64: # %bb.0:93; X64-NEXT: movzbl %dil, %eax94; X64-NEXT: imull $171, %eax, %eax95; X64-NEXT: shrl $9, %eax96; X64-NEXT: rolb $4, %al97; X64-NEXT: # kill: def $al killed $al killed $eax98; X64-NEXT: retq99 %lhs_div = udiv i8 %i, 3100 %rhs_div = udiv i8 %i, 48101 %lhs_shift = shl i8 %lhs_div, 4102 %out = or i8 %lhs_shift, %rhs_div103 ret i8 %out104}105 106define i64 @rolq_extract_mul_with_mask(i64 %i) nounwind {107; X86-LABEL: rolq_extract_mul_with_mask:108; X86: # %bb.0:109; X86-NEXT: movl {{[0-9]+}}(%esp), %eax110; X86-NEXT: leal (%eax,%eax,8), %ecx111; X86-NEXT: movl $9, %eax112; X86-NEXT: mull {{[0-9]+}}(%esp)113; X86-NEXT: addl %ecx, %edx114; X86-NEXT: shrdl $25, %eax, %edx115; X86-NEXT: movzbl %dl, %eax116; X86-NEXT: xorl %edx, %edx117; X86-NEXT: retl118;119; X64-LABEL: rolq_extract_mul_with_mask:120; X64: # %bb.0:121; X64-NEXT: leaq (%rdi,%rdi,8), %rax122; X64-NEXT: rolq $7, %rax123; X64-NEXT: movzbl %al, %eax124; X64-NEXT: retq125 %lhs_mul = mul i64 %i, 1152126 %rhs_mul = mul i64 %i, 9127 %lhs_and = and i64 %lhs_mul, 160128 %rhs_shift = lshr i64 %rhs_mul, 57129 %out = or i64 %lhs_and, %rhs_shift130 ret i64 %out131}132 133; Result would undershift134define i64 @no_extract_shl(i64 %i) nounwind {135; X86-LABEL: no_extract_shl:136; X86: # %bb.0:137; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx138; X86-NEXT: movl {{[0-9]+}}(%esp), %eax139; X86-NEXT: movl %eax, %edx140; X86-NEXT: shldl $10, %ecx, %edx141; X86-NEXT: shll $10, %ecx142; X86-NEXT: shrl $20, %eax143; X86-NEXT: andl $127, %eax144; X86-NEXT: orl %ecx, %eax145; X86-NEXT: retl146;147; X64-LABEL: no_extract_shl:148; X64: # %bb.0:149; X64-NEXT: movq %rdi, %rax150; X64-NEXT: shlq $10, %rax151; X64-NEXT: shrq $52, %rdi152; X64-NEXT: andl $127, %edi153; X64-NEXT: orq %rdi, %rax154; X64-NEXT: retq155 %lhs_mul = shl i64 %i, 5156 %rhs_mul = shl i64 %i, 10157 %lhs_shift = lshr i64 %lhs_mul, 57158 %out = or i64 %lhs_shift, %rhs_mul159 ret i64 %out160}161 162; Result would overshift163define i32 @no_extract_shrl(i32 %i) nounwind {164; X86-LABEL: no_extract_shrl:165; X86: # %bb.0:166; X86-NEXT: movl {{[0-9]+}}(%esp), %eax167; X86-NEXT: movl %eax, %ecx168; X86-NEXT: shrl $9, %ecx169; X86-NEXT: andl $-8, %eax170; X86-NEXT: shll $25, %eax171; X86-NEXT: orl %ecx, %eax172; X86-NEXT: retl173;174; X64-LABEL: no_extract_shrl:175; X64: # %bb.0:176; X64-NEXT: movl %edi, %eax177; X64-NEXT: shrl $9, %eax178; X64-NEXT: andl $-8, %edi179; X64-NEXT: shll $25, %edi180; X64-NEXT: orl %edi, %eax181; X64-NEXT: retq182 %lhs_div = lshr i32 %i, 3183 %rhs_div = lshr i32 %i, 9184 %lhs_shift = shl i32 %lhs_div, 28185 %out = or i32 %lhs_shift, %rhs_div186 ret i32 %out187}188 189; Can factor 128 from 2304, but result is 18 instead of 9190define i16 @no_extract_mul(i16 %i) nounwind {191; X86-LABEL: no_extract_mul:192; X86: # %bb.0:193; X86-NEXT: movl {{[0-9]+}}(%esp), %eax194; X86-NEXT: leal (%eax,%eax,8), %ecx195; X86-NEXT: shll $8, %eax196; X86-NEXT: leal (%eax,%eax,8), %edx197; X86-NEXT: movzwl %cx, %eax198; X86-NEXT: shrl $9, %eax199; X86-NEXT: orl %edx, %eax200; X86-NEXT: # kill: def $ax killed $ax killed $eax201; X86-NEXT: retl202;203; X64-LABEL: no_extract_mul:204; X64: # %bb.0:205; X64-NEXT: # kill: def $edi killed $edi def $rdi206; X64-NEXT: movl %edi, %eax207; X64-NEXT: shll $8, %edi208; X64-NEXT: leal (%rdi,%rdi,8), %ecx209; X64-NEXT: leal (%rax,%rax,8), %eax210; X64-NEXT: movzwl %ax, %eax211; X64-NEXT: shrl $9, %eax212; X64-NEXT: orl %ecx, %eax213; X64-NEXT: # kill: def $ax killed $ax killed $eax214; X64-NEXT: retq215 %lhs_mul = mul i16 %i, 2304216 %rhs_mul = mul i16 %i, 9217 %rhs_shift = lshr i16 %rhs_mul, 9218 %out = or i16 %lhs_mul, %rhs_shift219 ret i16 %out220}221 222; Can't evenly factor 16 from 49223define i8 @no_extract_udiv(i8 %i) nounwind {224; X86-LABEL: no_extract_udiv:225; X86: # %bb.0:226; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax227; X86-NEXT: imull $171, %eax, %ecx228; X86-NEXT: imull $79, %eax, %edx229; X86-NEXT: subb %dh, %al230; X86-NEXT: shrb %al231; X86-NEXT: addb %dh, %al232; X86-NEXT: shrb $5, %al233; X86-NEXT: shlb $3, %ch234; X86-NEXT: orb %al, %ch235; X86-NEXT: andb $-9, %ch236; X86-NEXT: movb %ch, %al237; X86-NEXT: retl238;239; X64-LABEL: no_extract_udiv:240; X64: # %bb.0:241; X64-NEXT: movzbl %dil, %ecx242; X64-NEXT: imull $171, %ecx, %eax243; X64-NEXT: shrl $8, %eax244; X64-NEXT: imull $79, %ecx, %edx245; X64-NEXT: shrl $8, %edx246; X64-NEXT: subb %dl, %cl247; X64-NEXT: shrb %cl248; X64-NEXT: addb %dl, %cl249; X64-NEXT: shrb $5, %cl250; X64-NEXT: shlb $3, %al251; X64-NEXT: orb %cl, %al252; X64-NEXT: andb $-9, %al253; X64-NEXT: # kill: def $al killed $al killed $eax254; X64-NEXT: retq255 %lhs_div = udiv i8 %i, 3256 %rhs_div = udiv i8 %i, 49257 %lhs_shift = shl i8 %lhs_div,4258 %out = or i8 %lhs_shift, %rhs_div259 ret i8 %out260}261 262; DAGCombiner transforms shl X, 1 into add X, X.263define i32 @extract_add_1(i32 %i) nounwind {264; X86-LABEL: extract_add_1:265; X86: # %bb.0:266; X86-NEXT: movl {{[0-9]+}}(%esp), %eax267; X86-NEXT: roll %eax268; X86-NEXT: retl269;270; X64-LABEL: extract_add_1:271; X64: # %bb.0:272; X64-NEXT: movl %edi, %eax273; X64-NEXT: roll %eax274; X64-NEXT: retq275 %ii = add i32 %i, %i276 %rhs = lshr i32 %i, 31277 %out = or i32 %ii, %rhs278 ret i32 %out279}280 281define i32 @extract_add_1_comut(i32 %i) nounwind {282; X86-LABEL: extract_add_1_comut:283; X86: # %bb.0:284; X86-NEXT: movl {{[0-9]+}}(%esp), %eax285; X86-NEXT: roll %eax286; X86-NEXT: retl287;288; X64-LABEL: extract_add_1_comut:289; X64: # %bb.0:290; X64-NEXT: movl %edi, %eax291; X64-NEXT: roll %eax292; X64-NEXT: retq293 %ii = add i32 %i, %i294 %lhs = lshr i32 %i, 31295 %out = or i32 %lhs, %ii296 ret i32 %out297}298 299define i32 @no_extract_add_1(i32 %i) nounwind {300; X86-LABEL: no_extract_add_1:301; X86: # %bb.0:302; X86-NEXT: movl {{[0-9]+}}(%esp), %eax303; X86-NEXT: leal (%eax,%eax), %ecx304; X86-NEXT: shrl $27, %eax305; X86-NEXT: orl %ecx, %eax306; X86-NEXT: retl307;308; X64-LABEL: no_extract_add_1:309; X64: # %bb.0:310; X64-NEXT: # kill: def $edi killed $edi def $rdi311; X64-NEXT: leal (%rdi,%rdi), %eax312; X64-NEXT: shrl $27, %edi313; X64-NEXT: orl %edi, %eax314; X64-NEXT: retq315 %ii = add i32 %i, %i316 %rhs = lshr i32 %i, 27317 %out = or i32 %ii, %rhs318 ret i32 %out319}320