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 | #define IN_TARGET_CODE 1 |
20 | |
21 | #include "config.h" |
22 | #include "system.h" |
23 | #include "coretypes.h" |
24 | #include "backend.h" |
25 | #include "rtl.h" |
26 | #include "tree.h" |
27 | #include "memmodel.h" |
28 | #include "gimple.h" |
29 | #include "cfghooks.h" |
30 | #include "cfgloop.h" |
31 | #include "df.h" |
32 | #include "tm_p.h" |
33 | #include "stringpool.h" |
34 | #include "expmed.h" |
35 | #include "optabs.h" |
36 | #include "regs.h" |
37 | #include "emit-rtl.h" |
38 | #include "recog.h" |
39 | #include "cgraph.h" |
40 | #include "diagnostic.h" |
41 | #include "cfgbuild.h" |
42 | #include "alias.h" |
43 | #include "fold-const.h" |
44 | #include "attribs.h" |
45 | #include "calls.h" |
46 | #include "stor-layout.h" |
47 | #include "varasm.h" |
48 | #include "output.h" |
49 | #include "insn-attr.h" |
50 | #include "flags.h" |
51 | #include "except.h" |
52 | #include "explow.h" |
53 | #include "expr.h" |
54 | #include "cfgrtl.h" |
55 | #include "common/common-target.h" |
56 | #include "langhooks.h" |
57 | #include "reload.h" |
58 | #include "gimplify.h" |
59 | #include "dwarf2.h" |
60 | #include "tm-constrs.h" |
61 | #include "cselib.h" |
62 | #include "sched-int.h" |
63 | #include "opts.h" |
64 | #include "tree-pass.h" |
65 | #include "context.h" |
66 | #include "pass_manager.h" |
67 | #include "target-globals.h" |
68 | #include "gimple-iterator.h" |
69 | #include "shrink-wrap.h" |
70 | #include "builtins.h" |
71 | #include "rtl-iter.h" |
72 | #include "tree-iterator.h" |
73 | #include "dbgcnt.h" |
74 | #include "case-cfn-macros.h" |
75 | #include "dojump.h" |
76 | #include "fold-const-call.h" |
77 | #include "tree-vrp.h" |
78 | #include "tree-ssanames.h" |
79 | #include "selftest.h" |
80 | #include "selftest-rtl.h" |
81 | #include "print-rtl.h" |
82 | #include "intl.h" |
83 | #include "ifcvt.h" |
84 | #include "symbol-summary.h" |
85 | #include "ipa-prop.h" |
86 | #include "ipa-fnsummary.h" |
87 | #include "wide-int-bitmask.h" |
88 | #include "tree-vector-builder.h" |
89 | #include "debug.h" |
90 | #include "dwarf2out.h" |
91 | #include "i386-options.h" |
92 | |
93 | #include "x86-tune-costs.h" |
94 | |
95 | #ifndef SUBTARGET32_DEFAULT_CPU |
96 | #define SUBTARGET32_DEFAULT_CPU "i386" |
97 | #endif |
98 | |
99 | /* Processor feature/optimization bitmasks. */ |
100 | #define m_NONE HOST_WIDE_INT_0U |
101 | #define m_ALL (~HOST_WIDE_INT_0U) |
102 | #define m_386 (HOST_WIDE_INT_1U<<PROCESSOR_I386) |
103 | #define m_486 (HOST_WIDE_INT_1U<<PROCESSOR_I486) |
104 | #define m_PENT (HOST_WIDE_INT_1U<<PROCESSOR_PENTIUM) |
105 | #define m_LAKEMONT (HOST_WIDE_INT_1U<<PROCESSOR_LAKEMONT) |
106 | #define m_PPRO (HOST_WIDE_INT_1U<<PROCESSOR_PENTIUMPRO) |
107 | #define m_PENT4 (HOST_WIDE_INT_1U<<PROCESSOR_PENTIUM4) |
108 | #define m_NOCONA (HOST_WIDE_INT_1U<<PROCESSOR_NOCONA) |
109 | #define m_P4_NOCONA (m_PENT4 | m_NOCONA) |
110 | #define m_CORE2 (HOST_WIDE_INT_1U<<PROCESSOR_CORE2) |
111 | #define m_NEHALEM (HOST_WIDE_INT_1U<<PROCESSOR_NEHALEM) |
112 | #define m_SANDYBRIDGE (HOST_WIDE_INT_1U<<PROCESSOR_SANDYBRIDGE) |
113 | #define m_HASWELL (HOST_WIDE_INT_1U<<PROCESSOR_HASWELL) |
114 | #define m_BONNELL (HOST_WIDE_INT_1U<<PROCESSOR_BONNELL) |
115 | #define m_SILVERMONT (HOST_WIDE_INT_1U<<PROCESSOR_SILVERMONT) |
116 | #define m_KNL (HOST_WIDE_INT_1U<<PROCESSOR_KNL) |
117 | #define m_KNM (HOST_WIDE_INT_1U<<PROCESSOR_KNM) |
118 | #define m_SKYLAKE (HOST_WIDE_INT_1U<<PROCESSOR_SKYLAKE) |
119 | #define m_SKYLAKE_AVX512 (HOST_WIDE_INT_1U<<PROCESSOR_SKYLAKE_AVX512) |
120 | #define m_CANNONLAKE (HOST_WIDE_INT_1U<<PROCESSOR_CANNONLAKE) |
121 | #define m_ICELAKE_CLIENT (HOST_WIDE_INT_1U<<PROCESSOR_ICELAKE_CLIENT) |
122 | #define m_ICELAKE_SERVER (HOST_WIDE_INT_1U<<PROCESSOR_ICELAKE_SERVER) |
123 | #define m_CASCADELAKE (HOST_WIDE_INT_1U<<PROCESSOR_CASCADELAKE) |
124 | #define m_TIGERLAKE (HOST_WIDE_INT_1U<<PROCESSOR_TIGERLAKE) |
125 | #define m_COOPERLAKE (HOST_WIDE_INT_1U<<PROCESSOR_COOPERLAKE) |
126 | #define m_SAPPHIRERAPIDS (HOST_WIDE_INT_1U<<PROCESSOR_SAPPHIRERAPIDS) |
127 | #define m_ALDERLAKE (HOST_WIDE_INT_1U<<PROCESSOR_ALDERLAKE) |
128 | #define m_ROCKETLAKE (HOST_WIDE_INT_1U<<PROCESSOR_ROCKETLAKE) |
129 | #define m_GRANITERAPIDS (HOST_WIDE_INT_1U<<PROCESSOR_GRANITERAPIDS) |
130 | #define m_GRANITERAPIDS_D (HOST_WIDE_INT_1U<<PROCESSOR_GRANITERAPIDS_D) |
131 | #define m_ARROWLAKE (HOST_WIDE_INT_1U<<PROCESSOR_ARROWLAKE) |
132 | #define m_ARROWLAKE_S (HOST_WIDE_INT_1U<<PROCESSOR_ARROWLAKE_S) |
133 | #define m_PANTHERLAKE (HOST_WIDE_INT_1U<<PROCESSOR_PANTHERLAKE) |
134 | #define m_CORE_AVX512 (m_SKYLAKE_AVX512 | m_CANNONLAKE \ |
135 | | m_ICELAKE_CLIENT | m_ICELAKE_SERVER | m_CASCADELAKE \ |
136 | | m_TIGERLAKE | m_COOPERLAKE | m_SAPPHIRERAPIDS \ |
137 | | m_ROCKETLAKE | m_GRANITERAPIDS | m_GRANITERAPIDS_D) |
138 | #define m_CORE_AVX2 (m_HASWELL | m_SKYLAKE | m_CORE_AVX512) |
139 | #define m_CORE_ALL (m_CORE2 | m_NEHALEM | m_SANDYBRIDGE | m_CORE_AVX2) |
140 | #define m_CORE_HYBRID (m_ALDERLAKE | m_ARROWLAKE | m_ARROWLAKE_S \ |
141 | | m_PANTHERLAKE) |
142 | #define m_GOLDMONT (HOST_WIDE_INT_1U<<PROCESSOR_GOLDMONT) |
143 | #define m_GOLDMONT_PLUS (HOST_WIDE_INT_1U<<PROCESSOR_GOLDMONT_PLUS) |
144 | #define m_TREMONT (HOST_WIDE_INT_1U<<PROCESSOR_TREMONT) |
145 | #define m_SIERRAFOREST (HOST_WIDE_INT_1U<<PROCESSOR_SIERRAFOREST) |
146 | #define m_GRANDRIDGE (HOST_WIDE_INT_1U<<PROCESSOR_GRANDRIDGE) |
147 | #define m_CLEARWATERFOREST (HOST_WIDE_INT_1U<<PROCESSOR_CLEARWATERFOREST) |
148 | #define m_CORE_ATOM (m_SIERRAFOREST | m_GRANDRIDGE | m_CLEARWATERFOREST) |
149 | #define m_INTEL (HOST_WIDE_INT_1U<<PROCESSOR_INTEL) |
150 | /* Gather Data Sampling / CVE-2022-40982 / INTEL-SA-00828. |
151 | Software mitigation. */ |
152 | #define m_GDS (m_SKYLAKE | m_SKYLAKE_AVX512 | m_CANNONLAKE \ |
153 | | m_ICELAKE_CLIENT | m_ICELAKE_SERVER | m_CASCADELAKE \ |
154 | | m_TIGERLAKE | m_COOPERLAKE | m_ROCKETLAKE) |
155 | |
156 | #define m_LUJIAZUI (HOST_WIDE_INT_1U<<PROCESSOR_LUJIAZUI) |
157 | #define m_YONGFENG (HOST_WIDE_INT_1U<<PROCESSOR_YONGFENG) |
158 | #define m_ZHAOXIN (m_LUJIAZUI | m_YONGFENG) |
159 | |
160 | #define m_GEODE (HOST_WIDE_INT_1U<<PROCESSOR_GEODE) |
161 | #define m_K6 (HOST_WIDE_INT_1U<<PROCESSOR_K6) |
162 | #define m_K6_GEODE (m_K6 | m_GEODE) |
163 | #define m_K8 (HOST_WIDE_INT_1U<<PROCESSOR_K8) |
164 | #define m_ATHLON (HOST_WIDE_INT_1U<<PROCESSOR_ATHLON) |
165 | #define m_ATHLON_K8 (m_K8 | m_ATHLON) |
166 | #define m_AMDFAM10 (HOST_WIDE_INT_1U<<PROCESSOR_AMDFAM10) |
167 | #define m_BDVER1 (HOST_WIDE_INT_1U<<PROCESSOR_BDVER1) |
168 | #define m_BDVER2 (HOST_WIDE_INT_1U<<PROCESSOR_BDVER2) |
169 | #define m_BDVER3 (HOST_WIDE_INT_1U<<PROCESSOR_BDVER3) |
170 | #define m_BDVER4 (HOST_WIDE_INT_1U<<PROCESSOR_BDVER4) |
171 | #define m_ZNVER1 (HOST_WIDE_INT_1U<<PROCESSOR_ZNVER1) |
172 | #define m_ZNVER2 (HOST_WIDE_INT_1U<<PROCESSOR_ZNVER2) |
173 | #define m_ZNVER3 (HOST_WIDE_INT_1U<<PROCESSOR_ZNVER3) |
174 | #define m_ZNVER4 (HOST_WIDE_INT_1U<<PROCESSOR_ZNVER4) |
175 | #define m_BTVER1 (HOST_WIDE_INT_1U<<PROCESSOR_BTVER1) |
176 | #define m_BTVER2 (HOST_WIDE_INT_1U<<PROCESSOR_BTVER2) |
177 | #define m_BDVER (m_BDVER1 | m_BDVER2 | m_BDVER3 | m_BDVER4) |
178 | #define m_BTVER (m_BTVER1 | m_BTVER2) |
179 | #define m_ZNVER (m_ZNVER1 | m_ZNVER2 | m_ZNVER3 | m_ZNVER4) |
180 | #define m_AMD_MULTIPLE (m_ATHLON_K8 | m_AMDFAM10 | m_BDVER | m_BTVER \ |
181 | | m_ZNVER) |
182 | |
183 | #define m_GENERIC (HOST_WIDE_INT_1U<<PROCESSOR_GENERIC) |
184 | |
185 | const char* ix86_tune_feature_names[X86_TUNE_LAST] = { |
186 | #undef DEF_TUNE |
187 | #define DEF_TUNE(tune, name, selector) name, |
188 | #include "x86-tune.def" |
189 | #undef DEF_TUNE |
190 | }; |
191 | |
192 | /* Feature tests against the various tunings. */ |
193 | unsigned char ix86_tune_features[X86_TUNE_LAST]; |
194 | |
195 | /* Feature tests against the various tunings used to create ix86_tune_features |
196 | based on the processor mask. */ |
197 | static unsigned HOST_WIDE_INT initial_ix86_tune_features[X86_TUNE_LAST] = { |
198 | #undef DEF_TUNE |
199 | #define DEF_TUNE(tune, name, selector) selector, |
200 | #include "x86-tune.def" |
201 | #undef DEF_TUNE |
202 | }; |
203 | |
204 | /* Feature tests against the various architecture variations. */ |
205 | unsigned char ix86_arch_features[X86_ARCH_LAST]; |
206 | |
207 | struct ix86_target_opts |
208 | { |
209 | const char *option; /* option string */ |
210 | HOST_WIDE_INT mask; /* isa mask options */ |
211 | }; |
212 | |
213 | /* This table is ordered so that options like -msse4.2 that imply other |
214 | ISAs come first. Target string will be displayed in the same order. */ |
215 | static struct ix86_target_opts isa2_opts[] = |
216 | { |
217 | { .option: "-mcx16" , OPTION_MASK_ISA2_CX16 }, |
218 | { .option: "-mvaes" , OPTION_MASK_ISA2_VAES }, |
219 | { .option: "-mrdpid" , OPTION_MASK_ISA2_RDPID }, |
220 | { .option: "-mpconfig" , OPTION_MASK_ISA2_PCONFIG }, |
221 | { .option: "-mwbnoinvd" , OPTION_MASK_ISA2_WBNOINVD }, |
222 | { .option: "-mavx512vp2intersect" , OPTION_MASK_ISA2_AVX512VP2INTERSECT }, |
223 | { .option: "-msgx" , OPTION_MASK_ISA2_SGX }, |
224 | { .option: "-mavx5124vnniw" , OPTION_MASK_ISA2_AVX5124VNNIW }, |
225 | { .option: "-mavx5124fmaps" , OPTION_MASK_ISA2_AVX5124FMAPS }, |
226 | { .option: "-mhle" , OPTION_MASK_ISA2_HLE }, |
227 | { .option: "-mmovbe" , OPTION_MASK_ISA2_MOVBE }, |
228 | { .option: "-mclzero" , OPTION_MASK_ISA2_CLZERO }, |
229 | { .option: "-mmwaitx" , OPTION_MASK_ISA2_MWAITX }, |
230 | { .option: "-mmwait" , OPTION_MASK_ISA2_MWAIT }, |
231 | { .option: "-mmovdir64b" , OPTION_MASK_ISA2_MOVDIR64B }, |
232 | { .option: "-mwaitpkg" , OPTION_MASK_ISA2_WAITPKG }, |
233 | { .option: "-mcldemote" , OPTION_MASK_ISA2_CLDEMOTE }, |
234 | { .option: "-mptwrite" , OPTION_MASK_ISA2_PTWRITE }, |
235 | { .option: "-mavx512bf16" , OPTION_MASK_ISA2_AVX512BF16 }, |
236 | { .option: "-menqcmd" , OPTION_MASK_ISA2_ENQCMD }, |
237 | { .option: "-mserialize" , OPTION_MASK_ISA2_SERIALIZE }, |
238 | { .option: "-mtsxldtrk" , OPTION_MASK_ISA2_TSXLDTRK }, |
239 | { .option: "-mamx-tile" , OPTION_MASK_ISA2_AMX_TILE }, |
240 | { .option: "-mamx-int8" , OPTION_MASK_ISA2_AMX_INT8 }, |
241 | { .option: "-mamx-bf16" , OPTION_MASK_ISA2_AMX_BF16 }, |
242 | { .option: "-muintr" , OPTION_MASK_ISA2_UINTR }, |
243 | { .option: "-mhreset" , OPTION_MASK_ISA2_HRESET }, |
244 | { .option: "-mkl" , OPTION_MASK_ISA2_KL }, |
245 | { .option: "-mwidekl" , OPTION_MASK_ISA2_WIDEKL }, |
246 | { .option: "-mavxvnni" , OPTION_MASK_ISA2_AVXVNNI }, |
247 | { .option: "-mavx512fp16" , OPTION_MASK_ISA2_AVX512FP16 }, |
248 | { .option: "-mavxifma" , OPTION_MASK_ISA2_AVXIFMA }, |
249 | { .option: "-mavxvnniint8" , OPTION_MASK_ISA2_AVXVNNIINT8 }, |
250 | { .option: "-mavxneconvert" , OPTION_MASK_ISA2_AVXNECONVERT }, |
251 | { .option: "-mcmpccxadd" , OPTION_MASK_ISA2_CMPCCXADD }, |
252 | { .option: "-mamx-fp16" , OPTION_MASK_ISA2_AMX_FP16 }, |
253 | { .option: "-mprefetchi" , OPTION_MASK_ISA2_PREFETCHI }, |
254 | { .option: "-mraoint" , OPTION_MASK_ISA2_RAOINT }, |
255 | { .option: "-mamx-complex" , OPTION_MASK_ISA2_AMX_COMPLEX }, |
256 | { .option: "-mavxvnniint16" , OPTION_MASK_ISA2_AVXVNNIINT16 }, |
257 | { .option: "-msm3" , OPTION_MASK_ISA2_SM3 }, |
258 | { .option: "-msha512" , OPTION_MASK_ISA2_SHA512 }, |
259 | { .option: "-msm4" , OPTION_MASK_ISA2_SM4 }, |
260 | { .option: "-mevex512" , OPTION_MASK_ISA2_EVEX512 }, |
261 | { .option: "-musermsr" , OPTION_MASK_ISA2_USER_MSR } |
262 | }; |
263 | static struct ix86_target_opts isa_opts[] = |
264 | { |
265 | { .option: "-mavx512vpopcntdq" , OPTION_MASK_ISA_AVX512VPOPCNTDQ }, |
266 | { .option: "-mavx512bitalg" , OPTION_MASK_ISA_AVX512BITALG }, |
267 | { .option: "-mvpclmulqdq" , OPTION_MASK_ISA_VPCLMULQDQ }, |
268 | { .option: "-mgfni" , OPTION_MASK_ISA_GFNI }, |
269 | { .option: "-mavx512vnni" , OPTION_MASK_ISA_AVX512VNNI }, |
270 | { .option: "-mavx512vbmi2" , OPTION_MASK_ISA_AVX512VBMI2 }, |
271 | { .option: "-mavx512vbmi" , OPTION_MASK_ISA_AVX512VBMI }, |
272 | { .option: "-mavx512ifma" , OPTION_MASK_ISA_AVX512IFMA }, |
273 | { .option: "-mavx512vl" , OPTION_MASK_ISA_AVX512VL }, |
274 | { .option: "-mavx512bw" , OPTION_MASK_ISA_AVX512BW }, |
275 | { .option: "-mavx512dq" , OPTION_MASK_ISA_AVX512DQ }, |
276 | { .option: "-mavx512er" , OPTION_MASK_ISA_AVX512ER }, |
277 | { .option: "-mavx512pf" , OPTION_MASK_ISA_AVX512PF }, |
278 | { .option: "-mavx512cd" , OPTION_MASK_ISA_AVX512CD }, |
279 | { .option: "-mavx512f" , OPTION_MASK_ISA_AVX512F }, |
280 | { .option: "-mavx2" , OPTION_MASK_ISA_AVX2 }, |
281 | { .option: "-mfma" , OPTION_MASK_ISA_FMA }, |
282 | { .option: "-mxop" , OPTION_MASK_ISA_XOP }, |
283 | { .option: "-mfma4" , OPTION_MASK_ISA_FMA4 }, |
284 | { .option: "-mf16c" , OPTION_MASK_ISA_F16C }, |
285 | { .option: "-mavx" , OPTION_MASK_ISA_AVX }, |
286 | /*{ "-msse4" OPTION_MASK_ISA_SSE4 }, */ |
287 | { .option: "-msse4.2" , OPTION_MASK_ISA_SSE4_2 }, |
288 | { .option: "-msse4.1" , OPTION_MASK_ISA_SSE4_1 }, |
289 | { .option: "-msse4a" , OPTION_MASK_ISA_SSE4A }, |
290 | { .option: "-mssse3" , OPTION_MASK_ISA_SSSE3 }, |
291 | { .option: "-msse3" , OPTION_MASK_ISA_SSE3 }, |
292 | { .option: "-maes" , OPTION_MASK_ISA_AES }, |
293 | { .option: "-msha" , OPTION_MASK_ISA_SHA }, |
294 | { .option: "-mpclmul" , OPTION_MASK_ISA_PCLMUL }, |
295 | { .option: "-msse2" , OPTION_MASK_ISA_SSE2 }, |
296 | { .option: "-msse" , OPTION_MASK_ISA_SSE }, |
297 | { .option: "-m3dnowa" , OPTION_MASK_ISA_3DNOW_A }, |
298 | { .option: "-m3dnow" , OPTION_MASK_ISA_3DNOW }, |
299 | { .option: "-mmmx" , OPTION_MASK_ISA_MMX }, |
300 | { .option: "-mrtm" , OPTION_MASK_ISA_RTM }, |
301 | { .option: "-mprfchw" , OPTION_MASK_ISA_PRFCHW }, |
302 | { .option: "-mrdseed" , OPTION_MASK_ISA_RDSEED }, |
303 | { .option: "-madx" , OPTION_MASK_ISA_ADX }, |
304 | { .option: "-mprefetchwt1" , OPTION_MASK_ISA_PREFETCHWT1 }, |
305 | { .option: "-mclflushopt" , OPTION_MASK_ISA_CLFLUSHOPT }, |
306 | { .option: "-mxsaves" , OPTION_MASK_ISA_XSAVES }, |
307 | { .option: "-mxsavec" , OPTION_MASK_ISA_XSAVEC }, |
308 | { .option: "-mxsaveopt" , OPTION_MASK_ISA_XSAVEOPT }, |
309 | { .option: "-mxsave" , OPTION_MASK_ISA_XSAVE }, |
310 | { .option: "-mabm" , OPTION_MASK_ISA_ABM }, |
311 | { .option: "-mbmi" , OPTION_MASK_ISA_BMI }, |
312 | { .option: "-mbmi2" , OPTION_MASK_ISA_BMI2 }, |
313 | { .option: "-mlzcnt" , OPTION_MASK_ISA_LZCNT }, |
314 | { .option: "-mtbm" , OPTION_MASK_ISA_TBM }, |
315 | { .option: "-mpopcnt" , OPTION_MASK_ISA_POPCNT }, |
316 | { .option: "-msahf" , OPTION_MASK_ISA_SAHF }, |
317 | { .option: "-mcrc32" , OPTION_MASK_ISA_CRC32 }, |
318 | { .option: "-mfsgsbase" , OPTION_MASK_ISA_FSGSBASE }, |
319 | { .option: "-mrdrnd" , OPTION_MASK_ISA_RDRND }, |
320 | { .option: "-mpku" , OPTION_MASK_ISA_PKU }, |
321 | { .option: "-mlwp" , OPTION_MASK_ISA_LWP }, |
322 | { .option: "-mfxsr" , OPTION_MASK_ISA_FXSR }, |
323 | { .option: "-mclwb" , OPTION_MASK_ISA_CLWB }, |
324 | { .option: "-mshstk" , OPTION_MASK_ISA_SHSTK }, |
325 | { .option: "-mmovdiri" , OPTION_MASK_ISA_MOVDIRI } |
326 | }; |
327 | |
328 | /* Return 1 if TRAIT NAME is present in the OpenMP context's |
329 | device trait set, return 0 if not present in any OpenMP context in the |
330 | whole translation unit, or -1 if not present in the current OpenMP context |
331 | but might be present in another OpenMP context in the same TU. */ |
332 | |
333 | int |
334 | ix86_omp_device_kind_arch_isa (enum omp_device_kind_arch_isa trait, |
335 | const char *name) |
336 | { |
337 | switch (trait) |
338 | { |
339 | case omp_device_kind: |
340 | return strcmp (s1: name, s2: "cpu" ) == 0; |
341 | case omp_device_arch: |
342 | if (strcmp (s1: name, s2: "x86" ) == 0) |
343 | return 1; |
344 | if (TARGET_64BIT) |
345 | { |
346 | if (TARGET_X32) |
347 | return strcmp (s1: name, s2: "x32" ) == 0; |
348 | else |
349 | return strcmp (s1: name, s2: "x86_64" ) == 0; |
350 | } |
351 | if (strcmp (s1: name, s2: "ia32" ) == 0 || strcmp (s1: name, s2: "i386" ) == 0) |
352 | return 1; |
353 | if (strcmp (s1: name, s2: "i486" ) == 0) |
354 | return ix86_arch != PROCESSOR_I386 ? 1 : -1; |
355 | if (strcmp (s1: name, s2: "i586" ) == 0) |
356 | return (ix86_arch != PROCESSOR_I386 |
357 | && ix86_arch != PROCESSOR_I486) ? 1 : -1; |
358 | if (strcmp (s1: name, s2: "i686" ) == 0) |
359 | return (ix86_arch != PROCESSOR_I386 |
360 | && ix86_arch != PROCESSOR_I486 |
361 | && ix86_arch != PROCESSOR_LAKEMONT |
362 | && ix86_arch != PROCESSOR_PENTIUM) ? 1 : -1; |
363 | return 0; |
364 | case omp_device_isa: |
365 | for (int i = 0; i < 2; i++) |
366 | { |
367 | struct ix86_target_opts *opts = i ? isa2_opts : isa_opts; |
368 | size_t nopts = i ? ARRAY_SIZE (isa2_opts) : ARRAY_SIZE (isa_opts); |
369 | HOST_WIDE_INT mask = i ? ix86_isa_flags2 : ix86_isa_flags; |
370 | for (size_t n = 0; n < nopts; n++) |
371 | { |
372 | /* Handle sse4 as an alias to sse4.2. */ |
373 | if (opts[n].mask == OPTION_MASK_ISA_SSE4_2) |
374 | { |
375 | if (strcmp (s1: name, s2: "sse4" ) == 0) |
376 | return (mask & opts[n].mask) != 0 ? 1 : -1; |
377 | } |
378 | if (strcmp (s1: name, s2: opts[n].option + 2) == 0) |
379 | return (mask & opts[n].mask) != 0 ? 1 : -1; |
380 | } |
381 | } |
382 | return 0; |
383 | default: |
384 | gcc_unreachable (); |
385 | } |
386 | } |
387 | |
388 | /* Return a string that documents the current -m options. The caller is |
389 | responsible for freeing the string. */ |
390 | |
391 | char * |
392 | ix86_target_string (HOST_WIDE_INT isa, HOST_WIDE_INT isa2, |
393 | int flags, int flags2, |
394 | const char *arch, const char *tune, |
395 | enum fpmath_unit fpmath, |
396 | enum prefer_vector_width pvw, |
397 | enum prefer_vector_width move_max, |
398 | enum prefer_vector_width store_max, |
399 | bool add_nl_p, bool add_abi_p) |
400 | { |
401 | /* Flag options. */ |
402 | static struct ix86_target_opts flag_opts[] = |
403 | { |
404 | { .option: "-m128bit-long-double" , MASK_128BIT_LONG_DOUBLE }, |
405 | { .option: "-mlong-double-128" , MASK_LONG_DOUBLE_128 }, |
406 | { .option: "-mlong-double-64" , MASK_LONG_DOUBLE_64 }, |
407 | { .option: "-m80387" , MASK_80387 }, |
408 | { .option: "-maccumulate-outgoing-args" , MASK_ACCUMULATE_OUTGOING_ARGS }, |
409 | { .option: "-malign-double" , MASK_ALIGN_DOUBLE }, |
410 | { .option: "-mcld" , MASK_CLD }, |
411 | { .option: "-mfp-ret-in-387" , MASK_FLOAT_RETURNS }, |
412 | { .option: "-mieee-fp" , MASK_IEEE_FP }, |
413 | { .option: "-minline-all-stringops" , MASK_INLINE_ALL_STRINGOPS }, |
414 | { .option: "-minline-stringops-dynamically" , MASK_INLINE_STRINGOPS_DYNAMICALLY }, |
415 | { .option: "-mms-bitfields" , MASK_MS_BITFIELD_LAYOUT }, |
416 | { .option: "-mno-align-stringops" , MASK_NO_ALIGN_STRINGOPS }, |
417 | { .option: "-mno-fancy-math-387" , MASK_NO_FANCY_MATH_387 }, |
418 | { .option: "-mno-push-args" , MASK_NO_PUSH_ARGS }, |
419 | { .option: "-mno-red-zone" , MASK_NO_RED_ZONE }, |
420 | { .option: "-momit-leaf-frame-pointer" , MASK_OMIT_LEAF_FRAME_POINTER }, |
421 | { .option: "-mrecip" , MASK_RECIP }, |
422 | { .option: "-mrtd" , MASK_RTD }, |
423 | { .option: "-msseregparm" , MASK_SSEREGPARM }, |
424 | { .option: "-mstack-arg-probe" , MASK_STACK_PROBE }, |
425 | { .option: "-mtls-direct-seg-refs" , MASK_TLS_DIRECT_SEG_REFS }, |
426 | { .option: "-mvect8-ret-in-mem" , MASK_VECT8_RETURNS }, |
427 | { .option: "-m8bit-idiv" , MASK_USE_8BIT_IDIV }, |
428 | { .option: "-mvzeroupper" , MASK_VZEROUPPER }, |
429 | { .option: "-mstv" , MASK_STV }, |
430 | { .option: "-mavx256-split-unaligned-load" , MASK_AVX256_SPLIT_UNALIGNED_LOAD }, |
431 | { .option: "-mavx256-split-unaligned-store" , MASK_AVX256_SPLIT_UNALIGNED_STORE }, |
432 | { .option: "-mcall-ms2sysv-xlogues" , MASK_CALL_MS2SYSV_XLOGUES }, |
433 | { .option: "-mrelax-cmpxchg-loop" , MASK_RELAX_CMPXCHG_LOOP } |
434 | }; |
435 | |
436 | /* Additional flag options. */ |
437 | static struct ix86_target_opts flag2_opts[] = |
438 | { |
439 | { .option: "-mgeneral-regs-only" , OPTION_MASK_GENERAL_REGS_ONLY } |
440 | }; |
441 | |
442 | const char *opts[ARRAY_SIZE (isa_opts) + ARRAY_SIZE (isa2_opts) |
443 | + ARRAY_SIZE (flag_opts) + ARRAY_SIZE (flag2_opts) + 6][2]; |
444 | |
445 | char isa_other[40]; |
446 | char isa2_other[40]; |
447 | char flags_other[40]; |
448 | char flags2_other[40]; |
449 | unsigned num = 0; |
450 | unsigned i, j; |
451 | char *ret; |
452 | char *ptr; |
453 | size_t len; |
454 | size_t line_len; |
455 | size_t sep_len; |
456 | const char *abi; |
457 | |
458 | memset (s: opts, c: '\0', n: sizeof (opts)); |
459 | |
460 | /* Add -march= option. */ |
461 | if (arch) |
462 | { |
463 | opts[num][0] = "-march=" ; |
464 | opts[num++][1] = arch; |
465 | } |
466 | |
467 | /* Add -mtune= option. */ |
468 | if (tune) |
469 | { |
470 | opts[num][0] = "-mtune=" ; |
471 | opts[num++][1] = tune; |
472 | } |
473 | |
474 | /* Add -m32/-m64/-mx32. */ |
475 | if (add_abi_p) |
476 | { |
477 | if ((isa & OPTION_MASK_ISA_64BIT) != 0) |
478 | { |
479 | if ((isa & OPTION_MASK_ABI_64) != 0) |
480 | abi = "-m64" ; |
481 | else |
482 | abi = "-mx32" ; |
483 | } |
484 | else |
485 | abi = "-m32" ; |
486 | opts[num++][0] = abi; |
487 | } |
488 | isa &= ~(OPTION_MASK_ISA_64BIT | OPTION_MASK_ABI_64 | OPTION_MASK_ABI_X32); |
489 | |
490 | /* Pick out the options in isa2 options. */ |
491 | for (i = 0; i < ARRAY_SIZE (isa2_opts); i++) |
492 | { |
493 | if ((isa2 & isa2_opts[i].mask) != 0) |
494 | { |
495 | opts[num++][0] = isa2_opts[i].option; |
496 | isa2 &= ~ isa2_opts[i].mask; |
497 | } |
498 | } |
499 | |
500 | if (isa2 && add_nl_p) |
501 | { |
502 | opts[num++][0] = isa2_other; |
503 | sprintf (s: isa2_other, format: "(other isa2: %#" HOST_WIDE_INT_PRINT "x)" , isa2); |
504 | } |
505 | |
506 | /* Pick out the options in isa options. */ |
507 | for (i = 0; i < ARRAY_SIZE (isa_opts); i++) |
508 | { |
509 | if ((isa & isa_opts[i].mask) != 0) |
510 | { |
511 | opts[num++][0] = isa_opts[i].option; |
512 | isa &= ~ isa_opts[i].mask; |
513 | } |
514 | } |
515 | |
516 | if (isa && add_nl_p) |
517 | { |
518 | opts[num++][0] = isa_other; |
519 | sprintf (s: isa_other, format: "(other isa: %#" HOST_WIDE_INT_PRINT "x)" , isa); |
520 | } |
521 | |
522 | /* Add flag options. */ |
523 | for (i = 0; i < ARRAY_SIZE (flag_opts); i++) |
524 | { |
525 | if ((flags & flag_opts[i].mask) != 0) |
526 | { |
527 | opts[num++][0] = flag_opts[i].option; |
528 | flags &= ~ flag_opts[i].mask; |
529 | } |
530 | } |
531 | |
532 | if (flags && add_nl_p) |
533 | { |
534 | opts[num++][0] = flags_other; |
535 | sprintf (s: flags_other, format: "(other flags: %#x)" , flags); |
536 | } |
537 | |
538 | /* Add additional flag options. */ |
539 | for (i = 0; i < ARRAY_SIZE (flag2_opts); i++) |
540 | { |
541 | if ((flags2 & flag2_opts[i].mask) != 0) |
542 | { |
543 | opts[num++][0] = flag2_opts[i].option; |
544 | flags2 &= ~ flag2_opts[i].mask; |
545 | } |
546 | } |
547 | |
548 | if (flags2 && add_nl_p) |
549 | { |
550 | opts[num++][0] = flags2_other; |
551 | sprintf (s: flags2_other, format: "(other flags2: %#x)" , flags2); |
552 | } |
553 | |
554 | /* Add -mfpmath= option. */ |
555 | if (fpmath) |
556 | { |
557 | opts[num][0] = "-mfpmath=" ; |
558 | switch ((int) fpmath) |
559 | { |
560 | case FPMATH_387: |
561 | opts[num++][1] = "387" ; |
562 | break; |
563 | |
564 | case FPMATH_SSE: |
565 | opts[num++][1] = "sse" ; |
566 | break; |
567 | |
568 | case FPMATH_387 | FPMATH_SSE: |
569 | opts[num++][1] = "sse+387" ; |
570 | break; |
571 | |
572 | default: |
573 | gcc_unreachable (); |
574 | } |
575 | } |
576 | |
577 | auto add_vector_width = [&opts, &num] (prefer_vector_width pvw, |
578 | const char *cmd) |
579 | { |
580 | opts[num][0] = cmd; |
581 | switch ((int) pvw) |
582 | { |
583 | case PVW_AVX128: |
584 | opts[num++][1] = "128" ; |
585 | break; |
586 | |
587 | case PVW_AVX256: |
588 | opts[num++][1] = "256" ; |
589 | break; |
590 | |
591 | case PVW_AVX512: |
592 | opts[num++][1] = "512" ; |
593 | break; |
594 | |
595 | default: |
596 | gcc_unreachable (); |
597 | } |
598 | }; |
599 | |
600 | /* Add -mprefer-vector-width= option. */ |
601 | if (pvw) |
602 | add_vector_width (pvw, "-mprefer-vector-width=" ); |
603 | |
604 | /* Add -mmove-max= option. */ |
605 | if (move_max) |
606 | add_vector_width (move_max, "-mmove-max=" ); |
607 | |
608 | /* Add -mstore-max= option. */ |
609 | if (store_max) |
610 | add_vector_width (store_max, "-mstore-max=" ); |
611 | |
612 | /* Any options? */ |
613 | if (num == 0) |
614 | return NULL; |
615 | |
616 | gcc_assert (num < ARRAY_SIZE (opts)); |
617 | |
618 | /* Size the string. */ |
619 | len = 0; |
620 | sep_len = (add_nl_p) ? 3 : 1; |
621 | for (i = 0; i < num; i++) |
622 | { |
623 | len += sep_len; |
624 | for (j = 0; j < 2; j++) |
625 | if (opts[i][j]) |
626 | len += strlen (s: opts[i][j]); |
627 | } |
628 | |
629 | /* Build the string. */ |
630 | ret = ptr = (char *) xmalloc (len); |
631 | line_len = 0; |
632 | |
633 | for (i = 0; i < num; i++) |
634 | { |
635 | size_t len2[2]; |
636 | |
637 | for (j = 0; j < 2; j++) |
638 | len2[j] = (opts[i][j]) ? strlen (s: opts[i][j]) : 0; |
639 | |
640 | if (i != 0) |
641 | { |
642 | *ptr++ = ' '; |
643 | line_len++; |
644 | |
645 | if (add_nl_p && line_len + len2[0] + len2[1] > 70) |
646 | { |
647 | *ptr++ = '\\'; |
648 | *ptr++ = '\n'; |
649 | line_len = 0; |
650 | } |
651 | } |
652 | |
653 | for (j = 0; j < 2; j++) |
654 | if (opts[i][j]) |
655 | { |
656 | memcpy (dest: ptr, src: opts[i][j], n: len2[j]); |
657 | ptr += len2[j]; |
658 | line_len += len2[j]; |
659 | } |
660 | } |
661 | |
662 | *ptr = '\0'; |
663 | gcc_assert (ret + len >= ptr); |
664 | |
665 | return ret; |
666 | } |
667 | |
668 | /* Function that is callable from the debugger to print the current |
669 | options. */ |
670 | void ATTRIBUTE_UNUSED |
671 | ix86_debug_options (void) |
672 | { |
673 | char *opts = ix86_target_string (ix86_isa_flags, ix86_isa_flags2, |
674 | target_flags, ix86_target_flags, |
675 | ix86_arch_string, ix86_tune_string, |
676 | ix86_fpmath, prefer_vector_width_type, |
677 | ix86_move_max, ix86_store_max, |
678 | add_nl_p: true, add_abi_p: true); |
679 | |
680 | if (opts) |
681 | { |
682 | fprintf (stderr, format: "%s\n\n" , opts); |
683 | free (ptr: opts); |
684 | } |
685 | else |
686 | fputs (s: "<no options>\n\n" , stderr); |
687 | |
688 | return; |
689 | } |
690 | |
691 | /* Save the current options */ |
692 | |
693 | void |
694 | ix86_function_specific_save (struct cl_target_option *ptr, |
695 | struct gcc_options *opts, |
696 | struct gcc_options */* opts_set */) |
697 | { |
698 | ptr->arch = ix86_arch; |
699 | ptr->schedule = ix86_schedule; |
700 | ptr->prefetch_sse = ix86_prefetch_sse; |
701 | ptr->tune = ix86_tune; |
702 | ptr->branch_cost = ix86_branch_cost; |
703 | ptr->tune_defaulted = ix86_tune_defaulted; |
704 | ptr->arch_specified = ix86_arch_specified; |
705 | ptr->x_ix86_apx_features = opts->x_ix86_apx_features; |
706 | ptr->x_ix86_isa_flags_explicit = opts->x_ix86_isa_flags_explicit; |
707 | ptr->x_ix86_isa_flags2_explicit = opts->x_ix86_isa_flags2_explicit; |
708 | ptr->x_recip_mask_explicit = opts->x_recip_mask_explicit; |
709 | ptr->x_ix86_arch_string = opts->x_ix86_arch_string; |
710 | ptr->x_ix86_tune_string = opts->x_ix86_tune_string; |
711 | ptr->x_ix86_asm_dialect = opts->x_ix86_asm_dialect; |
712 | ptr->x_ix86_branch_cost = opts->x_ix86_branch_cost; |
713 | ptr->x_ix86_dump_tunes = opts->x_ix86_dump_tunes; |
714 | ptr->x_ix86_force_align_arg_pointer = opts->x_ix86_force_align_arg_pointer; |
715 | ptr->x_ix86_force_drap = opts->x_ix86_force_drap; |
716 | ptr->x_ix86_recip_name = opts->x_ix86_recip_name; |
717 | ptr->x_ix86_section_threshold = opts->x_ix86_section_threshold; |
718 | ptr->x_ix86_sse2avx = opts->x_ix86_sse2avx; |
719 | ptr->x_ix86_stack_protector_guard = opts->x_ix86_stack_protector_guard; |
720 | ptr->x_ix86_stringop_alg = opts->x_ix86_stringop_alg; |
721 | ptr->x_ix86_tls_dialect = opts->x_ix86_tls_dialect; |
722 | ptr->x_ix86_tune_ctrl_string = opts->x_ix86_tune_ctrl_string; |
723 | ptr->x_ix86_tune_memcpy_strategy = opts->x_ix86_tune_memcpy_strategy; |
724 | ptr->x_ix86_tune_memset_strategy = opts->x_ix86_tune_memset_strategy; |
725 | ptr->x_ix86_tune_no_default = opts->x_ix86_tune_no_default; |
726 | |
727 | /* The fields are char but the variables are not; make sure the |
728 | values fit in the fields. */ |
729 | gcc_assert (ptr->arch == ix86_arch); |
730 | gcc_assert (ptr->schedule == ix86_schedule); |
731 | gcc_assert (ptr->tune == ix86_tune); |
732 | gcc_assert (ptr->branch_cost == ix86_branch_cost); |
733 | } |
734 | |
735 | /* Feature tests against the various architecture variations, used to create |
736 | ix86_arch_features based on the processor mask. */ |
737 | static unsigned HOST_WIDE_INT initial_ix86_arch_features[X86_ARCH_LAST] = { |
738 | /* X86_ARCH_CMOV: Conditional move was added for pentiumpro. */ |
739 | ~(m_386 | m_486 | m_PENT | m_LAKEMONT | m_K6), |
740 | |
741 | /* X86_ARCH_CMPXCHG: Compare and exchange was added for 80486. */ |
742 | ~m_386, |
743 | |
744 | /* X86_ARCH_CMPXCHG8B: Compare and exchange 8 bytes was added for pentium. */ |
745 | ~(m_386 | m_486), |
746 | |
747 | /* X86_ARCH_XADD: Exchange and add was added for 80486. */ |
748 | ~m_386, |
749 | |
750 | /* X86_ARCH_BSWAP: Byteswap was added for 80486. */ |
751 | ~m_386, |
752 | }; |
753 | |
754 | /* This table must be in sync with enum processor_type in i386.h. */ |
755 | static const struct processor_costs *processor_cost_table[] = |
756 | { |
757 | &generic_cost, |
758 | &i386_cost, |
759 | &i486_cost, |
760 | &pentium_cost, |
761 | &lakemont_cost, |
762 | &pentiumpro_cost, |
763 | &pentium4_cost, |
764 | &nocona_cost, |
765 | &core_cost, |
766 | &core_cost, |
767 | &core_cost, |
768 | &core_cost, |
769 | &atom_cost, |
770 | &slm_cost, |
771 | &slm_cost, |
772 | &slm_cost, |
773 | &tremont_cost, |
774 | &alderlake_cost, |
775 | &alderlake_cost, |
776 | &alderlake_cost, |
777 | &slm_cost, |
778 | &slm_cost, |
779 | &skylake_cost, |
780 | &skylake_cost, |
781 | &icelake_cost, |
782 | &icelake_cost, |
783 | &icelake_cost, |
784 | &skylake_cost, |
785 | &icelake_cost, |
786 | &skylake_cost, |
787 | &icelake_cost, |
788 | &alderlake_cost, |
789 | &icelake_cost, |
790 | &icelake_cost, |
791 | &icelake_cost, |
792 | &alderlake_cost, |
793 | &alderlake_cost, |
794 | &alderlake_cost, |
795 | &intel_cost, |
796 | &lujiazui_cost, |
797 | &yongfeng_cost, |
798 | &geode_cost, |
799 | &k6_cost, |
800 | &athlon_cost, |
801 | &k8_cost, |
802 | &amdfam10_cost, |
803 | &bdver_cost, |
804 | &bdver_cost, |
805 | &bdver_cost, |
806 | &bdver_cost, |
807 | &btver1_cost, |
808 | &btver2_cost, |
809 | &znver1_cost, |
810 | &znver2_cost, |
811 | &znver3_cost, |
812 | &znver4_cost |
813 | }; |
814 | |
815 | /* Guarantee that the array is aligned with enum processor_type. */ |
816 | STATIC_ASSERT (ARRAY_SIZE (processor_cost_table) == PROCESSOR_max); |
817 | |
818 | static bool |
819 | ix86_option_override_internal (bool main_args_p, |
820 | struct gcc_options *opts, |
821 | struct gcc_options *opts_set); |
822 | static void |
823 | set_ix86_tune_features (struct gcc_options *opts, |
824 | enum processor_type ix86_tune, bool dump); |
825 | |
826 | /* Restore the current options */ |
827 | |
828 | void |
829 | ix86_function_specific_restore (struct gcc_options *opts, |
830 | struct gcc_options */* opts_set */, |
831 | struct cl_target_option *ptr) |
832 | { |
833 | enum processor_type old_tune = ix86_tune; |
834 | enum processor_type old_arch = ix86_arch; |
835 | unsigned HOST_WIDE_INT ix86_arch_mask; |
836 | int i; |
837 | |
838 | /* We don't change -fPIC. */ |
839 | opts->x_flag_pic = flag_pic; |
840 | |
841 | ix86_arch = (enum processor_type) ptr->arch; |
842 | ix86_schedule = (enum attr_cpu) ptr->schedule; |
843 | ix86_tune = (enum processor_type) ptr->tune; |
844 | ix86_prefetch_sse = ptr->prefetch_sse; |
845 | ix86_tune_defaulted = ptr->tune_defaulted; |
846 | ix86_arch_specified = ptr->arch_specified; |
847 | opts->x_ix86_apx_features = ptr->x_ix86_apx_features; |
848 | opts->x_ix86_isa_flags_explicit = ptr->x_ix86_isa_flags_explicit; |
849 | opts->x_ix86_isa_flags2_explicit = ptr->x_ix86_isa_flags2_explicit; |
850 | opts->x_recip_mask_explicit = ptr->x_recip_mask_explicit; |
851 | opts->x_ix86_arch_string = ptr->x_ix86_arch_string; |
852 | opts->x_ix86_tune_string = ptr->x_ix86_tune_string; |
853 | opts->x_ix86_asm_dialect = ptr->x_ix86_asm_dialect; |
854 | opts->x_ix86_branch_cost = ptr->x_ix86_branch_cost; |
855 | opts->x_ix86_dump_tunes = ptr->x_ix86_dump_tunes; |
856 | opts->x_ix86_force_align_arg_pointer = ptr->x_ix86_force_align_arg_pointer; |
857 | opts->x_ix86_force_drap = ptr->x_ix86_force_drap; |
858 | opts->x_ix86_recip_name = ptr->x_ix86_recip_name; |
859 | opts->x_ix86_section_threshold = ptr->x_ix86_section_threshold; |
860 | opts->x_ix86_sse2avx = ptr->x_ix86_sse2avx; |
861 | opts->x_ix86_stack_protector_guard = ptr->x_ix86_stack_protector_guard; |
862 | opts->x_ix86_stringop_alg = ptr->x_ix86_stringop_alg; |
863 | opts->x_ix86_tls_dialect = ptr->x_ix86_tls_dialect; |
864 | opts->x_ix86_tune_ctrl_string = ptr->x_ix86_tune_ctrl_string; |
865 | opts->x_ix86_tune_memcpy_strategy = ptr->x_ix86_tune_memcpy_strategy; |
866 | opts->x_ix86_tune_memset_strategy = ptr->x_ix86_tune_memset_strategy; |
867 | opts->x_ix86_tune_no_default = ptr->x_ix86_tune_no_default; |
868 | ix86_tune_cost = processor_cost_table[ix86_tune]; |
869 | /* TODO: ix86_cost should be chosen at instruction or function granuality |
870 | so for cold code we use size_cost even in !optimize_size compilation. */ |
871 | if (opts->x_optimize_size) |
872 | ix86_cost = &ix86_size_cost; |
873 | else |
874 | ix86_cost = ix86_tune_cost; |
875 | |
876 | /* Recreate the arch feature tests if the arch changed */ |
877 | if (old_arch != ix86_arch) |
878 | { |
879 | ix86_arch_mask = HOST_WIDE_INT_1U << ix86_arch; |
880 | for (i = 0; i < X86_ARCH_LAST; ++i) |
881 | ix86_arch_features[i] |
882 | = !!(initial_ix86_arch_features[i] & ix86_arch_mask); |
883 | } |
884 | |
885 | /* Recreate the tune optimization tests */ |
886 | if (old_tune != ix86_tune) |
887 | set_ix86_tune_features (opts, ix86_tune, dump: false); |
888 | } |
889 | |
890 | /* Adjust target options after streaming them in. This is mainly about |
891 | reconciling them with global options. */ |
892 | |
893 | void |
894 | ix86_function_specific_post_stream_in (struct cl_target_option *ptr) |
895 | { |
896 | /* flag_pic is a global option, but ix86_cmodel is target saved option |
897 | partly computed from flag_pic. If flag_pic is on, adjust x_ix86_cmodel |
898 | for PIC, or error out. */ |
899 | if (flag_pic) |
900 | switch (ptr->x_ix86_cmodel) |
901 | { |
902 | case CM_SMALL: |
903 | ptr->x_ix86_cmodel = CM_SMALL_PIC; |
904 | break; |
905 | |
906 | case CM_MEDIUM: |
907 | ptr->x_ix86_cmodel = CM_MEDIUM_PIC; |
908 | break; |
909 | |
910 | case CM_LARGE: |
911 | ptr->x_ix86_cmodel = CM_LARGE_PIC; |
912 | break; |
913 | |
914 | case CM_KERNEL: |
915 | error ("code model %s does not support PIC mode" , "kernel" ); |
916 | break; |
917 | |
918 | default: |
919 | break; |
920 | } |
921 | else |
922 | switch (ptr->x_ix86_cmodel) |
923 | { |
924 | case CM_SMALL_PIC: |
925 | ptr->x_ix86_cmodel = CM_SMALL; |
926 | break; |
927 | |
928 | case CM_MEDIUM_PIC: |
929 | ptr->x_ix86_cmodel = CM_MEDIUM; |
930 | break; |
931 | |
932 | case CM_LARGE_PIC: |
933 | ptr->x_ix86_cmodel = CM_LARGE; |
934 | break; |
935 | |
936 | default: |
937 | break; |
938 | } |
939 | } |
940 | |
941 | /* Print the current options */ |
942 | |
943 | void |
944 | ix86_function_specific_print (FILE *file, int indent, |
945 | struct cl_target_option *ptr) |
946 | { |
947 | char *target_string |
948 | = ix86_target_string (isa: ptr->x_ix86_isa_flags, isa2: ptr->x_ix86_isa_flags2, |
949 | flags: ptr->x_target_flags, flags2: ptr->x_ix86_target_flags, |
950 | NULL, NULL, fpmath: ptr->x_ix86_fpmath, |
951 | pvw: ptr->x_prefer_vector_width_type, |
952 | move_max: ptr->x_ix86_move_max, store_max: ptr->x_ix86_store_max, |
953 | add_nl_p: false, add_abi_p: true); |
954 | |
955 | gcc_assert (ptr->arch < PROCESSOR_max); |
956 | fprintf (stream: file, format: "%*sarch = %d (%s)\n" , |
957 | indent, "" , |
958 | ptr->arch, processor_names[ptr->arch]); |
959 | |
960 | gcc_assert (ptr->tune < PROCESSOR_max); |
961 | fprintf (stream: file, format: "%*stune = %d (%s)\n" , |
962 | indent, "" , |
963 | ptr->tune, processor_names[ptr->tune]); |
964 | |
965 | fprintf (stream: file, format: "%*sbranch_cost = %d\n" , indent, "" , ptr->branch_cost); |
966 | |
967 | if (target_string) |
968 | { |
969 | fprintf (stream: file, format: "%*s%s\n" , indent, "" , target_string); |
970 | free (ptr: target_string); |
971 | } |
972 | } |
973 | |
974 | |
975 | /* Inner function to process the attribute((target(...))), take an argument and |
976 | set the current options from the argument. If we have a list, recursively go |
977 | over the list. */ |
978 | |
979 | static bool |
980 | ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[], |
981 | struct gcc_options *opts, |
982 | struct gcc_options *opts_set, |
983 | struct gcc_options *enum_opts_set, |
984 | bool target_clone_attr) |
985 | { |
986 | char *next_optstr; |
987 | bool ret = true; |
988 | |
989 | #define IX86_ATTR_ISA(S,O) { S, sizeof (S)-1, ix86_opt_isa, O, 0 } |
990 | #define IX86_ATTR_STR(S,O) { S, sizeof (S)-1, ix86_opt_str, O, 0 } |
991 | #define IX86_ATTR_ENUM(S,O) { S, sizeof (S)-1, ix86_opt_enum, O, 0 } |
992 | #define IX86_ATTR_YES(S,O,M) { S, sizeof (S)-1, ix86_opt_yes, O, M } |
993 | #define IX86_ATTR_NO(S,O,M) { S, sizeof (S)-1, ix86_opt_no, O, M } |
994 | #define IX86_ATTR_IX86_YES(S,O,M) \ |
995 | { S, sizeof (S)-1, ix86_opt_ix86_yes, O, M } |
996 | #define IX86_ATTR_IX86_NO(S,O,M) \ |
997 | { S, sizeof (S)-1, ix86_opt_ix86_no, O, M } |
998 | |
999 | enum ix86_opt_type |
1000 | { |
1001 | ix86_opt_unknown, |
1002 | ix86_opt_yes, |
1003 | ix86_opt_no, |
1004 | ix86_opt_ix86_yes, |
1005 | ix86_opt_ix86_no, |
1006 | ix86_opt_str, |
1007 | ix86_opt_enum, |
1008 | ix86_opt_isa |
1009 | }; |
1010 | |
1011 | static const struct |
1012 | { |
1013 | const char *string; |
1014 | size_t len; |
1015 | enum ix86_opt_type type; |
1016 | int opt; |
1017 | int mask; |
1018 | } attrs[] = { |
1019 | /* isa options */ |
1020 | IX86_ATTR_ISA ("pconfig" , OPT_mpconfig), |
1021 | IX86_ATTR_ISA ("wbnoinvd" , OPT_mwbnoinvd), |
1022 | IX86_ATTR_ISA ("sgx" , OPT_msgx), |
1023 | IX86_ATTR_ISA ("avx5124fmaps" , OPT_mavx5124fmaps), |
1024 | IX86_ATTR_ISA ("avx5124vnniw" , OPT_mavx5124vnniw), |
1025 | IX86_ATTR_ISA ("avx512vpopcntdq" , OPT_mavx512vpopcntdq), |
1026 | IX86_ATTR_ISA ("avx512vbmi2" , OPT_mavx512vbmi2), |
1027 | IX86_ATTR_ISA ("avx512vnni" , OPT_mavx512vnni), |
1028 | IX86_ATTR_ISA ("avx512bitalg" , OPT_mavx512bitalg), |
1029 | IX86_ATTR_ISA ("avx512vp2intersect" , OPT_mavx512vp2intersect), |
1030 | |
1031 | IX86_ATTR_ISA ("avx512vbmi" , OPT_mavx512vbmi), |
1032 | IX86_ATTR_ISA ("avx512ifma" , OPT_mavx512ifma), |
1033 | IX86_ATTR_ISA ("avx512vl" , OPT_mavx512vl), |
1034 | IX86_ATTR_ISA ("avx512bw" , OPT_mavx512bw), |
1035 | IX86_ATTR_ISA ("avx512dq" , OPT_mavx512dq), |
1036 | IX86_ATTR_ISA ("avx512er" , OPT_mavx512er), |
1037 | IX86_ATTR_ISA ("avx512pf" , OPT_mavx512pf), |
1038 | IX86_ATTR_ISA ("avx512cd" , OPT_mavx512cd), |
1039 | IX86_ATTR_ISA ("avx512f" , OPT_mavx512f), |
1040 | IX86_ATTR_ISA ("avx2" , OPT_mavx2), |
1041 | IX86_ATTR_ISA ("fma" , OPT_mfma), |
1042 | IX86_ATTR_ISA ("xop" , OPT_mxop), |
1043 | IX86_ATTR_ISA ("fma4" , OPT_mfma4), |
1044 | IX86_ATTR_ISA ("f16c" , OPT_mf16c), |
1045 | IX86_ATTR_ISA ("avx" , OPT_mavx), |
1046 | IX86_ATTR_ISA ("sse4" , OPT_msse4), |
1047 | IX86_ATTR_ISA ("sse4.2" , OPT_msse4_2), |
1048 | IX86_ATTR_ISA ("sse4.1" , OPT_msse4_1), |
1049 | IX86_ATTR_ISA ("sse4a" , OPT_msse4a), |
1050 | IX86_ATTR_ISA ("ssse3" , OPT_mssse3), |
1051 | IX86_ATTR_ISA ("sse3" , OPT_msse3), |
1052 | IX86_ATTR_ISA ("aes" , OPT_maes), |
1053 | IX86_ATTR_ISA ("sha" , OPT_msha), |
1054 | IX86_ATTR_ISA ("pclmul" , OPT_mpclmul), |
1055 | IX86_ATTR_ISA ("sse2" , OPT_msse2), |
1056 | IX86_ATTR_ISA ("sse" , OPT_msse), |
1057 | IX86_ATTR_ISA ("3dnowa" , OPT_m3dnowa), |
1058 | IX86_ATTR_ISA ("3dnow" , OPT_m3dnow), |
1059 | IX86_ATTR_ISA ("mmx" , OPT_mmmx), |
1060 | IX86_ATTR_ISA ("rtm" , OPT_mrtm), |
1061 | IX86_ATTR_ISA ("prfchw" , OPT_mprfchw), |
1062 | IX86_ATTR_ISA ("rdseed" , OPT_mrdseed), |
1063 | IX86_ATTR_ISA ("adx" , OPT_madx), |
1064 | IX86_ATTR_ISA ("prefetchwt1" , OPT_mprefetchwt1), |
1065 | IX86_ATTR_ISA ("clflushopt" , OPT_mclflushopt), |
1066 | IX86_ATTR_ISA ("xsaves" , OPT_mxsaves), |
1067 | IX86_ATTR_ISA ("xsavec" , OPT_mxsavec), |
1068 | IX86_ATTR_ISA ("xsaveopt" , OPT_mxsaveopt), |
1069 | IX86_ATTR_ISA ("xsave" , OPT_mxsave), |
1070 | IX86_ATTR_ISA ("abm" , OPT_mabm), |
1071 | IX86_ATTR_ISA ("bmi" , OPT_mbmi), |
1072 | IX86_ATTR_ISA ("bmi2" , OPT_mbmi2), |
1073 | IX86_ATTR_ISA ("lzcnt" , OPT_mlzcnt), |
1074 | IX86_ATTR_ISA ("tbm" , OPT_mtbm), |
1075 | IX86_ATTR_ISA ("popcnt" , OPT_mpopcnt), |
1076 | IX86_ATTR_ISA ("cx16" , OPT_mcx16), |
1077 | IX86_ATTR_ISA ("sahf" , OPT_msahf), |
1078 | IX86_ATTR_ISA ("movbe" , OPT_mmovbe), |
1079 | IX86_ATTR_ISA ("crc32" , OPT_mcrc32), |
1080 | IX86_ATTR_ISA ("fsgsbase" , OPT_mfsgsbase), |
1081 | IX86_ATTR_ISA ("rdrnd" , OPT_mrdrnd), |
1082 | IX86_ATTR_ISA ("mwaitx" , OPT_mmwaitx), |
1083 | IX86_ATTR_ISA ("mwait" , OPT_mmwait), |
1084 | IX86_ATTR_ISA ("clzero" , OPT_mclzero), |
1085 | IX86_ATTR_ISA ("pku" , OPT_mpku), |
1086 | IX86_ATTR_ISA ("lwp" , OPT_mlwp), |
1087 | IX86_ATTR_ISA ("hle" , OPT_mhle), |
1088 | IX86_ATTR_ISA ("fxsr" , OPT_mfxsr), |
1089 | IX86_ATTR_ISA ("clwb" , OPT_mclwb), |
1090 | IX86_ATTR_ISA ("rdpid" , OPT_mrdpid), |
1091 | IX86_ATTR_ISA ("gfni" , OPT_mgfni), |
1092 | IX86_ATTR_ISA ("shstk" , OPT_mshstk), |
1093 | IX86_ATTR_ISA ("vaes" , OPT_mvaes), |
1094 | IX86_ATTR_ISA ("vpclmulqdq" , OPT_mvpclmulqdq), |
1095 | IX86_ATTR_ISA ("movdiri" , OPT_mmovdiri), |
1096 | IX86_ATTR_ISA ("movdir64b" , OPT_mmovdir64b), |
1097 | IX86_ATTR_ISA ("waitpkg" , OPT_mwaitpkg), |
1098 | IX86_ATTR_ISA ("cldemote" , OPT_mcldemote), |
1099 | IX86_ATTR_ISA ("uintr" , OPT_muintr), |
1100 | IX86_ATTR_ISA ("ptwrite" , OPT_mptwrite), |
1101 | IX86_ATTR_ISA ("kl" , OPT_mkl), |
1102 | IX86_ATTR_ISA ("widekl" , OPT_mwidekl), |
1103 | IX86_ATTR_ISA ("avx512bf16" , OPT_mavx512bf16), |
1104 | IX86_ATTR_ISA ("enqcmd" , OPT_menqcmd), |
1105 | IX86_ATTR_ISA ("serialize" , OPT_mserialize), |
1106 | IX86_ATTR_ISA ("tsxldtrk" , OPT_mtsxldtrk), |
1107 | IX86_ATTR_ISA ("amx-tile" , OPT_mamx_tile), |
1108 | IX86_ATTR_ISA ("amx-int8" , OPT_mamx_int8), |
1109 | IX86_ATTR_ISA ("amx-bf16" , OPT_mamx_bf16), |
1110 | IX86_ATTR_ISA ("hreset" , OPT_mhreset), |
1111 | IX86_ATTR_ISA ("avxvnni" , OPT_mavxvnni), |
1112 | IX86_ATTR_ISA ("avx512fp16" , OPT_mavx512fp16), |
1113 | IX86_ATTR_ISA ("avxifma" , OPT_mavxifma), |
1114 | IX86_ATTR_ISA ("avxvnniint8" , OPT_mavxvnniint8), |
1115 | IX86_ATTR_ISA ("avxneconvert" , OPT_mavxneconvert), |
1116 | IX86_ATTR_ISA ("cmpccxadd" , OPT_mcmpccxadd), |
1117 | IX86_ATTR_ISA ("amx-fp16" , OPT_mamx_fp16), |
1118 | IX86_ATTR_ISA ("prefetchi" , OPT_mprefetchi), |
1119 | IX86_ATTR_ISA ("raoint" , OPT_mraoint), |
1120 | IX86_ATTR_ISA ("amx-complex" , OPT_mamx_complex), |
1121 | IX86_ATTR_ISA ("avxvnniint16" , OPT_mavxvnniint16), |
1122 | IX86_ATTR_ISA ("sm3" , OPT_msm3), |
1123 | IX86_ATTR_ISA ("sha512" , OPT_msha512), |
1124 | IX86_ATTR_ISA ("sm4" , OPT_msm4), |
1125 | IX86_ATTR_ISA ("apxf" , OPT_mapxf), |
1126 | IX86_ATTR_ISA ("evex512" , OPT_mevex512), |
1127 | IX86_ATTR_ISA ("usermsr" , OPT_musermsr), |
1128 | |
1129 | /* enum options */ |
1130 | IX86_ATTR_ENUM ("fpmath=" , OPT_mfpmath_), |
1131 | IX86_ATTR_ENUM ("prefer-vector-width=" , OPT_mprefer_vector_width_), |
1132 | |
1133 | /* string options */ |
1134 | IX86_ATTR_STR ("arch=" , IX86_FUNCTION_SPECIFIC_ARCH), |
1135 | IX86_ATTR_STR ("tune=" , IX86_FUNCTION_SPECIFIC_TUNE), |
1136 | |
1137 | /* flag options */ |
1138 | IX86_ATTR_YES ("cld" , |
1139 | OPT_mcld, |
1140 | MASK_CLD), |
1141 | |
1142 | IX86_ATTR_NO ("fancy-math-387" , |
1143 | OPT_mfancy_math_387, |
1144 | MASK_NO_FANCY_MATH_387), |
1145 | |
1146 | IX86_ATTR_YES ("ieee-fp" , |
1147 | OPT_mieee_fp, |
1148 | MASK_IEEE_FP), |
1149 | |
1150 | IX86_ATTR_YES ("inline-all-stringops" , |
1151 | OPT_minline_all_stringops, |
1152 | MASK_INLINE_ALL_STRINGOPS), |
1153 | |
1154 | IX86_ATTR_YES ("inline-stringops-dynamically" , |
1155 | OPT_minline_stringops_dynamically, |
1156 | MASK_INLINE_STRINGOPS_DYNAMICALLY), |
1157 | |
1158 | IX86_ATTR_NO ("align-stringops" , |
1159 | OPT_mno_align_stringops, |
1160 | MASK_NO_ALIGN_STRINGOPS), |
1161 | |
1162 | IX86_ATTR_YES ("recip" , |
1163 | OPT_mrecip, |
1164 | MASK_RECIP), |
1165 | |
1166 | IX86_ATTR_IX86_YES ("general-regs-only" , |
1167 | OPT_mgeneral_regs_only, |
1168 | OPTION_MASK_GENERAL_REGS_ONLY), |
1169 | |
1170 | IX86_ATTR_YES ("relax-cmpxchg-loop" , |
1171 | OPT_mrelax_cmpxchg_loop, |
1172 | MASK_RELAX_CMPXCHG_LOOP), |
1173 | }; |
1174 | |
1175 | location_t loc |
1176 | = fndecl == NULL ? UNKNOWN_LOCATION : DECL_SOURCE_LOCATION (fndecl); |
1177 | const char *attr_name = target_clone_attr ? "target_clone" : "target" ; |
1178 | |
1179 | /* If this is a list, recurse to get the options. */ |
1180 | if (TREE_CODE (args) == TREE_LIST) |
1181 | { |
1182 | for (; args; args = TREE_CHAIN (args)) |
1183 | if (TREE_VALUE (args) |
1184 | && !ix86_valid_target_attribute_inner_p (fndecl, TREE_VALUE (args), |
1185 | p_strings, opts, opts_set, |
1186 | enum_opts_set, |
1187 | target_clone_attr)) |
1188 | ret = false; |
1189 | |
1190 | return ret; |
1191 | } |
1192 | |
1193 | else if (TREE_CODE (args) != STRING_CST) |
1194 | { |
1195 | error_at (loc, "attribute %qs argument is not a string" , attr_name); |
1196 | return false; |
1197 | } |
1198 | |
1199 | /* Handle multiple arguments separated by commas. */ |
1200 | next_optstr = ASTRDUP (TREE_STRING_POINTER (args)); |
1201 | |
1202 | while (next_optstr && *next_optstr != '\0') |
1203 | { |
1204 | char *p = next_optstr; |
1205 | char *orig_p = p; |
1206 | char *comma = strchr (s: next_optstr, c: ','); |
1207 | size_t len, opt_len; |
1208 | int opt; |
1209 | bool opt_set_p; |
1210 | char ch; |
1211 | unsigned i; |
1212 | enum ix86_opt_type type = ix86_opt_unknown; |
1213 | int mask = 0; |
1214 | |
1215 | if (comma) |
1216 | { |
1217 | *comma = '\0'; |
1218 | len = comma - next_optstr; |
1219 | next_optstr = comma + 1; |
1220 | } |
1221 | else |
1222 | { |
1223 | len = strlen (s: p); |
1224 | next_optstr = NULL; |
1225 | } |
1226 | |
1227 | /* Recognize no-xxx. */ |
1228 | if (len > 3 && p[0] == 'n' && p[1] == 'o' && p[2] == '-') |
1229 | { |
1230 | opt_set_p = false; |
1231 | p += 3; |
1232 | len -= 3; |
1233 | } |
1234 | else |
1235 | opt_set_p = true; |
1236 | |
1237 | /* Find the option. */ |
1238 | ch = *p; |
1239 | opt = N_OPTS; |
1240 | for (i = 0; i < ARRAY_SIZE (attrs); i++) |
1241 | { |
1242 | type = attrs[i].type; |
1243 | opt_len = attrs[i].len; |
1244 | if (ch == attrs[i].string[0] |
1245 | && ((type != ix86_opt_str && type != ix86_opt_enum) |
1246 | ? len == opt_len |
1247 | : len > opt_len) |
1248 | && memcmp (s1: p, s2: attrs[i].string, n: opt_len) == 0) |
1249 | { |
1250 | opt = attrs[i].opt; |
1251 | mask = attrs[i].mask; |
1252 | break; |
1253 | } |
1254 | } |
1255 | |
1256 | /* Process the option. */ |
1257 | if (opt == N_OPTS) |
1258 | { |
1259 | error_at (loc, "attribute %qs argument %qs is unknown" , |
1260 | attr_name, orig_p); |
1261 | ret = false; |
1262 | } |
1263 | |
1264 | else if (type == ix86_opt_isa) |
1265 | { |
1266 | struct cl_decoded_option decoded; |
1267 | |
1268 | generate_option (opt_index: opt, NULL, value: opt_set_p, CL_TARGET, decoded: &decoded); |
1269 | ix86_handle_option (opts, opts_set, |
1270 | decoded: &decoded, loc: input_location); |
1271 | } |
1272 | |
1273 | else if (type == ix86_opt_yes || type == ix86_opt_no) |
1274 | { |
1275 | if (type == ix86_opt_no) |
1276 | opt_set_p = !opt_set_p; |
1277 | |
1278 | if (opt_set_p) |
1279 | opts->x_target_flags |= mask; |
1280 | else |
1281 | opts->x_target_flags &= ~mask; |
1282 | } |
1283 | |
1284 | else if (type == ix86_opt_ix86_yes || type == ix86_opt_ix86_no) |
1285 | { |
1286 | if (mask == OPTION_MASK_GENERAL_REGS_ONLY) |
1287 | { |
1288 | if (!opt_set_p) |
1289 | { |
1290 | error_at (loc, "pragma or attribute %<target(\"%s\")%> " |
1291 | "does not allow a negated form" , p); |
1292 | return false; |
1293 | } |
1294 | |
1295 | if (type != ix86_opt_ix86_yes) |
1296 | gcc_unreachable (); |
1297 | |
1298 | opts->x_ix86_target_flags |= mask; |
1299 | |
1300 | struct cl_decoded_option decoded; |
1301 | generate_option (opt_index: opt, NULL, value: opt_set_p, CL_TARGET, |
1302 | decoded: &decoded); |
1303 | ix86_handle_option (opts, opts_set, decoded: &decoded, |
1304 | loc: input_location); |
1305 | } |
1306 | else |
1307 | { |
1308 | if (type == ix86_opt_ix86_no) |
1309 | opt_set_p = !opt_set_p; |
1310 | |
1311 | if (opt_set_p) |
1312 | opts->x_ix86_target_flags |= mask; |
1313 | else |
1314 | opts->x_ix86_target_flags &= ~mask; |
1315 | } |
1316 | } |
1317 | |
1318 | else if (type == ix86_opt_str) |
1319 | { |
1320 | if (p_strings[opt]) |
1321 | { |
1322 | error_at (loc, "attribute value %qs was already specified " |
1323 | "in %qs attribute" , orig_p, attr_name); |
1324 | ret = false; |
1325 | } |
1326 | else |
1327 | { |
1328 | p_strings[opt] = xstrdup (p + opt_len); |
1329 | if (opt == IX86_FUNCTION_SPECIFIC_ARCH) |
1330 | { |
1331 | /* If arch= is set, clear all bits in x_ix86_isa_flags, |
1332 | except for ISA_64BIT, ABI_64, ABI_X32, and CODE16 |
1333 | and all bits in x_ix86_isa_flags2. */ |
1334 | opts->x_ix86_isa_flags &= (OPTION_MASK_ISA_64BIT |
1335 | | OPTION_MASK_ABI_64 |
1336 | | OPTION_MASK_ABI_X32 |
1337 | | OPTION_MASK_CODE16); |
1338 | opts->x_ix86_isa_flags_explicit &= (OPTION_MASK_ISA_64BIT |
1339 | | OPTION_MASK_ABI_64 |
1340 | | OPTION_MASK_ABI_X32 |
1341 | | OPTION_MASK_CODE16); |
1342 | opts->x_ix86_isa_flags2 = 0; |
1343 | opts->x_ix86_isa_flags2_explicit = 0; |
1344 | } |
1345 | } |
1346 | } |
1347 | |
1348 | else if (type == ix86_opt_enum) |
1349 | { |
1350 | bool arg_ok; |
1351 | int value; |
1352 | |
1353 | arg_ok = opt_enum_arg_to_value (opt_index: opt, arg: p + opt_len, value: &value, CL_TARGET); |
1354 | if (arg_ok) |
1355 | set_option (opts, opts_set: enum_opts_set, opt_index: opt, value, |
1356 | arg: p + opt_len, kind: DK_UNSPECIFIED, loc: input_location, |
1357 | dc: global_dc); |
1358 | else |
1359 | { |
1360 | error_at (loc, "attribute value %qs is unknown in %qs attribute" , |
1361 | orig_p, attr_name); |
1362 | ret = false; |
1363 | } |
1364 | } |
1365 | |
1366 | else |
1367 | gcc_unreachable (); |
1368 | } |
1369 | |
1370 | return ret; |
1371 | } |
1372 | |
1373 | /* Release allocated strings. */ |
1374 | static void |
1375 | release_options_strings (char **option_strings) |
1376 | { |
1377 | /* Free up memory allocated to hold the strings */ |
1378 | for (unsigned i = 0; i < IX86_FUNCTION_SPECIFIC_MAX; i++) |
1379 | free (ptr: option_strings[i]); |
1380 | } |
1381 | |
1382 | /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */ |
1383 | |
1384 | tree |
1385 | ix86_valid_target_attribute_tree (tree fndecl, tree args, |
1386 | struct gcc_options *opts, |
1387 | struct gcc_options *opts_set, |
1388 | bool target_clone_attr) |
1389 | { |
1390 | const char *orig_arch_string = opts->x_ix86_arch_string; |
1391 | const char *orig_tune_string = opts->x_ix86_tune_string; |
1392 | enum fpmath_unit orig_fpmath_set = opts_set->x_ix86_fpmath; |
1393 | enum prefer_vector_width orig_pvw_set = opts_set->x_prefer_vector_width_type; |
1394 | enum prefer_vector_width orig_ix86_move_max_set |
1395 | = opts_set->x_ix86_move_max; |
1396 | enum prefer_vector_width orig_ix86_store_max_set |
1397 | = opts_set->x_ix86_store_max; |
1398 | int orig_tune_defaulted = ix86_tune_defaulted; |
1399 | int orig_arch_specified = ix86_arch_specified; |
1400 | char *option_strings[IX86_FUNCTION_SPECIFIC_MAX] = { NULL, NULL }; |
1401 | tree t = NULL_TREE; |
1402 | struct cl_target_option *def |
1403 | = TREE_TARGET_OPTION (target_option_default_node); |
1404 | struct gcc_options enum_opts_set; |
1405 | |
1406 | memset (s: &enum_opts_set, c: 0, n: sizeof (enum_opts_set)); |
1407 | |
1408 | /* Process each of the options on the chain. */ |
1409 | if (!ix86_valid_target_attribute_inner_p (fndecl, args, p_strings: option_strings, opts, |
1410 | opts_set, enum_opts_set: &enum_opts_set, |
1411 | target_clone_attr)) |
1412 | return error_mark_node; |
1413 | |
1414 | /* If the changed options are different from the default, rerun |
1415 | ix86_option_override_internal, and then save the options away. |
1416 | The string options are attribute options, and will be undone |
1417 | when we copy the save structure. */ |
1418 | if (opts->x_ix86_isa_flags != def->x_ix86_isa_flags |
1419 | || opts->x_ix86_isa_flags2 != def->x_ix86_isa_flags2 |
1420 | || opts->x_target_flags != def->x_target_flags |
1421 | || option_strings[IX86_FUNCTION_SPECIFIC_ARCH] |
1422 | || option_strings[IX86_FUNCTION_SPECIFIC_TUNE] |
1423 | || enum_opts_set.x_ix86_fpmath |
1424 | || enum_opts_set.x_prefer_vector_width_type) |
1425 | { |
1426 | /* If we are using the default tune= or arch=, undo the string assigned, |
1427 | and use the default. */ |
1428 | if (option_strings[IX86_FUNCTION_SPECIFIC_ARCH]) |
1429 | opts->x_ix86_arch_string |
1430 | = ggc_strdup (option_strings[IX86_FUNCTION_SPECIFIC_ARCH]); |
1431 | else if (!orig_arch_specified) |
1432 | opts->x_ix86_arch_string = NULL; |
1433 | |
1434 | if (option_strings[IX86_FUNCTION_SPECIFIC_TUNE]) |
1435 | opts->x_ix86_tune_string |
1436 | = ggc_strdup (option_strings[IX86_FUNCTION_SPECIFIC_TUNE]); |
1437 | /* If we have explicit arch string and no tune string specified, set |
1438 | tune_string to NULL and later it will be overriden by arch_string |
1439 | so target clones can get proper optimization. */ |
1440 | else if (option_strings[IX86_FUNCTION_SPECIFIC_ARCH] |
1441 | || orig_tune_defaulted) |
1442 | opts->x_ix86_tune_string = NULL; |
1443 | |
1444 | /* If fpmath= is not set, and we now have sse2 on 32-bit, use it. */ |
1445 | if (enum_opts_set.x_ix86_fpmath) |
1446 | opts_set->x_ix86_fpmath = (enum fpmath_unit) 1; |
1447 | if (enum_opts_set.x_prefer_vector_width_type) |
1448 | opts_set->x_prefer_vector_width_type = (enum prefer_vector_width) 1; |
1449 | |
1450 | /* Do any overrides, such as arch=xxx, or tune=xxx support. */ |
1451 | bool r = ix86_option_override_internal (main_args_p: false, opts, opts_set); |
1452 | if (!r) |
1453 | { |
1454 | release_options_strings (option_strings); |
1455 | return error_mark_node; |
1456 | } |
1457 | |
1458 | /* Add any builtin functions with the new isa if any. */ |
1459 | ix86_add_new_builtins (isa: opts->x_ix86_isa_flags, isa2: opts->x_ix86_isa_flags2); |
1460 | |
1461 | enum excess_precision orig_ix86_excess_precision |
1462 | = opts->x_ix86_excess_precision; |
1463 | bool orig_ix86_unsafe_math_optimizations |
1464 | = opts->x_ix86_unsafe_math_optimizations; |
1465 | opts->x_ix86_excess_precision = opts->x_flag_excess_precision; |
1466 | opts->x_ix86_unsafe_math_optimizations |
1467 | = opts->x_flag_unsafe_math_optimizations; |
1468 | |
1469 | /* Save the current options unless we are validating options for |
1470 | #pragma. */ |
1471 | t = build_target_option_node (opts, opts_set); |
1472 | |
1473 | opts->x_ix86_arch_string = orig_arch_string; |
1474 | opts->x_ix86_tune_string = orig_tune_string; |
1475 | opts_set->x_ix86_fpmath = orig_fpmath_set; |
1476 | opts_set->x_prefer_vector_width_type = orig_pvw_set; |
1477 | opts_set->x_ix86_move_max = orig_ix86_move_max_set; |
1478 | opts_set->x_ix86_store_max = orig_ix86_store_max_set; |
1479 | opts->x_ix86_excess_precision = orig_ix86_excess_precision; |
1480 | opts->x_ix86_unsafe_math_optimizations |
1481 | = orig_ix86_unsafe_math_optimizations; |
1482 | |
1483 | release_options_strings (option_strings); |
1484 | } |
1485 | |
1486 | return t; |
1487 | } |
1488 | |
1489 | static GTY(()) tree target_attribute_cache[3]; |
1490 | |
1491 | /* Hook to validate attribute((target("string"))). */ |
1492 | |
1493 | bool |
1494 | ix86_valid_target_attribute_p (tree fndecl, |
1495 | tree ARG_UNUSED (name), |
1496 | tree args, |
1497 | int flags) |
1498 | { |
1499 | struct gcc_options func_options, func_options_set; |
1500 | tree new_target, new_optimize; |
1501 | bool ret = true; |
1502 | |
1503 | /* attribute((target("default"))) does nothing, beyond |
1504 | affecting multi-versioning. */ |
1505 | if (TREE_VALUE (args) |
1506 | && TREE_CODE (TREE_VALUE (args)) == STRING_CST |
1507 | && TREE_CHAIN (args) == NULL_TREE |
1508 | && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), s2: "default" ) == 0) |
1509 | return true; |
1510 | |
1511 | if ((DECL_FUNCTION_SPECIFIC_TARGET (fndecl) == target_attribute_cache[1] |
1512 | || DECL_FUNCTION_SPECIFIC_TARGET (fndecl) == NULL_TREE) |
1513 | && (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) |
1514 | == target_attribute_cache[2] |
1515 | || DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) == NULL_TREE) |
1516 | && simple_cst_list_equal (args, target_attribute_cache[0])) |
1517 | { |
1518 | DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = target_attribute_cache[1]; |
1519 | DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) |
1520 | = target_attribute_cache[2]; |
1521 | return true; |
1522 | } |
1523 | |
1524 | tree old_optimize = build_optimization_node (opts: &global_options, |
1525 | opts_set: &global_options_set); |
1526 | |
1527 | /* Get the optimization options of the current function. */ |
1528 | tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); |
1529 | |
1530 | if (!func_optimize) |
1531 | func_optimize = old_optimize; |
1532 | |
1533 | /* Init func_options. */ |
1534 | memset (s: &func_options, c: 0, n: sizeof (func_options)); |
1535 | init_options_struct (opts: &func_options, NULL); |
1536 | lang_hooks.init_options_struct (&func_options); |
1537 | memset (s: &func_options_set, c: 0, n: sizeof (func_options_set)); |
1538 | |
1539 | cl_optimization_restore (&func_options, &func_options_set, |
1540 | TREE_OPTIMIZATION (func_optimize)); |
1541 | |
1542 | /* Initialize func_options to the default before its target options can |
1543 | be set. */ |
1544 | tree old_target = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); |
1545 | if (old_target == NULL_TREE) |
1546 | old_target = target_option_default_node; |
1547 | cl_target_option_restore (&func_options, &func_options_set, |
1548 | TREE_TARGET_OPTION (old_target)); |
1549 | |
1550 | /* FLAGS == 1 is used for target_clones attribute. */ |
1551 | new_target |
1552 | = ix86_valid_target_attribute_tree (fndecl, args, opts: &func_options, |
1553 | opts_set: &func_options_set, target_clone_attr: flags == 1); |
1554 | |
1555 | new_optimize = build_optimization_node (opts: &func_options, opts_set: &func_options_set); |
1556 | |
1557 | if (new_target == error_mark_node) |
1558 | ret = false; |
1559 | |
1560 | else if (new_target) |
1561 | { |
1562 | if (DECL_FUNCTION_SPECIFIC_TARGET (fndecl) == NULL_TREE |
1563 | && DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) == NULL_TREE) |
1564 | { |
1565 | target_attribute_cache[0] = copy_list (args); |
1566 | target_attribute_cache[1] = new_target; |
1567 | target_attribute_cache[2] |
1568 | = old_optimize != new_optimize ? new_optimize : NULL_TREE; |
1569 | } |
1570 | |
1571 | DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target; |
1572 | |
1573 | if (old_optimize != new_optimize) |
1574 | DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize; |
1575 | } |
1576 | |
1577 | return ret; |
1578 | } |
1579 | |
1580 | const char *stringop_alg_names[] = { |
1581 | #define DEF_ALG(alg, name) #name, |
1582 | #include "stringop.def" |
1583 | #undef DEF_ALG |
1584 | }; |
1585 | |
1586 | /* Parse parameter string passed to -mmemcpy-strategy= or -mmemset-strategy=. |
1587 | The string is of the following form (or comma separated list of it): |
1588 | |
1589 | strategy_alg:max_size:[align|noalign] |
1590 | |
1591 | where the full size range for the strategy is either [0, max_size] or |
1592 | [min_size, max_size], in which min_size is the max_size + 1 of the |
1593 | preceding range. The last size range must have max_size == -1. |
1594 | |
1595 | Examples: |
1596 | |
1597 | 1. |
1598 | -mmemcpy-strategy=libcall:-1:noalign |
1599 | |
1600 | this is equivalent to (for known size memcpy) -mstringop-strategy=libcall |
1601 | |
1602 | |
1603 | 2. |
1604 | -mmemset-strategy=rep_8byte:16:noalign,vector_loop:2048:align,libcall:-1:noalign |
1605 | |
1606 | This is to tell the compiler to use the following strategy for memset |
1607 | 1) when the expected size is between [1, 16], use rep_8byte strategy; |
1608 | 2) when the size is between [17, 2048], use vector_loop; |
1609 | 3) when the size is > 2048, use libcall. */ |
1610 | |
1611 | struct stringop_size_range |
1612 | { |
1613 | int max; |
1614 | stringop_alg alg; |
1615 | bool noalign; |
1616 | }; |
1617 | |
1618 | static void |
1619 | ix86_parse_stringop_strategy_string (char *strategy_str, bool is_memset) |
1620 | { |
1621 | const struct stringop_algs *default_algs; |
1622 | stringop_size_range input_ranges[MAX_STRINGOP_ALGS]; |
1623 | char *curr_range_str, *next_range_str; |
1624 | const char *opt = is_memset ? "-mmemset_strategy=" : "-mmemcpy_strategy=" ; |
1625 | int i = 0, n = 0; |
1626 | |
1627 | if (is_memset) |
1628 | default_algs = &ix86_cost->memset[TARGET_64BIT != 0]; |
1629 | else |
1630 | default_algs = &ix86_cost->memcpy[TARGET_64BIT != 0]; |
1631 | |
1632 | curr_range_str = strategy_str; |
1633 | |
1634 | do |
1635 | { |
1636 | int maxs; |
1637 | char alg_name[128]; |
1638 | char align[16]; |
1639 | next_range_str = strchr (s: curr_range_str, c: ','); |
1640 | if (next_range_str) |
1641 | *next_range_str++ = '\0'; |
1642 | |
1643 | if (sscanf (s: curr_range_str, format: "%20[^:]:%d:%10s" , alg_name, &maxs, |
1644 | align) != 3) |
1645 | { |
1646 | error ("wrong argument %qs to option %qs" , curr_range_str, opt); |
1647 | return; |
1648 | } |
1649 | |
1650 | if (n > 0 && (maxs < (input_ranges[n - 1].max + 1) && maxs != -1)) |
1651 | { |
1652 | error ("size ranges of option %qs should be increasing" , opt); |
1653 | return; |
1654 | } |
1655 | |
1656 | for (i = 0; i < last_alg; i++) |
1657 | if (!strcmp (s1: alg_name, s2: stringop_alg_names[i])) |
1658 | break; |
1659 | |
1660 | if (i == last_alg) |
1661 | { |
1662 | error ("wrong strategy name %qs specified for option %qs" , |
1663 | alg_name, opt); |
1664 | |
1665 | auto_vec <const char *> candidates; |
1666 | for (i = 0; i < last_alg; i++) |
1667 | if ((stringop_alg) i != rep_prefix_8_byte || TARGET_64BIT) |
1668 | candidates.safe_push (obj: stringop_alg_names[i]); |
1669 | |
1670 | char *s; |
1671 | const char *hint |
1672 | = candidates_list_and_hint (arg: alg_name, str&: s, candidates); |
1673 | if (hint) |
1674 | inform (input_location, |
1675 | "valid arguments to %qs are: %s; did you mean %qs?" , |
1676 | opt, s, hint); |
1677 | else |
1678 | inform (input_location, "valid arguments to %qs are: %s" , |
1679 | opt, s); |
1680 | XDELETEVEC (s); |
1681 | return; |
1682 | } |
1683 | |
1684 | if ((stringop_alg) i == rep_prefix_8_byte |
1685 | && !TARGET_64BIT) |
1686 | { |
1687 | /* rep; movq isn't available in 32-bit code. */ |
1688 | error ("strategy name %qs specified for option %qs " |
1689 | "not supported for 32-bit code" , alg_name, opt); |
1690 | return; |
1691 | } |
1692 | |
1693 | input_ranges[n].max = maxs; |
1694 | input_ranges[n].alg = (stringop_alg) i; |
1695 | if (!strcmp (s1: align, s2: "align" )) |
1696 | input_ranges[n].noalign = false; |
1697 | else if (!strcmp (s1: align, s2: "noalign" )) |
1698 | input_ranges[n].noalign = true; |
1699 | else |
1700 | { |
1701 | error ("unknown alignment %qs specified for option %qs" , align, opt); |
1702 | return; |
1703 | } |
1704 | n++; |
1705 | curr_range_str = next_range_str; |
1706 | } |
1707 | while (curr_range_str); |
1708 | |
1709 | if (input_ranges[n - 1].max != -1) |
1710 | { |
1711 | error ("the max value for the last size range should be -1" |
1712 | " for option %qs" , opt); |
1713 | return; |
1714 | } |
1715 | |
1716 | if (n > MAX_STRINGOP_ALGS) |
1717 | { |
1718 | error ("too many size ranges specified in option %qs" , opt); |
1719 | return; |
1720 | } |
1721 | |
1722 | /* Now override the default algs array. */ |
1723 | for (i = 0; i < n; i++) |
1724 | { |
1725 | *const_cast<int *>(&default_algs->size[i].max) = input_ranges[i].max; |
1726 | *const_cast<stringop_alg *>(&default_algs->size[i].alg) |
1727 | = input_ranges[i].alg; |
1728 | *const_cast<int *>(&default_algs->size[i].noalign) |
1729 | = input_ranges[i].noalign; |
1730 | } |
1731 | } |
1732 | |
1733 | |
1734 | /* parse -mtune-ctrl= option. When DUMP is true, |
1735 | print the features that are explicitly set. */ |
1736 | |
1737 | static void |
1738 | parse_mtune_ctrl_str (struct gcc_options *opts, bool dump) |
1739 | { |
1740 | if (!opts->x_ix86_tune_ctrl_string) |
1741 | return; |
1742 | |
1743 | char *next_feature_string = NULL; |
1744 | char *curr_feature_string = xstrdup (opts->x_ix86_tune_ctrl_string); |
1745 | char *orig = curr_feature_string; |
1746 | int i; |
1747 | do |
1748 | { |
1749 | bool clear = false; |
1750 | |
1751 | next_feature_string = strchr (s: curr_feature_string, c: ','); |
1752 | if (next_feature_string) |
1753 | *next_feature_string++ = '\0'; |
1754 | if (*curr_feature_string == '^') |
1755 | { |
1756 | curr_feature_string++; |
1757 | clear = true; |
1758 | } |
1759 | |
1760 | if (!strcmp (s1: curr_feature_string, s2: "use_gather" )) |
1761 | { |
1762 | ix86_tune_features[X86_TUNE_USE_GATHER_2PARTS] = !clear; |
1763 | ix86_tune_features[X86_TUNE_USE_GATHER_4PARTS] = !clear; |
1764 | ix86_tune_features[X86_TUNE_USE_GATHER_8PARTS] = !clear; |
1765 | if (dump) |
1766 | fprintf (stderr, format: "Explicitly %s features use_gather_2parts," |
1767 | " use_gather_4parts, use_gather_8parts\n" , |
1768 | clear ? "clear" : "set" ); |
1769 | |
1770 | } |
1771 | else if (!strcmp (s1: curr_feature_string, s2: "use_scatter" )) |
1772 | { |
1773 | ix86_tune_features[X86_TUNE_USE_SCATTER_2PARTS] = !clear; |
1774 | ix86_tune_features[X86_TUNE_USE_SCATTER_4PARTS] = !clear; |
1775 | ix86_tune_features[X86_TUNE_USE_SCATTER_8PARTS] = !clear; |
1776 | if (dump) |
1777 | fprintf (stderr, format: "Explicitly %s features use_scatter_2parts," |
1778 | " use_scatter_4parts, use_scatter_8parts\n" , |
1779 | clear ? "clear" : "set" ); |
1780 | } |
1781 | else |
1782 | { |
1783 | for (i = 0; i < X86_TUNE_LAST; i++) |
1784 | { |
1785 | if (!strcmp (s1: curr_feature_string, s2: ix86_tune_feature_names[i])) |
1786 | { |
1787 | ix86_tune_features[i] = !clear; |
1788 | if (dump) |
1789 | fprintf (stderr, format: "Explicitly %s feature %s\n" , |
1790 | clear ? "clear" : "set" , ix86_tune_feature_names[i]); |
1791 | break; |
1792 | } |
1793 | } |
1794 | |
1795 | if (i == X86_TUNE_LAST) |
1796 | error ("unknown parameter to option %<-mtune-ctrl%>: %s" , |
1797 | clear ? curr_feature_string - 1 : curr_feature_string); |
1798 | } |
1799 | curr_feature_string = next_feature_string; |
1800 | } |
1801 | while (curr_feature_string); |
1802 | free (ptr: orig); |
1803 | } |
1804 | |
1805 | /* Helper function to set ix86_tune_features. IX86_TUNE is the |
1806 | processor type. */ |
1807 | |
1808 | static void |
1809 | set_ix86_tune_features (struct gcc_options *opts, |
1810 | enum processor_type ix86_tune, bool dump) |
1811 | { |
1812 | unsigned HOST_WIDE_INT ix86_tune_mask = HOST_WIDE_INT_1U << ix86_tune; |
1813 | int i; |
1814 | |
1815 | for (i = 0; i < X86_TUNE_LAST; ++i) |
1816 | { |
1817 | if (ix86_tune_no_default) |
1818 | ix86_tune_features[i] = 0; |
1819 | else |
1820 | ix86_tune_features[i] |
1821 | = !!(initial_ix86_tune_features[i] & ix86_tune_mask); |
1822 | } |
1823 | |
1824 | if (dump) |
1825 | { |
1826 | fprintf (stderr, format: "List of x86 specific tuning parameter names:\n" ); |
1827 | for (i = 0; i < X86_TUNE_LAST; i++) |
1828 | fprintf (stderr, format: "%s : %s\n" , ix86_tune_feature_names[i], |
1829 | ix86_tune_features[i] ? "on" : "off" ); |
1830 | } |
1831 | |
1832 | parse_mtune_ctrl_str (opts, dump); |
1833 | } |
1834 | |
1835 | |
1836 | /* Default align_* from the processor table. */ |
1837 | |
1838 | static void |
1839 | ix86_default_align (struct gcc_options *opts) |
1840 | { |
1841 | /* -falign-foo without argument: supply one. */ |
1842 | if (opts->x_flag_align_loops && !opts->x_str_align_loops) |
1843 | opts->x_str_align_loops = processor_cost_table[ix86_tune]->align_loop; |
1844 | if (opts->x_flag_align_jumps && !opts->x_str_align_jumps) |
1845 | opts->x_str_align_jumps = processor_cost_table[ix86_tune]->align_jump; |
1846 | if (opts->x_flag_align_labels && !opts->x_str_align_labels) |
1847 | opts->x_str_align_labels = processor_cost_table[ix86_tune]->align_label; |
1848 | if (opts->x_flag_align_functions && !opts->x_str_align_functions) |
1849 | opts->x_str_align_functions = processor_cost_table[ix86_tune]->align_func; |
1850 | } |
1851 | |
1852 | #ifndef USE_IX86_FRAME_POINTER |
1853 | #define USE_IX86_FRAME_POINTER 0 |
1854 | #endif |
1855 | |
1856 | /* (Re)compute option overrides affected by optimization levels in |
1857 | target-specific ways. */ |
1858 | |
1859 | static void |
1860 | ix86_recompute_optlev_based_flags (struct gcc_options *opts, |
1861 | struct gcc_options *opts_set) |
1862 | { |
1863 | /* Set the default values for switches whose default depends on TARGET_64BIT |
1864 | in case they weren't overwritten by command line options. */ |
1865 | if (TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
1866 | { |
1867 | if (opts->x_optimize >= 1) |
1868 | SET_OPTION_IF_UNSET (opts, opts_set, flag_omit_frame_pointer, |
1869 | !USE_IX86_FRAME_POINTER); |
1870 | if (opts->x_flag_asynchronous_unwind_tables |
1871 | && TARGET_64BIT_MS_ABI) |
1872 | SET_OPTION_IF_UNSET (opts, opts_set, flag_unwind_tables, 1); |
1873 | if (opts->x_flag_asynchronous_unwind_tables == 2) |
1874 | opts->x_flag_unwind_tables |
1875 | = opts->x_flag_asynchronous_unwind_tables = 1; |
1876 | if (opts->x_flag_pcc_struct_return == 2) |
1877 | opts->x_flag_pcc_struct_return = 0; |
1878 | } |
1879 | else |
1880 | { |
1881 | if (opts->x_optimize >= 1) |
1882 | SET_OPTION_IF_UNSET (opts, opts_set, flag_omit_frame_pointer, |
1883 | !(USE_IX86_FRAME_POINTER || opts->x_optimize_size)); |
1884 | if (opts->x_flag_asynchronous_unwind_tables == 2) |
1885 | opts->x_flag_asynchronous_unwind_tables = !USE_IX86_FRAME_POINTER; |
1886 | if (opts->x_flag_pcc_struct_return == 2) |
1887 | { |
1888 | /* Intel MCU psABI specifies that -freg-struct-return should |
1889 | be on. Instead of setting DEFAULT_PCC_STRUCT_RETURN to 0, |
1890 | we check -miamcu so that -freg-struct-return is always |
1891 | turned on if -miamcu is used. */ |
1892 | if (TARGET_IAMCU_P (opts->x_target_flags)) |
1893 | opts->x_flag_pcc_struct_return = 0; |
1894 | else |
1895 | opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN; |
1896 | } |
1897 | } |
1898 | } |
1899 | |
1900 | /* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE hook. */ |
1901 | |
1902 | void |
1903 | ix86_override_options_after_change (void) |
1904 | { |
1905 | /* Default align_* from the processor table. */ |
1906 | ix86_default_align (opts: &global_options); |
1907 | |
1908 | ix86_recompute_optlev_based_flags (opts: &global_options, opts_set: &global_options_set); |
1909 | |
1910 | /* Disable unrolling small loops when there's explicit |
1911 | -f{,no}unroll-loop. */ |
1912 | if ((OPTION_SET_P (flag_unroll_loops)) |
1913 | || (OPTION_SET_P (flag_unroll_all_loops) |
1914 | && flag_unroll_all_loops)) |
1915 | { |
1916 | if (!OPTION_SET_P (ix86_unroll_only_small_loops)) |
1917 | ix86_unroll_only_small_loops = 0; |
1918 | /* Re-enable -frename-registers and -fweb if funroll-loops |
1919 | enabled. */ |
1920 | if (!OPTION_SET_P (flag_web)) |
1921 | flag_web = flag_unroll_loops; |
1922 | if (!OPTION_SET_P (flag_rename_registers)) |
1923 | flag_rename_registers = flag_unroll_loops; |
1924 | /* -fcunroll-grow-size default follws -f[no]-unroll-loops. */ |
1925 | if (!OPTION_SET_P (flag_cunroll_grow_size)) |
1926 | flag_cunroll_grow_size = flag_unroll_loops |
1927 | || flag_peel_loops |
1928 | || optimize >= 3; |
1929 | } |
1930 | else |
1931 | { |
1932 | if (!OPTION_SET_P (flag_cunroll_grow_size)) |
1933 | flag_cunroll_grow_size = flag_peel_loops || optimize >= 3; |
1934 | } |
1935 | |
1936 | } |
1937 | |
1938 | /* Clear stack slot assignments remembered from previous functions. |
1939 | This is called from INIT_EXPANDERS once before RTL is emitted for each |
1940 | function. */ |
1941 | |
1942 | static struct machine_function * |
1943 | ix86_init_machine_status (void) |
1944 | { |
1945 | struct machine_function *f; |
1946 | |
1947 | f = ggc_cleared_alloc<machine_function> (); |
1948 | f->call_abi = ix86_abi; |
1949 | f->stack_frame_required = true; |
1950 | f->silent_p = true; |
1951 | |
1952 | return f; |
1953 | } |
1954 | |
1955 | /* Override various settings based on options. If MAIN_ARGS_P, the |
1956 | options are from the command line, otherwise they are from |
1957 | attributes. Return true if there's an error related to march |
1958 | option. */ |
1959 | |
1960 | static bool |
1961 | ix86_option_override_internal (bool main_args_p, |
1962 | struct gcc_options *opts, |
1963 | struct gcc_options *opts_set) |
1964 | { |
1965 | unsigned int i; |
1966 | unsigned HOST_WIDE_INT ix86_arch_mask; |
1967 | const bool ix86_tune_specified = (opts->x_ix86_tune_string != NULL); |
1968 | |
1969 | /* -mrecip options. */ |
1970 | static struct |
1971 | { |
1972 | const char *string; /* option name */ |
1973 | unsigned int mask; /* mask bits to set */ |
1974 | } |
1975 | const recip_options[] = |
1976 | { |
1977 | { .string: "all" , RECIP_MASK_ALL }, |
1978 | { .string: "none" , RECIP_MASK_NONE }, |
1979 | { .string: "div" , RECIP_MASK_DIV }, |
1980 | { .string: "sqrt" , RECIP_MASK_SQRT }, |
1981 | { .string: "vec-div" , RECIP_MASK_VEC_DIV }, |
1982 | { .string: "vec-sqrt" , RECIP_MASK_VEC_SQRT }, |
1983 | }; |
1984 | |
1985 | |
1986 | /* Turn off both OPTION_MASK_ABI_64 and OPTION_MASK_ABI_X32 if |
1987 | TARGET_64BIT_DEFAULT is true and TARGET_64BIT is false. */ |
1988 | if (TARGET_64BIT_DEFAULT && !TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
1989 | opts->x_ix86_isa_flags &= ~(OPTION_MASK_ABI_64 | OPTION_MASK_ABI_X32); |
1990 | #ifdef TARGET_BI_ARCH |
1991 | else |
1992 | { |
1993 | #if TARGET_BI_ARCH == 1 |
1994 | /* When TARGET_BI_ARCH == 1, by default, OPTION_MASK_ABI_64 |
1995 | is on and OPTION_MASK_ABI_X32 is off. We turn off |
1996 | OPTION_MASK_ABI_64 if OPTION_MASK_ABI_X32 is turned on by |
1997 | -mx32. */ |
1998 | if (TARGET_X32_P (opts->x_ix86_isa_flags)) |
1999 | opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_64; |
2000 | #else |
2001 | /* When TARGET_BI_ARCH == 2, by default, OPTION_MASK_ABI_X32 is |
2002 | on and OPTION_MASK_ABI_64 is off. We turn off |
2003 | OPTION_MASK_ABI_X32 if OPTION_MASK_ABI_64 is turned on by |
2004 | -m64 or OPTION_MASK_CODE16 is turned on by -m16. */ |
2005 | if (TARGET_LP64_P (opts->x_ix86_isa_flags) |
2006 | || TARGET_16BIT_P (opts->x_ix86_isa_flags)) |
2007 | opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32; |
2008 | #endif |
2009 | if (TARGET_64BIT_P (opts->x_ix86_isa_flags) |
2010 | && TARGET_IAMCU_P (opts->x_target_flags)) |
2011 | sorry ("Intel MCU psABI isn%'t supported in %s mode" , |
2012 | TARGET_X32_P (opts->x_ix86_isa_flags) ? "x32" : "64-bit" ); |
2013 | } |
2014 | #endif |
2015 | |
2016 | if (TARGET_X32_P (opts->x_ix86_isa_flags)) |
2017 | { |
2018 | /* Always turn on OPTION_MASK_ISA_64BIT and turn off |
2019 | OPTION_MASK_ABI_64 for TARGET_X32. */ |
2020 | opts->x_ix86_isa_flags |= OPTION_MASK_ISA_64BIT; |
2021 | opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_64; |
2022 | } |
2023 | else if (TARGET_16BIT_P (opts->x_ix86_isa_flags)) |
2024 | opts->x_ix86_isa_flags &= ~(OPTION_MASK_ISA_64BIT |
2025 | | OPTION_MASK_ABI_X32 |
2026 | | OPTION_MASK_ABI_64); |
2027 | else if (TARGET_LP64_P (opts->x_ix86_isa_flags)) |
2028 | { |
2029 | /* Always turn on OPTION_MASK_ISA_64BIT and turn off |
2030 | OPTION_MASK_ABI_X32 for TARGET_LP64. */ |
2031 | opts->x_ix86_isa_flags |= OPTION_MASK_ISA_64BIT; |
2032 | opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32; |
2033 | } |
2034 | |
2035 | #ifdef SUBTARGET_OVERRIDE_OPTIONS |
2036 | SUBTARGET_OVERRIDE_OPTIONS; |
2037 | #endif |
2038 | |
2039 | #ifdef SUBSUBTARGET_OVERRIDE_OPTIONS |
2040 | SUBSUBTARGET_OVERRIDE_OPTIONS; |
2041 | #endif |
2042 | |
2043 | #ifdef HAVE_LD_BROKEN_PE_DWARF5 |
2044 | /* If the PE linker has broken DWARF 5 support, make |
2045 | DWARF 4 the default. */ |
2046 | if (TARGET_PECOFF) |
2047 | SET_OPTION_IF_UNSET (opts, opts_set, dwarf_version, 4); |
2048 | #endif |
2049 | |
2050 | /* -fPIC is the default for x86_64. */ |
2051 | if (TARGET_MACHO && TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2052 | opts->x_flag_pic = 2; |
2053 | |
2054 | /* Need to check -mtune=generic first. */ |
2055 | if (opts->x_ix86_tune_string) |
2056 | { |
2057 | /* As special support for cross compilers we read -mtune=native |
2058 | as -mtune=generic. With native compilers we won't see the |
2059 | -mtune=native, as it was changed by the driver. */ |
2060 | if (!strcmp (s1: opts->x_ix86_tune_string, s2: "native" )) |
2061 | opts->x_ix86_tune_string = "generic" ; |
2062 | else if (!strcmp (s1: opts->x_ix86_tune_string, s2: "x86-64" )) |
2063 | warning (OPT_Wdeprecated, |
2064 | main_args_p |
2065 | ? G_("%<-mtune=x86-64%> is deprecated; use %<-mtune=k8%> " |
2066 | "or %<-mtune=generic%> instead as appropriate" ) |
2067 | : G_("%<target(\"tune=x86-64\")%> is deprecated; use " |
2068 | "%<target(\"tune=k8\")%> or %<target(\"tune=generic\")%>" |
2069 | " instead as appropriate" )); |
2070 | } |
2071 | else |
2072 | { |
2073 | if (opts->x_ix86_arch_string) |
2074 | opts->x_ix86_tune_string = opts->x_ix86_arch_string; |
2075 | if (!opts->x_ix86_tune_string) |
2076 | { |
2077 | opts->x_ix86_tune_string = processor_names[TARGET_CPU_DEFAULT]; |
2078 | ix86_tune_defaulted = 1; |
2079 | } |
2080 | |
2081 | /* opts->x_ix86_tune_string is set to opts->x_ix86_arch_string |
2082 | or defaulted. We need to use a sensible tune option. */ |
2083 | if (startswith (str: opts->x_ix86_tune_string, prefix: "x86-64" ) |
2084 | && (opts->x_ix86_tune_string[6] == '\0' |
2085 | || (!strcmp (s1: opts->x_ix86_tune_string + 6, s2: "-v2" ) |
2086 | || !strcmp (s1: opts->x_ix86_tune_string + 6, s2: "-v3" ) |
2087 | || !strcmp (s1: opts->x_ix86_tune_string + 6, s2: "-v4" )))) |
2088 | opts->x_ix86_tune_string = "generic" ; |
2089 | } |
2090 | |
2091 | if (opts->x_ix86_stringop_alg == rep_prefix_8_byte |
2092 | && !TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2093 | { |
2094 | /* rep; movq isn't available in 32-bit code. */ |
2095 | error ("%<-mstringop-strategy=rep_8byte%> not supported for 32-bit code" ); |
2096 | opts->x_ix86_stringop_alg = no_stringop; |
2097 | } |
2098 | |
2099 | if (TARGET_APX_F && !TARGET_64BIT) |
2100 | error ("%<-mapxf%> is not supported for 32-bit code" ); |
2101 | |
2102 | if (TARGET_UINTR && !TARGET_64BIT) |
2103 | error ("%<-muintr%> not supported for 32-bit code" ); |
2104 | |
2105 | if (ix86_lam_type && !TARGET_LP64) |
2106 | error ("%<-mlam=%> option: [u48|u57] not supported for 32-bit code" ); |
2107 | |
2108 | if (!opts->x_ix86_arch_string) |
2109 | opts->x_ix86_arch_string |
2110 | = TARGET_64BIT_P (opts->x_ix86_isa_flags) |
2111 | ? "x86-64" : SUBTARGET32_DEFAULT_CPU; |
2112 | else |
2113 | ix86_arch_specified = 1; |
2114 | |
2115 | if (opts_set->x_ix86_pmode) |
2116 | { |
2117 | if ((TARGET_LP64_P (opts->x_ix86_isa_flags) |
2118 | && opts->x_ix86_pmode == PMODE_SI) |
2119 | || (!TARGET_64BIT_P (opts->x_ix86_isa_flags) |
2120 | && opts->x_ix86_pmode == PMODE_DI)) |
2121 | error ("address mode %qs not supported in the %s bit mode" , |
2122 | TARGET_64BIT_P (opts->x_ix86_isa_flags) ? "short" : "long" , |
2123 | TARGET_64BIT_P (opts->x_ix86_isa_flags) ? "64" : "32" ); |
2124 | } |
2125 | else |
2126 | opts->x_ix86_pmode = TARGET_LP64_P (opts->x_ix86_isa_flags) |
2127 | ? PMODE_DI : PMODE_SI; |
2128 | |
2129 | SET_OPTION_IF_UNSET (opts, opts_set, ix86_abi, DEFAULT_ABI); |
2130 | |
2131 | if (opts->x_ix86_abi == MS_ABI && TARGET_X32_P (opts->x_ix86_isa_flags)) |
2132 | error ("%<-mabi=ms%> not supported with X32 ABI" ); |
2133 | gcc_assert (opts->x_ix86_abi == SYSV_ABI || opts->x_ix86_abi == MS_ABI); |
2134 | |
2135 | const char *abi_name = opts->x_ix86_abi == MS_ABI ? "ms" : "sysv" ; |
2136 | if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS) |
2137 | && opts->x_ix86_abi != DEFAULT_ABI) |
2138 | error ("%<-mabi=%s%> not supported with %<-fsanitize=address%>" , abi_name); |
2139 | if ((opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) |
2140 | && opts->x_ix86_abi != DEFAULT_ABI) |
2141 | error ("%<-mabi=%s%> not supported with %<-fsanitize=kernel-address%>" , |
2142 | abi_name); |
2143 | if ((opts->x_flag_sanitize & SANITIZE_THREAD) |
2144 | && opts->x_ix86_abi != DEFAULT_ABI) |
2145 | error ("%<-mabi=%s%> not supported with %<-fsanitize=thread%>" , abi_name); |
2146 | |
2147 | /* For targets using ms ABI enable ms-extensions, if not |
2148 | explicit turned off. For non-ms ABI we turn off this |
2149 | option. */ |
2150 | SET_OPTION_IF_UNSET (opts, opts_set, flag_ms_extensions, |
2151 | (MS_ABI == DEFAULT_ABI)); |
2152 | |
2153 | if (opts_set->x_ix86_cmodel) |
2154 | { |
2155 | switch (opts->x_ix86_cmodel) |
2156 | { |
2157 | case CM_SMALL: |
2158 | case CM_SMALL_PIC: |
2159 | if (opts->x_flag_pic) |
2160 | opts->x_ix86_cmodel = CM_SMALL_PIC; |
2161 | if (!TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2162 | error ("code model %qs not supported in the %s bit mode" , |
2163 | "small" , "32" ); |
2164 | break; |
2165 | |
2166 | case CM_MEDIUM: |
2167 | case CM_MEDIUM_PIC: |
2168 | if (opts->x_flag_pic) |
2169 | opts->x_ix86_cmodel = CM_MEDIUM_PIC; |
2170 | if (!TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2171 | error ("code model %qs not supported in the %s bit mode" , |
2172 | "medium" , "32" ); |
2173 | else if (TARGET_X32_P (opts->x_ix86_isa_flags)) |
2174 | error ("code model %qs not supported in x32 mode" , |
2175 | "medium" ); |
2176 | break; |
2177 | |
2178 | case CM_LARGE: |
2179 | case CM_LARGE_PIC: |
2180 | if (opts->x_flag_pic) |
2181 | opts->x_ix86_cmodel = CM_LARGE_PIC; |
2182 | if (!TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2183 | error ("code model %qs not supported in the %s bit mode" , |
2184 | "large" , "32" ); |
2185 | else if (TARGET_X32_P (opts->x_ix86_isa_flags)) |
2186 | error ("code model %qs not supported in x32 mode" , |
2187 | "large" ); |
2188 | break; |
2189 | |
2190 | case CM_32: |
2191 | if (opts->x_flag_pic) |
2192 | error ("code model %s does not support PIC mode" , "32" ); |
2193 | if (TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2194 | error ("code model %qs not supported in the %s bit mode" , |
2195 | "32" , "64" ); |
2196 | break; |
2197 | |
2198 | case CM_KERNEL: |
2199 | if (opts->x_flag_pic) |
2200 | { |
2201 | error ("code model %s does not support PIC mode" , "kernel" ); |
2202 | opts->x_ix86_cmodel = CM_32; |
2203 | } |
2204 | if (!TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2205 | error ("code model %qs not supported in the %s bit mode" , |
2206 | "kernel" , "32" ); |
2207 | break; |
2208 | |
2209 | default: |
2210 | gcc_unreachable (); |
2211 | } |
2212 | } |
2213 | else |
2214 | { |
2215 | /* For TARGET_64BIT and MS_ABI, force pic on, in order to enable the |
2216 | use of rip-relative addressing. This eliminates fixups that |
2217 | would otherwise be needed if this object is to be placed in a |
2218 | DLL, and is essentially just as efficient as direct addressing. */ |
2219 | if (TARGET_64BIT_P (opts->x_ix86_isa_flags) |
2220 | && (TARGET_RDOS || TARGET_PECOFF)) |
2221 | opts->x_ix86_cmodel = CM_MEDIUM_PIC, opts->x_flag_pic = 1; |
2222 | else if (TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2223 | opts->x_ix86_cmodel = opts->x_flag_pic ? CM_SMALL_PIC : CM_SMALL; |
2224 | else |
2225 | opts->x_ix86_cmodel = CM_32; |
2226 | } |
2227 | if (TARGET_MACHO && opts->x_ix86_asm_dialect == ASM_INTEL) |
2228 | { |
2229 | error ("%<-masm=intel%> not supported in this configuration" ); |
2230 | opts->x_ix86_asm_dialect = ASM_ATT; |
2231 | } |
2232 | if ((TARGET_64BIT_P (opts->x_ix86_isa_flags) != 0) |
2233 | != ((opts->x_ix86_isa_flags & OPTION_MASK_ISA_64BIT) != 0)) |
2234 | sorry ("%i-bit mode not compiled in" , |
2235 | (opts->x_ix86_isa_flags & OPTION_MASK_ISA_64BIT) ? 64 : 32); |
2236 | |
2237 | /* Last processor_alias_table must point to "generic" entry. */ |
2238 | gcc_checking_assert (strcmp (processor_alias_table[pta_size - 1].name, |
2239 | "generic" ) == 0); |
2240 | for (i = 0; i < pta_size; i++) |
2241 | if (! strcmp (s1: opts->x_ix86_arch_string, s2: processor_alias_table[i].name)) |
2242 | { |
2243 | if (!strcmp (s1: opts->x_ix86_arch_string, s2: "generic" )) |
2244 | { |
2245 | error (main_args_p |
2246 | ? G_("%<generic%> CPU can be used only for %<-mtune=%> " |
2247 | "switch" ) |
2248 | : G_("%<generic%> CPU can be used only for " |
2249 | "%<target(\"tune=\")%> attribute" )); |
2250 | return false; |
2251 | } |
2252 | else if (!strcmp (s1: opts->x_ix86_arch_string, s2: "intel" )) |
2253 | { |
2254 | error (main_args_p |
2255 | ? G_("%<intel%> CPU can be used only for %<-mtune=%> " |
2256 | "switch" ) |
2257 | : G_("%<intel%> CPU can be used only for " |
2258 | "%<target(\"tune=\")%> attribute" )); |
2259 | return false; |
2260 | } |
2261 | |
2262 | if (TARGET_64BIT_P (opts->x_ix86_isa_flags) |
2263 | && !((processor_alias_table[i].flags & PTA_64BIT) != 0)) |
2264 | { |
2265 | error ("CPU you selected does not support x86-64 " |
2266 | "instruction set" ); |
2267 | return false; |
2268 | } |
2269 | |
2270 | ix86_schedule = processor_alias_table[i].schedule; |
2271 | ix86_arch = processor_alias_table[i].processor; |
2272 | |
2273 | /* Default cpu tuning to the architecture, unless the table |
2274 | entry requests not to do this. Used by the x86-64 psABI |
2275 | micro-architecture levels. */ |
2276 | if ((processor_alias_table[i].flags & PTA_NO_TUNE) == 0) |
2277 | ix86_tune = ix86_arch; |
2278 | else |
2279 | ix86_tune = PROCESSOR_GENERIC; |
2280 | |
2281 | /* Enable PTA flags that are enabled by default by a -march option. */ |
2282 | #define TARGET_EXPLICIT_NO_SAHF_P(opts) (false) |
2283 | #define SET_TARGET_NO_SAHF(opts) {} |
2284 | #define TARGET_EXPLICIT_PREFETCH_SSE_P(opts) (false) |
2285 | #define SET_TARGET_PREFETCH_SSE(opts) {} |
2286 | #define TARGET_EXPLICIT_NO_TUNE_P(opts) (false) |
2287 | #define SET_TARGET_NO_TUNE(opts) {} |
2288 | #define TARGET_EXPLICIT_NO_80387_P(opts) (false) |
2289 | #define SET_TARGET_NO_80387(opts) {} |
2290 | |
2291 | #define DEF_PTA(NAME) \ |
2292 | if (((processor_alias_table[i].flags & PTA_ ## NAME) != 0) \ |
2293 | && PTA_ ## NAME != PTA_64BIT \ |
2294 | && (TARGET_64BIT || PTA_ ## NAME != PTA_UINTR) \ |
2295 | && !TARGET_EXPLICIT_ ## NAME ## _P (opts)) \ |
2296 | SET_TARGET_ ## NAME (opts); |
2297 | #include "i386-isa.def" |
2298 | #undef DEF_PTA |
2299 | |
2300 | |
2301 | if (!(TARGET_64BIT_P (opts->x_ix86_isa_flags) |
2302 | && ((processor_alias_table[i].flags & PTA_NO_SAHF) != 0)) |
2303 | && !TARGET_EXPLICIT_SAHF_P (opts)) |
2304 | SET_TARGET_SAHF (opts); |
2305 | |
2306 | if (((processor_alias_table[i].flags & PTA_ABM) != 0) |
2307 | && !TARGET_EXPLICIT_ABM_P (opts)) |
2308 | { |
2309 | if (!TARGET_EXPLICIT_LZCNT_P (opts)) |
2310 | SET_TARGET_LZCNT (opts); |
2311 | if (!TARGET_EXPLICIT_POPCNT_P (opts)) |
2312 | SET_TARGET_POPCNT (opts); |
2313 | } |
2314 | |
2315 | /* Enable apx if apxf or apx_features are not |
2316 | explicitly set for -march. */ |
2317 | if (TARGET_64BIT_P (opts->x_ix86_isa_flags) |
2318 | && ((processor_alias_table[i].flags & PTA_APX_F) != 0) |
2319 | && !TARGET_EXPLICIT_APX_F_P (opts) |
2320 | && !OPTION_SET_P (ix86_apx_features)) |
2321 | opts->x_ix86_apx_features = apx_all; |
2322 | |
2323 | if ((processor_alias_table[i].flags |
2324 | & (PTA_PREFETCH_SSE | PTA_SSE)) != 0) |
2325 | ix86_prefetch_sse = true; |
2326 | |
2327 | /* Don't enable x87 instructions if only general registers are |
2328 | allowed by target("general-regs-only") function attribute or |
2329 | -mgeneral-regs-only. */ |
2330 | if (!(opts->x_ix86_target_flags & OPTION_MASK_GENERAL_REGS_ONLY) |
2331 | && !(opts_set->x_target_flags & MASK_80387)) |
2332 | { |
2333 | if (((processor_alias_table[i].flags & PTA_NO_80387) != 0)) |
2334 | opts->x_target_flags &= ~MASK_80387; |
2335 | else |
2336 | opts->x_target_flags |= MASK_80387; |
2337 | } |
2338 | break; |
2339 | } |
2340 | |
2341 | if (i == pta_size) |
2342 | { |
2343 | error (main_args_p |
2344 | ? G_("bad value %qs for %<-march=%> switch" ) |
2345 | : G_("bad value %qs for %<target(\"arch=\")%> attribute" ), |
2346 | opts->x_ix86_arch_string); |
2347 | |
2348 | auto_vec <const char *> candidates; |
2349 | for (i = 0; i < pta_size; i++) |
2350 | if (strcmp (s1: processor_alias_table[i].name, s2: "generic" ) |
2351 | && strcmp (s1: processor_alias_table[i].name, s2: "intel" ) |
2352 | && (!TARGET_64BIT_P (opts->x_ix86_isa_flags) |
2353 | || ((processor_alias_table[i].flags & PTA_64BIT) != 0))) |
2354 | candidates.safe_push (obj: processor_alias_table[i].name); |
2355 | |
2356 | #ifdef HAVE_LOCAL_CPU_DETECT |
2357 | /* Add also "native" as possible value. */ |
2358 | candidates.safe_push (obj: "native" ); |
2359 | #endif |
2360 | |
2361 | char *s; |
2362 | const char *hint |
2363 | = candidates_list_and_hint (arg: opts->x_ix86_arch_string, str&: s, candidates); |
2364 | if (hint) |
2365 | inform (input_location, |
2366 | main_args_p |
2367 | ? G_("valid arguments to %<-march=%> switch are: " |
2368 | "%s; did you mean %qs?" ) |
2369 | : G_("valid arguments to %<target(\"arch=\")%> attribute are: " |
2370 | "%s; did you mean %qs?" ), s, hint); |
2371 | else |
2372 | inform (input_location, |
2373 | main_args_p |
2374 | ? G_("valid arguments to %<-march=%> switch are: %s" ) |
2375 | : G_("valid arguments to %<target(\"arch=\")%> attribute " |
2376 | "are: %s" ), s); |
2377 | XDELETEVEC (s); |
2378 | } |
2379 | |
2380 | ix86_arch_mask = HOST_WIDE_INT_1U << ix86_arch; |
2381 | for (i = 0; i < X86_ARCH_LAST; ++i) |
2382 | ix86_arch_features[i] = !!(initial_ix86_arch_features[i] & ix86_arch_mask); |
2383 | |
2384 | for (i = 0; i < pta_size; i++) |
2385 | if (! strcmp (s1: opts->x_ix86_tune_string, s2: processor_alias_table[i].name) |
2386 | && (processor_alias_table[i].flags & PTA_NO_TUNE) == 0) |
2387 | { |
2388 | ix86_schedule = processor_alias_table[i].schedule; |
2389 | ix86_tune = processor_alias_table[i].processor; |
2390 | if (TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2391 | { |
2392 | if (!((processor_alias_table[i].flags & PTA_64BIT) != 0)) |
2393 | { |
2394 | if (ix86_tune_defaulted) |
2395 | { |
2396 | opts->x_ix86_tune_string = "x86-64" ; |
2397 | for (i = 0; i < pta_size; i++) |
2398 | if (! strcmp (s1: opts->x_ix86_tune_string, |
2399 | s2: processor_alias_table[i].name)) |
2400 | break; |
2401 | ix86_schedule = processor_alias_table[i].schedule; |
2402 | ix86_tune = processor_alias_table[i].processor; |
2403 | } |
2404 | else |
2405 | error ("CPU you selected does not support x86-64 " |
2406 | "instruction set" ); |
2407 | } |
2408 | } |
2409 | /* Intel CPUs have always interpreted SSE prefetch instructions as |
2410 | NOPs; so, we can enable SSE prefetch instructions even when |
2411 | -mtune (rather than -march) points us to a processor that has them. |
2412 | However, the VIA C3 gives a SIGILL, so we only do that for i686 and |
2413 | higher processors. */ |
2414 | if (TARGET_CMOV |
2415 | && ((processor_alias_table[i].flags |
2416 | & (PTA_PREFETCH_SSE | PTA_SSE)) != 0)) |
2417 | ix86_prefetch_sse = true; |
2418 | break; |
2419 | } |
2420 | |
2421 | if (ix86_tune_specified && i == pta_size) |
2422 | { |
2423 | error (main_args_p |
2424 | ? G_("bad value %qs for %<-mtune=%> switch" ) |
2425 | : G_("bad value %qs for %<target(\"tune=\")%> attribute" ), |
2426 | opts->x_ix86_tune_string); |
2427 | |
2428 | auto_vec <const char *> candidates; |
2429 | for (i = 0; i < pta_size; i++) |
2430 | if ((!TARGET_64BIT_P (opts->x_ix86_isa_flags) |
2431 | || ((processor_alias_table[i].flags & PTA_64BIT) != 0)) |
2432 | && (processor_alias_table[i].flags & PTA_NO_TUNE) == 0) |
2433 | candidates.safe_push (obj: processor_alias_table[i].name); |
2434 | |
2435 | #ifdef HAVE_LOCAL_CPU_DETECT |
2436 | /* Add also "native" as possible value. */ |
2437 | candidates.safe_push (obj: "native" ); |
2438 | #endif |
2439 | |
2440 | char *s; |
2441 | const char *hint |
2442 | = candidates_list_and_hint (arg: opts->x_ix86_tune_string, str&: s, candidates); |
2443 | if (hint) |
2444 | inform (input_location, |
2445 | main_args_p |
2446 | ? G_("valid arguments to %<-mtune=%> switch are: " |
2447 | "%s; did you mean %qs?" ) |
2448 | : G_("valid arguments to %<target(\"tune=\")%> attribute are: " |
2449 | "%s; did you mean %qs?" ), s, hint); |
2450 | else |
2451 | inform (input_location, |
2452 | main_args_p |
2453 | ? G_("valid arguments to %<-mtune=%> switch are: %s" ) |
2454 | : G_("valid arguments to %<target(\"tune=\")%> attribute " |
2455 | "are: %s" ), s); |
2456 | XDELETEVEC (s); |
2457 | } |
2458 | |
2459 | set_ix86_tune_features (opts, ix86_tune, dump: opts->x_ix86_dump_tunes); |
2460 | |
2461 | ix86_override_options_after_change (); |
2462 | |
2463 | ix86_tune_cost = processor_cost_table[ix86_tune]; |
2464 | /* TODO: ix86_cost should be chosen at instruction or function granuality |
2465 | so for cold code we use size_cost even in !optimize_size compilation. */ |
2466 | if (opts->x_optimize_size) |
2467 | ix86_cost = &ix86_size_cost; |
2468 | else |
2469 | ix86_cost = ix86_tune_cost; |
2470 | |
2471 | /* Arrange to set up i386_stack_locals for all functions. */ |
2472 | init_machine_status = ix86_init_machine_status; |
2473 | |
2474 | /* Override APX flag here if ISA bit is set. */ |
2475 | if (TARGET_APX_F && !OPTION_SET_P (ix86_apx_features)) |
2476 | opts->x_ix86_apx_features = apx_all; |
2477 | |
2478 | /* Validate -mregparm= value. */ |
2479 | if (opts_set->x_ix86_regparm) |
2480 | { |
2481 | if (TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2482 | warning (0, "%<-mregparm%> is ignored in 64-bit mode" ); |
2483 | else if (TARGET_IAMCU_P (opts->x_target_flags)) |
2484 | warning (0, "%<-mregparm%> is ignored for Intel MCU psABI" ); |
2485 | if (opts->x_ix86_regparm > REGPARM_MAX) |
2486 | { |
2487 | error ("%<-mregparm=%d%> is not between 0 and %d" , |
2488 | opts->x_ix86_regparm, REGPARM_MAX); |
2489 | opts->x_ix86_regparm = 0; |
2490 | } |
2491 | } |
2492 | if (TARGET_IAMCU_P (opts->x_target_flags) |
2493 | || TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2494 | opts->x_ix86_regparm = REGPARM_MAX; |
2495 | |
2496 | /* Provide default for -mbranch-cost= value. */ |
2497 | SET_OPTION_IF_UNSET (opts, opts_set, ix86_branch_cost, |
2498 | ix86_tune_cost->branch_cost); |
2499 | |
2500 | if (TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2501 | { |
2502 | opts->x_target_flags |
2503 | |= TARGET_SUBTARGET64_DEFAULT & ~opts_set->x_target_flags; |
2504 | |
2505 | if (!ix86_arch_specified) |
2506 | opts->x_ix86_isa_flags |
2507 | |= TARGET_SUBTARGET64_ISA_DEFAULT & ~opts->x_ix86_isa_flags_explicit; |
2508 | |
2509 | if (!TARGET_128BIT_LONG_DOUBLE_P (opts->x_target_flags)) |
2510 | error ("%<-m96bit-long-double%> is not compatible with this target" ); |
2511 | |
2512 | if (TARGET_RTD_P (opts->x_target_flags)) |
2513 | warning (0, |
2514 | main_args_p |
2515 | ? G_("%<-mrtd%> is ignored in 64bit mode" ) |
2516 | : G_("%<target(\"rtd\")%> is ignored in 64bit mode" )); |
2517 | } |
2518 | else |
2519 | { |
2520 | opts->x_target_flags |
2521 | |= TARGET_SUBTARGET32_DEFAULT & ~opts_set->x_target_flags; |
2522 | |
2523 | if (!ix86_arch_specified) |
2524 | opts->x_ix86_isa_flags |
2525 | |= TARGET_SUBTARGET32_ISA_DEFAULT & ~opts->x_ix86_isa_flags_explicit; |
2526 | |
2527 | /* i386 ABI does not specify red zone. It still makes sense to use it |
2528 | when programmer takes care to stack from being destroyed. */ |
2529 | if (!(opts_set->x_target_flags & MASK_NO_RED_ZONE)) |
2530 | opts->x_target_flags |= MASK_NO_RED_ZONE; |
2531 | } |
2532 | |
2533 | /* Keep nonleaf frame pointers. */ |
2534 | if (opts->x_flag_omit_frame_pointer) |
2535 | opts->x_target_flags &= ~MASK_OMIT_LEAF_FRAME_POINTER; |
2536 | else if (TARGET_OMIT_LEAF_FRAME_POINTER_P (opts->x_target_flags)) |
2537 | opts->x_flag_omit_frame_pointer = 1; |
2538 | |
2539 | /* If we're doing fast math, we don't care about comparison order |
2540 | wrt NaNs. This lets us use a shorter comparison sequence. */ |
2541 | if (opts->x_flag_finite_math_only) |
2542 | opts->x_target_flags &= ~MASK_IEEE_FP; |
2543 | |
2544 | /* If the architecture always has an FPU, turn off NO_FANCY_MATH_387, |
2545 | since the insns won't need emulation. */ |
2546 | if (ix86_tune_features [X86_TUNE_ALWAYS_FANCY_MATH_387]) |
2547 | opts->x_target_flags &= ~MASK_NO_FANCY_MATH_387; |
2548 | |
2549 | /* Likewise, if the target doesn't have a 387, or we've specified |
2550 | software floating point, don't use 387 inline intrinsics. */ |
2551 | if (!TARGET_80387_P (opts->x_target_flags)) |
2552 | opts->x_target_flags |= MASK_NO_FANCY_MATH_387; |
2553 | |
2554 | /* Turn on MMX builtins for -msse. */ |
2555 | if (TARGET_SSE_P (opts->x_ix86_isa_flags)) |
2556 | opts->x_ix86_isa_flags |
2557 | |= OPTION_MASK_ISA_MMX & ~opts->x_ix86_isa_flags_explicit; |
2558 | |
2559 | /* Enable SSE prefetch. */ |
2560 | if (TARGET_SSE_P (opts->x_ix86_isa_flags) |
2561 | || (TARGET_PRFCHW_P (opts->x_ix86_isa_flags) |
2562 | && !TARGET_3DNOW_P (opts->x_ix86_isa_flags)) |
2563 | || TARGET_PREFETCHWT1_P (opts->x_ix86_isa_flags)) |
2564 | ix86_prefetch_sse = true; |
2565 | |
2566 | /* Enable mwait/monitor instructions for -msse3. */ |
2567 | if (TARGET_SSE3_P (opts->x_ix86_isa_flags)) |
2568 | opts->x_ix86_isa_flags2 |
2569 | |= OPTION_MASK_ISA2_MWAIT & ~opts->x_ix86_isa_flags2_explicit; |
2570 | |
2571 | /* Enable popcnt instruction for -msse4.2 or -mabm. */ |
2572 | if (TARGET_SSE4_2_P (opts->x_ix86_isa_flags) |
2573 | || TARGET_ABM_P (opts->x_ix86_isa_flags)) |
2574 | opts->x_ix86_isa_flags |
2575 | |= OPTION_MASK_ISA_POPCNT & ~opts->x_ix86_isa_flags_explicit; |
2576 | |
2577 | /* Enable crc32 instruction for -msse4.2. */ |
2578 | if (TARGET_SSE4_2_P (opts->x_ix86_isa_flags)) |
2579 | opts->x_ix86_isa_flags |
2580 | |= OPTION_MASK_ISA_CRC32 & ~opts->x_ix86_isa_flags_explicit; |
2581 | |
2582 | /* Enable lzcnt instruction for -mabm. */ |
2583 | if (TARGET_ABM_P(opts->x_ix86_isa_flags)) |
2584 | opts->x_ix86_isa_flags |
2585 | |= OPTION_MASK_ISA_LZCNT & ~opts->x_ix86_isa_flags_explicit; |
2586 | |
2587 | /* Disable BMI, BMI2 and TBM instructions for -m16. */ |
2588 | if (TARGET_16BIT_P(opts->x_ix86_isa_flags)) |
2589 | opts->x_ix86_isa_flags |
2590 | &= ~((OPTION_MASK_ISA_BMI | OPTION_MASK_ISA_BMI2 | OPTION_MASK_ISA_TBM) |
2591 | & ~opts->x_ix86_isa_flags_explicit); |
2592 | |
2593 | /* Set EVEX512 target if it is not explicitly set |
2594 | when AVX512 is enabled. */ |
2595 | if (TARGET_AVX512F_P(opts->x_ix86_isa_flags) |
2596 | && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_EVEX512)) |
2597 | opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_EVEX512; |
2598 | |
2599 | /* Disable AVX512{PF,ER,4VNNIW,4FAMPS} for -mno-evex512. */ |
2600 | if (!TARGET_EVEX512_P(opts->x_ix86_isa_flags2)) |
2601 | { |
2602 | opts->x_ix86_isa_flags |
2603 | &= ~(OPTION_MASK_ISA_AVX512PF | OPTION_MASK_ISA_AVX512ER); |
2604 | opts->x_ix86_isa_flags2 |
2605 | &= ~(OPTION_MASK_ISA2_AVX5124FMAPS | OPTION_MASK_ISA2_AVX5124VNNIW); |
2606 | } |
2607 | |
2608 | /* Validate -mpreferred-stack-boundary= value or default it to |
2609 | PREFERRED_STACK_BOUNDARY_DEFAULT. */ |
2610 | ix86_preferred_stack_boundary = PREFERRED_STACK_BOUNDARY_DEFAULT; |
2611 | if (opts_set->x_ix86_preferred_stack_boundary_arg) |
2612 | { |
2613 | int min = TARGET_64BIT_P (opts->x_ix86_isa_flags)? 3 : 2; |
2614 | int max = TARGET_SEH ? 4 : 12; |
2615 | |
2616 | if (opts->x_ix86_preferred_stack_boundary_arg < min |
2617 | || opts->x_ix86_preferred_stack_boundary_arg > max) |
2618 | { |
2619 | if (min == max) |
2620 | error ("%<-mpreferred-stack-boundary%> is not supported " |
2621 | "for this target" ); |
2622 | else |
2623 | error ("%<-mpreferred-stack-boundary=%d%> is not between %d and %d" , |
2624 | opts->x_ix86_preferred_stack_boundary_arg, min, max); |
2625 | } |
2626 | else |
2627 | ix86_preferred_stack_boundary |
2628 | = (1 << opts->x_ix86_preferred_stack_boundary_arg) * BITS_PER_UNIT; |
2629 | } |
2630 | |
2631 | /* Set the default value for -mstackrealign. */ |
2632 | SET_OPTION_IF_UNSET (opts, opts_set, ix86_force_align_arg_pointer, |
2633 | STACK_REALIGN_DEFAULT); |
2634 | |
2635 | ix86_default_incoming_stack_boundary = PREFERRED_STACK_BOUNDARY; |
2636 | |
2637 | /* Validate -mincoming-stack-boundary= value or default it to |
2638 | MIN_STACK_BOUNDARY/PREFERRED_STACK_BOUNDARY. */ |
2639 | ix86_incoming_stack_boundary = ix86_default_incoming_stack_boundary; |
2640 | if (opts_set->x_ix86_incoming_stack_boundary_arg) |
2641 | { |
2642 | int min = TARGET_64BIT_P (opts->x_ix86_isa_flags) ? 3 : 2; |
2643 | |
2644 | if (opts->x_ix86_incoming_stack_boundary_arg < min |
2645 | || opts->x_ix86_incoming_stack_boundary_arg > 12) |
2646 | error ("%<-mincoming-stack-boundary=%d%> is not between %d and 12" , |
2647 | opts->x_ix86_incoming_stack_boundary_arg, min); |
2648 | else |
2649 | { |
2650 | ix86_user_incoming_stack_boundary |
2651 | = (1 << opts->x_ix86_incoming_stack_boundary_arg) * BITS_PER_UNIT; |
2652 | ix86_incoming_stack_boundary |
2653 | = ix86_user_incoming_stack_boundary; |
2654 | } |
2655 | } |
2656 | |
2657 | #ifndef NO_PROFILE_COUNTERS |
2658 | if (flag_nop_mcount) |
2659 | error ("%<-mnop-mcount%> is not compatible with this target" ); |
2660 | #endif |
2661 | if (flag_nop_mcount && flag_pic) |
2662 | error ("%<-mnop-mcount%> is not implemented for %<-fPIC%>" ); |
2663 | |
2664 | /* Accept -msseregparm only if at least SSE support is enabled. */ |
2665 | if (TARGET_SSEREGPARM_P (opts->x_target_flags) |
2666 | && ! TARGET_SSE_P (opts->x_ix86_isa_flags)) |
2667 | error (main_args_p |
2668 | ? G_("%<-msseregparm%> used without SSE enabled" ) |
2669 | : G_("%<target(\"sseregparm\")%> used without SSE enabled" )); |
2670 | |
2671 | if (opts_set->x_ix86_fpmath) |
2672 | { |
2673 | if (opts->x_ix86_fpmath & FPMATH_SSE) |
2674 | { |
2675 | if (!TARGET_SSE_P (opts->x_ix86_isa_flags)) |
2676 | { |
2677 | if (TARGET_80387_P (opts->x_target_flags)) |
2678 | { |
2679 | warning (0, "SSE instruction set disabled, using 387 arithmetics" ); |
2680 | opts->x_ix86_fpmath = FPMATH_387; |
2681 | } |
2682 | } |
2683 | else if ((opts->x_ix86_fpmath & FPMATH_387) |
2684 | && !TARGET_80387_P (opts->x_target_flags)) |
2685 | { |
2686 | warning (0, "387 instruction set disabled, using SSE arithmetics" ); |
2687 | opts->x_ix86_fpmath = FPMATH_SSE; |
2688 | } |
2689 | } |
2690 | } |
2691 | /* For all chips supporting SSE2, -mfpmath=sse performs better than |
2692 | fpmath=387. The second is however default at many targets since the |
2693 | extra 80bit precision of temporaries is considered to be part of ABI. |
2694 | Overwrite the default at least for -ffast-math. |
2695 | TODO: -mfpmath=both seems to produce same performing code with bit |
2696 | smaller binaries. It is however not clear if register allocation is |
2697 | ready for this setting. |
2698 | Also -mfpmath=387 is overall a lot more compact (bout 4-5%) than SSE |
2699 | codegen. We may switch to 387 with -ffast-math for size optimized |
2700 | functions. */ |
2701 | else if (fast_math_flags_set_p (&global_options) |
2702 | && TARGET_SSE2_P (opts->x_ix86_isa_flags)) |
2703 | opts->x_ix86_fpmath = FPMATH_SSE; |
2704 | else |
2705 | opts->x_ix86_fpmath = TARGET_FPMATH_DEFAULT_P (opts->x_ix86_isa_flags); |
2706 | |
2707 | /* Use external vectorized library in vectorizing intrinsics. */ |
2708 | if (opts_set->x_ix86_veclibabi_type) |
2709 | switch (opts->x_ix86_veclibabi_type) |
2710 | { |
2711 | case ix86_veclibabi_type_svml: |
2712 | ix86_veclib_handler = &ix86_veclibabi_svml; |
2713 | break; |
2714 | |
2715 | case ix86_veclibabi_type_acml: |
2716 | ix86_veclib_handler = &ix86_veclibabi_acml; |
2717 | break; |
2718 | |
2719 | default: |
2720 | gcc_unreachable (); |
2721 | } |
2722 | |
2723 | if (ix86_tune_features [X86_TUNE_ACCUMULATE_OUTGOING_ARGS] |
2724 | && !(opts_set->x_target_flags & MASK_ACCUMULATE_OUTGOING_ARGS)) |
2725 | opts->x_target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS; |
2726 | |
2727 | /* If stack probes are required, the space used for large function |
2728 | arguments on the stack must also be probed, so enable |
2729 | -maccumulate-outgoing-args so this happens in the prologue. */ |
2730 | if (TARGET_STACK_PROBE_P (opts->x_target_flags) |
2731 | && !(opts->x_target_flags & MASK_ACCUMULATE_OUTGOING_ARGS)) |
2732 | { |
2733 | if (opts_set->x_target_flags & MASK_ACCUMULATE_OUTGOING_ARGS) |
2734 | warning (0, |
2735 | main_args_p |
2736 | ? G_("stack probing requires %<-maccumulate-outgoing-args%> " |
2737 | "for correctness" ) |
2738 | : G_("stack probing requires " |
2739 | "%<target(\"accumulate-outgoing-args\")%> for " |
2740 | "correctness" )); |
2741 | opts->x_target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS; |
2742 | } |
2743 | |
2744 | /* Stack realignment without -maccumulate-outgoing-args requires %ebp, |
2745 | so enable -maccumulate-outgoing-args when %ebp is fixed. */ |
2746 | if (fixed_regs[BP_REG] |
2747 | && !(opts->x_target_flags & MASK_ACCUMULATE_OUTGOING_ARGS)) |
2748 | { |
2749 | if (opts_set->x_target_flags & MASK_ACCUMULATE_OUTGOING_ARGS) |
2750 | warning (0, |
2751 | main_args_p |
2752 | ? G_("fixed ebp register requires " |
2753 | "%<-maccumulate-outgoing-args%>" ) |
2754 | : G_("fixed ebp register requires " |
2755 | "%<target(\"accumulate-outgoing-args\")%>" )); |
2756 | opts->x_target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS; |
2757 | } |
2758 | |
2759 | /* Figure out what ASM_GENERATE_INTERNAL_LABEL builds as a prefix. */ |
2760 | { |
2761 | char *p; |
2762 | ASM_GENERATE_INTERNAL_LABEL (internal_label_prefix, "LX" , 0); |
2763 | p = strchr (s: internal_label_prefix, c: 'X'); |
2764 | internal_label_prefix_len = p - internal_label_prefix; |
2765 | *p = '\0'; |
2766 | } |
2767 | |
2768 | /* When scheduling description is not available, disable scheduler pass |
2769 | so it won't slow down the compilation and make x87 code slower. */ |
2770 | if (!TARGET_SCHEDULE) |
2771 | opts->x_flag_schedule_insns_after_reload = opts->x_flag_schedule_insns = 0; |
2772 | |
2773 | SET_OPTION_IF_UNSET (opts, opts_set, param_simultaneous_prefetches, |
2774 | ix86_tune_cost->simultaneous_prefetches); |
2775 | SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_line_size, |
2776 | ix86_tune_cost->prefetch_block); |
2777 | SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_size, |
2778 | ix86_tune_cost->l1_cache_size); |
2779 | SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size, |
2780 | ix86_tune_cost->l2_cache_size); |
2781 | |
2782 | /* 64B is the accepted value for these for all x86. */ |
2783 | SET_OPTION_IF_UNSET (&global_options, &global_options_set, |
2784 | param_destruct_interfere_size, 64); |
2785 | SET_OPTION_IF_UNSET (&global_options, &global_options_set, |
2786 | param_construct_interfere_size, 64); |
2787 | |
2788 | /* Enable sw prefetching at -O3 for CPUS that prefetching is helpful. */ |
2789 | if (opts->x_flag_prefetch_loop_arrays < 0 |
2790 | && HAVE_prefetch |
2791 | && (opts->x_optimize >= 3 || opts->x_flag_profile_use) |
2792 | && !opts->x_optimize_size |
2793 | && TARGET_SOFTWARE_PREFETCHING_BENEFICIAL) |
2794 | opts->x_flag_prefetch_loop_arrays = 1; |
2795 | |
2796 | /* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0) |
2797 | can be opts->x_optimized to ap = __builtin_next_arg (0). */ |
2798 | if (!TARGET_64BIT_P (opts->x_ix86_isa_flags) && !opts->x_flag_split_stack) |
2799 | targetm.expand_builtin_va_start = NULL; |
2800 | |
2801 | #ifdef USE_IX86_CLD |
2802 | /* Use -mcld by default for 32-bit code if configured with --enable-cld. */ |
2803 | if (!TARGET_64BIT_P (opts->x_ix86_isa_flags)) |
2804 | opts->x_target_flags |= MASK_CLD & ~opts_set->x_target_flags; |
2805 | #endif |
2806 | |
2807 | /* Set the default value for -mfentry. */ |
2808 | if (!opts_set->x_flag_fentry) |
2809 | opts->x_flag_fentry = TARGET_SEH; |
2810 | else |
2811 | { |
2812 | if (!TARGET_64BIT_P (opts->x_ix86_isa_flags) && opts->x_flag_pic |
2813 | && opts->x_flag_fentry) |
2814 | sorry ("%<-mfentry%> isn%'t supported for 32-bit in combination " |
2815 | "with %<-fpic%>" ); |
2816 | else if (TARGET_SEH && !opts->x_flag_fentry) |
2817 | sorry ("%<-mno-fentry%> isn%'t compatible with SEH" ); |
2818 | } |
2819 | |
2820 | if (TARGET_SEH && TARGET_CALL_MS2SYSV_XLOGUES) |
2821 | sorry ("%<-mcall-ms2sysv-xlogues%> isn%'t currently supported with SEH" ); |
2822 | |
2823 | if (!(opts_set->x_target_flags & MASK_VZEROUPPER) |
2824 | && TARGET_EMIT_VZEROUPPER |
2825 | && flag_expensive_optimizations |
2826 | && !optimize_size) |
2827 | opts->x_target_flags |= MASK_VZEROUPPER; |
2828 | if (!(opts_set->x_target_flags & MASK_STV)) |
2829 | opts->x_target_flags |= MASK_STV; |
2830 | /* Disable STV if -mpreferred-stack-boundary={2,3} or |
2831 | -mincoming-stack-boundary={2,3} or -mstackrealign - the needed |
2832 | stack realignment will be extra cost the pass doesn't take into |
2833 | account and the pass can't realign the stack. */ |
2834 | if (ix86_preferred_stack_boundary < 128 |
2835 | || ix86_incoming_stack_boundary < 128 |
2836 | || opts->x_ix86_force_align_arg_pointer) |
2837 | opts->x_target_flags &= ~MASK_STV; |
2838 | if (!ix86_tune_features[X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL] |
2839 | && !(opts_set->x_target_flags & MASK_AVX256_SPLIT_UNALIGNED_LOAD)) |
2840 | opts->x_target_flags |= MASK_AVX256_SPLIT_UNALIGNED_LOAD; |
2841 | else if (!main_args_p |
2842 | && ix86_tune_features[X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL]) |
2843 | opts->x_target_flags &= ~MASK_AVX256_SPLIT_UNALIGNED_LOAD; |
2844 | |
2845 | if (!ix86_tune_features[X86_TUNE_AVX256_UNALIGNED_STORE_OPTIMAL] |
2846 | && !(opts_set->x_target_flags & MASK_AVX256_SPLIT_UNALIGNED_STORE)) |
2847 | opts->x_target_flags |= MASK_AVX256_SPLIT_UNALIGNED_STORE; |
2848 | else if (!main_args_p |
2849 | && ix86_tune_features[X86_TUNE_AVX256_UNALIGNED_STORE_OPTIMAL]) |
2850 | opts->x_target_flags &= ~MASK_AVX256_SPLIT_UNALIGNED_STORE; |
2851 | |
2852 | /* Enable 128-bit AVX instruction generation |
2853 | for the auto-vectorizer. */ |
2854 | if (ix86_tune_features[X86_TUNE_AVX128_OPTIMAL] |
2855 | && (opts_set->x_prefer_vector_width_type == PVW_NONE)) |
2856 | opts->x_prefer_vector_width_type = PVW_AVX128; |
2857 | |
2858 | /* Use 256-bit AVX instruction generation |
2859 | in the auto-vectorizer. */ |
2860 | if (ix86_tune_features[X86_TUNE_AVX256_OPTIMAL] |
2861 | && (opts_set->x_prefer_vector_width_type == PVW_NONE)) |
2862 | opts->x_prefer_vector_width_type = PVW_AVX256; |
2863 | |
2864 | if (opts_set->x_ix86_move_max == PVW_NONE) |
2865 | { |
2866 | /* Set the maximum number of bits can be moved from memory to |
2867 | memory efficiently. */ |
2868 | if (ix86_tune_features[X86_TUNE_AVX512_MOVE_BY_PIECES]) |
2869 | opts->x_ix86_move_max = PVW_AVX512; |
2870 | else if (ix86_tune_features[X86_TUNE_AVX256_MOVE_BY_PIECES]) |
2871 | opts->x_ix86_move_max = PVW_AVX256; |
2872 | else |
2873 | { |
2874 | opts->x_ix86_move_max = opts->x_prefer_vector_width_type; |
2875 | if (opts_set->x_ix86_move_max == PVW_NONE) |
2876 | { |
2877 | if (TARGET_AVX512F_P (opts->x_ix86_isa_flags) |
2878 | && TARGET_EVEX512_P (opts->x_ix86_isa_flags2)) |
2879 | opts->x_ix86_move_max = PVW_AVX512; |
2880 | else |
2881 | opts->x_ix86_move_max = PVW_AVX128; |
2882 | } |
2883 | } |
2884 | } |
2885 | |
2886 | if (opts_set->x_ix86_store_max == PVW_NONE) |
2887 | { |
2888 | /* Set the maximum number of bits can be stored to memory |
2889 | efficiently. */ |
2890 | if (ix86_tune_features[X86_TUNE_AVX512_STORE_BY_PIECES]) |
2891 | opts->x_ix86_store_max = PVW_AVX512; |
2892 | else if (ix86_tune_features[X86_TUNE_AVX256_STORE_BY_PIECES]) |
2893 | opts->x_ix86_store_max = PVW_AVX256; |
2894 | else |
2895 | { |
2896 | opts->x_ix86_store_max = opts->x_prefer_vector_width_type; |
2897 | if (opts_set->x_ix86_store_max == PVW_NONE) |
2898 | { |
2899 | if (TARGET_AVX512F_P (opts->x_ix86_isa_flags) |
2900 | && TARGET_EVEX512_P (opts->x_ix86_isa_flags2)) |
2901 | opts->x_ix86_store_max = PVW_AVX512; |
2902 | else |
2903 | opts->x_ix86_store_max = PVW_AVX128; |
2904 | } |
2905 | } |
2906 | } |
2907 | |
2908 | if (opts->x_ix86_recip_name) |
2909 | { |
2910 | char *p = ASTRDUP (opts->x_ix86_recip_name); |
2911 | char *q; |
2912 | unsigned int mask; |
2913 | bool invert; |
2914 | |
2915 | while ((q = strtok (s: p, delim: "," )) != NULL) |
2916 | { |
2917 | p = NULL; |
2918 | if (*q == '!') |
2919 | { |
2920 | invert = true; |
2921 | q++; |
2922 | } |
2923 | else |
2924 | invert = false; |
2925 | |
2926 | if (!strcmp (s1: q, s2: "default" )) |
2927 | mask = RECIP_MASK_ALL; |
2928 | else |
2929 | { |
2930 | for (i = 0; i < ARRAY_SIZE (recip_options); i++) |
2931 | if (!strcmp (s1: q, s2: recip_options[i].string)) |
2932 | { |
2933 | mask = recip_options[i].mask; |
2934 | break; |
2935 | } |
2936 | |
2937 | if (i == ARRAY_SIZE (recip_options)) |
2938 | { |
2939 | error ("unknown option for %<-mrecip=%s%>" , q); |
2940 | invert = false; |
2941 | mask = RECIP_MASK_NONE; |
2942 | } |
2943 | } |
2944 | |
2945 | opts->x_recip_mask_explicit |= mask; |
2946 | if (invert) |
2947 | opts->x_recip_mask &= ~mask; |
2948 | else |
2949 | opts->x_recip_mask |= mask; |
2950 | } |
2951 | } |
2952 | |
2953 | if (TARGET_RECIP_P (opts->x_target_flags)) |
2954 | opts->x_recip_mask |= RECIP_MASK_ALL & ~opts->x_recip_mask_explicit; |
2955 | else if (opts_set->x_target_flags & MASK_RECIP) |
2956 | opts->x_recip_mask &= ~(RECIP_MASK_ALL & ~opts->x_recip_mask_explicit); |
2957 | |
2958 | /* Default long double to 64-bit for 32-bit Bionic and to __float128 |
2959 | for 64-bit Bionic. Also default long double to 64-bit for Intel |
2960 | MCU psABI. */ |
2961 | if ((TARGET_HAS_BIONIC || TARGET_IAMCU) |
2962 | && !(opts_set->x_target_flags |
2963 | & (MASK_LONG_DOUBLE_64 | MASK_LONG_DOUBLE_128))) |
2964 | opts->x_target_flags |= (TARGET_64BIT |
2965 | ? MASK_LONG_DOUBLE_128 |
2966 | : MASK_LONG_DOUBLE_64); |
2967 | |
2968 | /* Only one of them can be active. */ |
2969 | gcc_assert ((opts->x_target_flags & MASK_LONG_DOUBLE_64) == 0 |
2970 | || (opts->x_target_flags & MASK_LONG_DOUBLE_128) == 0); |
2971 | |
2972 | /* Handle stack protector */ |
2973 | if (!opts_set->x_ix86_stack_protector_guard) |
2974 | { |
2975 | #ifdef TARGET_THREAD_SSP_OFFSET |
2976 | if (!TARGET_HAS_BIONIC) |
2977 | opts->x_ix86_stack_protector_guard = SSP_TLS; |
2978 | else |
2979 | #endif |
2980 | opts->x_ix86_stack_protector_guard = SSP_GLOBAL; |
2981 | } |
2982 | |
2983 | if (opts_set->x_ix86_stack_protector_guard_offset_str) |
2984 | { |
2985 | char *endp; |
2986 | const char *str = opts->x_ix86_stack_protector_guard_offset_str; |
2987 | |
2988 | errno = 0; |
2989 | int64_t offset; |
2990 | |
2991 | #if defined(INT64_T_IS_LONG) |
2992 | offset = strtol (nptr: str, endptr: &endp, base: 0); |
2993 | #else |
2994 | offset = strtoll (str, &endp, 0); |
2995 | #endif |
2996 | |
2997 | if (!*str || *endp || errno) |
2998 | error ("%qs is not a valid number " |
2999 | "in %<-mstack-protector-guard-offset=%>" , str); |
3000 | |
3001 | if (!IN_RANGE (offset, HOST_WIDE_INT_C (-0x80000000), |
3002 | HOST_WIDE_INT_C (0x7fffffff))) |
3003 | error ("%qs is not a valid offset " |
3004 | "in %<-mstack-protector-guard-offset=%>" , str); |
3005 | |
3006 | opts->x_ix86_stack_protector_guard_offset = offset; |
3007 | } |
3008 | #ifdef TARGET_THREAD_SSP_OFFSET |
3009 | else |
3010 | opts->x_ix86_stack_protector_guard_offset = TARGET_THREAD_SSP_OFFSET; |
3011 | #endif |
3012 | |
3013 | if (opts_set->x_ix86_stack_protector_guard_reg_str) |
3014 | { |
3015 | const char *str = opts->x_ix86_stack_protector_guard_reg_str; |
3016 | addr_space_t seg = ADDR_SPACE_GENERIC; |
3017 | |
3018 | /* Discard optional register prefix. */ |
3019 | if (str[0] == '%') |
3020 | str++; |
3021 | |
3022 | if (strlen (s: str) == 2 && str[1] == 's') |
3023 | { |
3024 | if (str[0] == 'f') |
3025 | seg = ADDR_SPACE_SEG_FS; |
3026 | else if (str[0] == 'g') |
3027 | seg = ADDR_SPACE_SEG_GS; |
3028 | } |
3029 | |
3030 | if (seg == ADDR_SPACE_GENERIC) |
3031 | error ("%qs is not a valid base register " |
3032 | "in %<-mstack-protector-guard-reg=%>" , |
3033 | opts->x_ix86_stack_protector_guard_reg_str); |
3034 | |
3035 | opts->x_ix86_stack_protector_guard_reg = seg; |
3036 | } |
3037 | else |
3038 | { |
3039 | opts->x_ix86_stack_protector_guard_reg = DEFAULT_TLS_SEG_REG; |
3040 | |
3041 | /* The kernel uses a different segment register for performance |
3042 | reasons; a system call would not have to trash the userspace |
3043 | segment register, which would be expensive. */ |
3044 | if (opts->x_ix86_cmodel == CM_KERNEL) |
3045 | opts->x_ix86_stack_protector_guard_reg = ADDR_SPACE_SEG_GS; |
3046 | } |
3047 | |
3048 | /* Handle -mmemcpy-strategy= and -mmemset-strategy= */ |
3049 | if (opts->x_ix86_tune_memcpy_strategy) |
3050 | { |
3051 | char *str = xstrdup (opts->x_ix86_tune_memcpy_strategy); |
3052 | ix86_parse_stringop_strategy_string (strategy_str: str, is_memset: false); |
3053 | free (ptr: str); |
3054 | } |
3055 | |
3056 | if (opts->x_ix86_tune_memset_strategy) |
3057 | { |
3058 | char *str = xstrdup (opts->x_ix86_tune_memset_strategy); |
3059 | ix86_parse_stringop_strategy_string (strategy_str: str, is_memset: true); |
3060 | free (ptr: str); |
3061 | } |
3062 | |
3063 | /* Save the initial options in case the user does function specific |
3064 | options. */ |
3065 | if (main_args_p) |
3066 | { |
3067 | opts->x_ix86_excess_precision |
3068 | = opts->x_flag_excess_precision; |
3069 | opts->x_ix86_unsafe_math_optimizations |
3070 | = opts->x_flag_unsafe_math_optimizations; |
3071 | target_option_default_node = target_option_current_node |
3072 | = build_target_option_node (opts, opts_set); |
3073 | } |
3074 | |
3075 | if (opts->x_flag_cf_protection != CF_NONE) |
3076 | { |
3077 | if ((opts->x_flag_cf_protection & CF_BRANCH) == CF_BRANCH |
3078 | && !TARGET_64BIT && !TARGET_CMOV) |
3079 | error ("%<-fcf-protection%> is not compatible with this target" ); |
3080 | |
3081 | opts->x_flag_cf_protection |
3082 | = (cf_protection_level) (opts->x_flag_cf_protection | CF_SET); |
3083 | } |
3084 | |
3085 | if (ix86_tune_features [X86_TUNE_AVOID_256FMA_CHAINS]) |
3086 | SET_OPTION_IF_UNSET (opts, opts_set, param_avoid_fma_max_bits, 512); |
3087 | else if (ix86_tune_features [X86_TUNE_AVOID_256FMA_CHAINS]) |
3088 | SET_OPTION_IF_UNSET (opts, opts_set, param_avoid_fma_max_bits, 256); |
3089 | else if (ix86_tune_features [X86_TUNE_AVOID_128FMA_CHAINS]) |
3090 | SET_OPTION_IF_UNSET (opts, opts_set, param_avoid_fma_max_bits, 128); |
3091 | |
3092 | /* PR86952: jump table usage with retpolines is slow. |
3093 | The PR provides some numbers about the slowness. */ |
3094 | if (ix86_indirect_branch != indirect_branch_keep) |
3095 | SET_OPTION_IF_UNSET (opts, opts_set, flag_jump_tables, 0); |
3096 | |
3097 | SET_OPTION_IF_UNSET (opts, opts_set, param_ira_consider_dup_in_all_alts, 0); |
3098 | |
3099 | /* Fully masking the main or the epilogue vectorized loop is not |
3100 | profitable generally so leave it disabled until we get more |
3101 | fine grained control & costing. */ |
3102 | SET_OPTION_IF_UNSET (opts, opts_set, param_vect_partial_vector_usage, 0); |
3103 | |
3104 | return true; |
3105 | } |
3106 | |
3107 | /* Implement the TARGET_OPTION_OVERRIDE hook. */ |
3108 | |
3109 | void |
3110 | ix86_option_override (void) |
3111 | { |
3112 | ix86_option_override_internal (main_args_p: true, opts: &global_options, opts_set: &global_options_set); |
3113 | } |
3114 | |
3115 | /* Remember the last target of ix86_set_current_function. */ |
3116 | static GTY(()) tree ix86_previous_fndecl; |
3117 | |
3118 | /* Set targets globals to the default (or current #pragma GCC target |
3119 | if active). Invalidate ix86_previous_fndecl cache. */ |
3120 | |
3121 | void |
3122 | ix86_reset_previous_fndecl (void) |
3123 | { |
3124 | tree new_tree = target_option_current_node; |
3125 | cl_target_option_restore (&global_options, &global_options_set, |
3126 | TREE_TARGET_OPTION (new_tree)); |
3127 | if (TREE_TARGET_GLOBALS (new_tree)) |
3128 | restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); |
3129 | else if (new_tree == target_option_default_node) |
3130 | restore_target_globals (g: &default_target_globals); |
3131 | else |
3132 | TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts (); |
3133 | ix86_previous_fndecl = NULL_TREE; |
3134 | } |
3135 | |
3136 | /* Add target attribute to SIMD clone NODE if needed. */ |
3137 | |
3138 | void |
3139 | ix86_simd_clone_adjust (struct cgraph_node *node) |
3140 | { |
3141 | const char *str = NULL; |
3142 | |
3143 | /* Attributes need to be adjusted for definitions, not declarations. */ |
3144 | if (!node->definition) |
3145 | return; |
3146 | |
3147 | gcc_assert (node->decl == cfun->decl); |
3148 | switch (node->simdclone->vecsize_mangle) |
3149 | { |
3150 | case 'b': |
3151 | if (!TARGET_SSE2) |
3152 | str = "sse2" ; |
3153 | break; |
3154 | case 'c': |
3155 | if (TARGET_PREFER_AVX128) |
3156 | { |
3157 | if (!TARGET_AVX) |
3158 | str = "avx,prefer-vector-width=256" ; |
3159 | else |
3160 | str = "prefer-vector-width=256" ; |
3161 | } |
3162 | else if (!TARGET_AVX) |
3163 | str = "avx" ; |
3164 | break; |
3165 | case 'd': |
3166 | if (TARGET_PREFER_AVX128) |
3167 | { |
3168 | if (!TARGET_AVX2) |
3169 | str = "avx2,prefer-vector-width=256" ; |
3170 | else |
3171 | str = "prefer-vector-width=256" ; |
3172 | } |
3173 | else if (!TARGET_AVX2) |
3174 | str = "avx2" ; |
3175 | break; |
3176 | case 'e': |
3177 | if (TARGET_PREFER_AVX256) |
3178 | { |
3179 | if (!TARGET_AVX512F || !TARGET_EVEX512) |
3180 | str = "avx512f,evex512,prefer-vector-width=512" ; |
3181 | else |
3182 | str = "prefer-vector-width=512" ; |
3183 | } |
3184 | else if (!TARGET_AVX512F || !TARGET_EVEX512) |
3185 | str = "avx512f,evex512" ; |
3186 | break; |
3187 | default: |
3188 | gcc_unreachable (); |
3189 | } |
3190 | if (str == NULL) |
3191 | return; |
3192 | push_cfun (NULL); |
3193 | tree args = build_tree_list (NULL_TREE, build_string (strlen (s: str), str)); |
3194 | bool ok = ix86_valid_target_attribute_p (fndecl: node->decl, NULL, args, flags: 0); |
3195 | gcc_assert (ok); |
3196 | pop_cfun (); |
3197 | ix86_reset_previous_fndecl (); |
3198 | ix86_set_current_function (fndecl: node->decl); |
3199 | } |
3200 | |
3201 | |
3202 | |
3203 | /* Set the func_type field from the function FNDECL. */ |
3204 | |
3205 | static void |
3206 | ix86_set_func_type (tree fndecl) |
3207 | { |
3208 | if (cfun->machine->func_type == TYPE_UNKNOWN) |
3209 | { |
3210 | if (lookup_attribute (attr_name: "interrupt" , |
3211 | TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) |
3212 | { |
3213 | if (ix86_function_naked (fn: fndecl)) |
3214 | error_at (DECL_SOURCE_LOCATION (fndecl), |
3215 | "interrupt and naked attributes are not compatible" ); |
3216 | |
3217 | int nargs = 0; |
3218 | for (tree arg = DECL_ARGUMENTS (fndecl); |
3219 | arg; |
3220 | arg = TREE_CHAIN (arg)) |
3221 | nargs++; |
3222 | cfun->machine->no_caller_saved_registers = true; |
3223 | cfun->machine->func_type |
3224 | = nargs == 2 ? TYPE_EXCEPTION : TYPE_INTERRUPT; |
3225 | |
3226 | ix86_optimize_mode_switching[X86_DIRFLAG] = 1; |
3227 | |
3228 | /* Only dwarf2out.cc can handle -WORD(AP) as a pointer argument. */ |
3229 | if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG) |
3230 | sorry ("only DWARF debug format is supported for interrupt " |
3231 | "service routine" ); |
3232 | } |
3233 | else |
3234 | { |
3235 | cfun->machine->func_type = TYPE_NORMAL; |
3236 | if (lookup_attribute (attr_name: "no_caller_saved_registers" , |
3237 | TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) |
3238 | cfun->machine->no_caller_saved_registers = true; |
3239 | } |
3240 | } |
3241 | } |
3242 | |
3243 | /* Set the indirect_branch_type field from the function FNDECL. */ |
3244 | |
3245 | static void |
3246 | ix86_set_indirect_branch_type (tree fndecl) |
3247 | { |
3248 | if (cfun->machine->indirect_branch_type == indirect_branch_unset) |
3249 | { |
3250 | tree attr = lookup_attribute (attr_name: "indirect_branch" , |
3251 | DECL_ATTRIBUTES (fndecl)); |
3252 | if (attr != NULL) |
3253 | { |
3254 | tree args = TREE_VALUE (attr); |
3255 | if (args == NULL) |
3256 | gcc_unreachable (); |
3257 | tree cst = TREE_VALUE (args); |
3258 | if (strcmp (TREE_STRING_POINTER (cst), s2: "keep" ) == 0) |
3259 | cfun->machine->indirect_branch_type = indirect_branch_keep; |
3260 | else if (strcmp (TREE_STRING_POINTER (cst), s2: "thunk" ) == 0) |
3261 | cfun->machine->indirect_branch_type = indirect_branch_thunk; |
3262 | else if (strcmp (TREE_STRING_POINTER (cst), s2: "thunk-inline" ) == 0) |
3263 | cfun->machine->indirect_branch_type = indirect_branch_thunk_inline; |
3264 | else if (strcmp (TREE_STRING_POINTER (cst), s2: "thunk-extern" ) == 0) |
3265 | cfun->machine->indirect_branch_type = indirect_branch_thunk_extern; |
3266 | else |
3267 | gcc_unreachable (); |
3268 | } |
3269 | else |
3270 | cfun->machine->indirect_branch_type = ix86_indirect_branch; |
3271 | |
3272 | /* -mcmodel=large is not compatible with -mindirect-branch=thunk |
3273 | nor -mindirect-branch=thunk-extern. */ |
3274 | if ((ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC) |
3275 | && ((cfun->machine->indirect_branch_type |
3276 | == indirect_branch_thunk_extern) |
3277 | || (cfun->machine->indirect_branch_type |
3278 | == indirect_branch_thunk))) |
3279 | error ("%<-mindirect-branch=%s%> and %<-mcmodel=large%> are not " |
3280 | "compatible" , |
3281 | ((cfun->machine->indirect_branch_type |
3282 | == indirect_branch_thunk_extern) |
3283 | ? "thunk-extern" : "thunk" )); |
3284 | |
3285 | if (cfun->machine->indirect_branch_type != indirect_branch_keep |
3286 | && (cfun->machine->indirect_branch_type |
3287 | != indirect_branch_thunk_extern) |
3288 | && (flag_cf_protection & CF_RETURN)) |
3289 | error ("%<-mindirect-branch%> and %<-fcf-protection%> are not " |
3290 | "compatible" ); |
3291 | } |
3292 | |
3293 | if (cfun->machine->function_return_type == indirect_branch_unset) |
3294 | { |
3295 | tree attr = lookup_attribute (attr_name: "function_return" , |
3296 | DECL_ATTRIBUTES (fndecl)); |
3297 | if (attr != NULL) |
3298 | { |
3299 | tree args = TREE_VALUE (attr); |
3300 | if (args == NULL) |
3301 | gcc_unreachable (); |
3302 | tree cst = TREE_VALUE (args); |
3303 | if (strcmp (TREE_STRING_POINTER (cst), s2: "keep" ) == 0) |
3304 | cfun->machine->function_return_type = indirect_branch_keep; |
3305 | else if (strcmp (TREE_STRING_POINTER (cst), s2: "thunk" ) == 0) |
3306 | cfun->machine->function_return_type = indirect_branch_thunk; |
3307 | else if (strcmp (TREE_STRING_POINTER (cst), s2: "thunk-inline" ) == 0) |
3308 | cfun->machine->function_return_type = indirect_branch_thunk_inline; |
3309 | else if (strcmp (TREE_STRING_POINTER (cst), s2: "thunk-extern" ) == 0) |
3310 | cfun->machine->function_return_type = indirect_branch_thunk_extern; |
3311 | else |
3312 | gcc_unreachable (); |
3313 | } |
3314 | else |
3315 | cfun->machine->function_return_type = ix86_function_return; |
3316 | |
3317 | /* -mcmodel=large is not compatible with -mfunction-return=thunk |
3318 | nor -mfunction-return=thunk-extern. */ |
3319 | if ((ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC) |
3320 | && ((cfun->machine->function_return_type |
3321 | == indirect_branch_thunk_extern) |
3322 | || (cfun->machine->function_return_type |
3323 | == indirect_branch_thunk))) |
3324 | error ("%<-mfunction-return=%s%> and %<-mcmodel=large%> are not " |
3325 | "compatible" , |
3326 | ((cfun->machine->function_return_type |
3327 | == indirect_branch_thunk_extern) |
3328 | ? "thunk-extern" : "thunk" )); |
3329 | |
3330 | if (cfun->machine->function_return_type != indirect_branch_keep |
3331 | && (cfun->machine->function_return_type |
3332 | != indirect_branch_thunk_extern) |
3333 | && (flag_cf_protection & CF_RETURN)) |
3334 | error ("%<-mfunction-return%> and %<-fcf-protection%> are not " |
3335 | "compatible" ); |
3336 | } |
3337 | } |
3338 | |
3339 | /* Establish appropriate back-end context for processing the function |
3340 | FNDECL. The argument might be NULL to indicate processing at top |
3341 | level, outside of any function scope. */ |
3342 | void |
3343 | ix86_set_current_function (tree fndecl) |
3344 | { |
3345 | /* Only change the context if the function changes. This hook is called |
3346 | several times in the course of compiling a function, and we don't want to |
3347 | slow things down too much or call target_reinit when it isn't safe. */ |
3348 | if (fndecl == ix86_previous_fndecl) |
3349 | { |
3350 | /* There may be 2 function bodies for the same function FNDECL, |
3351 | one is extern inline and one isn't. Call ix86_set_func_type |
3352 | to set the func_type field. */ |
3353 | if (fndecl != NULL_TREE) |
3354 | { |
3355 | ix86_set_func_type (fndecl); |
3356 | ix86_set_indirect_branch_type (fndecl); |
3357 | } |
3358 | return; |
3359 | } |
3360 | |
3361 | tree old_tree; |
3362 | if (ix86_previous_fndecl == NULL_TREE) |
3363 | old_tree = target_option_current_node; |
3364 | else if (DECL_FUNCTION_SPECIFIC_TARGET (ix86_previous_fndecl)) |
3365 | old_tree = DECL_FUNCTION_SPECIFIC_TARGET (ix86_previous_fndecl); |
3366 | else |
3367 | old_tree = target_option_default_node; |
3368 | |
3369 | if (fndecl == NULL_TREE) |
3370 | { |
3371 | if (old_tree != target_option_current_node) |
3372 | ix86_reset_previous_fndecl (); |
3373 | return; |
3374 | } |
3375 | |
3376 | ix86_set_func_type (fndecl); |
3377 | ix86_set_indirect_branch_type (fndecl); |
3378 | |
3379 | tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); |
3380 | if (new_tree == NULL_TREE) |
3381 | new_tree = target_option_default_node; |
3382 | |
3383 | bool fp_flag_change |
3384 | = (flag_unsafe_math_optimizations |
3385 | != TREE_TARGET_OPTION (new_tree)->x_ix86_unsafe_math_optimizations |
3386 | || (flag_excess_precision |
3387 | != TREE_TARGET_OPTION (new_tree)->x_ix86_excess_precision)); |
3388 | if (old_tree != new_tree || fp_flag_change) |
3389 | { |
3390 | cl_target_option_restore (&global_options, &global_options_set, |
3391 | TREE_TARGET_OPTION (new_tree)); |
3392 | if (fp_flag_change) |
3393 | { |
3394 | ix86_excess_precision = flag_excess_precision; |
3395 | ix86_unsafe_math_optimizations = flag_unsafe_math_optimizations; |
3396 | DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_tree |
3397 | = build_target_option_node (opts: &global_options, opts_set: &global_options_set); |
3398 | } |
3399 | if (TREE_TARGET_GLOBALS (new_tree)) |
3400 | restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); |
3401 | else if (new_tree == target_option_default_node) |
3402 | restore_target_globals (g: &default_target_globals); |
3403 | else |
3404 | TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts (); |
3405 | } |
3406 | ix86_previous_fndecl = fndecl; |
3407 | |
3408 | static bool prev_no_caller_saved_registers; |
3409 | |
3410 | /* 64-bit MS and SYSV ABI have different set of call used registers. |
3411 | Avoid expensive re-initialization of init_regs each time we switch |
3412 | function context. */ |
3413 | if (TARGET_64BIT |
3414 | && (call_used_or_fixed_reg_p (SI_REG) |
3415 | == (cfun->machine->call_abi == MS_ABI))) |
3416 | reinit_regs (); |
3417 | /* Need to re-initialize init_regs if caller-saved registers are |
3418 | changed. */ |
3419 | else if (prev_no_caller_saved_registers |
3420 | != cfun->machine->no_caller_saved_registers) |
3421 | reinit_regs (); |
3422 | |
3423 | if (cfun->machine->func_type != TYPE_NORMAL |
3424 | || cfun->machine->no_caller_saved_registers) |
3425 | { |
3426 | /* Don't allow SSE, MMX nor x87 instructions since they |
3427 | may change processor state. */ |
3428 | const char *isa; |
3429 | if (TARGET_SSE) |
3430 | isa = "SSE" ; |
3431 | else if (TARGET_MMX) |
3432 | isa = "MMX/3Dnow" ; |
3433 | else if (TARGET_80387) |
3434 | isa = "80387" ; |
3435 | else |
3436 | isa = NULL; |
3437 | if (isa != NULL) |
3438 | { |
3439 | if (cfun->machine->func_type != TYPE_NORMAL) |
3440 | sorry (cfun->machine->func_type == TYPE_EXCEPTION |
3441 | ? G_("%s instructions aren%'t allowed in an" |
3442 | " exception service routine" ) |
3443 | : G_("%s instructions aren%'t allowed in an" |
3444 | " interrupt service routine" ), |
3445 | isa); |
3446 | else |
3447 | sorry ("%s instructions aren%'t allowed in a function with " |
3448 | "the %<no_caller_saved_registers%> attribute" , isa); |
3449 | /* Don't issue the same error twice. */ |
3450 | cfun->machine->func_type = TYPE_NORMAL; |
3451 | cfun->machine->no_caller_saved_registers = false; |
3452 | } |
3453 | } |
3454 | |
3455 | prev_no_caller_saved_registers |
3456 | = cfun->machine->no_caller_saved_registers; |
3457 | } |
3458 | |
3459 | /* Implement the TARGET_OFFLOAD_OPTIONS hook. */ |
3460 | char * |
3461 | ix86_offload_options (void) |
3462 | { |
3463 | if (TARGET_LP64) |
3464 | return xstrdup ("-foffload-abi=lp64" ); |
3465 | return xstrdup ("-foffload-abi=ilp32" ); |
3466 | } |
3467 | |
3468 | /* Handle "cdecl", "stdcall", "fastcall", "regparm", "thiscall", |
3469 | and "sseregparm" calling convention attributes; |
3470 | arguments as in struct attribute_spec.handler. */ |
3471 | |
3472 | static tree |
3473 | ix86_handle_cconv_attribute (tree *node, tree name, tree args, int, |
3474 | bool *no_add_attrs) |
3475 | { |
3476 | if (TREE_CODE (*node) != FUNCTION_TYPE |
3477 | && TREE_CODE (*node) != METHOD_TYPE |
3478 | && TREE_CODE (*node) != FIELD_DECL |
3479 | && TREE_CODE (*node) != TYPE_DECL) |
3480 | { |
3481 | warning (OPT_Wattributes, "%qE attribute only applies to functions" , |
3482 | name); |
3483 | *no_add_attrs = true; |
3484 | return NULL_TREE; |
3485 | } |
3486 | |
3487 | /* Can combine regparm with all attributes but fastcall, and thiscall. */ |
3488 | if (is_attribute_p (attr_name: "regparm" , ident: name)) |
3489 | { |
3490 | tree cst; |
3491 | |
3492 | if (lookup_attribute (attr_name: "fastcall" , TYPE_ATTRIBUTES (*node))) |
3493 | { |
3494 | error ("fastcall and regparm attributes are not compatible" ); |
3495 | } |
3496 | |
3497 | if (lookup_attribute (attr_name: "thiscall" , TYPE_ATTRIBUTES (*node))) |
3498 | { |
3499 | error ("regparam and thiscall attributes are not compatible" ); |
3500 | } |
3501 | |
3502 | cst = TREE_VALUE (args); |
3503 | if (TREE_CODE (cst) != INTEGER_CST) |
3504 | { |
3505 | warning (OPT_Wattributes, |
3506 | "%qE attribute requires an integer constant argument" , |
3507 | name); |
3508 | *no_add_attrs = true; |
3509 | } |
3510 | else if (compare_tree_int (cst, REGPARM_MAX) > 0) |
3511 | { |
3512 | warning (OPT_Wattributes, "argument to %qE attribute larger than %d" , |
3513 | name, REGPARM_MAX); |
3514 | *no_add_attrs = true; |
3515 | } |
3516 | |
3517 | return NULL_TREE; |
3518 | } |
3519 | |
3520 | if (TARGET_64BIT) |
3521 | { |
3522 | /* Do not warn when emulating the MS ABI. */ |
3523 | if ((TREE_CODE (*node) != FUNCTION_TYPE |
3524 | && TREE_CODE (*node) != METHOD_TYPE) |
3525 | || ix86_function_type_abi (*node) != MS_ABI) |
3526 | warning (OPT_Wattributes, "%qE attribute ignored" , |
3527 | name); |
3528 | *no_add_attrs = true; |
3529 | return NULL_TREE; |
3530 | } |
3531 | |
3532 | /* Can combine fastcall with stdcall (redundant) and sseregparm. */ |
3533 | if (is_attribute_p (attr_name: "fastcall" , ident: name)) |
3534 | { |
3535 | if (lookup_attribute (attr_name: "cdecl" , TYPE_ATTRIBUTES (*node))) |
3536 | { |
3537 | error ("fastcall and cdecl attributes are not compatible" ); |
3538 | } |
3539 | if (lookup_attribute (attr_name: "stdcall" , TYPE_ATTRIBUTES (*node))) |
3540 | { |
3541 | error ("fastcall and stdcall attributes are not compatible" ); |
3542 | } |
3543 | if (lookup_attribute (attr_name: "regparm" , TYPE_ATTRIBUTES (*node))) |
3544 | { |
3545 | error ("fastcall and regparm attributes are not compatible" ); |
3546 | } |
3547 | if (lookup_attribute (attr_name: "thiscall" , TYPE_ATTRIBUTES (*node))) |
3548 | { |
3549 | error ("fastcall and thiscall attributes are not compatible" ); |
3550 | } |
3551 | } |
3552 | |
3553 | /* Can combine stdcall with fastcall (redundant), regparm and |
3554 | sseregparm. */ |
3555 | else if (is_attribute_p (attr_name: "stdcall" , ident: name)) |
3556 | { |
3557 | if (lookup_attribute (attr_name: "cdecl" , TYPE_ATTRIBUTES (*node))) |
3558 | { |
3559 | error ("stdcall and cdecl attributes are not compatible" ); |
3560 | } |
3561 | if (lookup_attribute (attr_name: "fastcall" , TYPE_ATTRIBUTES (*node))) |
3562 | { |
3563 | error ("stdcall and fastcall attributes are not compatible" ); |
3564 | } |
3565 | if (lookup_attribute (attr_name: "thiscall" , TYPE_ATTRIBUTES (*node))) |
3566 | { |
3567 | error ("stdcall and thiscall attributes are not compatible" ); |
3568 | } |
3569 | } |
3570 | |
3571 | /* Can combine cdecl with regparm and sseregparm. */ |
3572 | else if (is_attribute_p (attr_name: "cdecl" , ident: name)) |
3573 | { |
3574 | if (lookup_attribute (attr_name: "stdcall" , TYPE_ATTRIBUTES (*node))) |
3575 | { |
3576 | error ("stdcall and cdecl attributes are not compatible" ); |
3577 | } |
3578 | if (lookup_attribute (attr_name: "fastcall" , TYPE_ATTRIBUTES (*node))) |
3579 | { |
3580 | error ("fastcall and cdecl attributes are not compatible" ); |
3581 | } |
3582 | if (lookup_attribute (attr_name: "thiscall" , TYPE_ATTRIBUTES (*node))) |
3583 | { |
3584 | error ("cdecl and thiscall attributes are not compatible" ); |
3585 | } |
3586 | } |
3587 | else if (is_attribute_p (attr_name: "thiscall" , ident: name)) |
3588 | { |
3589 | if (TREE_CODE (*node) != METHOD_TYPE && pedantic) |
3590 | warning (OPT_Wattributes, "%qE attribute is used for non-class method" , |
3591 | name); |
3592 | if (lookup_attribute (attr_name: "stdcall" , TYPE_ATTRIBUTES (*node))) |
3593 | { |
3594 | error ("stdcall and thiscall attributes are not compatible" ); |
3595 | } |
3596 | if (lookup_attribute (attr_name: "fastcall" , TYPE_ATTRIBUTES (*node))) |
3597 | { |
3598 | error ("fastcall and thiscall attributes are not compatible" ); |
3599 | } |
3600 | if (lookup_attribute (attr_name: "cdecl" , TYPE_ATTRIBUTES (*node))) |
3601 | { |
3602 | error ("cdecl and thiscall attributes are not compatible" ); |
3603 | } |
3604 | } |
3605 | |
3606 | /* Can combine sseregparm with all attributes. */ |
3607 | |
3608 | return NULL_TREE; |
3609 | } |
3610 | |
3611 | #ifndef CHECK_STACK_LIMIT |
3612 | #define CHECK_STACK_LIMIT (-1) |
3613 | #endif |
3614 | |
3615 | /* The transactional memory builtins are implicitly regparm or fastcall |
3616 | depending on the ABI. Override the generic do-nothing attribute that |
3617 | these builtins were declared with, and replace it with one of the two |
3618 | attributes that we expect elsewhere. */ |
3619 | |
3620 | static tree |
3621 | ix86_handle_tm_regparm_attribute (tree *node, tree, tree, |
3622 | int flags, bool *no_add_attrs) |
3623 | { |
3624 | tree alt; |
3625 | |
3626 | /* In no case do we want to add the placeholder attribute. */ |
3627 | *no_add_attrs = true; |
3628 | |
3629 | /* The 64-bit ABI is unchanged for transactional memory. */ |
3630 | if (TARGET_64BIT) |
3631 | return NULL_TREE; |
3632 | |
3633 | /* ??? Is there a better way to validate 32-bit windows? We have |
3634 | cfun->machine->call_abi, but that seems to be set only for 64-bit. */ |
3635 | if (CHECK_STACK_LIMIT > 0) |
3636 | alt = tree_cons (get_identifier ("fastcall" ), NULL, NULL); |
3637 | else |
3638 | { |
3639 | alt = tree_cons (NULL, build_int_cst (NULL, 2), NULL); |
3640 | alt = tree_cons (get_identifier ("regparm" ), alt, NULL); |
3641 | } |
3642 | decl_attributes (node, alt, flags); |
3643 | |
3644 | return NULL_TREE; |
3645 | } |
3646 | |
3647 | /* Handle a "force_align_arg_pointer" attribute. */ |
3648 | |
3649 | static tree |
3650 | ix86_handle_force_align_arg_pointer_attribute (tree *node, tree name, |
3651 | tree, int, bool *no_add_attrs) |
3652 | { |
3653 | if (TREE_CODE (*node) != FUNCTION_TYPE |
3654 | && TREE_CODE (*node) != METHOD_TYPE |
3655 | && TREE_CODE (*node) != FIELD_DECL |
3656 | && TREE_CODE (*node) != TYPE_DECL) |
3657 | { |
3658 | warning (OPT_Wattributes, "%qE attribute only applies to functions" , |
3659 | name); |
3660 | *no_add_attrs = true; |
3661 | } |
3662 | |
3663 | return NULL_TREE; |
3664 | } |
3665 | |
3666 | /* Handle a "ms_struct" or "gcc_struct" attribute; arguments as in |
3667 | struct attribute_spec.handler. */ |
3668 | |
3669 | static tree |
3670 | ix86_handle_struct_attribute (tree *node, tree name, tree, int, |
3671 | bool *no_add_attrs) |
3672 | { |
3673 | tree *type = NULL; |
3674 | if (DECL_P (*node)) |
3675 | { |
3676 | if (TREE_CODE (*node) == TYPE_DECL) |
3677 | type = &TREE_TYPE (*node); |
3678 | } |
3679 | else |
3680 | type = node; |
3681 | |
3682 | if (!(type && RECORD_OR_UNION_TYPE_P (*type))) |
3683 | { |
3684 | warning (OPT_Wattributes, "%qE attribute ignored" , |
3685 | name); |
3686 | *no_add_attrs = true; |
3687 | } |
3688 | |
3689 | else if ((is_attribute_p (attr_name: "ms_struct" , ident: name) |
3690 | && lookup_attribute (attr_name: "gcc_struct" , TYPE_ATTRIBUTES (*type))) |
3691 | || ((is_attribute_p (attr_name: "gcc_struct" , ident: name) |
3692 | && lookup_attribute (attr_name: "ms_struct" , TYPE_ATTRIBUTES (*type))))) |
3693 | { |
3694 | warning (OPT_Wattributes, "%qE incompatible attribute ignored" , |
3695 | name); |
3696 | *no_add_attrs = true; |
3697 | } |
3698 | |
3699 | return NULL_TREE; |
3700 | } |
3701 | |
3702 | /* Handle a "callee_pop_aggregate_return" attribute; arguments as |
3703 | in struct attribute_spec handler. */ |
3704 | |
3705 | static tree |
3706 | ix86_handle_callee_pop_aggregate_return (tree *node, tree name, tree args, int, |
3707 | bool *no_add_attrs) |
3708 | { |
3709 | if (TREE_CODE (*node) != FUNCTION_TYPE |
3710 | && TREE_CODE (*node) != METHOD_TYPE |
3711 | && TREE_CODE (*node) != FIELD_DECL |
3712 | && TREE_CODE (*node) != TYPE_DECL) |
3713 | { |
3714 | warning (OPT_Wattributes, "%qE attribute only applies to functions" , |
3715 | name); |
3716 | *no_add_attrs = true; |
3717 | return NULL_TREE; |
3718 | } |
3719 | if (TARGET_64BIT) |
3720 | { |
3721 | warning (OPT_Wattributes, "%qE attribute only available for 32-bit" , |
3722 | name); |
3723 | *no_add_attrs = true; |
3724 | return NULL_TREE; |
3725 | } |
3726 | if (is_attribute_p (attr_name: "callee_pop_aggregate_return" , ident: name)) |
3727 | { |
3728 | tree cst; |
3729 | |
3730 | cst = TREE_VALUE (args); |
3731 | if (TREE_CODE (cst) != INTEGER_CST) |
3732 | { |
3733 | warning (OPT_Wattributes, |
3734 | "%qE attribute requires an integer constant argument" , |
3735 | name); |
3736 | *no_add_attrs = true; |
3737 | } |
3738 | else if (compare_tree_int (cst, 0) != 0 |
3739 | && compare_tree_int (cst, 1) != 0) |
3740 | { |
3741 | warning (OPT_Wattributes, |
3742 | "argument to %qE attribute is neither zero, nor one" , |
3743 | name); |
3744 | *no_add_attrs = true; |
3745 | } |
3746 | |
3747 | return NULL_TREE; |
3748 | } |
3749 | |
3750 | return NULL_TREE; |
3751 | } |
3752 | |
3753 | /* Handle a "ms_abi" or "sysv" attribute; arguments as in |
3754 | struct attribute_spec.handler. */ |
3755 | |
3756 | static tree |
3757 | ix86_handle_abi_attribute (tree *node, tree name, tree, int, |
3758 | bool *no_add_attrs) |
3759 | { |
3760 | if (TREE_CODE (*node) != FUNCTION_TYPE |
3761 | && TREE_CODE (*node) != METHOD_TYPE |
3762 | && TREE_CODE (*node) != FIELD_DECL |
3763 | && TREE_CODE (*node) != TYPE_DECL) |
3764 | { |
3765 | warning (OPT_Wattributes, "%qE attribute only applies to functions" , |
3766 | name); |
3767 | *no_add_attrs = true; |
3768 | return NULL_TREE; |
3769 | } |
3770 | |
3771 | /* Can combine regparm with all attributes but fastcall. */ |
3772 | if (is_attribute_p (attr_name: "ms_abi" , ident: name)) |
3773 | { |
3774 | if (lookup_attribute (attr_name: "sysv_abi" , TYPE_ATTRIBUTES (*node))) |
3775 | { |
3776 | error ("%qs and %qs attributes are not compatible" , |
3777 | "ms_abi" , "sysv_abi" ); |
3778 | } |
3779 | |
3780 | return NULL_TREE; |
3781 | } |
3782 | else if (is_attribute_p (attr_name: "sysv_abi" , ident: name)) |
3783 | { |
3784 | if (lookup_attribute (attr_name: "ms_abi" , TYPE_ATTRIBUTES (*node))) |
3785 | { |
3786 | error ("%qs and %qs attributes are not compatible" , |
3787 | "ms_abi" , "sysv_abi" ); |
3788 | } |
3789 | |
3790 | return NULL_TREE; |
3791 | } |
3792 | |
3793 | return NULL_TREE; |
3794 | } |
3795 | |
3796 | static tree |
3797 | ix86_handle_fndecl_attribute (tree *node, tree name, tree args, int, |
3798 | bool *no_add_attrs) |
3799 | { |
3800 | if (TREE_CODE (*node) != FUNCTION_DECL) |
3801 | { |
3802 | warning (OPT_Wattributes, "%qE attribute only applies to functions" , |
3803 | name); |
3804 | *no_add_attrs = true; |
3805 | } |
3806 | |
3807 | if (is_attribute_p (attr_name: "indirect_branch" , ident: name)) |
3808 | { |
3809 | tree cst = TREE_VALUE (args); |
3810 | if (TREE_CODE (cst) != STRING_CST) |
3811 | { |
3812 | warning (OPT_Wattributes, |
3813 | "%qE attribute requires a string constant argument" , |
3814 | name); |
3815 | *no_add_attrs = true; |
3816 | } |
3817 | else if (strcmp (TREE_STRING_POINTER (cst), s2: "keep" ) != 0 |
3818 | && strcmp (TREE_STRING_POINTER (cst), s2: "thunk" ) != 0 |
3819 | && strcmp (TREE_STRING_POINTER (cst), s2: "thunk-inline" ) != 0 |
3820 | && strcmp (TREE_STRING_POINTER (cst), s2: "thunk-extern" ) != 0) |
3821 | { |
3822 | warning (OPT_Wattributes, |
3823 | "argument to %qE attribute is not " |
3824 | "(keep|thunk|thunk-inline|thunk-extern)" , name); |
3825 | *no_add_attrs = true; |
3826 | } |
3827 | } |
3828 | |
3829 | if (is_attribute_p (attr_name: "function_return" , ident: name)) |
3830 | { |
3831 | tree cst = TREE_VALUE (args); |
3832 | if (TREE_CODE (cst) != STRING_CST) |
3833 | { |
3834 | warning (OPT_Wattributes, |
3835 | "%qE attribute requires a string constant argument" , |
3836 | name); |
3837 | *no_add_attrs = true; |
3838 | } |
3839 | else if (strcmp (TREE_STRING_POINTER (cst), s2: "keep" ) != 0 |
3840 | && strcmp (TREE_STRING_POINTER (cst), s2: "thunk" ) != 0 |
3841 | && strcmp (TREE_STRING_POINTER (cst), s2: "thunk-inline" ) != 0 |
3842 | && strcmp (TREE_STRING_POINTER (cst), s2: "thunk-extern" ) != 0) |
3843 | { |
3844 | warning (OPT_Wattributes, |
3845 | "argument to %qE attribute is not " |
3846 | "(keep|thunk|thunk-inline|thunk-extern)" , name); |
3847 | *no_add_attrs = true; |
3848 | } |
3849 | } |
3850 | |
3851 | return NULL_TREE; |
3852 | } |
3853 | |
3854 | static tree |
3855 | ix86_handle_no_caller_saved_registers_attribute (tree *, tree, tree, |
3856 | int, bool *) |
3857 | { |
3858 | return NULL_TREE; |
3859 | } |
3860 | |
3861 | static tree |
3862 | ix86_handle_interrupt_attribute (tree *node, tree, tree, int, bool *) |
3863 | { |
3864 | /* DECL_RESULT and DECL_ARGUMENTS do not exist there yet, |
3865 | but the function type contains args and return type data. */ |
3866 | tree func_type = *node; |
3867 | tree return_type = TREE_TYPE (func_type); |
3868 | |
3869 | int nargs = 0; |
3870 | tree current_arg_type = TYPE_ARG_TYPES (func_type); |
3871 | while (current_arg_type |
3872 | && ! VOID_TYPE_P (TREE_VALUE (current_arg_type))) |
3873 | { |
3874 | if (nargs == 0) |
3875 | { |
3876 | if (! POINTER_TYPE_P (TREE_VALUE (current_arg_type))) |
3877 | error ("interrupt service routine should have a pointer " |
3878 | "as the first argument" ); |
3879 | } |
3880 | else if (nargs == 1) |
3881 | { |
3882 | if (TREE_CODE (TREE_VALUE (current_arg_type)) != INTEGER_TYPE |
3883 | || TYPE_MODE (TREE_VALUE (current_arg_type)) != word_mode) |
3884 | error ("interrupt service routine should have %qs " |
3885 | "as the second argument" , |
3886 | TARGET_64BIT |
3887 | ? (TARGET_X32 ? "unsigned long long int" |
3888 | : "unsigned long int" ) |
3889 | : "unsigned int" ); |
3890 | } |
3891 | nargs++; |
3892 | current_arg_type = TREE_CHAIN (current_arg_type); |
3893 | } |
3894 | if (!nargs || nargs > 2) |
3895 | error ("interrupt service routine can only have a pointer argument " |
3896 | "and an optional integer argument" ); |
3897 | if (! VOID_TYPE_P (return_type)) |
3898 | error ("interrupt service routine must return %<void%>" ); |
3899 | |
3900 | return NULL_TREE; |
3901 | } |
3902 | |
3903 | /* Handle fentry_name / fentry_section attribute. */ |
3904 | |
3905 | static tree |
3906 | ix86_handle_fentry_name (tree *node, tree name, tree args, |
3907 | int, bool *no_add_attrs) |
3908 | { |
3909 | if (TREE_CODE (*node) == FUNCTION_DECL |
3910 | && TREE_CODE (TREE_VALUE (args)) == STRING_CST) |
3911 | /* Do nothing else, just set the attribute. We'll get at |
3912 | it later with lookup_attribute. */ |
3913 | ; |
3914 | else |
3915 | { |
3916 | warning (OPT_Wattributes, "%qE attribute ignored" , name); |
3917 | *no_add_attrs = true; |
3918 | } |
3919 | |
3920 | return NULL_TREE; |
3921 | } |
3922 | |
3923 | /* Handle a "nodirect_extern_access" attribute; arguments as in |
3924 | struct attribute_spec.handler. */ |
3925 | |
3926 | static tree |
3927 | handle_nodirect_extern_access_attribute (tree *pnode, tree name, |
3928 | tree ARG_UNUSED (args), |
3929 | int ARG_UNUSED (flags), |
3930 | bool *no_add_attrs) |
3931 | { |
3932 | tree node = *pnode; |
3933 | |
3934 | if (VAR_OR_FUNCTION_DECL_P (node)) |
3935 | { |
3936 | if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL |
3937 | && !DECL_EXTERNAL (node)) || !TREE_PUBLIC (node)) |
3938 | { |
3939 | warning (OPT_Wattributes, |
3940 | "%qE attribute have effect only on public objects" , name); |
3941 | *no_add_attrs = true; |
3942 | } |
3943 | } |
3944 | else |
3945 | { |
3946 | warning (OPT_Wattributes, "%qE attribute ignored" , name); |
3947 | *no_add_attrs = true; |
3948 | } |
3949 | |
3950 | return NULL_TREE; |
3951 | } |
3952 | |
3953 | /* Table of valid machine attributes. */ |
3954 | const struct attribute_spec ix86_attribute_table[] = |
3955 | { |
3956 | /* { name, min_len, max_len, decl_req, type_req, fn_type_req, |
3957 | affects_type_identity, handler, exclude } */ |
3958 | /* Stdcall attribute says callee is responsible for popping arguments |
3959 | if they are not variable. */ |
3960 | { .name: "stdcall" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: true, .handler: ix86_handle_cconv_attribute, |
3961 | NULL }, |
3962 | /* Fastcall attribute says callee is responsible for popping arguments |
3963 | if they are not variable. */ |
3964 | { .name: "fastcall" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: true, .handler: ix86_handle_cconv_attribute, |
3965 | NULL }, |
3966 | /* Thiscall attribute says callee is responsible for popping arguments |
3967 | if they are not variable. */ |
3968 | { .name: "thiscall" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: true, .handler: ix86_handle_cconv_attribute, |
3969 | NULL }, |
3970 | /* Cdecl attribute says the callee is a normal C declaration */ |
3971 | { .name: "cdecl" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: true, .handler: ix86_handle_cconv_attribute, |
3972 | NULL }, |
3973 | /* Regparm attribute specifies how many integer arguments are to be |
3974 | passed in registers. */ |
3975 | { .name: "regparm" , .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: true, .handler: ix86_handle_cconv_attribute, |
3976 | NULL }, |
3977 | /* Sseregparm attribute says we are using x86_64 calling conventions |
3978 | for FP arguments. */ |
3979 | { .name: "sseregparm" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: true, .handler: ix86_handle_cconv_attribute, |
3980 | NULL }, |
3981 | /* The transactional memory builtins are implicitly regparm or fastcall |
3982 | depending on the ABI. Override the generic do-nothing attribute that |
3983 | these builtins were declared with. */ |
3984 | { .name: "*tm regparm" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: true, |
3985 | .handler: ix86_handle_tm_regparm_attribute, NULL }, |
3986 | /* force_align_arg_pointer says this function realigns the stack at entry. */ |
3987 | { .name: "force_align_arg_pointer" , .min_length: 0, .max_length: 0, |
3988 | .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, .handler: ix86_handle_force_align_arg_pointer_attribute, |
3989 | NULL }, |
3990 | #if TARGET_DLLIMPORT_DECL_ATTRIBUTES |
3991 | { "dllimport" , 0, 0, false, false, false, false, handle_dll_attribute, |
3992 | NULL }, |
3993 | { "dllexport" , 0, 0, false, false, false, false, handle_dll_attribute, |
3994 | NULL }, |
3995 | { "shared" , 0, 0, true, false, false, false, |
3996 | ix86_handle_shared_attribute, NULL }, |
3997 | #endif |
3998 | { .name: "ms_struct" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
3999 | .handler: ix86_handle_struct_attribute, NULL }, |
4000 | { .name: "gcc_struct" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
4001 | .handler: ix86_handle_struct_attribute, NULL }, |
4002 | #ifdef SUBTARGET_ATTRIBUTE_TABLE |
4003 | SUBTARGET_ATTRIBUTE_TABLE, |
4004 | #endif |
4005 | /* ms_abi and sysv_abi calling convention function attributes. */ |
4006 | { .name: "ms_abi" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: true, .handler: ix86_handle_abi_attribute, NULL }, |
4007 | { .name: "sysv_abi" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: true, .handler: ix86_handle_abi_attribute, |
4008 | NULL }, |
4009 | { .name: "ms_abi va_list" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false, NULL, NULL }, |
4010 | { .name: "sysv_abi va_list" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false, NULL, NULL }, |
4011 | { .name: "ms_hook_prologue" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
4012 | .handler: ix86_handle_fndecl_attribute, NULL }, |
4013 | { .name: "callee_pop_aggregate_return" , .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: true, |
4014 | .handler: ix86_handle_callee_pop_aggregate_return, NULL }, |
4015 | { .name: "interrupt" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, |
4016 | .handler: ix86_handle_interrupt_attribute, NULL }, |
4017 | { .name: "no_caller_saved_registers" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, |
4018 | .handler: ix86_handle_no_caller_saved_registers_attribute, NULL }, |
4019 | { .name: "naked" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
4020 | .handler: ix86_handle_fndecl_attribute, NULL }, |
4021 | { .name: "indirect_branch" , .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
4022 | .handler: ix86_handle_fndecl_attribute, NULL }, |
4023 | { .name: "function_return" , .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
4024 | .handler: ix86_handle_fndecl_attribute, NULL }, |
4025 | { .name: "indirect_return" , .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false, |
4026 | NULL, NULL }, |
4027 | { .name: "fentry_name" , .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
4028 | .handler: ix86_handle_fentry_name, NULL }, |
4029 | { .name: "fentry_section" , .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
4030 | .handler: ix86_handle_fentry_name, NULL }, |
4031 | { .name: "cf_check" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
4032 | .handler: ix86_handle_fndecl_attribute, NULL }, |
4033 | { .name: "nodirect_extern_access" , .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false, |
4034 | .handler: handle_nodirect_extern_access_attribute, NULL }, |
4035 | |
4036 | /* End element. */ |
4037 | { NULL, .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false, NULL, NULL } |
4038 | }; |
4039 | |
4040 | #include "gt-i386-options.h" |
4041 | |