1 1.1 mrg /* IR-agnostic target query functions relating to optabs 2 1.1 mrg Copyright (C) 1987-2022 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg This file is part of GCC. 5 1.1 mrg 6 1.1 mrg GCC is free software; you can redistribute it and/or modify it under 7 1.1 mrg the terms of the GNU General Public License as published by the Free 8 1.1 mrg Software Foundation; either version 3, or (at your option) any later 9 1.1 mrg version. 10 1.1 mrg 11 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 1.1 mrg for more details. 15 1.1 mrg 16 1.1 mrg You should have received a copy of the GNU General Public License 17 1.1 mrg along with GCC; see the file COPYING3. If not see 18 1.1 mrg <http://www.gnu.org/licenses/>. */ 19 1.1 mrg 20 1.1 mrg 21 1.1 mrg #include "config.h" 22 1.1 mrg #include "system.h" 23 1.1 mrg #include "coretypes.h" 24 1.1 mrg #include "target.h" 25 1.1 mrg #include "insn-codes.h" 26 1.1 mrg #include "optabs-query.h" 27 1.1 mrg #include "optabs-libfuncs.h" 28 1.1 mrg #include "insn-config.h" 29 1.1 mrg #include "rtl.h" 30 1.1 mrg #include "recog.h" 31 1.1 mrg #include "vec-perm-indices.h" 32 1.1 mrg 33 1.1 mrg struct target_optabs default_target_optabs; 34 1.1 mrg struct target_optabs *this_fn_optabs = &default_target_optabs; 35 1.1 mrg #if SWITCHABLE_TARGET 36 1.1 mrg struct target_optabs *this_target_optabs = &default_target_optabs; 37 1.1 mrg #endif 38 1.1 mrg 39 1.1 mrg /* Return the insn used to perform conversion OP from mode FROM_MODE 40 1.1 mrg to mode TO_MODE; return CODE_FOR_nothing if the target does not have 41 1.1 mrg such an insn, or if it is unsuitable for optimization type OPT_TYPE. */ 42 1.1 mrg 43 1.1 mrg insn_code 44 1.1 mrg convert_optab_handler (convert_optab optab, machine_mode to_mode, 45 1.1 mrg machine_mode from_mode, optimization_type opt_type) 46 1.1 mrg { 47 1.1 mrg insn_code icode = convert_optab_handler (optab, to_mode, from_mode); 48 1.1 mrg if (icode == CODE_FOR_nothing 49 1.1 mrg || !targetm.optab_supported_p (optab, to_mode, from_mode, opt_type)) 50 1.1 mrg return CODE_FOR_nothing; 51 1.1 mrg return icode; 52 1.1 mrg } 53 1.1 mrg 54 1.1 mrg /* Return the insn used to implement mode MODE of OP; return 55 1.1 mrg CODE_FOR_nothing if the target does not have such an insn, 56 1.1 mrg or if it is unsuitable for optimization type OPT_TYPE. */ 57 1.1 mrg 58 1.1 mrg insn_code 59 1.1 mrg direct_optab_handler (convert_optab optab, machine_mode mode, 60 1.1 mrg optimization_type opt_type) 61 1.1 mrg { 62 1.1 mrg insn_code icode = direct_optab_handler (optab, mode); 63 1.1 mrg if (icode == CODE_FOR_nothing 64 1.1 mrg || !targetm.optab_supported_p (optab, mode, mode, opt_type)) 65 1.1 mrg return CODE_FOR_nothing; 66 1.1 mrg return icode; 67 1.1 mrg } 68 1.1 mrg 69 1.1 mrg /* Enumerates the possible types of structure operand to an 70 1.1 mrg extraction_insn. */ 71 1.1 mrg enum extraction_type { ET_unaligned_mem, ET_reg }; 72 1.1 mrg 73 1.1 mrg /* Check whether insv, extv or extzv pattern ICODE can be used for an 74 1.1 mrg insertion or extraction of type TYPE on a structure of mode MODE. 75 1.1 mrg Return true if so and fill in *INSN accordingly. STRUCT_OP is the 76 1.1 mrg operand number of the structure (the first sign_extract or zero_extract 77 1.1 mrg operand) and FIELD_OP is the operand number of the field (the other 78 1.1 mrg side of the set from the sign_extract or zero_extract). */ 79 1.1 mrg 80 1.1 mrg static bool 81 1.1 mrg get_traditional_extraction_insn (extraction_insn *insn, 82 1.1 mrg enum extraction_type type, 83 1.1 mrg machine_mode mode, 84 1.1 mrg enum insn_code icode, 85 1.1 mrg int struct_op, int field_op) 86 1.1 mrg { 87 1.1 mrg const struct insn_data_d *data = &insn_data[icode]; 88 1.1 mrg 89 1.1 mrg machine_mode struct_mode = data->operand[struct_op].mode; 90 1.1 mrg if (struct_mode == VOIDmode) 91 1.1 mrg struct_mode = word_mode; 92 1.1 mrg if (mode != struct_mode) 93 1.1 mrg return false; 94 1.1 mrg 95 1.1 mrg machine_mode field_mode = data->operand[field_op].mode; 96 1.1 mrg if (field_mode == VOIDmode) 97 1.1 mrg field_mode = word_mode; 98 1.1 mrg 99 1.1 mrg machine_mode pos_mode = data->operand[struct_op + 2].mode; 100 1.1 mrg if (pos_mode == VOIDmode) 101 1.1 mrg pos_mode = word_mode; 102 1.1 mrg 103 1.1 mrg insn->icode = icode; 104 1.1 mrg insn->field_mode = as_a <scalar_int_mode> (field_mode); 105 1.1 mrg if (type == ET_unaligned_mem) 106 1.1 mrg insn->struct_mode = byte_mode; 107 1.1 mrg else if (struct_mode == BLKmode) 108 1.1 mrg insn->struct_mode = opt_scalar_int_mode (); 109 1.1 mrg else 110 1.1 mrg insn->struct_mode = as_a <scalar_int_mode> (struct_mode); 111 1.1 mrg insn->pos_mode = as_a <scalar_int_mode> (pos_mode); 112 1.1 mrg return true; 113 1.1 mrg } 114 1.1 mrg 115 1.1 mrg /* Return true if an optab exists to perform an insertion or extraction 116 1.1 mrg of type TYPE in mode MODE. Describe the instruction in *INSN if so. 117 1.1 mrg 118 1.1 mrg REG_OPTAB is the optab to use for register structures and 119 1.1 mrg MISALIGN_OPTAB is the optab to use for misaligned memory structures. 120 1.1 mrg POS_OP is the operand number of the bit position. */ 121 1.1 mrg 122 1.1 mrg static bool 123 1.1 mrg get_optab_extraction_insn (class extraction_insn *insn, 124 1.1 mrg enum extraction_type type, 125 1.1 mrg machine_mode mode, direct_optab reg_optab, 126 1.1 mrg direct_optab misalign_optab, int pos_op) 127 1.1 mrg { 128 1.1 mrg direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab); 129 1.1 mrg enum insn_code icode = direct_optab_handler (optab, mode); 130 1.1 mrg if (icode == CODE_FOR_nothing) 131 1.1 mrg return false; 132 1.1 mrg 133 1.1 mrg const struct insn_data_d *data = &insn_data[icode]; 134 1.1 mrg 135 1.1 mrg machine_mode pos_mode = data->operand[pos_op].mode; 136 1.1 mrg if (pos_mode == VOIDmode) 137 1.1 mrg pos_mode = word_mode; 138 1.1 mrg 139 1.1 mrg insn->icode = icode; 140 1.1 mrg insn->field_mode = as_a <scalar_int_mode> (mode); 141 1.1 mrg if (type == ET_unaligned_mem) 142 1.1 mrg insn->struct_mode = opt_scalar_int_mode (); 143 1.1 mrg else 144 1.1 mrg insn->struct_mode = insn->field_mode; 145 1.1 mrg insn->pos_mode = as_a <scalar_int_mode> (pos_mode); 146 1.1 mrg return true; 147 1.1 mrg } 148 1.1 mrg 149 1.1 mrg /* Return true if an instruction exists to perform an insertion or 150 1.1 mrg extraction (PATTERN says which) of type TYPE in mode MODE. 151 1.1 mrg Describe the instruction in *INSN if so. */ 152 1.1 mrg 153 1.1 mrg static bool 154 1.1 mrg get_extraction_insn (extraction_insn *insn, 155 1.1 mrg enum extraction_pattern pattern, 156 1.1 mrg enum extraction_type type, 157 1.1 mrg machine_mode mode) 158 1.1 mrg { 159 1.1 mrg switch (pattern) 160 1.1 mrg { 161 1.1 mrg case EP_insv: 162 1.1 mrg if (targetm.have_insv () 163 1.1 mrg && get_traditional_extraction_insn (insn, type, mode, 164 1.1 mrg targetm.code_for_insv, 0, 3)) 165 1.1 mrg return true; 166 1.1 mrg return get_optab_extraction_insn (insn, type, mode, insv_optab, 167 1.1 mrg insvmisalign_optab, 2); 168 1.1 mrg 169 1.1 mrg case EP_extv: 170 1.1 mrg if (targetm.have_extv () 171 1.1 mrg && get_traditional_extraction_insn (insn, type, mode, 172 1.1 mrg targetm.code_for_extv, 1, 0)) 173 1.1 mrg return true; 174 1.1 mrg return get_optab_extraction_insn (insn, type, mode, extv_optab, 175 1.1 mrg extvmisalign_optab, 3); 176 1.1 mrg 177 1.1 mrg case EP_extzv: 178 1.1 mrg if (targetm.have_extzv () 179 1.1 mrg && get_traditional_extraction_insn (insn, type, mode, 180 1.1 mrg targetm.code_for_extzv, 1, 0)) 181 1.1 mrg return true; 182 1.1 mrg return get_optab_extraction_insn (insn, type, mode, extzv_optab, 183 1.1 mrg extzvmisalign_optab, 3); 184 1.1 mrg 185 1.1 mrg default: 186 1.1 mrg gcc_unreachable (); 187 1.1 mrg } 188 1.1 mrg } 189 1.1 mrg 190 1.1 mrg /* Return true if an instruction exists to access a field of mode 191 1.1 mrg FIELDMODE in a structure that has STRUCT_BITS significant bits. 192 1.1 mrg Describe the "best" such instruction in *INSN if so. PATTERN and 193 1.1 mrg TYPE describe the type of insertion or extraction we want to perform. 194 1.1 mrg 195 1.1 mrg For an insertion, the number of significant structure bits includes 196 1.1 mrg all bits of the target. For an extraction, it need only include the 197 1.1 mrg most significant bit of the field. Larger widths are acceptable 198 1.1 mrg in both cases. */ 199 1.1 mrg 200 1.1 mrg static bool 201 1.1 mrg get_best_extraction_insn (extraction_insn *insn, 202 1.1 mrg enum extraction_pattern pattern, 203 1.1 mrg enum extraction_type type, 204 1.1 mrg unsigned HOST_WIDE_INT struct_bits, 205 1.1 mrg machine_mode field_mode) 206 1.1 mrg { 207 1.1 mrg opt_scalar_int_mode mode_iter; 208 1.1 mrg FOR_EACH_MODE_FROM (mode_iter, smallest_int_mode_for_size (struct_bits)) 209 1.1 mrg { 210 1.1 mrg scalar_int_mode mode = mode_iter.require (); 211 1.1 mrg if (get_extraction_insn (insn, pattern, type, mode)) 212 1.1 mrg { 213 1.1 mrg FOR_EACH_MODE_FROM (mode_iter, mode) 214 1.1 mrg { 215 1.1 mrg mode = mode_iter.require (); 216 1.1 mrg if (maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (field_mode)) 217 1.1 mrg || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode, 218 1.1 mrg field_mode)) 219 1.1 mrg break; 220 1.1 mrg get_extraction_insn (insn, pattern, type, mode); 221 1.1 mrg } 222 1.1 mrg return true; 223 1.1 mrg } 224 1.1 mrg } 225 1.1 mrg return false; 226 1.1 mrg } 227 1.1 mrg 228 1.1 mrg /* Return true if an instruction exists to access a field of mode 229 1.1 mrg FIELDMODE in a register structure that has STRUCT_BITS significant bits. 230 1.1 mrg Describe the "best" such instruction in *INSN if so. PATTERN describes 231 1.1 mrg the type of insertion or extraction we want to perform. 232 1.1 mrg 233 1.1 mrg For an insertion, the number of significant structure bits includes 234 1.1 mrg all bits of the target. For an extraction, it need only include the 235 1.1 mrg most significant bit of the field. Larger widths are acceptable 236 1.1 mrg in both cases. */ 237 1.1 mrg 238 1.1 mrg bool 239 1.1 mrg get_best_reg_extraction_insn (extraction_insn *insn, 240 1.1 mrg enum extraction_pattern pattern, 241 1.1 mrg unsigned HOST_WIDE_INT struct_bits, 242 1.1 mrg machine_mode field_mode) 243 1.1 mrg { 244 1.1 mrg return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits, 245 1.1 mrg field_mode); 246 1.1 mrg } 247 1.1 mrg 248 1.1 mrg /* Return true if an instruction exists to access a field of BITSIZE 249 1.1 mrg bits starting BITNUM bits into a memory structure. Describe the 250 1.1 mrg "best" such instruction in *INSN if so. PATTERN describes the type 251 1.1 mrg of insertion or extraction we want to perform and FIELDMODE is the 252 1.1 mrg natural mode of the extracted field. 253 1.1 mrg 254 1.1 mrg The instructions considered here only access bytes that overlap 255 1.1 mrg the bitfield; they do not touch any surrounding bytes. */ 256 1.1 mrg 257 1.1 mrg bool 258 1.1 mrg get_best_mem_extraction_insn (extraction_insn *insn, 259 1.1 mrg enum extraction_pattern pattern, 260 1.1 mrg HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum, 261 1.1 mrg machine_mode field_mode) 262 1.1 mrg { 263 1.1 mrg unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT 264 1.1 mrg + bitsize 265 1.1 mrg + BITS_PER_UNIT - 1); 266 1.1 mrg struct_bits -= struct_bits % BITS_PER_UNIT; 267 1.1 mrg return get_best_extraction_insn (insn, pattern, ET_unaligned_mem, 268 1.1 mrg struct_bits, field_mode); 269 1.1 mrg } 270 1.1 mrg 271 1.1 mrg /* Return the insn code used to extend FROM_MODE to TO_MODE. 272 1.1 mrg UNSIGNEDP specifies zero-extension instead of sign-extension. If 273 1.1 mrg no such operation exists, CODE_FOR_nothing will be returned. */ 274 1.1 mrg 275 1.1 mrg enum insn_code 276 1.1 mrg can_extend_p (machine_mode to_mode, machine_mode from_mode, 277 1.1 mrg int unsignedp) 278 1.1 mrg { 279 1.1 mrg if (unsignedp < 0 && targetm.have_ptr_extend ()) 280 1.1 mrg return targetm.code_for_ptr_extend; 281 1.1 mrg 282 1.1 mrg convert_optab tab = unsignedp ? zext_optab : sext_optab; 283 1.1 mrg return convert_optab_handler (tab, to_mode, from_mode); 284 1.1 mrg } 285 1.1 mrg 286 1.1 mrg /* Return the insn code to convert fixed-point mode FIXMODE to floating-point 287 1.1 mrg mode FLTMODE, or CODE_FOR_nothing if no such instruction exists. 288 1.1 mrg UNSIGNEDP specifies whether FIXMODE is unsigned. */ 289 1.1 mrg 290 1.1 mrg enum insn_code 291 1.1 mrg can_float_p (machine_mode fltmode, machine_mode fixmode, 292 1.1 mrg int unsignedp) 293 1.1 mrg { 294 1.1 mrg convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab; 295 1.1 mrg return convert_optab_handler (tab, fltmode, fixmode); 296 1.1 mrg } 297 1.1 mrg 298 1.1 mrg /* Return the insn code to convert floating-point mode FLTMODE to fixed-point 299 1.1 mrg mode FIXMODE, or CODE_FOR_nothing if no such instruction exists. 300 1.1 mrg UNSIGNEDP specifies whether FIXMODE is unsigned. 301 1.1 mrg 302 1.1 mrg On a successful return, set *TRUNCP_PTR to true if it is necessary to 303 1.1 mrg output an explicit FTRUNC before the instruction. */ 304 1.1 mrg 305 1.1 mrg enum insn_code 306 1.1 mrg can_fix_p (machine_mode fixmode, machine_mode fltmode, 307 1.1 mrg int unsignedp, bool *truncp_ptr) 308 1.1 mrg { 309 1.1 mrg convert_optab tab; 310 1.1 mrg enum insn_code icode; 311 1.1 mrg 312 1.1 mrg tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab; 313 1.1 mrg icode = convert_optab_handler (tab, fixmode, fltmode); 314 1.1 mrg if (icode != CODE_FOR_nothing) 315 1.1 mrg { 316 1.1 mrg *truncp_ptr = false; 317 1.1 mrg return icode; 318 1.1 mrg } 319 1.1 mrg 320 1.1 mrg /* FIXME: This requires a port to define both FIX and FTRUNC pattern 321 1.1 mrg for this to work. We need to rework the fix* and ftrunc* patterns 322 1.1 mrg and documentation. */ 323 1.1 mrg tab = unsignedp ? ufix_optab : sfix_optab; 324 1.1 mrg icode = convert_optab_handler (tab, fixmode, fltmode); 325 1.1 mrg if (icode != CODE_FOR_nothing 326 1.1 mrg && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing) 327 1.1 mrg { 328 1.1 mrg *truncp_ptr = true; 329 1.1 mrg return icode; 330 1.1 mrg } 331 1.1 mrg 332 1.1 mrg return CODE_FOR_nothing; 333 1.1 mrg } 334 1.1 mrg 335 1.1 mrg /* Return nonzero if a conditional move of mode MODE is supported. 336 1.1 mrg 337 1.1 mrg This function is for combine so it can tell whether an insn that looks 338 1.1 mrg like a conditional move is actually supported by the hardware. If we 339 1.1 mrg guess wrong we lose a bit on optimization, but that's it. */ 340 1.1 mrg /* ??? sparc64 supports conditionally moving integers values based on fp 341 1.1 mrg comparisons, and vice versa. How do we handle them? */ 342 1.1 mrg 343 1.1 mrg bool 344 1.1 mrg can_conditionally_move_p (machine_mode mode) 345 1.1 mrg { 346 1.1 mrg return direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing; 347 1.1 mrg } 348 1.1 mrg 349 1.1 mrg /* If a target doesn't implement a permute on a vector with multibyte 350 1.1 mrg elements, we can try to do the same permute on byte elements. 351 1.1 mrg If this makes sense for vector mode MODE then return the appropriate 352 1.1 mrg byte vector mode. */ 353 1.1 mrg 354 1.1 mrg opt_machine_mode 355 1.1 mrg qimode_for_vec_perm (machine_mode mode) 356 1.1 mrg { 357 1.1 mrg if (GET_MODE_INNER (mode) != QImode) 358 1.1 mrg return related_vector_mode (mode, QImode, GET_MODE_SIZE (mode)); 359 1.1 mrg return opt_machine_mode (); 360 1.1 mrg } 361 1.1 mrg 362 1.1 mrg /* Return true if selector SEL can be represented in the integer 363 1.1 mrg equivalent of vector mode MODE. */ 364 1.1 mrg 365 1.1 mrg bool 366 1.1 mrg selector_fits_mode_p (machine_mode mode, const vec_perm_indices &sel) 367 1.1 mrg { 368 1.1 mrg unsigned HOST_WIDE_INT mask = GET_MODE_MASK (GET_MODE_INNER (mode)); 369 1.1 mrg return (mask == HOST_WIDE_INT_M1U 370 1.1 mrg || sel.all_in_range_p (0, mask + 1)); 371 1.1 mrg } 372 1.1 mrg 373 1.1 mrg /* Return true if VEC_PERM_EXPRs with variable selector operands can be 374 1.1 mrg expanded using SIMD extensions of the CPU. MODE is the mode of the 375 1.1 mrg vectors being permuted. */ 376 1.1 mrg 377 1.1 mrg bool 378 1.1 mrg can_vec_perm_var_p (machine_mode mode) 379 1.1 mrg { 380 1.1 mrg /* If the target doesn't implement a vector mode for the vector type, 381 1.1 mrg then no operations are supported. */ 382 1.1 mrg if (!VECTOR_MODE_P (mode)) 383 1.1 mrg return false; 384 1.1 mrg 385 1.1 mrg if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing) 386 1.1 mrg return true; 387 1.1 mrg 388 1.1 mrg /* We allow fallback to a QI vector mode, and adjust the mask. */ 389 1.1 mrg machine_mode qimode; 390 1.1 mrg if (!qimode_for_vec_perm (mode).exists (&qimode) 391 1.1 mrg || maybe_gt (GET_MODE_NUNITS (qimode), GET_MODE_MASK (QImode) + 1)) 392 1.1 mrg return false; 393 1.1 mrg 394 1.1 mrg if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing) 395 1.1 mrg return false; 396 1.1 mrg 397 1.1 mrg /* In order to support the lowering of variable permutations, 398 1.1 mrg we need to support shifts and adds. */ 399 1.1 mrg if (GET_MODE_UNIT_SIZE (mode) > 2 400 1.1 mrg && optab_handler (ashl_optab, mode) == CODE_FOR_nothing 401 1.1 mrg && optab_handler (vashl_optab, mode) == CODE_FOR_nothing) 402 1.1 mrg return false; 403 1.1 mrg if (optab_handler (add_optab, qimode) == CODE_FOR_nothing) 404 1.1 mrg return false; 405 1.1 mrg 406 1.1 mrg return true; 407 1.1 mrg } 408 1.1 mrg 409 1.1 mrg /* Return true if the target directly supports VEC_PERM_EXPRs on vectors 410 1.1 mrg of mode MODE using the selector SEL. ALLOW_VARIABLE_P is true if it 411 1.1 mrg is acceptable to force the selector into a register and use a variable 412 1.1 mrg permute (if the target supports that). 413 1.1 mrg 414 1.1 mrg Note that additional permutations representing whole-vector shifts may 415 1.1 mrg also be handled via the vec_shr or vec_shl optab, but only where the 416 1.1 mrg second input vector is entirely constant zeroes; this case is not dealt 417 1.1 mrg with here. */ 418 1.1 mrg 419 1.1 mrg bool 420 1.1 mrg can_vec_perm_const_p (machine_mode mode, const vec_perm_indices &sel, 421 1.1 mrg bool allow_variable_p) 422 1.1 mrg { 423 1.1 mrg /* If the target doesn't implement a vector mode for the vector type, 424 1.1 mrg then no operations are supported. */ 425 1.1 mrg if (!VECTOR_MODE_P (mode)) 426 1.1 mrg return false; 427 1.1 mrg 428 1.1 mrg /* It's probably cheaper to test for the variable case first. */ 429 1.1 mrg if (allow_variable_p && selector_fits_mode_p (mode, sel)) 430 1.1 mrg { 431 1.1 mrg if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing) 432 1.1 mrg return true; 433 1.1 mrg 434 1.1 mrg /* Unlike can_vec_perm_var_p, we don't need to test for optabs 435 1.1 mrg related computing the QImode selector, since that happens at 436 1.1 mrg compile time. */ 437 1.1 mrg machine_mode qimode; 438 1.1 mrg if (qimode_for_vec_perm (mode).exists (&qimode)) 439 1.1 mrg { 440 1.1 mrg vec_perm_indices qimode_indices; 441 1.1 mrg qimode_indices.new_expanded_vector (sel, GET_MODE_UNIT_SIZE (mode)); 442 1.1 mrg if (selector_fits_mode_p (qimode, qimode_indices) 443 1.1 mrg && (direct_optab_handler (vec_perm_optab, qimode) 444 1.1 mrg != CODE_FOR_nothing)) 445 1.1 mrg return true; 446 1.1 mrg } 447 1.1 mrg } 448 1.1 mrg 449 1.1 mrg if (targetm.vectorize.vec_perm_const != NULL) 450 1.1 mrg { 451 1.1 mrg if (targetm.vectorize.vec_perm_const (mode, NULL_RTX, NULL_RTX, 452 1.1 mrg NULL_RTX, sel)) 453 1.1 mrg return true; 454 1.1 mrg 455 1.1 mrg /* ??? For completeness, we ought to check the QImode version of 456 1.1 mrg vec_perm_const_optab. But all users of this implicit lowering 457 1.1 mrg feature implement the variable vec_perm_optab, and the ia64 458 1.1 mrg port specifically doesn't want us to lower V2SF operations 459 1.1 mrg into integer operations. */ 460 1.1 mrg } 461 1.1 mrg 462 1.1 mrg return false; 463 1.1 mrg } 464 1.1 mrg 465 1.1 mrg /* Find a widening optab even if it doesn't widen as much as we want. 466 1.1 mrg E.g. if from_mode is HImode, and to_mode is DImode, and there is no 467 1.1 mrg direct HI->SI insn, then return SI->DI, if that exists. */ 468 1.1 mrg 469 1.1 mrg enum insn_code 470 1.1 mrg find_widening_optab_handler_and_mode (optab op, machine_mode to_mode, 471 1.1 mrg machine_mode from_mode, 472 1.1 mrg machine_mode *found_mode) 473 1.1 mrg { 474 1.1 mrg machine_mode limit_mode = to_mode; 475 1.1 mrg if (is_a <scalar_int_mode> (from_mode)) 476 1.1 mrg { 477 1.1 mrg gcc_checking_assert (is_a <scalar_int_mode> (to_mode) 478 1.1 mrg && known_lt (GET_MODE_PRECISION (from_mode), 479 1.1 mrg GET_MODE_PRECISION (to_mode))); 480 1.1 mrg /* The modes after FROM_MODE are all MODE_INT, so the only 481 1.1 mrg MODE_PARTIAL_INT mode we consider is FROM_MODE itself. 482 1.1 mrg If LIMIT_MODE is MODE_PARTIAL_INT, stop at the containing 483 1.1 mrg MODE_INT. */ 484 1.1 mrg if (GET_MODE_CLASS (limit_mode) == MODE_PARTIAL_INT) 485 1.1 mrg limit_mode = GET_MODE_WIDER_MODE (limit_mode).require (); 486 1.1 mrg } 487 1.1 mrg else 488 1.1 mrg gcc_checking_assert (GET_MODE_CLASS (from_mode) == GET_MODE_CLASS (to_mode) 489 1.1 mrg && from_mode < to_mode); 490 1.1 mrg FOR_EACH_MODE (from_mode, from_mode, limit_mode) 491 1.1 mrg { 492 1.1 mrg enum insn_code handler = convert_optab_handler (op, to_mode, from_mode); 493 1.1 mrg 494 1.1 mrg if (handler != CODE_FOR_nothing) 495 1.1 mrg { 496 1.1 mrg if (found_mode) 497 1.1 mrg *found_mode = from_mode; 498 1.1 mrg return handler; 499 1.1 mrg } 500 1.1 mrg } 501 1.1 mrg 502 1.1 mrg return CODE_FOR_nothing; 503 1.1 mrg } 504 1.1 mrg 505 1.1 mrg /* Return non-zero if a highpart multiply is supported of can be synthisized. 506 1.1 mrg For the benefit of expand_mult_highpart, the return value is 1 for direct, 507 1.1 mrg 2 for even/odd widening, and 3 for hi/lo widening. */ 508 1.1 mrg 509 1.1 mrg int 510 1.1 mrg can_mult_highpart_p (machine_mode mode, bool uns_p) 511 1.1 mrg { 512 1.1 mrg optab op; 513 1.1 mrg 514 1.1 mrg op = uns_p ? umul_highpart_optab : smul_highpart_optab; 515 1.1 mrg if (optab_handler (op, mode) != CODE_FOR_nothing) 516 1.1 mrg return 1; 517 1.1 mrg 518 1.1 mrg /* If the mode is an integral vector, synth from widening operations. */ 519 1.1 mrg if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT) 520 1.1 mrg return 0; 521 1.1 mrg 522 1.1 mrg poly_int64 nunits = GET_MODE_NUNITS (mode); 523 1.1 mrg 524 1.1 mrg op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab; 525 1.1 mrg if (optab_handler (op, mode) != CODE_FOR_nothing) 526 1.1 mrg { 527 1.1 mrg op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab; 528 1.1 mrg if (optab_handler (op, mode) != CODE_FOR_nothing) 529 1.1 mrg { 530 1.1 mrg /* The encoding has 2 interleaved stepped patterns. */ 531 1.1 mrg vec_perm_builder sel (nunits, 2, 3); 532 1.1 mrg for (unsigned int i = 0; i < 6; ++i) 533 1.1 mrg sel.quick_push (!BYTES_BIG_ENDIAN 534 1.1 mrg + (i & ~1) 535 1.1 mrg + ((i & 1) ? nunits : 0)); 536 1.1 mrg vec_perm_indices indices (sel, 2, nunits); 537 1.1 mrg if (can_vec_perm_const_p (mode, indices)) 538 1.1 mrg return 2; 539 1.1 mrg } 540 1.1 mrg } 541 1.1 mrg 542 1.1 mrg op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab; 543 1.1 mrg if (optab_handler (op, mode) != CODE_FOR_nothing) 544 1.1 mrg { 545 1.1 mrg op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab; 546 1.1 mrg if (optab_handler (op, mode) != CODE_FOR_nothing) 547 1.1 mrg { 548 1.1 mrg /* The encoding has a single stepped pattern. */ 549 1.1 mrg vec_perm_builder sel (nunits, 1, 3); 550 1.1 mrg for (unsigned int i = 0; i < 3; ++i) 551 1.1 mrg sel.quick_push (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1)); 552 1.1 mrg vec_perm_indices indices (sel, 2, nunits); 553 1.1 mrg if (can_vec_perm_const_p (mode, indices)) 554 1.1 mrg return 3; 555 1.1 mrg } 556 1.1 mrg } 557 1.1 mrg 558 1.1 mrg return 0; 559 1.1 mrg } 560 1.1 mrg 561 1.1 mrg /* Return true if target supports vector masked load/store for mode. */ 562 1.1 mrg 563 1.1 mrg bool 564 1.1 mrg can_vec_mask_load_store_p (machine_mode mode, 565 1.1 mrg machine_mode mask_mode, 566 1.1 mrg bool is_load) 567 1.1 mrg { 568 1.1 mrg optab op = is_load ? maskload_optab : maskstore_optab; 569 1.1 mrg machine_mode vmode; 570 1.1 mrg 571 1.1 mrg /* If mode is vector mode, check it directly. */ 572 1.1 mrg if (VECTOR_MODE_P (mode)) 573 1.1 mrg return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing; 574 1.1 mrg 575 1.1 mrg /* Otherwise, return true if there is some vector mode with 576 1.1 mrg the mask load/store supported. */ 577 1.1 mrg 578 1.1 mrg /* See if there is any chance the mask load or store might be 579 1.1 mrg vectorized. If not, punt. */ 580 1.1 mrg scalar_mode smode; 581 1.1 mrg if (!is_a <scalar_mode> (mode, &smode)) 582 1.1 mrg return false; 583 1.1 mrg 584 1.1 mrg vmode = targetm.vectorize.preferred_simd_mode (smode); 585 1.1 mrg if (VECTOR_MODE_P (vmode) 586 1.1 mrg && targetm.vectorize.get_mask_mode (vmode).exists (&mask_mode) 587 1.1 mrg && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) 588 1.1 mrg return true; 589 1.1 mrg 590 1.1 mrg auto_vector_modes vector_modes; 591 1.1 mrg targetm.vectorize.autovectorize_vector_modes (&vector_modes, true); 592 1.1 mrg for (machine_mode base_mode : vector_modes) 593 1.1 mrg if (related_vector_mode (base_mode, smode).exists (&vmode) 594 1.1 mrg && targetm.vectorize.get_mask_mode (vmode).exists (&mask_mode) 595 1.1 mrg && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) 596 1.1 mrg return true; 597 1.1 mrg return false; 598 1.1 mrg } 599 1.1 mrg 600 1.1 mrg /* If target supports vector load/store with length for vector mode MODE, 601 1.1 mrg return the corresponding vector mode, otherwise return opt_machine_mode (). 602 1.1 mrg There are two flavors for vector load/store with length, one is to measure 603 1.1 mrg length with bytes, the other is to measure length with lanes. 604 1.1 mrg As len_{load,store} optabs point out, for the flavor with bytes, we use 605 1.1 mrg VnQI to wrap the other supportable same size vector modes. */ 606 1.1 mrg 607 1.1 mrg opt_machine_mode 608 1.1 mrg get_len_load_store_mode (machine_mode mode, bool is_load) 609 1.1 mrg { 610 1.1 mrg optab op = is_load ? len_load_optab : len_store_optab; 611 1.1 mrg gcc_assert (VECTOR_MODE_P (mode)); 612 1.1 mrg 613 1.1 mrg /* Check if length in lanes supported for this mode directly. */ 614 1.1 mrg if (direct_optab_handler (op, mode)) 615 1.1 mrg return mode; 616 1.1 mrg 617 1.1 mrg /* Check if length in bytes supported for same vector size VnQI. */ 618 1.1 mrg machine_mode vmode; 619 1.1 mrg poly_uint64 nunits = GET_MODE_SIZE (mode); 620 1.1 mrg if (related_vector_mode (mode, QImode, nunits).exists (&vmode) 621 1.1 mrg && direct_optab_handler (op, vmode)) 622 1.1 mrg return vmode; 623 1.1 mrg 624 1.1 mrg return opt_machine_mode (); 625 1.1 mrg } 626 1.1 mrg 627 1.1 mrg /* Return true if there is a compare_and_swap pattern. */ 628 1.1 mrg 629 1.1 mrg bool 630 1.1 mrg can_compare_and_swap_p (machine_mode mode, bool allow_libcall) 631 1.1 mrg { 632 1.1 mrg enum insn_code icode; 633 1.1 mrg 634 1.1 mrg /* Check for __atomic_compare_and_swap. */ 635 1.1 mrg icode = direct_optab_handler (atomic_compare_and_swap_optab, mode); 636 1.1 mrg if (icode != CODE_FOR_nothing) 637 1.1 mrg return true; 638 1.1 mrg 639 1.1 mrg /* Check for __sync_compare_and_swap. */ 640 1.1 mrg icode = optab_handler (sync_compare_and_swap_optab, mode); 641 1.1 mrg if (icode != CODE_FOR_nothing) 642 1.1 mrg return true; 643 1.1 mrg if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode)) 644 1.1 mrg return true; 645 1.1 mrg 646 1.1 mrg /* No inline compare and swap. */ 647 1.1 mrg return false; 648 1.1 mrg } 649 1.1 mrg 650 1.1 mrg /* Return true if an atomic exchange can be performed. */ 651 1.1 mrg 652 1.1 mrg bool 653 1.1 mrg can_atomic_exchange_p (machine_mode mode, bool allow_libcall) 654 1.1 mrg { 655 1.1 mrg enum insn_code icode; 656 1.1 mrg 657 1.1 mrg /* Check for __atomic_exchange. */ 658 1.1 mrg icode = direct_optab_handler (atomic_exchange_optab, mode); 659 1.1 mrg if (icode != CODE_FOR_nothing) 660 1.1 mrg return true; 661 1.1 mrg 662 1.1 mrg /* Don't check __sync_test_and_set, as on some platforms that 663 1.1 mrg has reduced functionality. Targets that really do support 664 1.1 mrg a proper exchange should simply be updated to the __atomics. */ 665 1.1 mrg 666 1.1 mrg return can_compare_and_swap_p (mode, allow_libcall); 667 1.1 mrg } 668 1.1 mrg 669 1.1 mrg /* Return true if an atomic load can be performed without falling back to 670 1.1 mrg a compare-and-swap. */ 671 1.1 mrg 672 1.1 mrg bool 673 1.1 mrg can_atomic_load_p (machine_mode mode) 674 1.1 mrg { 675 1.1 mrg enum insn_code icode; 676 1.1 mrg 677 1.1 mrg /* Does the target supports the load directly? */ 678 1.1 mrg icode = direct_optab_handler (atomic_load_optab, mode); 679 1.1 mrg if (icode != CODE_FOR_nothing) 680 1.1 mrg return true; 681 1.1 mrg 682 1.1 mrg /* If the size of the object is greater than word size on this target, 683 1.1 mrg then we assume that a load will not be atomic. Also see 684 1.1 mrg expand_atomic_load. */ 685 1.1 mrg return known_le (GET_MODE_PRECISION (mode), BITS_PER_WORD); 686 1.1 mrg } 687 1.1 mrg 688 1.1 mrg /* Determine whether "1 << x" is relatively cheap in word_mode. */ 689 1.1 mrg 690 1.1 mrg bool 691 1.1 mrg lshift_cheap_p (bool speed_p) 692 1.1 mrg { 693 1.1 mrg /* FIXME: This should be made target dependent via this "this_target" 694 1.1 mrg mechanism, similar to e.g. can_copy_init_p in gcse.cc. */ 695 1.1 mrg static bool init[2] = { false, false }; 696 1.1 mrg static bool cheap[2] = { true, true }; 697 1.1 mrg 698 1.1 mrg /* If the targer has no lshift in word_mode, the operation will most 699 1.1 mrg probably not be cheap. ??? Does GCC even work for such targets? */ 700 1.1 mrg if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing) 701 1.1 mrg return false; 702 1.1 mrg 703 1.1 mrg if (!init[speed_p]) 704 1.1 mrg { 705 1.1 mrg rtx reg = gen_raw_REG (word_mode, 10000); 706 1.1 mrg int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg), 707 1.1 mrg word_mode, speed_p); 708 1.1 mrg cheap[speed_p] = cost < COSTS_N_INSNS (3); 709 1.1 mrg init[speed_p] = true; 710 1.1 mrg } 711 1.1 mrg 712 1.1 mrg return cheap[speed_p]; 713 1.1 mrg } 714 1.1 mrg 715 1.1 mrg /* If MODE is not VOIDmode, return true if vector conversion optab OP supports 716 1.1 mrg that mode, given that the second mode is always an integer vector. 717 1.1 mrg If MODE is VOIDmode, return true if OP supports any vector mode. */ 718 1.1 mrg 719 1.1 mrg static bool 720 1.1 mrg supports_vec_convert_optab_p (optab op, machine_mode mode) 721 1.1 mrg { 722 1.1 mrg int start = mode == VOIDmode ? 0 : mode; 723 1.1 mrg int end = mode == VOIDmode ? MAX_MACHINE_MODE - 1 : mode; 724 1.1 mrg for (int i = start; i <= end; ++i) 725 1.1 mrg if (VECTOR_MODE_P ((machine_mode) i)) 726 1.1 mrg for (int j = MIN_MODE_VECTOR_INT; j < MAX_MODE_VECTOR_INT; ++j) 727 1.1 mrg if (convert_optab_handler (op, (machine_mode) i, 728 1.1 mrg (machine_mode) j) != CODE_FOR_nothing) 729 1.1 mrg return true; 730 1.1 mrg 731 1.1 mrg return false; 732 1.1 mrg } 733 1.1 mrg 734 1.1 mrg /* If MODE is not VOIDmode, return true if vec_gather_load is available for 735 1.1 mrg that mode. If MODE is VOIDmode, return true if gather_load is available 736 1.1 mrg for at least one vector mode. */ 737 1.1 mrg 738 1.1 mrg bool 739 1.1 mrg supports_vec_gather_load_p (machine_mode mode) 740 1.1 mrg { 741 1.1 mrg if (!this_fn_optabs->supports_vec_gather_load[mode]) 742 1.1 mrg this_fn_optabs->supports_vec_gather_load[mode] 743 1.1 mrg = (supports_vec_convert_optab_p (gather_load_optab, mode) 744 1.1 mrg || supports_vec_convert_optab_p (mask_gather_load_optab, mode) 745 1.1 mrg ? 1 : -1); 746 1.1 mrg 747 1.1 mrg return this_fn_optabs->supports_vec_gather_load[mode] > 0; 748 1.1 mrg } 749 1.1 mrg 750 1.1 mrg /* If MODE is not VOIDmode, return true if vec_scatter_store is available for 751 1.1 mrg that mode. If MODE is VOIDmode, return true if scatter_store is available 752 1.1 mrg for at least one vector mode. */ 753 1.1 mrg 754 1.1 mrg bool 755 1.1 mrg supports_vec_scatter_store_p (machine_mode mode) 756 1.1 mrg { 757 1.1 mrg if (!this_fn_optabs->supports_vec_scatter_store[mode]) 758 1.1 mrg this_fn_optabs->supports_vec_scatter_store[mode] 759 1.1 mrg = (supports_vec_convert_optab_p (scatter_store_optab, mode) 760 1.1 mrg || supports_vec_convert_optab_p (mask_scatter_store_optab, mode) 761 1.1 mrg ? 1 : -1); 762 1.1 mrg 763 1.1 mrg return this_fn_optabs->supports_vec_scatter_store[mode] > 0; 764 1.1 mrg } 765 1.1 mrg 766 1.1 mrg /* Whether we can extract part of the vector mode MODE as 767 1.1 mrg (scalar or vector) mode EXTR_MODE. */ 768 1.1 mrg 769 1.1 mrg bool 770 1.1 mrg can_vec_extract (machine_mode mode, machine_mode extr_mode) 771 1.1 mrg { 772 1.1 mrg unsigned m; 773 1.1 mrg if (!VECTOR_MODE_P (mode) 774 1.1 mrg || !constant_multiple_p (GET_MODE_SIZE (mode), 775 1.1 mrg GET_MODE_SIZE (extr_mode), &m)) 776 1.1 mrg return false; 777 1.1 mrg 778 1.1 mrg if (convert_optab_handler (vec_extract_optab, mode, extr_mode) 779 1.1 mrg != CODE_FOR_nothing) 780 1.1 mrg return true; 781 1.1 mrg 782 1.1 mrg /* Besides a direct vec_extract we can also use an element extract from 783 1.1 mrg an integer vector mode with elements of the size of the extr_mode. */ 784 1.1 mrg scalar_int_mode imode; 785 1.1 mrg machine_mode vmode; 786 1.1 mrg if (!int_mode_for_size (GET_MODE_BITSIZE (extr_mode), 0).exists (&imode) 787 1.1 mrg || !related_vector_mode (mode, imode, m).exists (&vmode) 788 1.1 mrg || (convert_optab_handler (vec_extract_optab, vmode, imode) 789 1.1 mrg == CODE_FOR_nothing)) 790 1.1 mrg return false; 791 1.1 mrg /* We assume we can pun mode to vmode and imode to extr_mode. */ 792 1.1 mrg return true; 793 1.1 mrg } 794