1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=i686-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=X86,NOBMI-X86 3; RUN: llc -mtriple=i686-unknown-linux-gnu -mattr=+bmi < %s | FileCheck %s --check-prefixes=X86,BMI-X86 4; RUN: llc -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=X64,NOBMI-X64 5; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+bmi < %s | FileCheck %s --check-prefixes=X64,BMI-X64 6 7; Fold 8; ptr - (ptr & mask) 9; To 10; ptr & (~mask) 11; 12; This needs to be a backend-level fold because only by now pointers 13; 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=44448 17 18; The basic positive tests 19 20define i32 @t0_32(i32 %ptr, i32 %mask) nounwind { 21; NOBMI-X86-LABEL: t0_32: 22; NOBMI-X86: # %bb.0: 23; NOBMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax 24; NOBMI-X86-NEXT: notl %eax 25; NOBMI-X86-NEXT: andl {{[0-9]+}}(%esp), %eax 26; NOBMI-X86-NEXT: retl 27; 28; BMI-X86-LABEL: t0_32: 29; BMI-X86: # %bb.0: 30; BMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax 31; BMI-X86-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax 32; BMI-X86-NEXT: retl 33; 34; NOBMI-X64-LABEL: t0_32: 35; NOBMI-X64: # %bb.0: 36; NOBMI-X64-NEXT: movl %esi, %eax 37; NOBMI-X64-NEXT: notl %eax 38; NOBMI-X64-NEXT: andl %edi, %eax 39; NOBMI-X64-NEXT: retq 40; 41; BMI-X64-LABEL: t0_32: 42; BMI-X64: # %bb.0: 43; BMI-X64-NEXT: andnl %edi, %esi, %eax 44; BMI-X64-NEXT: retq 45 %bias = and i32 %ptr, %mask 46 %r = sub i32 %ptr, %bias 47 ret i32 %r 48} 49define i64 @t1_64(i64 %ptr, i64 %mask) nounwind { 50; NOBMI-X86-LABEL: t1_64: 51; NOBMI-X86: # %bb.0: 52; NOBMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax 53; NOBMI-X86-NEXT: movl {{[0-9]+}}(%esp), %edx 54; NOBMI-X86-NEXT: notl %eax 55; NOBMI-X86-NEXT: andl {{[0-9]+}}(%esp), %eax 56; NOBMI-X86-NEXT: notl %edx 57; NOBMI-X86-NEXT: andl {{[0-9]+}}(%esp), %edx 58; NOBMI-X86-NEXT: retl 59; 60; BMI-X86-LABEL: t1_64: 61; BMI-X86: # %bb.0: 62; BMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax 63; BMI-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 64; BMI-X86-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax 65; BMI-X86-NEXT: andnl {{[0-9]+}}(%esp), %ecx, %edx 66; BMI-X86-NEXT: retl 67; 68; NOBMI-X64-LABEL: t1_64: 69; NOBMI-X64: # %bb.0: 70; NOBMI-X64-NEXT: movq %rsi, %rax 71; NOBMI-X64-NEXT: notq %rax 72; NOBMI-X64-NEXT: andq %rdi, %rax 73; NOBMI-X64-NEXT: retq 74; 75; BMI-X64-LABEL: t1_64: 76; BMI-X64: # %bb.0: 77; BMI-X64-NEXT: andnq %rdi, %rsi, %rax 78; BMI-X64-NEXT: retq 79 %bias = and i64 %ptr, %mask 80 %r = sub i64 %ptr, %bias 81 ret i64 %r 82} 83 84define i32 @t2_commutative(i32 %ptr, i32 %mask) nounwind { 85; NOBMI-X86-LABEL: t2_commutative: 86; NOBMI-X86: # %bb.0: 87; NOBMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax 88; NOBMI-X86-NEXT: notl %eax 89; NOBMI-X86-NEXT: andl {{[0-9]+}}(%esp), %eax 90; NOBMI-X86-NEXT: retl 91; 92; BMI-X86-LABEL: t2_commutative: 93; BMI-X86: # %bb.0: 94; BMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax 95; BMI-X86-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax 96; BMI-X86-NEXT: retl 97; 98; NOBMI-X64-LABEL: t2_commutative: 99; NOBMI-X64: # %bb.0: 100; NOBMI-X64-NEXT: movl %esi, %eax 101; NOBMI-X64-NEXT: notl %eax 102; NOBMI-X64-NEXT: andl %edi, %eax 103; NOBMI-X64-NEXT: retq 104; 105; BMI-X64-LABEL: t2_commutative: 106; BMI-X64: # %bb.0: 107; BMI-X64-NEXT: andnl %edi, %esi, %eax 108; BMI-X64-NEXT: retq 109 %bias = and i32 %mask, %ptr ; swapped 110 %r = sub i32 %ptr, %bias 111 ret i32 %r 112} 113 114; Extra use tests 115 116define i32 @n3_extrause1(i32 %ptr, i32 %mask, i32* %bias_storage) nounwind { 117; X86-LABEL: n3_extrause1: 118; X86: # %bb.0: 119; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 120; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 121; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 122; X86-NEXT: andl %eax, %edx 123; X86-NEXT: movl %edx, (%ecx) 124; X86-NEXT: subl %edx, %eax 125; X86-NEXT: retl 126; 127; X64-LABEL: n3_extrause1: 128; X64: # %bb.0: 129; X64-NEXT: movl %edi, %eax 130; X64-NEXT: andl %edi, %esi 131; X64-NEXT: movl %esi, (%rdx) 132; X64-NEXT: subl %esi, %eax 133; X64-NEXT: retq 134 %bias = and i32 %ptr, %mask ; has extra uses, can't fold 135 store i32 %bias, i32* %bias_storage 136 %r = sub i32 %ptr, %bias 137 ret i32 %r 138} 139 140; Negative tests 141 142define i32 @n4_different_ptrs(i32 %ptr0, i32 %ptr1, i32 %mask) nounwind { 143; X86-LABEL: n4_different_ptrs: 144; X86: # %bb.0: 145; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 146; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 147; X86-NEXT: andl {{[0-9]+}}(%esp), %ecx 148; X86-NEXT: subl %ecx, %eax 149; X86-NEXT: retl 150; 151; X64-LABEL: n4_different_ptrs: 152; X64: # %bb.0: 153; X64-NEXT: movl %edi, %eax 154; X64-NEXT: andl %edx, %esi 155; X64-NEXT: subl %esi, %eax 156; X64-NEXT: retq 157 %bias = and i32 %ptr1, %mask ; not %ptr0 158 %r = sub i32 %ptr0, %bias ; not %ptr1 159 ret i32 %r 160} 161define i32 @n5_different_ptrs_commutative(i32 %ptr0, i32 %ptr1, i32 %mask) nounwind { 162; X86-LABEL: n5_different_ptrs_commutative: 163; X86: # %bb.0: 164; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 165; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 166; X86-NEXT: andl {{[0-9]+}}(%esp), %ecx 167; X86-NEXT: subl %ecx, %eax 168; X86-NEXT: retl 169; 170; X64-LABEL: n5_different_ptrs_commutative: 171; X64: # %bb.0: 172; X64-NEXT: movl %edi, %eax 173; X64-NEXT: andl %edx, %esi 174; X64-NEXT: subl %esi, %eax 175; X64-NEXT: retq 176 %bias = and i32 %mask, %ptr1 ; swapped, not %ptr0 177 %r = sub i32 %ptr0, %bias ; not %ptr1 178 ret i32 %r 179} 180 181define i32 @n6_not_lowbit_mask(i32 %ptr, i32 %mask) nounwind { 182; NOBMI-X86-LABEL: n6_not_lowbit_mask: 183; NOBMI-X86: # %bb.0: 184; NOBMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax 185; NOBMI-X86-NEXT: notl %eax 186; NOBMI-X86-NEXT: andl {{[0-9]+}}(%esp), %eax 187; NOBMI-X86-NEXT: retl 188; 189; BMI-X86-LABEL: n6_not_lowbit_mask: 190; BMI-X86: # %bb.0: 191; BMI-X86-NEXT: movl {{[0-9]+}}(%esp), %eax 192; BMI-X86-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax 193; BMI-X86-NEXT: retl 194; 195; NOBMI-X64-LABEL: n6_not_lowbit_mask: 196; NOBMI-X64: # %bb.0: 197; NOBMI-X64-NEXT: movl %esi, %eax 198; NOBMI-X64-NEXT: notl %eax 199; NOBMI-X64-NEXT: andl %edi, %eax 200; NOBMI-X64-NEXT: retq 201; 202; BMI-X64-LABEL: n6_not_lowbit_mask: 203; BMI-X64: # %bb.0: 204; BMI-X64-NEXT: andnl %edi, %esi, %eax 205; BMI-X64-NEXT: retq 206 %bias = and i32 %ptr, %mask 207 %r = sub i32 %ptr, %bias 208 ret i32 %r 209} 210 211define i32 @n7_sub_is_not_commutative(i32 %ptr, i32 %mask) nounwind { 212; X86-LABEL: n7_sub_is_not_commutative: 213; X86: # %bb.0: 214; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 215; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 216; X86-NEXT: andl %ecx, %eax 217; X86-NEXT: subl %ecx, %eax 218; X86-NEXT: retl 219; 220; X64-LABEL: n7_sub_is_not_commutative: 221; X64: # %bb.0: 222; X64-NEXT: movl %esi, %eax 223; X64-NEXT: andl %edi, %eax 224; X64-NEXT: subl %edi, %eax 225; X64-NEXT: retq 226 %bias = and i32 %ptr, %mask 227 %r = sub i32 %bias, %ptr ; wrong order 228 ret i32 %r 229} 230