288 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=i686-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=X86,NOBMI-X863; RUN: llc -mtriple=i686-unknown-linux-gnu -mattr=+bmi < %s | FileCheck %s --check-prefixes=X86,BMI-X864; RUN: llc -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=X64,NOBMI-X645; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+bmi < %s | FileCheck %s --check-prefixes=X64,BMI-X646 7; Fold8; ptr - (ptr & (alignment-1))9; To10; ptr & (0 - alignment)11;12; This needs to be a backend-level fold because only by now pointers13; are just registers; in middle-end IR this can only be done via @llvm.ptrmask()14; intrinsic which is not sufficiently widely-spread yet.15;16; https://bugs.llvm.org/show_bug.cgi?id=4444817 18; The basic positive tests19 20define i32 @t0_32(i32 %ptr, i32 %alignment) nounwind {21; X86-LABEL: t0_32:22; X86: # %bb.0:23; X86-NEXT: xorl %eax, %eax24; X86-NEXT: subl {{[0-9]+}}(%esp), %eax25; X86-NEXT: andl {{[0-9]+}}(%esp), %eax26; X86-NEXT: retl27;28; X64-LABEL: t0_32:29; X64: # %bb.0:30; X64-NEXT: movl %esi, %eax31; X64-NEXT: negl %eax32; X64-NEXT: andl %edi, %eax33; X64-NEXT: retq34 %mask = add i32 %alignment, -135 %bias = and i32 %ptr, %mask36 %r = sub i32 %ptr, %bias37 ret i32 %r38}39define i64 @t1_64(i64 %ptr, i64 %alignment) nounwind {40; X86-LABEL: t1_64:41; X86: # %bb.0:42; X86-NEXT: xorl %edx, %edx43; X86-NEXT: xorl %eax, %eax44; X86-NEXT: subl {{[0-9]+}}(%esp), %eax45; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx46; X86-NEXT: andl {{[0-9]+}}(%esp), %edx47; X86-NEXT: andl {{[0-9]+}}(%esp), %eax48; X86-NEXT: retl49;50; X64-LABEL: t1_64:51; X64: # %bb.0:52; X64-NEXT: movq %rsi, %rax53; X64-NEXT: negq %rax54; X64-NEXT: andq %rdi, %rax55; X64-NEXT: retq56 %mask = add i64 %alignment, -157 %bias = and i64 %ptr, %mask58 %r = sub i64 %ptr, %bias59 ret i64 %r60}61 62define i32 @t2_commutative(i32 %ptr, i32 %alignment) nounwind {63; X86-LABEL: t2_commutative:64; X86: # %bb.0:65; X86-NEXT: xorl %eax, %eax66; X86-NEXT: subl {{[0-9]+}}(%esp), %eax67; X86-NEXT: andl {{[0-9]+}}(%esp), %eax68; X86-NEXT: retl69;70; X64-LABEL: t2_commutative:71; X64: # %bb.0:72; X64-NEXT: movl %esi, %eax73; X64-NEXT: negl %eax74; X64-NEXT: andl %edi, %eax75; X64-NEXT: retq76 %mask = add i32 %alignment, -177 %bias = and i32 %mask, %ptr ; swapped78 %r = sub i32 %ptr, %bias79 ret i32 %r80}81 82; Extra use tests83 84define i32 @t3_extrause0(i32 %ptr, i32 %alignment, ptr %mask_storage) nounwind {85; NOBMI-X86-LABEL: t3_extrause0:86; NOBMI-X86: # %bb.0:87; NOBMI-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx88; NOBMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax89; NOBMI-X86-NEXT: decl %eax90; NOBMI-X86-NEXT: movl %eax, (%ecx)91; NOBMI-X86-NEXT: notl %eax92; NOBMI-X86-NEXT: andl {{[0-9]+}}(%esp), %eax93; NOBMI-X86-NEXT: retl94;95; BMI-X86-LABEL: t3_extrause0:96; BMI-X86: # %bb.0:97; BMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax98; BMI-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx99; BMI-X86-NEXT: decl %ecx100; BMI-X86-NEXT: movl %ecx, (%eax)101; BMI-X86-NEXT: andnl {{[0-9]+}}(%esp), %ecx, %eax102; BMI-X86-NEXT: retl103;104; NOBMI-X64-LABEL: t3_extrause0:105; NOBMI-X64: # %bb.0:106; NOBMI-X64-NEXT: # kill: def $esi killed $esi def $rsi107; NOBMI-X64-NEXT: leal -1(%rsi), %eax108; NOBMI-X64-NEXT: movl %eax, (%rdx)109; NOBMI-X64-NEXT: notl %eax110; NOBMI-X64-NEXT: andl %edi, %eax111; NOBMI-X64-NEXT: retq112;113; BMI-X64-LABEL: t3_extrause0:114; BMI-X64: # %bb.0:115; BMI-X64-NEXT: decl %esi116; BMI-X64-NEXT: movl %esi, (%rdx)117; BMI-X64-NEXT: andnl %edi, %esi, %eax118; BMI-X64-NEXT: retq119 %mask = add i32 %alignment, -1120 store i32 %mask, ptr %mask_storage121 %bias = and i32 %ptr, %mask122 %r = sub i32 %ptr, %bias123 ret i32 %r124}125define i32 @n4_extrause1(i32 %ptr, i32 %alignment, ptr %bias_storage) nounwind {126; X86-LABEL: n4_extrause1:127; X86: # %bb.0:128; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx129; X86-NEXT: movl {{[0-9]+}}(%esp), %eax130; X86-NEXT: movl {{[0-9]+}}(%esp), %edx131; X86-NEXT: decl %edx132; X86-NEXT: andl %eax, %edx133; X86-NEXT: movl %edx, (%ecx)134; X86-NEXT: subl %edx, %eax135; X86-NEXT: retl136;137; X64-LABEL: n4_extrause1:138; X64: # %bb.0:139; X64-NEXT: movl %edi, %eax140; X64-NEXT: decl %esi141; X64-NEXT: andl %edi, %esi142; X64-NEXT: movl %esi, (%rdx)143; X64-NEXT: subl %esi, %eax144; X64-NEXT: retq145 %mask = add i32 %alignment, -1146 %bias = and i32 %ptr, %mask ; has extra uses, can't fold147 store i32 %bias, ptr %bias_storage148 %r = sub i32 %ptr, %bias149 ret i32 %r150}151define i32 @n5_extrause2(i32 %ptr, i32 %alignment, ptr %mask_storage, ptr %bias_storage) nounwind {152; X86-LABEL: n5_extrause2:153; X86: # %bb.0:154; X86-NEXT: pushl %esi155; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx156; X86-NEXT: movl {{[0-9]+}}(%esp), %eax157; X86-NEXT: movl {{[0-9]+}}(%esp), %edx158; X86-NEXT: movl {{[0-9]+}}(%esp), %esi159; X86-NEXT: decl %esi160; X86-NEXT: movl %esi, (%edx)161; X86-NEXT: andl %eax, %esi162; X86-NEXT: movl %esi, (%ecx)163; X86-NEXT: subl %esi, %eax164; X86-NEXT: popl %esi165; X86-NEXT: retl166;167; X64-LABEL: n5_extrause2:168; X64: # %bb.0:169; X64-NEXT: movl %edi, %eax170; X64-NEXT: decl %esi171; X64-NEXT: movl %esi, (%rdx)172; X64-NEXT: andl %edi, %esi173; X64-NEXT: movl %esi, (%rcx)174; X64-NEXT: subl %esi, %eax175; X64-NEXT: retq176 %mask = add i32 %alignment, -1177 store i32 %mask, ptr %mask_storage178 %bias = and i32 %ptr, %mask ; has extra uses, can't fold179 store i32 %bias, ptr %bias_storage180 %r = sub i32 %ptr, %bias181 ret i32 %r182}183 184; Negative tests185 186define i32 @n6_different_ptrs(i32 %ptr0, i32 %ptr1, i32 %alignment) nounwind {187; X86-LABEL: n6_different_ptrs:188; X86: # %bb.0:189; X86-NEXT: movl {{[0-9]+}}(%esp), %eax190; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx191; X86-NEXT: decl %ecx192; X86-NEXT: andl {{[0-9]+}}(%esp), %ecx193; X86-NEXT: subl %ecx, %eax194; X86-NEXT: retl195;196; X64-LABEL: n6_different_ptrs:197; X64: # %bb.0:198; X64-NEXT: movl %edi, %eax199; X64-NEXT: decl %edx200; X64-NEXT: andl %esi, %edx201; X64-NEXT: subl %edx, %eax202; X64-NEXT: retq203 %mask = add i32 %alignment, -1204 %bias = and i32 %ptr1, %mask ; not %ptr0205 %r = sub i32 %ptr0, %bias ; not %ptr1206 ret i32 %r207}208define i32 @n7_different_ptrs_commutative(i32 %ptr0, i32 %ptr1, i32 %alignment) nounwind {209; X86-LABEL: n7_different_ptrs_commutative:210; X86: # %bb.0:211; X86-NEXT: movl {{[0-9]+}}(%esp), %eax212; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx213; X86-NEXT: decl %ecx214; X86-NEXT: andl {{[0-9]+}}(%esp), %ecx215; X86-NEXT: subl %ecx, %eax216; X86-NEXT: retl217;218; X64-LABEL: n7_different_ptrs_commutative:219; X64: # %bb.0:220; X64-NEXT: movl %edi, %eax221; X64-NEXT: decl %edx222; X64-NEXT: andl %esi, %edx223; X64-NEXT: subl %edx, %eax224; X64-NEXT: retq225 %mask = add i32 %alignment, -1226 %bias = and i32 %mask, %ptr1 ; swapped, not %ptr0227 %r = sub i32 %ptr0, %bias ; not %ptr1228 ret i32 %r229}230 231define i32 @n8_not_lowbit_mask(i32 %ptr, i32 %alignment) nounwind {232; NOBMI-X86-LABEL: n8_not_lowbit_mask:233; NOBMI-X86: # %bb.0:234; NOBMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax235; NOBMI-X86-NEXT: incl %eax236; NOBMI-X86-NEXT: notl %eax237; NOBMI-X86-NEXT: andl {{[0-9]+}}(%esp), %eax238; NOBMI-X86-NEXT: retl239;240; BMI-X86-LABEL: n8_not_lowbit_mask:241; BMI-X86: # %bb.0:242; BMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax243; BMI-X86-NEXT: incl %eax244; BMI-X86-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax245; BMI-X86-NEXT: retl246;247; NOBMI-X64-LABEL: n8_not_lowbit_mask:248; NOBMI-X64: # %bb.0:249; NOBMI-X64-NEXT: # kill: def $esi killed $esi def $rsi250; NOBMI-X64-NEXT: leal 1(%rsi), %eax251; NOBMI-X64-NEXT: notl %eax252; NOBMI-X64-NEXT: andl %edi, %eax253; NOBMI-X64-NEXT: retq254;255; BMI-X64-LABEL: n8_not_lowbit_mask:256; BMI-X64: # %bb.0:257; BMI-X64-NEXT: incl %esi258; BMI-X64-NEXT: andnl %edi, %esi, %eax259; BMI-X64-NEXT: retq260 %mask = add i32 %alignment, 1 ; not -1261 %bias = and i32 %ptr, %mask262 %r = sub i32 %ptr, %bias263 ret i32 %r264}265 266define i32 @n9_sub_is_not_commutative(i32 %ptr, i32 %alignment) nounwind {267; X86-LABEL: n9_sub_is_not_commutative:268; X86: # %bb.0:269; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx270; X86-NEXT: movl {{[0-9]+}}(%esp), %eax271; X86-NEXT: decl %eax272; X86-NEXT: andl %ecx, %eax273; X86-NEXT: subl %ecx, %eax274; X86-NEXT: retl275;276; X64-LABEL: n9_sub_is_not_commutative:277; X64: # %bb.0:278; X64-NEXT: # kill: def $esi killed $esi def $rsi279; X64-NEXT: leal -1(%rsi), %eax280; X64-NEXT: andl %edi, %eax281; X64-NEXT: subl %edi, %eax282; X64-NEXT: retq283 %mask = add i32 %alignment, -1284 %bias = and i32 %ptr, %mask285 %r = sub i32 %bias, %ptr ; wrong order286 ret i32 %r287}288