1 ; RUN: llc < %s -march=x86-64 -mtriple=x86_64-unknown-linux-gnu -mcpu=core2 | FileCheck %s -check-prefix=CHECK -check-prefix=SSE 2 ; RUN: llc < %s -march=x86-64 -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7-avx | FileCheck %s -check-prefix=CHECK -check-prefix=AVX 3 4 5 ; Verify that we correctly generate 'addsub' instructions from 6 ; a sequence of vector extracts + float add/sub + vector inserts. 7 8 define <4 x float> @test1(<4 x float> %A, <4 x float> %B) { 9 %1 = extractelement <4 x float> %A, i32 0 10 %2 = extractelement <4 x float> %B, i32 0 11 %sub = fsub float %1, %2 12 %3 = extractelement <4 x float> %A, i32 2 13 %4 = extractelement <4 x float> %B, i32 2 14 %sub2 = fsub float %3, %4 15 %5 = extractelement <4 x float> %A, i32 1 16 %6 = extractelement <4 x float> %B, i32 1 17 %add = fadd float %5, %6 18 %7 = extractelement <4 x float> %A, i32 3 19 %8 = extractelement <4 x float> %B, i32 3 20 %add2 = fadd float %7, %8 21 %vecinsert1 = insertelement <4 x float> undef, float %add, i32 1 22 %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 3 23 %vecinsert3 = insertelement <4 x float> %vecinsert2, float %sub, i32 0 24 %vecinsert4 = insertelement <4 x float> %vecinsert3, float %sub2, i32 2 25 ret <4 x float> %vecinsert4 26 } 27 ; CHECK-LABEL: test1 28 ; SSE: addsubps 29 ; AVX: vaddsubps 30 ; CHECK-NEXT: ret 31 32 33 define <4 x float> @test2(<4 x float> %A, <4 x float> %B) { 34 %1 = extractelement <4 x float> %A, i32 2 35 %2 = extractelement <4 x float> %B, i32 2 36 %sub2 = fsub float %1, %2 37 %3 = extractelement <4 x float> %A, i32 3 38 %4 = extractelement <4 x float> %B, i32 3 39 %add2 = fadd float %3, %4 40 %vecinsert1 = insertelement <4 x float> undef, float %sub2, i32 2 41 %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 3 42 ret <4 x float> %vecinsert2 43 } 44 ; CHECK-LABEL: test2 45 ; SSE: addsubps 46 ; AVX: vaddsubps 47 ; CHECK-NEXT: ret 48 49 50 define <4 x float> @test3(<4 x float> %A, <4 x float> %B) { 51 %1 = extractelement <4 x float> %A, i32 0 52 %2 = extractelement <4 x float> %B, i32 0 53 %sub = fsub float %1, %2 54 %3 = extractelement <4 x float> %A, i32 3 55 %4 = extractelement <4 x float> %B, i32 3 56 %add = fadd float %4, %3 57 %vecinsert1 = insertelement <4 x float> undef, float %sub, i32 0 58 %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add, i32 3 59 ret <4 x float> %vecinsert2 60 } 61 ; CHECK-LABEL: test3 62 ; SSE: addsubps 63 ; AVX: vaddsubps 64 ; CHECK-NEXT: ret 65 66 67 define <4 x float> @test4(<4 x float> %A, <4 x float> %B) { 68 %1 = extractelement <4 x float> %A, i32 2 69 %2 = extractelement <4 x float> %B, i32 2 70 %sub = fsub float %1, %2 71 %3 = extractelement <4 x float> %A, i32 1 72 %4 = extractelement <4 x float> %B, i32 1 73 %add = fadd float %3, %4 74 %vecinsert1 = insertelement <4 x float> undef, float %sub, i32 2 75 %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add, i32 1 76 ret <4 x float> %vecinsert2 77 } 78 ; CHECK-LABEL: test4 79 ; SSE: addsubps 80 ; AVX: vaddsubps 81 ; CHECK-NEXT: ret 82 83 84 define <4 x float> @test5(<4 x float> %A, <4 x float> %B) { 85 %1 = extractelement <4 x float> %A, i32 0 86 %2 = extractelement <4 x float> %B, i32 0 87 %sub2 = fsub float %1, %2 88 %3 = extractelement <4 x float> %A, i32 1 89 %4 = extractelement <4 x float> %B, i32 1 90 %add2 = fadd float %3, %4 91 %vecinsert1 = insertelement <4 x float> undef, float %sub2, i32 0 92 %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 1 93 ret <4 x float> %vecinsert2 94 } 95 ; CHECK-LABEL: test5 96 ; SSE: addsubps 97 ; AVX: vaddsubps 98 ; CHECK-NEXT: ret 99 100 101 define <4 x float> @test6(<4 x float> %A, <4 x float> %B) { 102 %1 = extractelement <4 x float> %A, i32 0 103 %2 = extractelement <4 x float> %B, i32 0 104 %sub = fsub float %1, %2 105 %3 = extractelement <4 x float> %A, i32 2 106 %4 = extractelement <4 x float> %B, i32 2 107 %sub2 = fsub float %3, %4 108 %5 = extractelement <4 x float> %A, i32 1 109 %6 = extractelement <4 x float> %B, i32 1 110 %add = fadd float %5, %6 111 %7 = extractelement <4 x float> %A, i32 3 112 %8 = extractelement <4 x float> %B, i32 3 113 %add2 = fadd float %7, %8 114 %vecinsert1 = insertelement <4 x float> undef, float %add, i32 1 115 %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 3 116 %vecinsert3 = insertelement <4 x float> %vecinsert2, float %sub, i32 0 117 %vecinsert4 = insertelement <4 x float> %vecinsert3, float %sub2, i32 2 118 ret <4 x float> %vecinsert4 119 } 120 ; CHECK-LABEL: test6 121 ; SSE: addsubps 122 ; AVX: vaddsubps 123 ; CHECK-NEXT: ret 124 125 126 define <4 x double> @test7(<4 x double> %A, <4 x double> %B) { 127 %1 = extractelement <4 x double> %A, i32 0 128 %2 = extractelement <4 x double> %B, i32 0 129 %sub = fsub double %1, %2 130 %3 = extractelement <4 x double> %A, i32 2 131 %4 = extractelement <4 x double> %B, i32 2 132 %sub2 = fsub double %3, %4 133 %5 = extractelement <4 x double> %A, i32 1 134 %6 = extractelement <4 x double> %B, i32 1 135 %add = fadd double %5, %6 136 %7 = extractelement <4 x double> %A, i32 3 137 %8 = extractelement <4 x double> %B, i32 3 138 %add2 = fadd double %7, %8 139 %vecinsert1 = insertelement <4 x double> undef, double %add, i32 1 140 %vecinsert2 = insertelement <4 x double> %vecinsert1, double %add2, i32 3 141 %vecinsert3 = insertelement <4 x double> %vecinsert2, double %sub, i32 0 142 %vecinsert4 = insertelement <4 x double> %vecinsert3, double %sub2, i32 2 143 ret <4 x double> %vecinsert4 144 } 145 ; CHECK-LABEL: test7 146 ; SSE: addsubpd 147 ; SSE-NEXT: addsubpd 148 ; AVX: vaddsubpd 149 ; AVX-NOT: vaddsubpd 150 ; CHECK: ret 151 152 153 define <2 x double> @test8(<2 x double> %A, <2 x double> %B) { 154 %1 = extractelement <2 x double> %A, i32 0 155 %2 = extractelement <2 x double> %B, i32 0 156 %sub = fsub double %1, %2 157 %3 = extractelement <2 x double> %A, i32 1 158 %4 = extractelement <2 x double> %B, i32 1 159 %add = fadd double %3, %4 160 %vecinsert1 = insertelement <2 x double> undef, double %sub, i32 0 161 %vecinsert2 = insertelement <2 x double> %vecinsert1, double %add, i32 1 162 ret <2 x double> %vecinsert2 163 } 164 ; CHECK-LABEL: test8 165 ; SSE: addsubpd 166 ; AVX: vaddsubpd 167 ; CHECK: ret 168 169 170 define <8 x float> @test9(<8 x float> %A, <8 x float> %B) { 171 %1 = extractelement <8 x float> %A, i32 0 172 %2 = extractelement <8 x float> %B, i32 0 173 %sub = fsub float %1, %2 174 %3 = extractelement <8 x float> %A, i32 2 175 %4 = extractelement <8 x float> %B, i32 2 176 %sub2 = fsub float %3, %4 177 %5 = extractelement <8 x float> %A, i32 1 178 %6 = extractelement <8 x float> %B, i32 1 179 %add = fadd float %5, %6 180 %7 = extractelement <8 x float> %A, i32 3 181 %8 = extractelement <8 x float> %B, i32 3 182 %add2 = fadd float %7, %8 183 %9 = extractelement <8 x float> %A, i32 4 184 %10 = extractelement <8 x float> %B, i32 4 185 %sub3 = fsub float %9, %10 186 %11 = extractelement <8 x float> %A, i32 6 187 %12 = extractelement <8 x float> %B, i32 6 188 %sub4 = fsub float %11, %12 189 %13 = extractelement <8 x float> %A, i32 5 190 %14 = extractelement <8 x float> %B, i32 5 191 %add3 = fadd float %13, %14 192 %15 = extractelement <8 x float> %A, i32 7 193 %16 = extractelement <8 x float> %B, i32 7 194 %add4 = fadd float %15, %16 195 %vecinsert1 = insertelement <8 x float> undef, float %add, i32 1 196 %vecinsert2 = insertelement <8 x float> %vecinsert1, float %add2, i32 3 197 %vecinsert3 = insertelement <8 x float> %vecinsert2, float %sub, i32 0 198 %vecinsert4 = insertelement <8 x float> %vecinsert3, float %sub2, i32 2 199 %vecinsert5 = insertelement <8 x float> %vecinsert4, float %add3, i32 5 200 %vecinsert6 = insertelement <8 x float> %vecinsert5, float %add4, i32 7 201 %vecinsert7 = insertelement <8 x float> %vecinsert6, float %sub3, i32 4 202 %vecinsert8 = insertelement <8 x float> %vecinsert7, float %sub4, i32 6 203 ret <8 x float> %vecinsert8 204 } 205 ; CHECK-LABEL: test9 206 ; SSE: addsubps 207 ; SSE-NEXT: addsubps 208 ; AVX: vaddsubps 209 ; AVX-NOT: vaddsubps 210 ; CHECK: ret 211 212 213 ; Verify that we don't generate addsub instruction for the following 214 ; functions. 215 define <4 x float> @test10(<4 x float> %A, <4 x float> %B) { 216 %1 = extractelement <4 x float> %A, i32 0 217 %2 = extractelement <4 x float> %B, i32 0 218 %sub = fsub float %1, %2 219 %vecinsert1 = insertelement <4 x float> undef, float %sub, i32 0 220 ret <4 x float> %vecinsert1 221 } 222 ; CHECK-LABEL: test10 223 ; CHECK-NOT: addsubps 224 ; CHECK: ret 225 226 227 define <4 x float> @test11(<4 x float> %A, <4 x float> %B) { 228 %1 = extractelement <4 x float> %A, i32 2 229 %2 = extractelement <4 x float> %B, i32 2 230 %sub = fsub float %1, %2 231 %vecinsert1 = insertelement <4 x float> undef, float %sub, i32 2 232 ret <4 x float> %vecinsert1 233 } 234 ; CHECK-LABEL: test11 235 ; CHECK-NOT: addsubps 236 ; CHECK: ret 237 238 239 define <4 x float> @test12(<4 x float> %A, <4 x float> %B) { 240 %1 = extractelement <4 x float> %A, i32 1 241 %2 = extractelement <4 x float> %B, i32 1 242 %add = fadd float %1, %2 243 %vecinsert1 = insertelement <4 x float> undef, float %add, i32 1 244 ret <4 x float> %vecinsert1 245 } 246 ; CHECK-LABEL: test12 247 ; CHECK-NOT: addsubps 248 ; CHECK: ret 249 250 251 define <4 x float> @test13(<4 x float> %A, <4 x float> %B) { 252 %1 = extractelement <4 x float> %A, i32 3 253 %2 = extractelement <4 x float> %B, i32 3 254 %add = fadd float %1, %2 255 %vecinsert1 = insertelement <4 x float> undef, float %add, i32 3 256 ret <4 x float> %vecinsert1 257 } 258 ; CHECK-LABEL: test13 259 ; CHECK-NOT: addsubps 260 ; CHECK: ret 261 262 263 define <4 x float> @test14(<4 x float> %A, <4 x float> %B) { 264 %1 = extractelement <4 x float> %A, i32 0 265 %2 = extractelement <4 x float> %B, i32 0 266 %sub = fsub float %1, %2 267 %3 = extractelement <4 x float> %A, i32 2 268 %4 = extractelement <4 x float> %B, i32 2 269 %sub2 = fsub float %3, %4 270 %vecinsert1 = insertelement <4 x float> undef, float %sub, i32 0 271 %vecinsert2 = insertelement <4 x float> %vecinsert1, float %sub2, i32 2 272 ret <4 x float> %vecinsert2 273 } 274 ; CHECK-LABEL: test14 275 ; CHECK-NOT: addsubps 276 ; CHECK: ret 277 278 279 define <4 x float> @test15(<4 x float> %A, <4 x float> %B) { 280 %1 = extractelement <4 x float> %A, i32 1 281 %2 = extractelement <4 x float> %B, i32 1 282 %add = fadd float %1, %2 283 %3 = extractelement <4 x float> %A, i32 3 284 %4 = extractelement <4 x float> %B, i32 3 285 %add2 = fadd float %3, %4 286 %vecinsert1 = insertelement <4 x float> undef, float %add, i32 1 287 %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 3 288 ret <4 x float> %vecinsert2 289 } 290 ; CHECK-LABEL: test15 291 ; CHECK-NOT: addsubps 292 ; CHECK: ret 293 294 295 define <4 x float> @test16(<4 x float> %A, <4 x float> %B) { 296 %1 = extractelement <4 x float> %A, i32 0 297 %2 = extractelement <4 x float> %B, i32 0 298 %sub = fsub float %1, undef 299 %3 = extractelement <4 x float> %A, i32 2 300 %4 = extractelement <4 x float> %B, i32 2 301 %sub2 = fsub float %3, %4 302 %5 = extractelement <4 x float> %A, i32 1 303 %6 = extractelement <4 x float> %B, i32 1 304 %add = fadd float %5, undef 305 %7 = extractelement <4 x float> %A, i32 3 306 %8 = extractelement <4 x float> %B, i32 3 307 %add2 = fadd float %7, %8 308 %vecinsert1 = insertelement <4 x float> undef, float %add, i32 1 309 %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 3 310 %vecinsert3 = insertelement <4 x float> %vecinsert2, float %sub, i32 0 311 %vecinsert4 = insertelement <4 x float> %vecinsert3, float %sub2, i32 2 312 ret <4 x float> %vecinsert4 313 } 314 ; CHECK-LABEL: test16 315 ; CHECK-NOT: addsubps 316 ; CHECK: ret 317 318 319