1 /* IR-agnostic target query functions relating to optabs 2 Copyright (C) 2001-2018 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 GCC is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 #ifndef GCC_OPTABS_QUERY_H 21 #define GCC_OPTABS_QUERY_H 22 23 #include "insn-opinit.h" 24 #include "target.h" 25 26 /* Return true if OP is a conversion optab. */ 27 28 inline bool 29 convert_optab_p (optab op) 30 { 31 return op > unknown_optab && op <= LAST_CONV_OPTAB; 32 } 33 34 /* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing 35 if the target does not have such an insn. */ 36 37 inline enum insn_code 38 optab_handler (optab op, machine_mode mode) 39 { 40 unsigned scode = (op << 16) | mode; 41 gcc_assert (op > LAST_CONV_OPTAB); 42 return raw_optab_handler (scode); 43 } 44 45 /* Return the insn used to perform conversion OP from mode FROM_MODE 46 to mode TO_MODE; return CODE_FOR_nothing if the target does not have 47 such an insn. */ 48 49 inline enum insn_code 50 convert_optab_handler (convert_optab op, machine_mode to_mode, 51 machine_mode from_mode) 52 { 53 unsigned scode = (op << 16) | (from_mode << 8) | to_mode; 54 gcc_assert (convert_optab_p (op)); 55 return raw_optab_handler (scode); 56 } 57 58 enum insn_code convert_optab_handler (convert_optab, machine_mode, 59 machine_mode, optimization_type); 60 61 /* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing 62 if the target does not have such an insn. */ 63 64 inline enum insn_code 65 direct_optab_handler (direct_optab op, machine_mode mode) 66 { 67 return optab_handler (op, mode); 68 } 69 70 enum insn_code direct_optab_handler (convert_optab, machine_mode, 71 optimization_type); 72 73 /* Return true if UNOPTAB is for a trapping-on-overflow operation. */ 74 75 inline bool 76 trapv_unoptab_p (optab unoptab) 77 { 78 return (unoptab == negv_optab 79 || unoptab == absv_optab); 80 } 81 82 /* Return true if BINOPTAB is for a trapping-on-overflow operation. */ 83 84 inline bool 85 trapv_binoptab_p (optab binoptab) 86 { 87 return (binoptab == addv_optab 88 || binoptab == subv_optab 89 || binoptab == smulv_optab); 90 } 91 92 /* Return insn code for a comparison operator with VMODE 93 resultin MASK_MODE, unsigned if UNS is true. */ 94 95 static inline enum insn_code 96 get_vec_cmp_icode (machine_mode vmode, machine_mode mask_mode, bool uns) 97 { 98 optab tab = uns ? vec_cmpu_optab : vec_cmp_optab; 99 return convert_optab_handler (tab, vmode, mask_mode); 100 } 101 102 /* Return insn code for a comparison operator with VMODE 103 resultin MASK_MODE (only for EQ/NE). */ 104 105 static inline enum insn_code 106 get_vec_cmp_eq_icode (machine_mode vmode, machine_mode mask_mode) 107 { 108 return convert_optab_handler (vec_cmpeq_optab, vmode, mask_mode); 109 } 110 111 /* Return insn code for a conditional operator with a comparison in 112 mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE. */ 113 114 inline enum insn_code 115 get_vcond_icode (machine_mode vmode, machine_mode cmode, bool uns) 116 { 117 enum insn_code icode = CODE_FOR_nothing; 118 if (uns) 119 icode = convert_optab_handler (vcondu_optab, vmode, cmode); 120 else 121 icode = convert_optab_handler (vcond_optab, vmode, cmode); 122 return icode; 123 } 124 125 /* Return insn code for a conditional operator with a mask mode 126 MMODE resulting in a value of mode VMODE. */ 127 128 static inline enum insn_code 129 get_vcond_mask_icode (machine_mode vmode, machine_mode mmode) 130 { 131 return convert_optab_handler (vcond_mask_optab, vmode, mmode); 132 } 133 134 /* Return insn code for a conditional operator with a comparison in 135 mode CMODE (only EQ/NE), resulting in a value of mode VMODE. */ 136 137 static inline enum insn_code 138 get_vcond_eq_icode (machine_mode vmode, machine_mode cmode) 139 { 140 return convert_optab_handler (vcondeq_optab, vmode, cmode); 141 } 142 143 /* Enumerates the possible extraction_insn operations. */ 144 enum extraction_pattern { EP_insv, EP_extv, EP_extzv }; 145 146 /* Describes an instruction that inserts or extracts a bitfield. */ 147 struct extraction_insn 148 { 149 /* The code of the instruction. */ 150 enum insn_code icode; 151 152 /* The mode that the structure operand should have. This is byte_mode 153 when using the legacy insv, extv and extzv patterns to access memory. 154 If no mode is given, the structure is a BLKmode memory. */ 155 opt_scalar_int_mode struct_mode; 156 157 /* The mode of the field to be inserted or extracted, and by extension 158 the mode of the insertion or extraction itself. */ 159 scalar_int_mode field_mode; 160 161 /* The mode of the field's bit position. This is only important 162 when the position is variable rather than constant. */ 163 scalar_int_mode pos_mode; 164 }; 165 166 bool get_best_reg_extraction_insn (extraction_insn *, 167 enum extraction_pattern, 168 unsigned HOST_WIDE_INT, machine_mode); 169 bool get_best_mem_extraction_insn (extraction_insn *, 170 enum extraction_pattern, 171 HOST_WIDE_INT, HOST_WIDE_INT, machine_mode); 172 173 enum insn_code can_extend_p (machine_mode, machine_mode, int); 174 enum insn_code can_float_p (machine_mode, machine_mode, int); 175 enum insn_code can_fix_p (machine_mode, machine_mode, int, bool *); 176 bool can_conditionally_move_p (machine_mode mode); 177 opt_machine_mode qimode_for_vec_perm (machine_mode); 178 bool selector_fits_mode_p (machine_mode, const vec_perm_indices &); 179 bool can_vec_perm_var_p (machine_mode); 180 bool can_vec_perm_const_p (machine_mode, const vec_perm_indices &, 181 bool = true); 182 /* Find a widening optab even if it doesn't widen as much as we want. */ 183 #define find_widening_optab_handler(A, B, C) \ 184 find_widening_optab_handler_and_mode (A, B, C, NULL) 185 enum insn_code find_widening_optab_handler_and_mode (optab, machine_mode, 186 machine_mode, 187 machine_mode *); 188 int can_mult_highpart_p (machine_mode, bool); 189 bool can_vec_mask_load_store_p (machine_mode, machine_mode, bool); 190 bool can_compare_and_swap_p (machine_mode, bool); 191 bool can_atomic_exchange_p (machine_mode, bool); 192 bool can_atomic_load_p (machine_mode); 193 bool lshift_cheap_p (bool); 194 bool supports_vec_gather_load_p (); 195 bool supports_vec_scatter_store_p (); 196 197 /* Version of find_widening_optab_handler_and_mode that operates on 198 specific mode types. */ 199 200 template<typename T> 201 inline enum insn_code 202 find_widening_optab_handler_and_mode (optab op, const T &to_mode, 203 const T &from_mode, T *found_mode) 204 { 205 machine_mode tmp; 206 enum insn_code icode = find_widening_optab_handler_and_mode 207 (op, machine_mode (to_mode), machine_mode (from_mode), &tmp); 208 if (icode != CODE_FOR_nothing && found_mode) 209 *found_mode = as_a <T> (tmp); 210 return icode; 211 } 212 213 #endif 214