1 /* Copyright (C) 1988-2020 Free Software Foundation, Inc. 2 3 This file is part of GCC. 4 5 GCC is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3, or (at your option) 8 any later version. 9 10 GCC is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with GCC; see the file COPYING3. If not see 17 <http://www.gnu.org/licenses/>. */ 18 19 #ifndef GCC_I386_FEATURES_H 20 #define GCC_I386_FEATURES_H 21 22 enum xlogue_stub { 23 XLOGUE_STUB_SAVE, 24 XLOGUE_STUB_RESTORE, 25 XLOGUE_STUB_RESTORE_TAIL, 26 XLOGUE_STUB_SAVE_HFP, 27 XLOGUE_STUB_RESTORE_HFP, 28 XLOGUE_STUB_RESTORE_HFP_TAIL, 29 30 XLOGUE_STUB_COUNT 31 }; 32 33 enum xlogue_stub_sets { 34 XLOGUE_SET_ALIGNED, 35 XLOGUE_SET_ALIGNED_PLUS_8, 36 XLOGUE_SET_HFP_ALIGNED_OR_REALIGN, 37 XLOGUE_SET_HFP_ALIGNED_PLUS_8, 38 39 XLOGUE_SET_COUNT 40 }; 41 42 /* Register save/restore layout used by out-of-line stubs. */ 43 class xlogue_layout { 44 public: 45 struct reginfo 46 { 47 unsigned regno; 48 HOST_WIDE_INT offset; /* Offset used by stub base pointer (rax or 49 rsi) to where each register is stored. */ 50 }; 51 get_nregs()52 unsigned get_nregs () const {return m_nregs;} get_stack_align_off_in()53 HOST_WIDE_INT get_stack_align_off_in () const {return m_stack_align_off_in;} 54 get_reginfo(unsigned reg)55 const reginfo &get_reginfo (unsigned reg) const 56 { 57 gcc_assert (reg < m_nregs); 58 return m_regs[reg]; 59 } 60 61 static const char *get_stub_name (enum xlogue_stub stub, 62 unsigned n_extra_args); 63 64 /* Returns an rtx for the stub's symbol based upon 65 1.) the specified stub (save, restore or restore_ret) and 66 2.) the value of cfun->machine->call_ms2sysv_extra_regs and 67 3.) rather or not stack alignment is being performed. */ 68 static rtx get_stub_rtx (enum xlogue_stub stub); 69 70 /* Returns the amount of stack space (including padding) that the stub 71 needs to store registers based upon data in the machine_function. */ get_stack_space_used()72 HOST_WIDE_INT get_stack_space_used () const 73 { 74 const struct machine_function *m = cfun->machine; 75 unsigned last_reg = m->call_ms2sysv_extra_regs + MIN_REGS - 1; 76 77 gcc_assert (m->call_ms2sysv_extra_regs <= MAX_EXTRA_REGS); 78 return m_regs[last_reg].offset + STUB_INDEX_OFFSET; 79 } 80 81 /* Returns the offset for the base pointer used by the stub. */ get_stub_ptr_offset()82 HOST_WIDE_INT get_stub_ptr_offset () const 83 { 84 return STUB_INDEX_OFFSET + m_stack_align_off_in; 85 } 86 87 static const class xlogue_layout &get_instance (); 88 static unsigned count_stub_managed_regs (); 89 static bool is_stub_managed_reg (unsigned regno, unsigned count); 90 91 static const HOST_WIDE_INT STUB_INDEX_OFFSET = 0x70; 92 static const unsigned MIN_REGS = NUM_X86_64_MS_CLOBBERED_REGS; 93 static const unsigned MAX_REGS = 18; 94 static const unsigned MAX_EXTRA_REGS = MAX_REGS - MIN_REGS; 95 static const unsigned VARIANT_COUNT = MAX_EXTRA_REGS + 1; 96 static const unsigned STUB_NAME_MAX_LEN = 20; 97 static const char * const STUB_BASE_NAMES[XLOGUE_STUB_COUNT]; 98 static const unsigned REG_ORDER[MAX_REGS]; 99 static const unsigned REG_ORDER_REALIGN[MAX_REGS]; 100 101 private: 102 xlogue_layout (); 103 xlogue_layout (HOST_WIDE_INT stack_align_off_in, bool hfp); 104 xlogue_layout (const xlogue_layout &); 105 106 /* True if hard frame pointer is used. */ 107 bool m_hfp; 108 109 /* Max number of register this layout manages. */ 110 unsigned m_nregs; 111 112 /* Incoming offset from 16-byte alignment. */ 113 HOST_WIDE_INT m_stack_align_off_in; 114 115 /* Register order and offsets. */ 116 struct reginfo m_regs[MAX_REGS]; 117 118 /* Lazy-inited cache of symbol names for stubs. */ 119 static char s_stub_names[2][XLOGUE_STUB_COUNT][VARIANT_COUNT] 120 [STUB_NAME_MAX_LEN]; 121 122 static const xlogue_layout s_instances[XLOGUE_SET_COUNT]; 123 }; 124 125 namespace { 126 127 class scalar_chain 128 { 129 public: 130 scalar_chain (enum machine_mode, enum machine_mode); 131 virtual ~scalar_chain (); 132 133 static unsigned max_id; 134 135 /* Scalar mode. */ 136 enum machine_mode smode; 137 /* Vector mode. */ 138 enum machine_mode vmode; 139 140 /* ID of a chain. */ 141 unsigned int chain_id; 142 /* A queue of instructions to be included into a chain. */ 143 bitmap queue; 144 /* Instructions included into a chain. */ 145 bitmap insns; 146 /* All registers defined by a chain. */ 147 bitmap defs; 148 /* Registers used in both vector and sclar modes. */ 149 bitmap defs_conv; 150 151 void build (bitmap candidates, unsigned insn_uid); 152 virtual int compute_convert_gain () = 0; 153 int convert (); 154 155 protected: 156 void add_to_queue (unsigned insn_uid); 157 void emit_conversion_insns (rtx insns, rtx_insn *pos); 158 159 private: 160 void add_insn (bitmap candidates, unsigned insn_uid); 161 void analyze_register_chain (bitmap candidates, df_ref ref); 162 virtual void mark_dual_mode_def (df_ref def) = 0; 163 virtual void convert_insn (rtx_insn *insn) = 0; 164 virtual void convert_registers () = 0; 165 }; 166 167 class general_scalar_chain : public scalar_chain 168 { 169 public: 170 general_scalar_chain (enum machine_mode smode_, enum machine_mode vmode_); 171 ~general_scalar_chain (); 172 int compute_convert_gain (); 173 private: 174 hash_map<rtx, rtx> defs_map; 175 bitmap insns_conv; 176 unsigned n_sse_to_integer; 177 unsigned n_integer_to_sse; 178 void mark_dual_mode_def (df_ref def); 179 void convert_insn (rtx_insn *insn); 180 void convert_op (rtx *op, rtx_insn *insn); 181 void convert_reg (rtx_insn *insn, rtx dst, rtx src); 182 void make_vector_copies (rtx_insn *, rtx); 183 void convert_registers (); 184 int vector_const_cost (rtx exp); 185 }; 186 187 class timode_scalar_chain : public scalar_chain 188 { 189 public: timode_scalar_chain()190 timode_scalar_chain () : scalar_chain (TImode, V1TImode) {} 191 192 /* Convert from TImode to V1TImode is always faster. */ compute_convert_gain()193 int compute_convert_gain () { return 1; } 194 195 private: 196 void mark_dual_mode_def (df_ref def); 197 void fix_debug_reg_uses (rtx reg); 198 void convert_insn (rtx_insn *insn); 199 /* We don't convert registers to difference size. */ convert_registers()200 void convert_registers () {} 201 }; 202 203 } // anon namespace 204 205 bool ix86_save_reg (unsigned int regno, bool maybe_eh_return, bool ignore_outlined); 206 int ix86_compare_version_priority (tree decl1, tree decl2); 207 tree ix86_generate_version_dispatcher_body (void *node_p); 208 tree ix86_get_function_versions_dispatcher (void *decl); 209 tree ix86_mangle_decl_assembler_name (tree decl, tree id); 210 211 212 #endif /* GCC_I386_FEATURES_H */ 213