1 | /* Copyright (C) 1988-2023 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 | |
52 | unsigned get_nregs () const {return m_nregs;} |
53 | HOST_WIDE_INT get_stack_align_off_in () const {return m_stack_align_off_in;} |
54 | |
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 ); |
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. */ |
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. */ |
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_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 | /* Limit on chain discovery. */ |
152 | unsigned max_visits; |
153 | |
154 | bitmap insns_conv; |
155 | hash_map<rtx, rtx> defs_map; |
156 | unsigned n_sse_to_integer; |
157 | unsigned n_integer_to_sse; |
158 | |
159 | bool build (bitmap candidates, unsigned insn_uid, bitmap disallowed); |
160 | virtual int compute_convert_gain () = 0; |
161 | int convert (); |
162 | |
163 | protected: |
164 | void add_to_queue (unsigned insn_uid); |
165 | void emit_conversion_insns (rtx insns, rtx_insn *pos); |
166 | rtx convert_compare (rtx op1, rtx op2, rtx_insn *insn); |
167 | void mark_dual_mode_def (df_ref def); |
168 | void convert_reg (rtx_insn *insn, rtx dst, rtx src); |
169 | void convert_insn_common (rtx_insn *insn); |
170 | void make_vector_copies (rtx_insn *, rtx); |
171 | void convert_registers (); |
172 | |
173 | private: |
174 | bool add_insn (bitmap candidates, unsigned insn_uid, bitmap disallowed); |
175 | bool analyze_register_chain (bitmap candidates, df_ref ref, |
176 | bitmap disallowed); |
177 | virtual void convert_insn (rtx_insn *insn) = 0; |
178 | virtual void convert_op (rtx *op, rtx_insn *insn) = 0; |
179 | }; |
180 | |
181 | class general_scalar_chain : public scalar_chain |
182 | { |
183 | public: |
184 | general_scalar_chain (enum machine_mode smode_, enum machine_mode vmode_) |
185 | : scalar_chain (smode_, vmode_) {} |
186 | int compute_convert_gain () final override; |
187 | |
188 | private: |
189 | void convert_insn (rtx_insn *insn) final override; |
190 | void convert_op (rtx *op, rtx_insn *insn) final override; |
191 | int vector_const_cost (rtx exp); |
192 | rtx convert_rotate (enum rtx_code, rtx op0, rtx op1, rtx_insn *insn); |
193 | }; |
194 | |
195 | class timode_scalar_chain : public scalar_chain |
196 | { |
197 | public: |
198 | timode_scalar_chain () : scalar_chain (TImode, V1TImode) {} |
199 | int compute_convert_gain () final override; |
200 | |
201 | private: |
202 | void fix_debug_reg_uses (rtx reg); |
203 | void convert_insn (rtx_insn *insn) final override; |
204 | void convert_op (rtx *op, rtx_insn *insn) final override; |
205 | }; |
206 | |
207 | } // anon namespace |
208 | |
209 | bool ix86_save_reg (unsigned int regno, bool maybe_eh_return, |
210 | bool ignore_outlined); |
211 | int ix86_compare_version_priority (tree decl1, tree decl2); |
212 | tree ix86_generate_version_dispatcher_body (void *node_p); |
213 | tree ix86_get_function_versions_dispatcher (void *decl); |
214 | tree ix86_mangle_decl_assembler_name (tree decl, tree id); |
215 | |
216 | |
217 | #endif /* GCC_I386_FEATURES_H */ |
218 | |