Line data Source code
1 : /* Copyright (C) 1988-2026 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 193166 : const reginfo &get_reginfo (unsigned reg) const
56 : {
57 193166 : gcc_assert (reg < m_nregs);
58 193166 : 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. */
72 35225 : HOST_WIDE_INT get_stack_space_used () const
73 : {
74 35225 : const struct machine_function *m = cfun->machine;
75 35225 : unsigned last_reg = m->call_ms2sysv_extra_regs + MIN_REGS - 1;
76 :
77 35225 : gcc_assert (m->call_ms2sysv_extra_regs <= MAX_EXTRA_REGS);
78 35225 : return m_regs[last_reg].offset + STUB_INDEX_OFFSET;
79 : }
80 :
81 : /* Returns the offset for the base pointer used by the stub. */
82 14666 : HOST_WIDE_INT get_stub_ptr_offset () const
83 : {
84 14666 : 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 : /* Limit on chain discovery. */
152 : unsigned max_visits;
153 :
154 : bitmap insns_conv;
155 : hash_map<rtx, rtx> defs_map;
156 : /* Cost of inserted conversion between ineteger and sse. */
157 : int cost_sse_integer;
158 : sreal weighted_cost_sse_integer;
159 : auto_vec<rtx_insn *> control_flow_insns;
160 :
161 : bool build (bitmap candidates, unsigned insn_uid, bitmap disallowed);
162 : virtual bool compute_convert_gain () = 0;
163 : int convert ();
164 :
165 : protected:
166 : void add_to_queue (unsigned insn_uid);
167 : void emit_conversion_insns (rtx insns, rtx_insn *pos);
168 : rtx convert_compare (rtx op1, rtx op2, rtx_insn *insn);
169 : void mark_dual_mode_def (df_ref def);
170 : void convert_reg (rtx_insn *insn, rtx dst, rtx src);
171 : void convert_insn_common (rtx_insn *insn);
172 : void make_vector_copies (rtx_insn *, rtx);
173 : void convert_registers ();
174 : void convert_op (rtx *op, rtx_insn *insn);
175 :
176 : private:
177 : bool add_insn (bitmap candidates, unsigned insn_uid, bitmap disallowed);
178 : bool analyze_register_chain (bitmap candidates, df_ref ref,
179 : bitmap disallowed);
180 : virtual void convert_insn (rtx_insn *insn) = 0;
181 : };
182 :
183 : class general_scalar_chain : public scalar_chain
184 : {
185 : public:
186 5904132 : general_scalar_chain (enum machine_mode smode_, enum machine_mode vmode_)
187 5904132 : : scalar_chain (smode_, vmode_) {}
188 : bool compute_convert_gain () final override;
189 :
190 : private:
191 : void convert_insn (rtx_insn *insn) final override;
192 : int vector_const_cost (rtx exp, basic_block bb);
193 : rtx convert_rotate (enum rtx_code, rtx op0, rtx op1, rtx_insn *insn);
194 : };
195 :
196 : class timode_scalar_chain : public scalar_chain
197 : {
198 : public:
199 473775 : timode_scalar_chain () : scalar_chain (TImode, V1TImode) {}
200 : bool compute_convert_gain () final override;
201 :
202 : private:
203 : void fix_debug_reg_uses (rtx reg);
204 : void convert_insn (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 */
|