1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefix=SSE 3 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefix=AVX 4 5 ; fold (sub x, 0) -> x 6 define <4 x i32> @combine_vec_sub_zero(<4 x i32> %a) { 7 ; SSE-LABEL: combine_vec_sub_zero: 8 ; SSE: # %bb.0: 9 ; SSE-NEXT: retq 10 ; 11 ; AVX-LABEL: combine_vec_sub_zero: 12 ; AVX: # %bb.0: 13 ; AVX-NEXT: retq 14 %1 = sub <4 x i32> %a, zeroinitializer 15 ret <4 x i32> %1 16 } 17 18 ; fold (sub x, x) -> 0 19 define <4 x i32> @combine_vec_sub_self(<4 x i32> %a) { 20 ; SSE-LABEL: combine_vec_sub_self: 21 ; SSE: # %bb.0: 22 ; SSE-NEXT: xorps %xmm0, %xmm0 23 ; SSE-NEXT: retq 24 ; 25 ; AVX-LABEL: combine_vec_sub_self: 26 ; AVX: # %bb.0: 27 ; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 28 ; AVX-NEXT: retq 29 %1 = sub <4 x i32> %a, %a 30 ret <4 x i32> %1 31 } 32 33 ; fold (sub x, c) -> (add x, -c) 34 define <4 x i32> @combine_vec_sub_constant(<4 x i32> %x) { 35 ; SSE-LABEL: combine_vec_sub_constant: 36 ; SSE: # %bb.0: 37 ; SSE-NEXT: psubd {{.*}}(%rip), %xmm0 38 ; SSE-NEXT: retq 39 ; 40 ; AVX-LABEL: combine_vec_sub_constant: 41 ; AVX: # %bb.0: 42 ; AVX-NEXT: vpsubd {{.*}}(%rip), %xmm0, %xmm0 43 ; AVX-NEXT: retq 44 %1 = sub <4 x i32> %x, <i32 0, i32 1, i32 2, i32 3> 45 ret <4 x i32> %1 46 } 47 48 ; Canonicalize (sub -1, x) -> ~x, i.e. (xor x, -1) 49 define <4 x i32> @combine_vec_sub_negone(<4 x i32> %x) { 50 ; SSE-LABEL: combine_vec_sub_negone: 51 ; SSE: # %bb.0: 52 ; SSE-NEXT: pcmpeqd %xmm1, %xmm1 53 ; SSE-NEXT: pxor %xmm1, %xmm0 54 ; SSE-NEXT: retq 55 ; 56 ; AVX-LABEL: combine_vec_sub_negone: 57 ; AVX: # %bb.0: 58 ; AVX-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1 59 ; AVX-NEXT: vpxor %xmm1, %xmm0, %xmm0 60 ; AVX-NEXT: retq 61 %1 = sub <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, %x 62 ret <4 x i32> %1 63 } 64 65 ; fold A-(A-B) -> B 66 define <4 x i32> @combine_vec_sub_sub(<4 x i32> %a, <4 x i32> %b) { 67 ; SSE-LABEL: combine_vec_sub_sub: 68 ; SSE: # %bb.0: 69 ; SSE-NEXT: movaps %xmm1, %xmm0 70 ; SSE-NEXT: retq 71 ; 72 ; AVX-LABEL: combine_vec_sub_sub: 73 ; AVX: # %bb.0: 74 ; AVX-NEXT: vmovaps %xmm1, %xmm0 75 ; AVX-NEXT: retq 76 %1 = sub <4 x i32> %a, %b 77 %2 = sub <4 x i32> %a, %1 78 ret <4 x i32> %2 79 } 80 81 ; fold (A+B)-A -> B 82 define <4 x i32> @combine_vec_sub_add0(<4 x i32> %a, <4 x i32> %b) { 83 ; SSE-LABEL: combine_vec_sub_add0: 84 ; SSE: # %bb.0: 85 ; SSE-NEXT: movaps %xmm1, %xmm0 86 ; SSE-NEXT: retq 87 ; 88 ; AVX-LABEL: combine_vec_sub_add0: 89 ; AVX: # %bb.0: 90 ; AVX-NEXT: vmovaps %xmm1, %xmm0 91 ; AVX-NEXT: retq 92 %1 = add <4 x i32> %a, %b 93 %2 = sub <4 x i32> %1, %a 94 ret <4 x i32> %2 95 } 96 97 ; fold (A+B)-B -> A 98 define <4 x i32> @combine_vec_sub_add1(<4 x i32> %a, <4 x i32> %b) { 99 ; SSE-LABEL: combine_vec_sub_add1: 100 ; SSE: # %bb.0: 101 ; SSE-NEXT: retq 102 ; 103 ; AVX-LABEL: combine_vec_sub_add1: 104 ; AVX: # %bb.0: 105 ; AVX-NEXT: retq 106 %1 = add <4 x i32> %a, %b 107 %2 = sub <4 x i32> %1, %b 108 ret <4 x i32> %2 109 } 110 111 ; fold C2-(A+C1) -> (C2-C1)-A 112 define <4 x i32> @combine_vec_sub_constant_add(<4 x i32> %a) { 113 ; SSE-LABEL: combine_vec_sub_constant_add: 114 ; SSE: # %bb.0: 115 ; SSE-NEXT: movdqa {{.*#+}} xmm1 = [3,1,4294967295,4294967293] 116 ; SSE-NEXT: psubd %xmm0, %xmm1 117 ; SSE-NEXT: movdqa %xmm1, %xmm0 118 ; SSE-NEXT: retq 119 ; 120 ; AVX-LABEL: combine_vec_sub_constant_add: 121 ; AVX: # %bb.0: 122 ; AVX-NEXT: vmovdqa {{.*#+}} xmm1 = [3,1,4294967295,4294967293] 123 ; AVX-NEXT: vpsubd %xmm0, %xmm1, %xmm0 124 ; AVX-NEXT: retq 125 %1 = add <4 x i32> %a, <i32 0, i32 1, i32 2, i32 3> 126 %2 = sub <4 x i32> <i32 3, i32 2, i32 1, i32 0>, %1 127 ret <4 x i32> %2 128 } 129 130 ; fold ((A+(B+C))-B) -> A+C 131 define <4 x i32> @combine_vec_sub_add_add(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) { 132 ; SSE-LABEL: combine_vec_sub_add_add: 133 ; SSE: # %bb.0: 134 ; SSE-NEXT: paddd %xmm2, %xmm0 135 ; SSE-NEXT: retq 136 ; 137 ; AVX-LABEL: combine_vec_sub_add_add: 138 ; AVX: # %bb.0: 139 ; AVX-NEXT: vpaddd %xmm2, %xmm0, %xmm0 140 ; AVX-NEXT: retq 141 %1 = add <4 x i32> %b, %c 142 %2 = add <4 x i32> %a, %1 143 %3 = sub <4 x i32> %2, %b 144 ret <4 x i32> %3 145 } 146 147 ; fold ((A+(B-C))-B) -> A-C 148 define <4 x i32> @combine_vec_sub_add_sub(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) { 149 ; SSE-LABEL: combine_vec_sub_add_sub: 150 ; SSE: # %bb.0: 151 ; SSE-NEXT: psubd %xmm2, %xmm0 152 ; SSE-NEXT: retq 153 ; 154 ; AVX-LABEL: combine_vec_sub_add_sub: 155 ; AVX: # %bb.0: 156 ; AVX-NEXT: vpsubd %xmm2, %xmm0, %xmm0 157 ; AVX-NEXT: retq 158 %1 = sub <4 x i32> %b, %c 159 %2 = add <4 x i32> %a, %1 160 %3 = sub <4 x i32> %2, %b 161 ret <4 x i32> %3 162 } 163 164 ; fold ((A-(B-C))-C) -> A-B 165 define <4 x i32> @combine_vec_sub_sub_sub(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) { 166 ; SSE-LABEL: combine_vec_sub_sub_sub: 167 ; SSE: # %bb.0: 168 ; SSE-NEXT: psubd %xmm1, %xmm0 169 ; SSE-NEXT: retq 170 ; 171 ; AVX-LABEL: combine_vec_sub_sub_sub: 172 ; AVX: # %bb.0: 173 ; AVX-NEXT: vpsubd %xmm1, %xmm0, %xmm0 174 ; AVX-NEXT: retq 175 %1 = sub <4 x i32> %b, %c 176 %2 = sub <4 x i32> %a, %1 177 %3 = sub <4 x i32> %2, %c 178 ret <4 x i32> %3 179 } 180 181 ; fold undef-A -> undef 182 define <4 x i32> @combine_vec_sub_undef0(<4 x i32> %a) { 183 ; SSE-LABEL: combine_vec_sub_undef0: 184 ; SSE: # %bb.0: 185 ; SSE-NEXT: retq 186 ; 187 ; AVX-LABEL: combine_vec_sub_undef0: 188 ; AVX: # %bb.0: 189 ; AVX-NEXT: retq 190 %1 = sub <4 x i32> undef, %a 191 ret <4 x i32> %1 192 } 193 194 ; fold A-undef -> undef 195 define <4 x i32> @combine_vec_sub_undef1(<4 x i32> %a) { 196 ; SSE-LABEL: combine_vec_sub_undef1: 197 ; SSE: # %bb.0: 198 ; SSE-NEXT: retq 199 ; 200 ; AVX-LABEL: combine_vec_sub_undef1: 201 ; AVX: # %bb.0: 202 ; AVX-NEXT: retq 203 %1 = sub <4 x i32> %a, undef 204 ret <4 x i32> %1 205 } 206 207 ; sub X, (sext Y i1) -> add X, (and Y 1) 208 define <4 x i32> @combine_vec_add_sext(<4 x i32> %x, <4 x i1> %y) { 209 ; SSE-LABEL: combine_vec_add_sext: 210 ; SSE: # %bb.0: 211 ; SSE-NEXT: pslld $31, %xmm1 212 ; SSE-NEXT: psrad $31, %xmm1 213 ; SSE-NEXT: psubd %xmm1, %xmm0 214 ; SSE-NEXT: retq 215 ; 216 ; AVX-LABEL: combine_vec_add_sext: 217 ; AVX: # %bb.0: 218 ; AVX-NEXT: vpslld $31, %xmm1, %xmm1 219 ; AVX-NEXT: vpsrad $31, %xmm1, %xmm1 220 ; AVX-NEXT: vpsubd %xmm1, %xmm0, %xmm0 221 ; AVX-NEXT: retq 222 %1 = sext <4 x i1> %y to <4 x i32> 223 %2 = sub <4 x i32> %x, %1 224 ret <4 x i32> %2 225 } 226 227 ; sub X, (sextinreg Y i1) -> add X, (and Y 1) 228 define <4 x i32> @combine_vec_sub_sextinreg(<4 x i32> %x, <4 x i32> %y) { 229 ; SSE-LABEL: combine_vec_sub_sextinreg: 230 ; SSE: # %bb.0: 231 ; SSE-NEXT: pslld $31, %xmm1 232 ; SSE-NEXT: psrad $31, %xmm1 233 ; SSE-NEXT: psubd %xmm1, %xmm0 234 ; SSE-NEXT: retq 235 ; 236 ; AVX-LABEL: combine_vec_sub_sextinreg: 237 ; AVX: # %bb.0: 238 ; AVX-NEXT: vpslld $31, %xmm1, %xmm1 239 ; AVX-NEXT: vpsrad $31, %xmm1, %xmm1 240 ; AVX-NEXT: vpsubd %xmm1, %xmm0, %xmm0 241 ; AVX-NEXT: retq 242 %1 = shl <4 x i32> %y, <i32 31, i32 31, i32 31, i32 31> 243 %2 = ashr <4 x i32> %1, <i32 31, i32 31, i32 31, i32 31> 244 %3 = sub <4 x i32> %x, %2 245 ret <4 x i32> %3 246 } 247