1 ;; Expander definitions for vector support between altivec & vsx. No 2 ;; instructions are in this file, this file provides the generic vector 3 ;; expander, and the actual vector instructions will be in altivec.md and 4 ;; vsx.md 5 6 ;; Copyright (C) 2009-2022 Free Software Foundation, Inc. 7 ;; Contributed by Michael Meissner <meissner (a] linux.vnet.ibm.com> 8 9 ;; This file is part of GCC. 10 11 ;; GCC is free software; you can redistribute it and/or modify it 12 ;; under the terms of the GNU General Public License as published 13 ;; by the Free Software Foundation; either version 3, or (at your 14 ;; option) any later version. 15 16 ;; GCC is distributed in the hope that it will be useful, but WITHOUT 17 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 18 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 19 ;; License for more details. 20 21 ;; You should have received a copy of the GNU General Public License 22 ;; along with GCC; see the file COPYING3. If not see 23 ;; <http://www.gnu.org/licenses/>. 24 25 26 ;; Vector int modes 27 (define_mode_iterator VEC_I [V16QI V8HI V4SI V2DI]) 28 29 ;; 128-bit int modes 30 (define_mode_iterator VEC_TI [V1TI TI]) 31 32 ;; Vector int modes for parity 33 (define_mode_iterator VEC_IP [V8HI 34 V4SI 35 V2DI 36 V1TI 37 TI]) 38 39 ;; Vector float modes 40 (define_mode_iterator VEC_F [V4SF V2DF]) 41 42 ;; Vector arithmetic modes 43 (define_mode_iterator VEC_A [V16QI V8HI V4SI V2DI V4SF V2DF]) 44 45 ;; Vector modes that need alginment via permutes 46 (define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF]) 47 48 ;; Vector logical modes 49 (define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI KF TF]) 50 51 ;; Vector modes for moves. Don't do TImode or TFmode here, since their 52 ;; moves are handled elsewhere. 53 (define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI KF]) 54 55 ;; Vector modes for types that don't need a realignment under VSX 56 (define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF V1TI KF TF]) 57 58 ;; Vector comparison modes 59 (define_mode_iterator VEC_C [V16QI V8HI V4SI V2DI V4SF V2DF V1TI]) 60 61 ;; Vector init/extract modes 62 (define_mode_iterator VEC_E [V16QI V8HI V4SI V2DI V4SF V2DF]) 63 64 ;; Vector modes for 64-bit base types 65 (define_mode_iterator VEC_64 [V2DI V2DF]) 66 67 ;; Vector integer modes 68 (define_mode_iterator VI [V4SI V8HI V16QI]) 69 70 ;; Base type from vector mode 71 (define_mode_attr VEC_base [(V16QI "QI") 72 (V8HI "HI") 73 (V4SI "SI") 74 (V2DI "DI") 75 (V4SF "SF") 76 (V2DF "DF") 77 (V1TI "TI") 78 (TI "TI")]) 79 80 ;; As above, but in lower case 81 (define_mode_attr VEC_base_l [(V16QI "qi") 82 (V8HI "hi") 83 (V4SI "si") 84 (V2DI "di") 85 (V4SF "sf") 86 (V2DF "df") 87 (V1TI "ti") 88 (TI "ti")]) 89 90 ;; Same size integer type for floating point data 91 (define_mode_attr VEC_int [(V4SF "v4si") 92 (V2DF "v2di")]) 93 94 (define_mode_attr VEC_INT [(V4SF "V4SI") 95 (V2DF "V2DI")]) 96 97 ;; constants for unspec 98 (define_c_enum "unspec" [UNSPEC_PREDICATE 99 UNSPEC_REDUC 100 UNSPEC_NEZ_P]) 101 102 ;; Vector reduction code iterators 103 (define_code_iterator VEC_reduc [plus smin smax]) 104 105 (define_code_attr VEC_reduc_name [(plus "plus") 106 (smin "smin") 107 (smax "smax")]) 108 109 (define_code_attr VEC_reduc_rtx [(plus "add") 110 (smin "smin") 111 (smax "smax")]) 112 113 ;; code iterators and attributes for vector FP comparison operators: 114 (define_code_iterator 115 vector_fp_comparison_simple [lt le ne ungt unge unlt unle]) 116 (define_code_iterator 117 vector_fp_comparison_complex [ltgt uneq unordered ordered]) 118 119 121 ;; Vector move instructions. Little-endian VSX loads and stores require 122 ;; special handling to circumvent "element endianness." 123 (define_expand "mov<mode>" 124 [(set (match_operand:VEC_M 0 "nonimmediate_operand") 125 (match_operand:VEC_M 1 "any_operand"))] 126 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" 127 { 128 if (can_create_pseudo_p ()) 129 { 130 if (CONSTANT_P (operands[1])) 131 { 132 if (FLOAT128_VECTOR_P (<MODE>mode)) 133 { 134 if (!easy_fp_constant (operands[1], <MODE>mode)) 135 operands[1] = force_const_mem (<MODE>mode, operands[1]); 136 } 137 else if (!easy_vector_constant (operands[1], <MODE>mode)) 138 operands[1] = force_const_mem (<MODE>mode, operands[1]); 139 } 140 141 if (!vlogical_operand (operands[0], <MODE>mode) 142 && !vlogical_operand (operands[1], <MODE>mode)) 143 operands[1] = force_reg (<MODE>mode, operands[1]); 144 } 145 /* When generating load/store instructions to/from VSX registers on 146 pre-power9 hardware in little endian mode, we need to emit register 147 permute instructions to byte swap the contents, since the VSX load/store 148 instructions do not include a byte swap as part of their operation. 149 Altivec loads and stores have no such problem, so we skip them below. */ 150 if (!BYTES_BIG_ENDIAN 151 && VECTOR_MEM_VSX_P (<MODE>mode) 152 && !TARGET_P9_VECTOR 153 && !gpr_or_gpr_p (operands[0], operands[1]) 154 && ((memory_operand (operands[0], <MODE>mode) 155 && !altivec_indexed_or_indirect_operand(operands[0], <MODE>mode)) 156 ^ (memory_operand (operands[1], <MODE>mode) 157 && !altivec_indexed_or_indirect_operand(operands[1], <MODE>mode)))) 158 { 159 rs6000_emit_le_vsx_move (operands[0], operands[1], <MODE>mode); 160 DONE; 161 } 162 }) 163 164 ;; Generic vector floating point load/store instructions. These will match 165 ;; insns defined in vsx.md or altivec.md depending on the switches. 166 (define_expand "vector_load_<mode>" 167 [(set (match_operand:VEC_M 0 "vfloat_operand") 168 (match_operand:VEC_M 1 "memory_operand"))] 169 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" 170 "") 171 172 (define_expand "vector_store_<mode>" 173 [(set (match_operand:VEC_M 0 "memory_operand") 174 (match_operand:VEC_M 1 "vfloat_operand"))] 175 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" 176 "") 177 178 ;; Splits if a GPR register was chosen for the move 179 (define_split 180 [(set (match_operand:VEC_L 0 "nonimmediate_operand") 181 (match_operand:VEC_L 1 "input_operand"))] 182 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode) 183 && reload_completed 184 && gpr_or_gpr_p (operands[0], operands[1]) 185 && !direct_move_p (operands[0], operands[1]) 186 && !quad_load_store_p (operands[0], operands[1])" 187 [(pc)] 188 { 189 rs6000_split_multireg_move (operands[0], operands[1]); 190 DONE; 191 }) 192 193 195 ;; Generic floating point vector arithmetic support 196 (define_expand "add<mode>3" 197 [(set (match_operand:VEC_F 0 "vfloat_operand") 198 (plus:VEC_F (match_operand:VEC_F 1 "vfloat_operand") 199 (match_operand:VEC_F 2 "vfloat_operand")))] 200 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 201 "") 202 203 (define_expand "sub<mode>3" 204 [(set (match_operand:VEC_F 0 "vfloat_operand") 205 (minus:VEC_F (match_operand:VEC_F 1 "vfloat_operand") 206 (match_operand:VEC_F 2 "vfloat_operand")))] 207 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 208 "") 209 210 (define_expand "mul<mode>3" 211 [(set (match_operand:VEC_F 0 "vfloat_operand") 212 (mult:VEC_F (match_operand:VEC_F 1 "vfloat_operand") 213 (match_operand:VEC_F 2 "vfloat_operand")))] 214 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 215 { 216 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) 217 { 218 emit_insn (gen_altivec_mulv4sf3 (operands[0], operands[1], operands[2])); 219 DONE; 220 } 221 }) 222 223 (define_expand "div<mode>3" 224 [(set (match_operand:VEC_F 0 "vfloat_operand") 225 (div:VEC_F (match_operand:VEC_F 1 "vfloat_operand") 226 (match_operand:VEC_F 2 "vfloat_operand")))] 227 "VECTOR_UNIT_VSX_P (<MODE>mode)" 228 { 229 if (RS6000_RECIP_AUTO_RE_P (<MODE>mode) 230 && can_create_pseudo_p () && flag_finite_math_only 231 && !flag_trapping_math && flag_reciprocal_math) 232 { 233 rs6000_emit_swdiv (operands[0], operands[1], operands[2], true); 234 DONE; 235 } 236 }) 237 238 (define_expand "neg<mode>2" 239 [(set (match_operand:VEC_F 0 "vfloat_operand") 240 (neg:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))] 241 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 242 { 243 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) 244 { 245 emit_insn (gen_altivec_negv4sf2 (operands[0], operands[1])); 246 DONE; 247 } 248 }) 249 250 (define_expand "abs<mode>2" 251 [(set (match_operand:VEC_F 0 "vfloat_operand") 252 (abs:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))] 253 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 254 { 255 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) 256 { 257 emit_insn (gen_altivec_absv4sf2 (operands[0], operands[1])); 258 DONE; 259 } 260 }) 261 262 (define_expand "smin<mode>3" 263 [(set (match_operand:VEC_F 0 "register_operand") 264 (smin:VEC_F (match_operand:VEC_F 1 "register_operand") 265 (match_operand:VEC_F 2 "register_operand")))] 266 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 267 "") 268 269 (define_expand "smax<mode>3" 270 [(set (match_operand:VEC_F 0 "register_operand") 271 (smax:VEC_F (match_operand:VEC_F 1 "register_operand") 272 (match_operand:VEC_F 2 "register_operand")))] 273 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 274 "") 275 276 277 (define_expand "sqrt<mode>2" 278 [(set (match_operand:VEC_F 0 "vfloat_operand") 279 (sqrt:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))] 280 "VECTOR_UNIT_VSX_P (<MODE>mode)" 281 { 282 if (<MODE>mode == V4SFmode 283 && !optimize_function_for_size_p (cfun) 284 && flag_finite_math_only && !flag_trapping_math 285 && flag_unsafe_math_optimizations) 286 { 287 rs6000_emit_swsqrt (operands[0], operands[1], 0); 288 DONE; 289 } 290 }) 291 292 (define_expand "rsqrte<mode>2" 293 [(set (match_operand:VEC_F 0 "vfloat_operand") 294 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")] 295 UNSPEC_RSQRT))] 296 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 297 "") 298 299 (define_expand "re<mode>2" 300 [(set (match_operand:VEC_F 0 "vfloat_operand") 301 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")] 302 UNSPEC_FRES))] 303 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 304 "") 305 306 (define_expand "ftrunc<mode>2" 307 [(set (match_operand:VEC_F 0 "vfloat_operand") 308 (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))] 309 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 310 "") 311 312 (define_expand "vector_ceil<mode>2" 313 [(set (match_operand:VEC_F 0 "vfloat_operand") 314 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")] 315 UNSPEC_FRIP))] 316 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 317 "") 318 319 (define_expand "vector_floor<mode>2" 320 [(set (match_operand:VEC_F 0 "vfloat_operand") 321 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand")] 322 UNSPEC_FRIM))] 323 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 324 "") 325 326 (define_expand "vector_btrunc<mode>2" 327 [(set (match_operand:VEC_F 0 "vfloat_operand") 328 (fix:VEC_F (match_operand:VEC_F 1 "vfloat_operand")))] 329 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 330 "") 331 332 (define_expand "vector_copysign<mode>3" 333 [(set (match_operand:VEC_F 0 "vfloat_operand") 334 (unspec:VEC_F [(match_operand:VEC_F 1 "vfloat_operand") 335 (match_operand:VEC_F 2 "vfloat_operand")] UNSPEC_COPYSIGN))] 336 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 337 { 338 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) 339 { 340 emit_insn (gen_altivec_copysign_v4sf3 (operands[0], operands[1], 341 operands[2])); 342 DONE; 343 } 344 }) 345 346 348 ;; Vector comparisons 349 (define_expand "vcond<mode><mode>" 350 [(set (match_operand:VEC_F 0 "vfloat_operand") 351 (if_then_else:VEC_F 352 (match_operator 3 "comparison_operator" 353 [(match_operand:VEC_F 4 "vfloat_operand") 354 (match_operand:VEC_F 5 "vfloat_operand")]) 355 (match_operand:VEC_F 1 "vfloat_operand") 356 (match_operand:VEC_F 2 "vfloat_operand")))] 357 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 358 { 359 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], 360 operands[3], operands[4], operands[5])) 361 DONE; 362 else 363 gcc_unreachable (); 364 }) 365 366 (define_expand "vcond<mode><mode>" 367 [(set (match_operand:VEC_I 0 "vint_operand") 368 (if_then_else:VEC_I 369 (match_operator 3 "comparison_operator" 370 [(match_operand:VEC_I 4 "vint_operand") 371 (match_operand:VEC_I 5 "vint_operand")]) 372 (match_operand:VEC_I 1 "vector_int_reg_or_same_bit") 373 (match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))] 374 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 375 { 376 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], 377 operands[3], operands[4], operands[5])) 378 DONE; 379 else 380 gcc_unreachable (); 381 }) 382 383 (define_expand "vcondv4sfv4si" 384 [(set (match_operand:V4SF 0 "vfloat_operand") 385 (if_then_else:V4SF 386 (match_operator 3 "comparison_operator" 387 [(match_operand:V4SI 4 "vint_operand") 388 (match_operand:V4SI 5 "vint_operand")]) 389 (match_operand:V4SF 1 "vfloat_operand") 390 (match_operand:V4SF 2 "vfloat_operand")))] 391 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode) 392 && VECTOR_UNIT_ALTIVEC_P (V4SImode)" 393 { 394 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], 395 operands[3], operands[4], operands[5])) 396 DONE; 397 else 398 gcc_unreachable (); 399 }) 400 401 (define_expand "vcondv4siv4sf" 402 [(set (match_operand:V4SI 0 "vint_operand") 403 (if_then_else:V4SI 404 (match_operator 3 "comparison_operator" 405 [(match_operand:V4SF 4 "vfloat_operand") 406 (match_operand:V4SF 5 "vfloat_operand")]) 407 (match_operand:V4SI 1 "vint_operand") 408 (match_operand:V4SI 2 "vint_operand")))] 409 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode) 410 && VECTOR_UNIT_ALTIVEC_P (V4SImode)" 411 { 412 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], 413 operands[3], operands[4], operands[5])) 414 DONE; 415 else 416 gcc_unreachable (); 417 }) 418 419 (define_expand "vcondv2dfv2di" 420 [(set (match_operand:V2DF 0 "vfloat_operand") 421 (if_then_else:V2DF 422 (match_operator 3 "comparison_operator" 423 [(match_operand:V2DI 4 "vint_operand") 424 (match_operand:V2DI 5 "vint_operand")]) 425 (match_operand:V2DF 1 "vfloat_operand") 426 (match_operand:V2DF 2 "vfloat_operand")))] 427 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode) 428 && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)" 429 { 430 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], 431 operands[3], operands[4], operands[5])) 432 DONE; 433 else 434 gcc_unreachable (); 435 }) 436 437 (define_expand "vcondv2div2df" 438 [(set (match_operand:V2DI 0 "vint_operand") 439 (if_then_else:V2DI 440 (match_operator 3 "comparison_operator" 441 [(match_operand:V2DF 4 "vfloat_operand") 442 (match_operand:V2DF 5 "vfloat_operand")]) 443 (match_operand:V2DI 1 "vint_operand") 444 (match_operand:V2DI 2 "vint_operand")))] 445 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode) 446 && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)" 447 { 448 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], 449 operands[3], operands[4], operands[5])) 450 DONE; 451 else 452 gcc_unreachable (); 453 }) 454 455 (define_expand "vcondu<mode><mode>" 456 [(set (match_operand:VEC_I 0 "vint_operand") 457 (if_then_else:VEC_I 458 (match_operator 3 "comparison_operator" 459 [(match_operand:VEC_I 4 "vint_operand") 460 (match_operand:VEC_I 5 "vint_operand")]) 461 (match_operand:VEC_I 1 "vector_int_reg_or_same_bit") 462 (match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))] 463 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 464 { 465 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], 466 operands[3], operands[4], operands[5])) 467 DONE; 468 else 469 gcc_unreachable (); 470 }) 471 472 (define_expand "vconduv4sfv4si" 473 [(set (match_operand:V4SF 0 "vfloat_operand") 474 (if_then_else:V4SF 475 (match_operator 3 "comparison_operator" 476 [(match_operand:V4SI 4 "vint_operand") 477 (match_operand:V4SI 5 "vint_operand")]) 478 (match_operand:V4SF 1 "vfloat_operand") 479 (match_operand:V4SF 2 "vfloat_operand")))] 480 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode) 481 && VECTOR_UNIT_ALTIVEC_P (V4SImode)" 482 { 483 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], 484 operands[3], operands[4], operands[5])) 485 DONE; 486 else 487 gcc_unreachable (); 488 }) 489 490 (define_expand "vconduv2dfv2di" 491 [(set (match_operand:V2DF 0 "vfloat_operand") 492 (if_then_else:V2DF 493 (match_operator 3 "comparison_operator" 494 [(match_operand:V2DI 4 "vint_operand") 495 (match_operand:V2DI 5 "vint_operand")]) 496 (match_operand:V2DF 1 "vfloat_operand") 497 (match_operand:V2DF 2 "vfloat_operand")))] 498 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode) 499 && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DImode)" 500 { 501 if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2], 502 operands[3], operands[4], operands[5])) 503 DONE; 504 else 505 gcc_unreachable (); 506 }) 507 508 ;; To support vector condition vectorization, define vcond_mask and vec_cmp. 509 510 ;; Same mode for condition true/false values and predicate operand. 511 (define_expand "vcond_mask_<mode><mode>" 512 [(match_operand:VEC_I 0 "vint_operand") 513 (match_operand:VEC_I 1 "vint_operand") 514 (match_operand:VEC_I 2 "vint_operand") 515 (match_operand:VEC_I 3 "vint_operand")] 516 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 517 { 518 emit_insn (gen_vector_select_<mode> (operands[0], operands[2], operands[1], 519 operands[3])); 520 DONE; 521 }) 522 523 ;; Condition true/false values are float but predicate operand is of 524 ;; type integer vector with same element size. 525 (define_expand "vcond_mask_<mode><VEC_int>" 526 [(match_operand:VEC_F 0 "vfloat_operand") 527 (match_operand:VEC_F 1 "vfloat_operand") 528 (match_operand:VEC_F 2 "vfloat_operand") 529 (match_operand:<VEC_INT> 3 "vint_operand")] 530 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 531 { 532 emit_insn (gen_vector_select_<mode> (operands[0], operands[2], operands[1], 533 gen_lowpart (<MODE>mode, operands[3]))); 534 DONE; 535 }) 536 537 ;; For signed integer vectors comparison. 538 (define_expand "vec_cmp<mode><mode>" 539 [(set (match_operand:VEC_I 0 "vint_operand") 540 (match_operator 1 "signed_or_equality_comparison_operator" 541 [(match_operand:VEC_I 2 "vint_operand") 542 (match_operand:VEC_I 3 "vint_operand")]))] 543 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 544 { 545 enum rtx_code code = GET_CODE (operands[1]); 546 rtx tmp = gen_reg_rtx (<MODE>mode); 547 switch (code) 548 { 549 case NE: 550 emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3])); 551 emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0])); 552 break; 553 case EQ: 554 emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3])); 555 break; 556 case GE: 557 emit_insn (gen_vector_nlt<mode> (operands[0],operands[2], operands[3], 558 tmp)); 559 break; 560 case GT: 561 emit_insn (gen_vector_gt<mode> (operands[0], operands[2], operands[3])); 562 break; 563 case LE: 564 emit_insn (gen_vector_ngt<mode> (operands[0], operands[2], operands[3], 565 tmp)); 566 break; 567 case LT: 568 emit_insn (gen_vector_gt<mode> (operands[0], operands[3], operands[2])); 569 break; 570 default: 571 gcc_unreachable (); 572 break; 573 } 574 DONE; 575 }) 576 577 ;; For unsigned integer vectors comparison. 578 (define_expand "vec_cmpu<mode><mode>" 579 [(set (match_operand:VEC_I 0 "vint_operand") 580 (match_operator 1 "unsigned_or_equality_comparison_operator" 581 [(match_operand:VEC_I 2 "vint_operand") 582 (match_operand:VEC_I 3 "vint_operand")]))] 583 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 584 { 585 enum rtx_code code = GET_CODE (operands[1]); 586 rtx tmp = gen_reg_rtx (<MODE>mode); 587 switch (code) 588 { 589 case NE: 590 emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3])); 591 emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0])); 592 break; 593 case EQ: 594 emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3])); 595 break; 596 case GEU: 597 emit_insn (gen_vector_nltu<mode> (operands[0], operands[2], operands[3], 598 tmp)); 599 break; 600 case GTU: 601 emit_insn (gen_vector_gtu<mode> (operands[0], operands[2], operands[3])); 602 break; 603 case LEU: 604 emit_insn (gen_vector_ngtu<mode> (operands[0], operands[2], operands[3], 605 tmp)); 606 break; 607 case LTU: 608 emit_insn (gen_vector_gtu<mode> (operands[0], operands[3], operands[2])); 609 break; 610 default: 611 gcc_unreachable (); 612 break; 613 } 614 DONE; 615 }) 616 617 ;; For float point vectors comparison. 618 (define_expand "vec_cmp<mode><VEC_int>" 619 [(set (match_operand:<VEC_INT> 0 "vint_operand") 620 (match_operator 1 "comparison_operator" 621 [(match_operand:VEC_F 2 "vfloat_operand") 622 (match_operand:VEC_F 3 "vfloat_operand")]))] 623 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 624 { 625 enum rtx_code code = GET_CODE (operands[1]); 626 rtx res = gen_reg_rtx (<MODE>mode); 627 switch (code) 628 { 629 case NE: 630 emit_insn (gen_vector_ne<mode> (res, operands[2], operands[3])); 631 break; 632 case EQ: 633 emit_insn (gen_vector_eq<mode> (res, operands[2], operands[3])); 634 break; 635 case GE: 636 emit_insn (gen_vector_ge<mode> (res, operands[2], operands[3])); 637 break; 638 case GT: 639 emit_insn (gen_vector_gt<mode> (res, operands[2], operands[3])); 640 break; 641 case LE: 642 emit_insn (gen_vector_le<mode> (res, operands[2], operands[3])); 643 break; 644 case LT: 645 emit_insn (gen_vector_lt<mode> (res, operands[2], operands[3])); 646 break; 647 case LTGT: 648 emit_insn (gen_vector_ltgt<mode> (res, operands[2], operands[3])); 649 break; 650 case UNORDERED: 651 emit_insn (gen_vector_unordered<mode> (res, operands[2], operands[3])); 652 break; 653 case ORDERED: 654 emit_insn (gen_vector_ordered<mode> (res, operands[2], operands[3])); 655 break; 656 case UNEQ: 657 emit_insn (gen_vector_uneq<mode> (res, operands[2], operands[3])); 658 break; 659 case UNGE: 660 emit_insn (gen_vector_unge<mode> (res, operands[2], operands[3])); 661 break; 662 case UNGT: 663 emit_insn (gen_vector_ungt<mode> (res, operands[2], operands[3])); 664 break; 665 case UNLE: 666 emit_insn (gen_vector_unle<mode> (res, operands[2], operands[3])); 667 break; 668 case UNLT: 669 emit_insn (gen_vector_unlt<mode> (res, operands[2], operands[3])); 670 break; 671 672 default: 673 gcc_unreachable (); 674 } 675 676 emit_insn (gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); 677 DONE; 678 }) 679 680 (define_expand "vector_eq<mode>" 681 [(set (match_operand:VEC_C 0 "vlogical_operand") 682 (eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand") 683 (match_operand:VEC_C 2 "vlogical_operand")))] 684 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 685 "") 686 687 (define_expand "vector_gt<mode>" 688 [(set (match_operand:VEC_C 0 "vlogical_operand") 689 (gt:VEC_C (match_operand:VEC_C 1 "vlogical_operand") 690 (match_operand:VEC_C 2 "vlogical_operand")))] 691 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 692 "") 693 694 ; >= for integer vectors: swap operands and apply not-greater-than 695 (define_expand "vector_nlt<mode>" 696 [(set (match_operand:VEC_I 3 "vlogical_operand") 697 (gt:VEC_I (match_operand:VEC_I 2 "vlogical_operand") 698 (match_operand:VEC_I 1 "vlogical_operand"))) 699 (set (match_operand:VEC_I 0 "vlogical_operand") 700 (not:VEC_I (match_dup 3)))] 701 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 702 { 703 operands[3] = gen_reg_rtx_and_attrs (operands[0]); 704 }) 705 706 (define_expand "vector_nltv1ti" 707 [(set (match_operand:V1TI 3 "vlogical_operand") 708 (gt:V1TI (match_operand:V1TI 2 "vlogical_operand") 709 (match_operand:V1TI 1 "vlogical_operand"))) 710 (set (match_operand:V1TI 0 "vlogical_operand") 711 (not:V1TI (match_dup 3)))] 712 "TARGET_POWER10" 713 { 714 operands[3] = gen_reg_rtx_and_attrs (operands[0]); 715 }) 716 717 (define_expand "vector_gtu<mode>" 718 [(set (match_operand:VEC_I 0 "vint_operand") 719 (gtu:VEC_I (match_operand:VEC_I 1 "vint_operand") 720 (match_operand:VEC_I 2 "vint_operand")))] 721 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 722 "") 723 724 (define_expand "vector_gtuv1ti" 725 [(set (match_operand:V1TI 0 "altivec_register_operand") 726 (gtu:V1TI (match_operand:V1TI 1 "altivec_register_operand") 727 (match_operand:V1TI 2 "altivec_register_operand")))] 728 "TARGET_POWER10" 729 "") 730 731 ; >= for integer vectors: swap operands and apply not-greater-than 732 (define_expand "vector_nltu<mode>" 733 [(set (match_operand:VEC_I 3 "vlogical_operand") 734 (gtu:VEC_I (match_operand:VEC_I 2 "vlogical_operand") 735 (match_operand:VEC_I 1 "vlogical_operand"))) 736 (set (match_operand:VEC_I 0 "vlogical_operand") 737 (not:VEC_I (match_dup 3)))] 738 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 739 { 740 operands[3] = gen_reg_rtx_and_attrs (operands[0]); 741 }) 742 743 (define_expand "vector_nltuv1ti" 744 [(set (match_operand:V1TI 3 "vlogical_operand") 745 (gtu:V1TI (match_operand:V1TI 2 "vlogical_operand") 746 (match_operand:V1TI 1 "vlogical_operand"))) 747 (set (match_operand:V1TI 0 "vlogical_operand") 748 (not:V1TI (match_dup 3)))] 749 "TARGET_POWER10" 750 { 751 operands[3] = gen_reg_rtx_and_attrs (operands[0]); 752 }) 753 754 (define_expand "vector_geu<mode>" 755 [(set (match_operand:VEC_I 0 "vint_operand") 756 (geu:VEC_I (match_operand:VEC_I 1 "vint_operand") 757 (match_operand:VEC_I 2 "vint_operand")))] 758 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 759 "") 760 761 ; <= for integer vectors: apply not-greater-than 762 (define_expand "vector_ngt<mode>" 763 [(set (match_operand:VEC_I 3 "vlogical_operand") 764 (gt:VEC_I (match_operand:VEC_I 1 "vlogical_operand") 765 (match_operand:VEC_I 2 "vlogical_operand"))) 766 (set (match_operand:VEC_I 0 "vlogical_operand") 767 (not:VEC_I (match_dup 3)))] 768 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 769 { 770 operands[3] = gen_reg_rtx_and_attrs (operands[0]); 771 }) 772 773 (define_expand "vector_ngtv1ti" 774 [(set (match_operand:V1TI 3 "vlogical_operand") 775 (gt:V1TI (match_operand:V1TI 1 "vlogical_operand") 776 (match_operand:V1TI 2 "vlogical_operand"))) 777 (set (match_operand:V1TI 0 "vlogical_operand") 778 (not:V1TI (match_dup 3)))] 779 "TARGET_POWER10" 780 { 781 operands[3] = gen_reg_rtx_and_attrs (operands[0]); 782 }) 783 784 (define_expand "vector_ngtu<mode>" 785 [(set (match_operand:VEC_I 3 "vlogical_operand") 786 (gtu:VEC_I (match_operand:VEC_I 1 "vlogical_operand") 787 (match_operand:VEC_I 2 "vlogical_operand"))) 788 (set (match_operand:VEC_I 0 "vlogical_operand") 789 (not:VEC_I (match_dup 3)))] 790 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 791 { 792 operands[3] = gen_reg_rtx_and_attrs (operands[0]); 793 }) 794 795 (define_expand "vector_ngtuv1ti" 796 [(set (match_operand:V1TI 3 "vlogical_operand") 797 (gtu:V1TI (match_operand:V1TI 1 "vlogical_operand") 798 (match_operand:V1TI 2 "vlogical_operand"))) 799 (set (match_operand:V1TI 0 "vlogical_operand") 800 (not:V1TI (match_dup 3)))] 801 "TARGET_POWER10" 802 { 803 operands[3] = gen_reg_rtx_and_attrs (operands[0]); 804 }) 805 806 ; There are 14 possible vector FP comparison operators, gt and eq of them have 807 ; been expanded above, so just support 12 remaining operators here. 808 809 ; For ge: 810 (define_expand "vector_ge<mode>" 811 [(set (match_operand:VEC_F 0 "vlogical_operand") 812 (ge:VEC_F (match_operand:VEC_F 1 "vlogical_operand") 813 (match_operand:VEC_F 2 "vlogical_operand")))] 814 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 815 "") 816 817 ; For lt/le/ne/ungt/unge/unlt/unle: 818 ; lt(a,b) = gt(b,a) 819 ; le(a,b) = ge(b,a) 820 ; unge(a,b) = ~lt(a,b) 821 ; unle(a,b) = ~gt(a,b) 822 ; ne(a,b) = ~eq(a,b) 823 ; ungt(a,b) = ~le(a,b) 824 ; unlt(a,b) = ~ge(a,b) 825 (define_insn_and_split "vector_<code><mode>" 826 [(set (match_operand:VEC_F 0 "vfloat_operand") 827 (vector_fp_comparison_simple:VEC_F 828 (match_operand:VEC_F 1 "vfloat_operand") 829 (match_operand:VEC_F 2 "vfloat_operand")))] 830 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && can_create_pseudo_p ()" 831 "#" 832 "&& can_create_pseudo_p ()" 833 [(pc)] 834 { 835 enum rtx_code cond = <CODE>; 836 bool need_invert = false; 837 838 if (cond == UNLE || cond == UNLT || cond == NE || cond == UNGE 839 || cond == UNGT) 840 { 841 cond = reverse_condition_maybe_unordered (cond); 842 need_invert = true; 843 } 844 845 if (cond == LT || cond == LE) 846 { 847 cond = swap_condition (cond); 848 std::swap (operands[1], operands[2]); 849 } 850 851 gcc_assert (cond == EQ || cond == GE || cond == GT); 852 853 rtx comp = gen_rtx_fmt_ee (cond, <MODE>mode, operands[1], operands[2]); 854 855 if (need_invert) 856 { 857 rtx res = gen_reg_rtx (<MODE>mode); 858 emit_insn (gen_rtx_SET (res, comp)); 859 emit_insn (gen_one_cmpl<mode>2 (operands[0], res)); 860 } 861 else 862 emit_insn (gen_rtx_SET (operands[0], comp)); 863 864 DONE; 865 }) 866 867 ; For ltgt/uneq/ordered/unordered: 868 ; ltgt: gt(a,b) | gt(b,a) 869 ; uneq: ~(gt(a,b) | gt(b,a)) 870 ; ordered: ge(a,b) | ge(b,a) 871 ; unordered: ~(ge(a,b) | ge(b,a)) 872 (define_insn_and_split "vector_<code><mode>" 873 [(set (match_operand:VEC_F 0 "vfloat_operand") 874 (vector_fp_comparison_complex:VEC_F 875 (match_operand:VEC_F 1 "vfloat_operand") 876 (match_operand:VEC_F 2 "vfloat_operand")))] 877 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && can_create_pseudo_p ()" 878 "#" 879 "&& can_create_pseudo_p ()" 880 [(pc)] 881 { 882 enum rtx_code cond = <CODE>; 883 bool need_invert = false; 884 885 if (cond == UNORDERED || cond == UNEQ) 886 { 887 cond = reverse_condition_maybe_unordered (cond); 888 need_invert = true; 889 } 890 891 if (cond == LTGT) 892 cond = GT; 893 else if (cond == ORDERED) 894 cond = GE; 895 else 896 gcc_unreachable (); 897 898 rtx comp1 = gen_rtx_fmt_ee (cond, <MODE>mode, operands[1], operands[2]); 899 rtx res1 = gen_reg_rtx (<MODE>mode); 900 emit_insn (gen_rtx_SET (res1, comp1)); 901 rtx comp2 = gen_rtx_fmt_ee (cond, <MODE>mode, operands[2], operands[1]); 902 rtx res2 = gen_reg_rtx (<MODE>mode); 903 emit_insn (gen_rtx_SET (res2, comp2)); 904 905 if (need_invert) 906 { 907 rtx not1 = gen_rtx_fmt_e (NOT, <MODE>mode, res1); 908 rtx not2 = gen_rtx_fmt_e (NOT, <MODE>mode, res2); 909 rtx comp3 = gen_rtx_fmt_ee (AND, <MODE>mode, not1, not2); 910 emit_insn (gen_rtx_SET (operands[0], comp3)); 911 } 912 else 913 emit_insn (gen_ior<mode>3 (operands[0], res1, res2)); 914 915 DONE; 916 }) 917 918 ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask 919 ;; which is in the reverse order that we want 920 (define_expand "vector_select_<mode>" 921 [(set (match_operand:VEC_L 0 "vlogical_operand") 922 (ior:VEC_L 923 (and:VEC_L (not:VEC_L (match_operand:VEC_L 3 "vlogical_operand")) 924 (match_operand:VEC_L 1 "vlogical_operand")) 925 (and:VEC_L (match_dup 3) 926 (match_operand:VEC_L 2 "vlogical_operand"))))] 927 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)") 928 929 (define_expand "vector_select_<mode>_uns" 930 [(set (match_operand:VEC_L 0 "vlogical_operand") 931 (ior:VEC_L 932 (and:VEC_L (not:VEC_L (match_operand:VEC_L 3 "vlogical_operand")) 933 (match_operand:VEC_L 1 "vlogical_operand")) 934 (and:VEC_L (match_dup 3) 935 (match_operand:VEC_L 2 "vlogical_operand"))))] 936 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)") 937 938 ;; Expansions that compare vectors producing a vector result and a predicate, 939 ;; setting CR6 to indicate a combined status 940 (define_expand "vector_eq_<mode>_p" 941 [(parallel 942 [(set (reg:CC CR6_REGNO) 943 (unspec:CC [(eq:CC (match_operand:VEC_A 1 "vlogical_operand") 944 (match_operand:VEC_A 2 "vlogical_operand"))] 945 UNSPEC_PREDICATE)) 946 (set (match_operand:VEC_A 0 "vlogical_operand") 947 (eq:VEC_A (match_dup 1) 948 (match_dup 2)))])] 949 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 950 "") 951 952 (define_expand "vector_eq_v1ti_p" 953 [(parallel 954 [(set (reg:CC CR6_REGNO) 955 (unspec:CC [(eq:CC (match_operand:V1TI 1 "altivec_register_operand") 956 (match_operand:V1TI 2 "altivec_register_operand"))] 957 UNSPEC_PREDICATE)) 958 (set (match_operand:V1TI 0 "vlogical_operand") 959 (eq:V1TI (match_dup 1) 960 (match_dup 2)))])] 961 "TARGET_POWER10" 962 "") 963 964 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the 965 ;; implementation of the vec_all_ne built-in functions on Power9. 966 (define_expand "vector_ne_<mode>_p" 967 [(parallel 968 [(set (reg:CC CR6_REGNO) 969 (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand") 970 (match_operand:VI 2 "vlogical_operand"))] 971 UNSPEC_PREDICATE)) 972 (set (match_dup 3) 973 (ne:VI (match_dup 1) 974 (match_dup 2)))]) 975 (set (match_operand:SI 0 "register_operand" "=r") 976 (lt:SI (reg:CC CR6_REGNO) 977 (const_int 0)))] 978 "TARGET_P9_VECTOR" 979 { 980 operands[3] = gen_reg_rtx (<MODE>mode); 981 }) 982 983 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the 984 ;; implementation of the vec_any_eq built-in functions on Power9. 985 (define_expand "vector_ae_<mode>_p" 986 [(parallel 987 [(set (reg:CC CR6_REGNO) 988 (unspec:CC [(ne:CC (match_operand:VI 1 "vlogical_operand") 989 (match_operand:VI 2 "vlogical_operand"))] 990 UNSPEC_PREDICATE)) 991 (set (match_dup 3) 992 (ne:VI (match_dup 1) 993 (match_dup 2)))]) 994 (set (match_operand:SI 0 "register_operand" "=r") 995 (lt:SI (reg:CC CR6_REGNO) 996 (const_int 0))) 997 (set (match_dup 0) 998 (xor:SI (match_dup 0) 999 (const_int 1)))] 1000 "TARGET_P9_VECTOR" 1001 { 1002 operands[3] = gen_reg_rtx (<MODE>mode); 1003 }) 1004 1005 ;; This expansion handles the V16QI, V8HI, and V4SI modes in the 1006 ;; implementation of the vec_all_nez and vec_any_eqz built-in 1007 ;; functions on Power9. 1008 (define_expand "vector_nez_<mode>_p" 1009 [(parallel 1010 [(set (reg:CC CR6_REGNO) 1011 (unspec:CC [(unspec:VI 1012 [(match_operand:VI 1 "vlogical_operand") 1013 (match_operand:VI 2 "vlogical_operand")] 1014 UNSPEC_NEZ_P)] 1015 UNSPEC_PREDICATE)) 1016 (set (match_operand:VI 0 "vlogical_operand") 1017 (unspec:VI [(match_dup 1) 1018 (match_dup 2)] 1019 UNSPEC_NEZ_P))])] 1020 "TARGET_P9_VECTOR" 1021 "") 1022 1023 ;; This expansion handles the V2DI mode in the implementation of the 1024 ;; vec_all_ne built-in function on Power9. 1025 ;; 1026 ;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode, 1027 ;; this expands into the same rtl that would be used for the Power8 1028 ;; architecture. 1029 (define_expand "vector_ne_v2di_p" 1030 [(parallel 1031 [(set (reg:CC CR6_REGNO) 1032 (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand") 1033 (match_operand:V2DI 2 "vlogical_operand"))] 1034 UNSPEC_PREDICATE)) 1035 (set (match_dup 3) 1036 (eq:V2DI (match_dup 1) 1037 (match_dup 2)))]) 1038 (set (match_operand:SI 0 "register_operand" "=r") 1039 (eq:SI (reg:CC CR6_REGNO) 1040 (const_int 0)))] 1041 "TARGET_P9_VECTOR" 1042 { 1043 operands[3] = gen_reg_rtx (V2DImode); 1044 }) 1045 1046 (define_expand "vector_ne_v1ti_p" 1047 [(parallel 1048 [(set (reg:CC CR6_REGNO) 1049 (unspec:CC [(eq:CC (match_operand:V1TI 1 "altivec_register_operand") 1050 (match_operand:V1TI 2 "altivec_register_operand"))] 1051 UNSPEC_PREDICATE)) 1052 (set (match_dup 3) 1053 (eq:V1TI (match_dup 1) 1054 (match_dup 2)))]) 1055 (set (match_operand:SI 0 "register_operand" "=r") 1056 (eq:SI (reg:CC CR6_REGNO) 1057 (const_int 0)))] 1058 "TARGET_POWER10" 1059 { 1060 operands[3] = gen_reg_rtx (V1TImode); 1061 }) 1062 1063 ;; This expansion handles the V2DI mode in the implementation of the 1064 ;; vec_any_eq built-in function on Power9. 1065 ;; 1066 ;; Since the Power9 "xvcmpne<mode>." instruction does not support DImode, 1067 ;; this expands into the same rtl that would be used for the Power8 1068 ;; architecture. 1069 (define_expand "vector_ae_v2di_p" 1070 [(parallel 1071 [(set (reg:CC CR6_REGNO) 1072 (unspec:CC [(eq:CC (match_operand:V2DI 1 "vlogical_operand") 1073 (match_operand:V2DI 2 "vlogical_operand"))] 1074 UNSPEC_PREDICATE)) 1075 (set (match_dup 3) 1076 (eq:V2DI (match_dup 1) 1077 (match_dup 2)))]) 1078 (set (match_operand:SI 0 "register_operand" "=r") 1079 (eq:SI (reg:CC CR6_REGNO) 1080 (const_int 0))) 1081 (set (match_dup 0) 1082 (xor:SI (match_dup 0) 1083 (const_int 1)))] 1084 "TARGET_P9_VECTOR" 1085 { 1086 operands[3] = gen_reg_rtx (V2DImode); 1087 }) 1088 1089 (define_expand "vector_ae_v1ti_p" 1090 [(parallel 1091 [(set (reg:CC CR6_REGNO) 1092 (unspec:CC [(eq:CC (match_operand:V1TI 1 "altivec_register_operand") 1093 (match_operand:V1TI 2 "altivec_register_operand"))] 1094 UNSPEC_PREDICATE)) 1095 (set (match_dup 3) 1096 (eq:V1TI (match_dup 1) 1097 (match_dup 2)))]) 1098 (set (match_operand:SI 0 "register_operand" "=r") 1099 (eq:SI (reg:CC CR6_REGNO) 1100 (const_int 0))) 1101 (set (match_dup 0) 1102 (xor:SI (match_dup 0) 1103 (const_int 1)))] 1104 "TARGET_POWER10" 1105 { 1106 operands[3] = gen_reg_rtx (V1TImode); 1107 }) 1108 1109 ;; This expansion handles the V4SF and V2DF modes in the Power9 1110 ;; implementation of the vec_all_ne built-in functions. Note that the 1111 ;; expansions for this pattern with these modes makes no use of power9- 1112 ;; specific instructions since there are no new power9 instructions 1113 ;; for vector compare not equal with floating point arguments. 1114 (define_expand "vector_ne_<mode>_p" 1115 [(parallel 1116 [(set (reg:CC CR6_REGNO) 1117 (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand") 1118 (match_operand:VEC_F 2 "vlogical_operand"))] 1119 UNSPEC_PREDICATE)) 1120 (set (match_dup 3) 1121 (eq:VEC_F (match_dup 1) 1122 (match_dup 2)))]) 1123 (set (match_operand:SI 0 "register_operand" "=r") 1124 (eq:SI (reg:CC CR6_REGNO) 1125 (const_int 0)))] 1126 "TARGET_P9_VECTOR" 1127 { 1128 operands[3] = gen_reg_rtx (<MODE>mode); 1129 }) 1130 1131 ;; This expansion handles the V4SF and V2DF modes in the Power9 1132 ;; implementation of the vec_any_eq built-in functions. Note that the 1133 ;; expansions for this pattern with these modes makes no use of power9- 1134 ;; specific instructions since there are no new power9 instructions 1135 ;; for vector compare not equal with floating point arguments. 1136 (define_expand "vector_ae_<mode>_p" 1137 [(parallel 1138 [(set (reg:CC CR6_REGNO) 1139 (unspec:CC [(eq:CC (match_operand:VEC_F 1 "vlogical_operand") 1140 (match_operand:VEC_F 2 "vlogical_operand"))] 1141 UNSPEC_PREDICATE)) 1142 (set (match_dup 3) 1143 (eq:VEC_F (match_dup 1) 1144 (match_dup 2)))]) 1145 (set (match_operand:SI 0 "register_operand" "=r") 1146 (eq:SI (reg:CC CR6_REGNO) 1147 (const_int 0))) 1148 (set (match_dup 0) 1149 (xor:SI (match_dup 0) 1150 (const_int 1)))] 1151 "TARGET_P9_VECTOR" 1152 { 1153 operands[3] = gen_reg_rtx (<MODE>mode); 1154 }) 1155 1156 (define_expand "vector_gt_<mode>_p" 1157 [(parallel 1158 [(set (reg:CC CR6_REGNO) 1159 (unspec:CC [(gt:CC (match_operand:VEC_A 1 "vlogical_operand") 1160 (match_operand:VEC_A 2 "vlogical_operand"))] 1161 UNSPEC_PREDICATE)) 1162 (set (match_operand:VEC_A 0 "vlogical_operand") 1163 (gt:VEC_A (match_dup 1) 1164 (match_dup 2)))])] 1165 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1166 "") 1167 1168 (define_expand "vector_gt_v1ti_p" 1169 [(parallel 1170 [(set (reg:CC CR6_REGNO) 1171 (unspec:CC [(gt:CC (match_operand:V1TI 1 "vlogical_operand") 1172 (match_operand:V1TI 2 "vlogical_operand"))] 1173 UNSPEC_PREDICATE)) 1174 (set (match_operand:V1TI 0 "vlogical_operand") 1175 (gt:V1TI (match_dup 1) 1176 (match_dup 2)))])] 1177 "TARGET_POWER10" 1178 "") 1179 1180 (define_expand "vector_ge_<mode>_p" 1181 [(parallel 1182 [(set (reg:CC CR6_REGNO) 1183 (unspec:CC [(ge:CC (match_operand:VEC_F 1 "vfloat_operand") 1184 (match_operand:VEC_F 2 "vfloat_operand"))] 1185 UNSPEC_PREDICATE)) 1186 (set (match_operand:VEC_F 0 "vfloat_operand") 1187 (ge:VEC_F (match_dup 1) 1188 (match_dup 2)))])] 1189 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1190 "") 1191 1192 (define_expand "vector_gtu_<mode>_p" 1193 [(parallel 1194 [(set (reg:CC CR6_REGNO) 1195 (unspec:CC [(gtu:CC (match_operand:VEC_I 1 "vint_operand") 1196 (match_operand:VEC_I 2 "vint_operand"))] 1197 UNSPEC_PREDICATE)) 1198 (set (match_operand:VEC_I 0 "vlogical_operand") 1199 (gtu:VEC_I (match_dup 1) 1200 (match_dup 2)))])] 1201 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1202 "") 1203 1204 (define_expand "vector_gtu_v1ti_p" 1205 [(parallel 1206 [(set (reg:CC CR6_REGNO) 1207 (unspec:CC [(gtu:CC (match_operand:V1TI 1 "altivec_register_operand") 1208 (match_operand:V1TI 2 "altivec_register_operand"))] 1209 UNSPEC_PREDICATE)) 1210 (set (match_operand:V1TI 0 "altivec_register_operand") 1211 (gtu:V1TI (match_dup 1) 1212 (match_dup 2)))])] 1213 "TARGET_POWER10" 1214 "") 1215 1216 ;; AltiVec/VSX predicates. 1217 1218 ;; This expansion is triggered during expansion of predicate built-in 1219 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the 1220 ;; altivec_expand_predicate_builtin() function when the value of the 1221 ;; integer constant first argument equals zero (aka __CR6_EQ in altivec.h). 1222 (define_expand "cr6_test_for_zero" 1223 [(set (match_operand:SI 0 "register_operand" "=r") 1224 (eq:SI (reg:CC CR6_REGNO) 1225 (const_int 0)))] 1226 "TARGET_ALTIVEC || TARGET_VSX" 1227 "") 1228 1229 ;; This expansion is triggered during expansion of predicate built-in 1230 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the 1231 ;; altivec_expand_predicate_builtin() function when the value of the 1232 ;; integer constant first argument equals one (aka __CR6_EQ_REV in altivec.h). 1233 (define_expand "cr6_test_for_zero_reverse" 1234 [(set (match_operand:SI 0 "register_operand" "=r") 1235 (eq:SI (reg:CC CR6_REGNO) 1236 (const_int 0))) 1237 (set (match_dup 0) 1238 (xor:SI (match_dup 0) 1239 (const_int 1)))] 1240 "TARGET_ALTIVEC || TARGET_VSX" 1241 "") 1242 1243 ;; This expansion is triggered during expansion of predicate built-in 1244 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the 1245 ;; altivec_expand_predicate_builtin() function when the value of the 1246 ;; integer constant first argument equals two (aka __CR6_LT in altivec.h). 1247 (define_expand "cr6_test_for_lt" 1248 [(set (match_operand:SI 0 "register_operand" "=r") 1249 (lt:SI (reg:CC CR6_REGNO) 1250 (const_int 0)))] 1251 "TARGET_ALTIVEC || TARGET_VSX" 1252 "") 1253 1254 ;; This expansion is triggered during expansion of predicate built-in 1255 ;; functions (built-ins defined with the RS6000_BUILTIN_P macro) by the 1256 ;; altivec_expand_predicate_builtin() function when the value of the 1257 ;; integer constant first argument equals three 1258 ;; (aka __CR6_LT_REV in altivec.h). 1259 (define_expand "cr6_test_for_lt_reverse" 1260 [(set (match_operand:SI 0 "register_operand" "=r") 1261 (lt:SI (reg:CC CR6_REGNO) 1262 (const_int 0))) 1263 (set (match_dup 0) 1264 (xor:SI (match_dup 0) 1265 (const_int 1)))] 1266 "TARGET_ALTIVEC || TARGET_VSX" 1267 "") 1268 1269 1271 ;; Vector count leading zeros 1272 (define_expand "clz<mode>2" 1273 [(set (match_operand:VEC_I 0 "register_operand") 1274 (clz:VEC_I (match_operand:VEC_I 1 "register_operand")))] 1275 "TARGET_P8_VECTOR") 1276 1277 ;; Vector count trailing zeros 1278 (define_expand "ctz<mode>2" 1279 [(set (match_operand:VEC_I 0 "register_operand") 1280 (ctz:VEC_I (match_operand:VEC_I 1 "register_operand")))] 1281 "TARGET_P9_VECTOR") 1282 1283 ;; Vector population count 1284 (define_expand "popcount<mode>2" 1285 [(set (match_operand:VEC_I 0 "register_operand") 1286 (popcount:VEC_I (match_operand:VEC_I 1 "register_operand")))] 1287 "TARGET_P8_VECTOR") 1288 1289 ;; Vector parity 1290 (define_expand "parity<mode>2" 1291 [(set (match_operand:VEC_IP 0 "register_operand") 1292 (parity:VEC_IP (match_operand:VEC_IP 1 "register_operand")))] 1293 "TARGET_P9_VECTOR" 1294 { 1295 rtx op1 = gen_lowpart (V16QImode, operands[1]); 1296 rtx res = gen_reg_rtx (V16QImode); 1297 emit_insn (gen_popcountv16qi2 (res, op1)); 1298 emit_insn (gen_rs6000_vprtyb<mode>2 (operands[0], 1299 gen_lowpart (<MODE>mode, res))); 1300 1301 DONE; 1302 }) 1303 1304 1306 ;; Same size conversions 1307 (define_expand "float<VEC_int><mode>2" 1308 [(set (match_operand:VEC_F 0 "vfloat_operand") 1309 (float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand")))] 1310 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1311 { 1312 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) 1313 { 1314 emit_insn (gen_altivec_vcfsx (operands[0], operands[1], const0_rtx)); 1315 DONE; 1316 } 1317 }) 1318 1319 (define_expand "floatuns<VEC_int><mode>2" 1320 [(set (match_operand:VEC_F 0 "vfloat_operand") 1321 (unsigned_float:VEC_F (match_operand:<VEC_INT> 1 "vint_operand")))] 1322 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1323 { 1324 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) 1325 { 1326 emit_insn (gen_altivec_vcfux (operands[0], operands[1], const0_rtx)); 1327 DONE; 1328 } 1329 }) 1330 1331 (define_expand "fix_trunc<mode><VEC_int>2" 1332 [(set (match_operand:<VEC_INT> 0 "vint_operand") 1333 (fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand")))] 1334 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1335 { 1336 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) 1337 { 1338 emit_insn (gen_altivec_vctsxs (operands[0], operands[1], const0_rtx)); 1339 DONE; 1340 } 1341 }) 1342 1343 (define_expand "fixuns_trunc<mode><VEC_int>2" 1344 [(set (match_operand:<VEC_INT> 0 "vint_operand") 1345 (unsigned_fix:<VEC_INT> (match_operand:VEC_F 1 "vfloat_operand")))] 1346 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1347 { 1348 if (<MODE>mode == V4SFmode && VECTOR_UNIT_ALTIVEC_P (<MODE>mode)) 1349 { 1350 emit_insn (gen_altivec_vctuxs (operands[0], operands[1], const0_rtx)); 1351 DONE; 1352 } 1353 }) 1354 1355 1357 ;; Vector initialization, set, extract 1358 (define_expand "vec_init<mode><VEC_base_l>" 1359 [(match_operand:VEC_E 0 "vlogical_operand") 1360 (match_operand:VEC_E 1 "")] 1361 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" 1362 { 1363 rs6000_expand_vector_init (operands[0], operands[1]); 1364 DONE; 1365 }) 1366 1367 (define_expand "vec_set<mode>" 1368 [(match_operand:VEC_E 0 "vlogical_operand") 1369 (match_operand:<VEC_base> 1 "register_operand") 1370 (match_operand 2 "vec_set_index_operand")] 1371 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" 1372 { 1373 rs6000_expand_vector_set (operands[0], operands[1], operands[2]); 1374 DONE; 1375 }) 1376 1377 (define_expand "vec_extract<mode><VEC_base_l>" 1378 [(match_operand:<VEC_base> 0 "register_operand") 1379 (match_operand:VEC_E 1 "vlogical_operand") 1380 (match_operand 2 "const_int_operand")] 1381 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" 1382 { 1383 rs6000_expand_vector_extract (operands[0], operands[1], operands[2]); 1384 DONE; 1385 }) 1386 1388 ;; Convert double word types to single word types 1389 (define_expand "vec_pack_trunc_v2df" 1390 [(match_operand:V4SF 0 "vfloat_operand") 1391 (match_operand:V2DF 1 "vfloat_operand") 1392 (match_operand:V2DF 2 "vfloat_operand")] 1393 "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC" 1394 { 1395 rtx r1 = gen_reg_rtx (V4SFmode); 1396 rtx r2 = gen_reg_rtx (V4SFmode); 1397 1398 emit_insn (gen_vsx_xvcvdpsp (r1, operands[1])); 1399 emit_insn (gen_vsx_xvcvdpsp (r2, operands[2])); 1400 rs6000_expand_extract_even (operands[0], r1, r2); 1401 DONE; 1402 }) 1403 1404 (define_expand "vec_pack_sfix_trunc_v2df" 1405 [(match_operand:V4SI 0 "vint_operand") 1406 (match_operand:V2DF 1 "vfloat_operand") 1407 (match_operand:V2DF 2 "vfloat_operand")] 1408 "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC" 1409 { 1410 rtx r1 = gen_reg_rtx (V4SImode); 1411 rtx r2 = gen_reg_rtx (V4SImode); 1412 1413 emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1])); 1414 emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2])); 1415 rs6000_expand_extract_even (operands[0], r1, r2); 1416 DONE; 1417 }) 1418 1419 (define_expand "vec_pack_ufix_trunc_v2df" 1420 [(match_operand:V4SI 0 "vint_operand") 1421 (match_operand:V2DF 1 "vfloat_operand") 1422 (match_operand:V2DF 2 "vfloat_operand")] 1423 "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC" 1424 { 1425 rtx r1 = gen_reg_rtx (V4SImode); 1426 rtx r2 = gen_reg_rtx (V4SImode); 1427 1428 emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1])); 1429 emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2])); 1430 rs6000_expand_extract_even (operands[0], r1, r2); 1431 DONE; 1432 }) 1433 1434 ;; Convert single word types to double word 1435 (define_expand "vec_unpacks_hi_v4sf" 1436 [(match_operand:V2DF 0 "vfloat_operand") 1437 (match_operand:V4SF 1 "vfloat_operand")] 1438 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)" 1439 { 1440 rtx reg = gen_reg_rtx (V4SFmode); 1441 1442 rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN); 1443 emit_insn (gen_vsx_xvcvspdp (operands[0], reg)); 1444 DONE; 1445 }) 1446 1447 (define_expand "vec_unpacks_lo_v4sf" 1448 [(match_operand:V2DF 0 "vfloat_operand") 1449 (match_operand:V4SF 1 "vfloat_operand")] 1450 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)" 1451 { 1452 rtx reg = gen_reg_rtx (V4SFmode); 1453 1454 rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN); 1455 emit_insn (gen_vsx_xvcvspdp (operands[0], reg)); 1456 DONE; 1457 }) 1458 1459 (define_expand "vec_unpacks_float_hi_v4si" 1460 [(match_operand:V2DF 0 "vfloat_operand") 1461 (match_operand:V4SI 1 "vint_operand")] 1462 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" 1463 { 1464 rtx reg = gen_reg_rtx (V4SImode); 1465 1466 rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN); 1467 emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg)); 1468 DONE; 1469 }) 1470 1471 (define_expand "vec_unpacks_float_lo_v4si" 1472 [(match_operand:V2DF 0 "vfloat_operand") 1473 (match_operand:V4SI 1 "vint_operand")] 1474 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" 1475 { 1476 rtx reg = gen_reg_rtx (V4SImode); 1477 1478 rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN); 1479 emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg)); 1480 DONE; 1481 }) 1482 1483 (define_expand "vec_unpacku_float_hi_v4si" 1484 [(match_operand:V2DF 0 "vfloat_operand") 1485 (match_operand:V4SI 1 "vint_operand")] 1486 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" 1487 { 1488 rtx reg = gen_reg_rtx (V4SImode); 1489 1490 rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN); 1491 emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg)); 1492 DONE; 1493 }) 1494 1495 (define_expand "vec_unpacku_float_lo_v4si" 1496 [(match_operand:V2DF 0 "vfloat_operand") 1497 (match_operand:V4SI 1 "vint_operand")] 1498 "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" 1499 { 1500 rtx reg = gen_reg_rtx (V4SImode); 1501 1502 rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN); 1503 emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg)); 1504 DONE; 1505 }) 1506 1507 1509 ;; Align vector loads with a permute. 1510 (define_expand "vec_realign_load_<mode>" 1511 [(match_operand:VEC_K 0 "vlogical_operand") 1512 (match_operand:VEC_K 1 "vlogical_operand") 1513 (match_operand:VEC_K 2 "vlogical_operand") 1514 (match_operand:V16QI 3 "vlogical_operand")] 1515 "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" 1516 { 1517 if (BYTES_BIG_ENDIAN) 1518 emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1], 1519 operands[2], operands[3])); 1520 else 1521 { 1522 /* We have changed lvsr to lvsl, so to complete the transformation 1523 of vperm for LE, we must swap the inputs. */ 1524 rtx unspec = gen_rtx_UNSPEC (<MODE>mode, 1525 gen_rtvec (3, operands[2], 1526 operands[1], operands[3]), 1527 UNSPEC_VPERM); 1528 emit_move_insn (operands[0], unspec); 1529 } 1530 DONE; 1531 }) 1532 1533 ;; Under VSX, vectors of 4/8 byte alignments do not need to be aligned 1534 ;; since the load already handles it. 1535 (define_expand "movmisalign<mode>" 1536 [(set (match_operand:VEC_N 0 "nonimmediate_operand") 1537 (match_operand:VEC_N 1 "any_operand"))] 1538 "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_ALLOW_MOVMISALIGN" 1539 { 1540 rs6000_emit_move (operands[0], operands[1], <MODE>mode); 1541 DONE; 1542 }) 1543 1544 ;; Vector shift right in bits. Currently supported ony for shift 1545 ;; amounts that can be expressed as byte shifts (divisible by 8). 1546 ;; General shift amounts can be supported using vsro + vsr. We're 1547 ;; not expecting to see these yet (the vectorizer currently 1548 ;; generates only shifts by a whole number of vector elements). 1549 ;; Note that the vec_shr operation is actually defined as 1550 ;; 'shift toward element 0' so is a shr for LE and shl for BE. 1551 (define_expand "vec_shr_<mode>" 1552 [(match_operand:VEC_L 0 "vlogical_operand") 1553 (match_operand:VEC_L 1 "vlogical_operand") 1554 (match_operand:QI 2 "reg_or_short_operand")] 1555 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1556 { 1557 rtx bitshift = operands[2]; 1558 rtx shift; 1559 rtx insn; 1560 rtx zero_reg, op1, op2; 1561 HOST_WIDE_INT bitshift_val; 1562 HOST_WIDE_INT byteshift_val; 1563 1564 if (! CONSTANT_P (bitshift)) 1565 FAIL; 1566 bitshift_val = INTVAL (bitshift); 1567 if (bitshift_val & 0x7) 1568 FAIL; 1569 byteshift_val = (bitshift_val >> 3); 1570 zero_reg = gen_reg_rtx (<MODE>mode); 1571 emit_move_insn (zero_reg, CONST0_RTX (<MODE>mode)); 1572 if (!BYTES_BIG_ENDIAN) 1573 { 1574 /* Note, byteshift_val can be 0! */ 1575 byteshift_val = -byteshift_val & 15; 1576 op1 = zero_reg; 1577 op2 = operands[1]; 1578 } 1579 else 1580 { 1581 op1 = operands[1]; 1582 op2 = zero_reg; 1583 } 1584 1585 if (TARGET_VSX && (byteshift_val & 0x3) == 0) 1586 { 1587 shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2); 1588 insn = gen_vsx_xxsldwi_<mode> (operands[0], op1, op2, shift); 1589 } 1590 else 1591 { 1592 shift = gen_rtx_CONST_INT (QImode, byteshift_val); 1593 insn = gen_altivec_vsldoi_<mode> (operands[0], op1, op2, shift); 1594 } 1595 1596 emit_insn (insn); 1597 DONE; 1598 }) 1599 1600 ;; Expanders for rotate each element in a vector 1601 (define_expand "vrotl<mode>3" 1602 [(set (match_operand:VEC_I 0 "vint_operand") 1603 (rotate:VEC_I (match_operand:VEC_I 1 "vint_operand") 1604 (match_operand:VEC_I 2 "vint_operand")))] 1605 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1606 "") 1607 1608 (define_expand "vrotlv1ti3" 1609 [(set (match_operand:V1TI 0 "vsx_register_operand" "=v") 1610 (rotate:V1TI (match_operand:V1TI 1 "vsx_register_operand" "v") 1611 (match_operand:V1TI 2 "vsx_register_operand" "v")))] 1612 "TARGET_POWER10" 1613 { 1614 /* Shift amount in needs to be put in bits[57:63] of 128-bit operand2. */ 1615 rtx tmp = gen_reg_rtx (V1TImode); 1616 1617 emit_insn (gen_xxswapd_v1ti (tmp, operands[2])); 1618 emit_insn (gen_altivec_vrlq (operands[0], operands[1], tmp)); 1619 DONE; 1620 }) 1621 1622 ;; Expanders for rotatert to make use of vrotl 1623 (define_expand "vrotr<mode>3" 1624 [(set (match_operand:VEC_I 0 "vint_operand") 1625 (rotatert:VEC_I (match_operand:VEC_I 1 "vint_operand") 1626 (match_operand:VEC_I 2 "vint_operand")))] 1627 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1628 { 1629 rtx rot_count = gen_reg_rtx (<MODE>mode); 1630 emit_insn (gen_neg<mode>2 (rot_count, operands[2])); 1631 emit_insn (gen_vrotl<mode>3 (operands[0], operands[1], rot_count)); 1632 DONE; 1633 }) 1634 1635 ;; Expanders for arithmetic shift left on each vector element 1636 (define_expand "vashl<mode>3" 1637 [(set (match_operand:VEC_I 0 "vint_operand") 1638 (ashift:VEC_I (match_operand:VEC_I 1 "vint_operand") 1639 (match_operand:VEC_I 2 "vint_operand")))] 1640 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1641 "") 1642 1643 ;; No immediate version of this 128-bit instruction 1644 (define_expand "vashl<mode>3" 1645 [(set (match_operand:VEC_TI 0 "vsx_register_operand" "=v") 1646 (ashift:VEC_TI (match_operand:VEC_TI 1 "vsx_register_operand") 1647 (match_operand:VEC_TI 2 "vsx_register_operand")))] 1648 "TARGET_POWER10" 1649 { 1650 /* Shift amount in needs to be put in bits[57:63] of 128-bit operand2. */ 1651 rtx tmp = gen_reg_rtx (<MODE>mode); 1652 1653 emit_insn (gen_xxswapd_v1ti (tmp, operands[2])); 1654 emit_insn(gen_altivec_vslq_<mode> (operands[0], operands[1], tmp)); 1655 DONE; 1656 }) 1657 1658 ;; Expanders for logical shift right on each vector element 1659 (define_expand "vlshr<mode>3" 1660 [(set (match_operand:VEC_I 0 "vint_operand") 1661 (lshiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand") 1662 (match_operand:VEC_I 2 "vint_operand")))] 1663 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1664 "") 1665 1666 ;; No immediate version of this 128-bit instruction 1667 (define_expand "vlshr<mode>3" 1668 [(set (match_operand:VEC_TI 0 "vsx_register_operand" "=v") 1669 (lshiftrt:VEC_TI (match_operand:VEC_TI 1 "vsx_register_operand") 1670 (match_operand:VEC_TI 2 "vsx_register_operand")))] 1671 "TARGET_POWER10" 1672 { 1673 /* Shift amount in needs to be put into bits[57:63] of 128-bit operand2. */ 1674 rtx tmp = gen_reg_rtx (<MODE>mode); 1675 1676 emit_insn (gen_xxswapd_v1ti (tmp, operands[2])); 1677 emit_insn(gen_altivec_vsrq_<mode> (operands[0], operands[1], tmp)); 1678 DONE; 1679 }) 1680 1681 ;; Expanders for arithmetic shift right on each vector element 1682 (define_expand "vashr<mode>3" 1683 [(set (match_operand:VEC_I 0 "vint_operand") 1684 (ashiftrt:VEC_I (match_operand:VEC_I 1 "vint_operand") 1685 (match_operand:VEC_I 2 "vint_operand")))] 1686 "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" 1687 "") 1688 1689 ;; No immediate version of this 128-bit instruction 1690 (define_expand "vashrv1ti3" 1691 [(set (match_operand:V1TI 0 "vsx_register_operand" "=v") 1692 (ashiftrt:V1TI (match_operand:V1TI 1 "vsx_register_operand" "v") 1693 (match_operand:V1TI 2 "vsx_register_operand" "v")))] 1694 "TARGET_POWER10" 1695 { 1696 /* Shift amount in needs to be put into bits[57:63] of 128-bit operand2. */ 1697 rtx tmp = gen_reg_rtx (V1TImode); 1698 1699 emit_insn (gen_xxswapd_v1ti (tmp, operands[2])); 1700 emit_insn (gen_altivec_vsraq (operands[0], operands[1], tmp)); 1701 DONE; 1702 }) 1703 1704 1706 ;; Vector reduction expanders for VSX 1707 ; The (VEC_reduc:... 1708 ; (op1) 1709 ; (unspec:... [(const_int 0)] UNSPEC_REDUC)) 1710 ; 1711 ; is to allow us to use a code iterator, but not completely list all of the 1712 ; vector rotates, etc. to prevent canonicalization 1713 1714 1715 (define_expand "reduc_<VEC_reduc:VEC_reduc_name>_scal_<VEC_F:mode>" 1716 [(match_operand:<VEC_base> 0 "register_operand") 1717 (VEC_reduc:VEC_F (match_operand:VEC_F 1 "vfloat_operand") 1718 (unspec:VEC_F [(const_int 0)] UNSPEC_REDUC))] 1719 "VECTOR_UNIT_VSX_P (<VEC_F:MODE>mode)" 1720 { 1721 rtx vec = gen_reg_rtx (<VEC_F:MODE>mode); 1722 rtx elt = BYTES_BIG_ENDIAN 1723 ? gen_int_mode (GET_MODE_NUNITS (<VEC_F:MODE>mode) - 1, QImode) 1724 : const0_rtx; 1725 emit_insn (gen_vsx_reduc_<VEC_reduc:VEC_reduc_name>_<VEC_F:mode> (vec, 1726 operand1)); 1727 emit_insn (gen_vsx_extract_<VEC_F:mode> (operand0, vec, elt)); 1728 DONE; 1729 }) 1730