File: | build/gcc/config/i386/i386-expand.cc |
Warning: | line 5678, column 15 Called function pointer is null (null dereference) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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_CODE1 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 "tree-vectorizer.h" | |||
70 | #include "shrink-wrap.h" | |||
71 | #include "builtins.h" | |||
72 | #include "rtl-iter.h" | |||
73 | #include "tree-iterator.h" | |||
74 | #include "dbgcnt.h" | |||
75 | #include "case-cfn-macros.h" | |||
76 | #include "dojump.h" | |||
77 | #include "fold-const-call.h" | |||
78 | #include "tree-vrp.h" | |||
79 | #include "tree-ssanames.h" | |||
80 | #include "selftest.h" | |||
81 | #include "selftest-rtl.h" | |||
82 | #include "print-rtl.h" | |||
83 | #include "intl.h" | |||
84 | #include "ifcvt.h" | |||
85 | #include "symbol-summary.h" | |||
86 | #include "ipa-prop.h" | |||
87 | #include "ipa-fnsummary.h" | |||
88 | #include "wide-int-bitmask.h" | |||
89 | #include "tree-vector-builder.h" | |||
90 | #include "debug.h" | |||
91 | #include "dwarf2out.h" | |||
92 | #include "i386-options.h" | |||
93 | #include "i386-builtins.h" | |||
94 | #include "i386-expand.h" | |||
95 | #include "asan.h" | |||
96 | ||||
97 | /* Split one or more double-mode RTL references into pairs of half-mode | |||
98 | references. The RTL can be REG, offsettable MEM, integer constant, or | |||
99 | CONST_DOUBLE. "operands" is a pointer to an array of double-mode RTLs to | |||
100 | split and "num" is its length. lo_half and hi_half are output arrays | |||
101 | that parallel "operands". */ | |||
102 | ||||
103 | void | |||
104 | split_double_mode (machine_mode mode, rtx operands[], | |||
105 | int num, rtx lo_half[], rtx hi_half[]) | |||
106 | { | |||
107 | machine_mode half_mode; | |||
108 | unsigned int byte; | |||
109 | rtx mem_op = NULL_RTX(rtx) 0; | |||
110 | int mem_num = 0; | |||
111 | ||||
112 | switch (mode) | |||
113 | { | |||
114 | case E_TImode: | |||
115 | half_mode = DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)); | |||
116 | break; | |||
117 | case E_DImode: | |||
118 | half_mode = SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)); | |||
119 | break; | |||
120 | case E_P2HImode: | |||
121 | half_mode = HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode)); | |||
122 | break; | |||
123 | case E_P2QImode: | |||
124 | half_mode = QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)); | |||
125 | break; | |||
126 | default: | |||
127 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 127, __FUNCTION__)); | |||
128 | } | |||
129 | ||||
130 | byte = GET_MODE_SIZE (half_mode)((unsigned short) mode_to_bytes (half_mode).coeffs[0]); | |||
131 | ||||
132 | while (num--) | |||
133 | { | |||
134 | rtx op = operands[num]; | |||
135 | ||||
136 | /* simplify_subreg refuse to split volatile memory addresses, | |||
137 | but we still have to handle it. */ | |||
138 | if (MEM_P (op)(((enum rtx_code) (op)->code) == MEM)) | |||
139 | { | |||
140 | if (mem_op && rtx_equal_p (op, mem_op)) | |||
141 | { | |||
142 | lo_half[num] = lo_half[mem_num]; | |||
143 | hi_half[num] = hi_half[mem_num]; | |||
144 | } | |||
145 | else | |||
146 | { | |||
147 | mem_op = op; | |||
148 | mem_num = num; | |||
149 | lo_half[num] = adjust_address (op, half_mode, 0)adjust_address_1 (op, half_mode, 0, 1, 1, 0, 0); | |||
150 | hi_half[num] = adjust_address (op, half_mode, byte)adjust_address_1 (op, half_mode, byte, 1, 1, 0, 0); | |||
151 | } | |||
152 | } | |||
153 | else | |||
154 | { | |||
155 | lo_half[num] = simplify_gen_subreg (half_mode, op, | |||
156 | GET_MODE (op)((machine_mode) (op)->mode) == VOIDmode((void) 0, E_VOIDmode) | |||
157 | ? mode : GET_MODE (op)((machine_mode) (op)->mode), 0); | |||
158 | ||||
159 | rtx tmp = simplify_gen_subreg (half_mode, op, | |||
160 | GET_MODE (op)((machine_mode) (op)->mode) == VOIDmode((void) 0, E_VOIDmode) | |||
161 | ? mode : GET_MODE (op)((machine_mode) (op)->mode), byte); | |||
162 | /* simplify_gen_subreg will return NULL RTX for the | |||
163 | high half of the paradoxical subreg. */ | |||
164 | hi_half[num] = tmp ? tmp : gen_reg_rtx (half_mode); | |||
165 | } | |||
166 | } | |||
167 | } | |||
168 | ||||
169 | /* Emit the double word assignment DST = { LO, HI }. */ | |||
170 | ||||
171 | void | |||
172 | split_double_concat (machine_mode mode, rtx dst, rtx lo, rtx hi) | |||
173 | { | |||
174 | rtx dlo, dhi; | |||
175 | int deleted_move_count = 0; | |||
176 | split_double_mode (mode, &dst, 1, &dlo, &dhi); | |||
177 | /* Constraints ensure that if both lo and hi are MEMs, then | |||
178 | dst has early-clobber and thus addresses of MEMs don't use | |||
179 | dlo/dhi registers. Otherwise if at least one of li and hi are MEMs, | |||
180 | dlo/dhi are registers. */ | |||
181 | if (MEM_P (lo)(((enum rtx_code) (lo)->code) == MEM) | |||
182 | && rtx_equal_p (dlo, hi) | |||
183 | && reg_overlap_mentioned_p (dhi, lo)) | |||
184 | { | |||
185 | /* If dlo is same as hi and lo's address uses dhi register, | |||
186 | code below would first emit_move_insn (dhi, hi) | |||
187 | and then emit_move_insn (dlo, lo). But the former | |||
188 | would invalidate lo's address. Load into dhi first, | |||
189 | then swap. */ | |||
190 | emit_move_insn (dhi, lo); | |||
191 | lo = dhi; | |||
192 | } | |||
193 | else if (MEM_P (hi)(((enum rtx_code) (hi)->code) == MEM) | |||
194 | && !MEM_P (lo)(((enum rtx_code) (lo)->code) == MEM) | |||
195 | && !rtx_equal_p (dlo, lo) | |||
196 | && reg_overlap_mentioned_p (dlo, hi)) | |||
197 | { | |||
198 | /* In this case, code below would first emit_move_insn (dlo, lo) | |||
199 | and then emit_move_insn (dhi, hi). But the former would | |||
200 | invalidate hi's address. */ | |||
201 | if (rtx_equal_p (dhi, lo)) | |||
202 | { | |||
203 | /* We can't load into dhi first, so load into dlo | |||
204 | first and we'll swap. */ | |||
205 | emit_move_insn (dlo, hi); | |||
206 | hi = dlo; | |||
207 | } | |||
208 | else | |||
209 | { | |||
210 | /* Load into dhi first. */ | |||
211 | emit_move_insn (dhi, hi); | |||
212 | hi = dhi; | |||
213 | } | |||
214 | } | |||
215 | if (!rtx_equal_p (dlo, hi)) | |||
216 | { | |||
217 | if (!rtx_equal_p (dlo, lo)) | |||
218 | emit_move_insn (dlo, lo); | |||
219 | else | |||
220 | deleted_move_count++; | |||
221 | if (!rtx_equal_p (dhi, hi)) | |||
222 | emit_move_insn (dhi, hi); | |||
223 | else | |||
224 | deleted_move_count++; | |||
225 | } | |||
226 | else if (!rtx_equal_p (lo, dhi)) | |||
227 | { | |||
228 | if (!rtx_equal_p (dhi, hi)) | |||
229 | emit_move_insn (dhi, hi); | |||
230 | else | |||
231 | deleted_move_count++; | |||
232 | if (!rtx_equal_p (dlo, lo)) | |||
233 | emit_move_insn (dlo, lo); | |||
234 | else | |||
235 | deleted_move_count++; | |||
236 | } | |||
237 | else if (mode == TImode(scalar_int_mode ((scalar_int_mode::from_int) E_TImode))) | |||
238 | emit_insn (gen_swapdi (dlo, dhi)); | |||
239 | else | |||
240 | emit_insn (gen_swapsi (dlo, dhi)); | |||
241 | ||||
242 | if (deleted_move_count == 2) | |||
243 | emit_note (NOTE_INSN_DELETED); | |||
244 | } | |||
245 | ||||
246 | ||||
247 | /* Generate either "mov $0, reg" or "xor reg, reg", as appropriate | |||
248 | for the target. */ | |||
249 | ||||
250 | void | |||
251 | ix86_expand_clear (rtx dest) | |||
252 | { | |||
253 | rtx tmp; | |||
254 | ||||
255 | /* We play register width games, which are only valid after reload. */ | |||
256 | gcc_assert (reload_completed)((void)(!(reload_completed) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 256, __FUNCTION__), 0 : 0)); | |||
257 | ||||
258 | /* Avoid HImode and its attendant prefix byte. */ | |||
259 | if (GET_MODE_SIZE (GET_MODE (dest))((unsigned short) mode_to_bytes (((machine_mode) (dest)->mode )).coeffs[0]) < 4) | |||
260 | dest = gen_rtx_REG (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), REGNO (dest)(rhs_regno(dest))); | |||
261 | tmp = gen_rtx_SET (dest, const0_rtx)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), (((const_int_rtx[64]))) ); | |||
262 | ||||
263 | if (!TARGET_USE_MOV0ix86_tune_features[X86_TUNE_USE_MOV0] || optimize_insn_for_size_p ()) | |||
264 | { | |||
265 | rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG))gen_rtx_fmt_e_stat ((CLOBBER), ((((void) 0, E_VOIDmode))), (( gen_rtx_REG (((void) 0, E_CCmode), 17))) ); | |||
266 | tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, tmp, clob))) ); | |||
267 | } | |||
268 | ||||
269 | emit_insn (tmp); | |||
270 | } | |||
271 | ||||
272 | /* Return true if V can be broadcasted from an integer of WIDTH bits | |||
273 | which is returned in VAL_BROADCAST. Otherwise, return false. */ | |||
274 | ||||
275 | static bool | |||
276 | ix86_broadcast (HOST_WIDE_INTlong v, unsigned int width, | |||
277 | HOST_WIDE_INTlong &val_broadcast) | |||
278 | { | |||
279 | wide_int val = wi::uhwi (v, HOST_BITS_PER_WIDE_INT64); | |||
280 | val_broadcast = wi::extract_uhwi (val, 0, width); | |||
281 | for (unsigned int i = width; i < HOST_BITS_PER_WIDE_INT64; i += width) | |||
282 | { | |||
283 | HOST_WIDE_INTlong each = wi::extract_uhwi (val, i, width); | |||
284 | if (val_broadcast != each) | |||
285 | return false; | |||
286 | } | |||
287 | val_broadcast = sext_hwi (val_broadcast, width); | |||
288 | return true; | |||
289 | } | |||
290 | ||||
291 | /* Convert the CONST_WIDE_INT operand OP to broadcast in MODE. */ | |||
292 | ||||
293 | static rtx | |||
294 | ix86_convert_const_wide_int_to_broadcast (machine_mode mode, rtx op) | |||
295 | { | |||
296 | /* Don't use integer vector broadcast if we can't move from GPR to SSE | |||
297 | register directly. */ | |||
298 | if (!TARGET_INTER_UNIT_MOVES_TO_VECix86_tune_features[X86_TUNE_INTER_UNIT_MOVES_TO_VEC]) | |||
299 | return nullptr; | |||
300 | ||||
301 | /* Convert CONST_WIDE_INT to a non-standard SSE constant integer | |||
302 | broadcast only if vector broadcast is available. */ | |||
303 | if (!TARGET_AVX((global_options.x_ix86_isa_flags & (1UL << 8)) != 0 ) | |||
304 | || !CONST_WIDE_INT_P (op)(((enum rtx_code) (op)->code) == CONST_WIDE_INT) | |||
305 | || standard_sse_constant_p (op, mode) | |||
306 | || (CONST_WIDE_INT_NUNITS (op)((int)__extension__ ({ __typeof ((op)) const _rtx = ((op)); if (((enum rtx_code) (_rtx)->code) != CONST_WIDE_INT) rtl_check_failed_flag ("CWI_GET_NUM_ELEM", _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 306, __FUNCTION__); _rtx; })->u2.num_elem) * HOST_BITS_PER_WIDE_INT64 | |||
307 | != GET_MODE_BITSIZE (mode)((unsigned short) mode_to_bits (mode).coeffs[0]))) | |||
308 | return nullptr; | |||
309 | ||||
310 | HOST_WIDE_INTlong val = CONST_WIDE_INT_ELT (op, 0)((op)->u.hwiv.elem[0]); | |||
311 | HOST_WIDE_INTlong val_broadcast; | |||
312 | scalar_int_mode broadcast_mode; | |||
313 | if (TARGET_AVX2((global_options.x_ix86_isa_flags & (1UL << 9)) != 0 ) | |||
314 | && ix86_broadcast (val, GET_MODE_BITSIZE (QImode)((unsigned short) mode_to_bits ((scalar_int_mode ((scalar_int_mode ::from_int) E_QImode))).coeffs[0]), | |||
315 | val_broadcast)) | |||
316 | broadcast_mode = QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)); | |||
317 | else if (TARGET_AVX2((global_options.x_ix86_isa_flags & (1UL << 9)) != 0 ) | |||
318 | && ix86_broadcast (val, GET_MODE_BITSIZE (HImode)((unsigned short) mode_to_bits ((scalar_int_mode ((scalar_int_mode ::from_int) E_HImode))).coeffs[0]), | |||
319 | val_broadcast)) | |||
320 | broadcast_mode = HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode)); | |||
321 | else if (ix86_broadcast (val, GET_MODE_BITSIZE (SImode)((unsigned short) mode_to_bits ((scalar_int_mode ((scalar_int_mode ::from_int) E_SImode))).coeffs[0]), | |||
322 | val_broadcast)) | |||
323 | broadcast_mode = SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)); | |||
324 | else if (TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) | |||
325 | && ix86_broadcast (val, GET_MODE_BITSIZE (DImode)((unsigned short) mode_to_bits ((scalar_int_mode ((scalar_int_mode ::from_int) E_DImode))).coeffs[0]), | |||
326 | val_broadcast)) | |||
327 | broadcast_mode = DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)); | |||
328 | else | |||
329 | return nullptr; | |||
330 | ||||
331 | /* Check if OP can be broadcasted from VAL. */ | |||
332 | for (int i = 1; i < CONST_WIDE_INT_NUNITS (op)((int)__extension__ ({ __typeof ((op)) const _rtx = ((op)); if (((enum rtx_code) (_rtx)->code) != CONST_WIDE_INT) rtl_check_failed_flag ("CWI_GET_NUM_ELEM", _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 332, __FUNCTION__); _rtx; })->u2.num_elem); i++) | |||
333 | if (val != CONST_WIDE_INT_ELT (op, i)((op)->u.hwiv.elem[i])) | |||
334 | return nullptr; | |||
335 | ||||
336 | unsigned int nunits = (GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) | |||
337 | / GET_MODE_SIZE (broadcast_mode)((unsigned short) mode_to_bytes (broadcast_mode).coeffs[0])); | |||
338 | machine_mode vector_mode; | |||
339 | if (!mode_for_vector (broadcast_mode, nunits).exists (&vector_mode)) | |||
340 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 340, __FUNCTION__)); | |||
341 | rtx target = gen_reg_rtx (vector_mode); | |||
342 | bool ok = ix86_expand_vector_init_duplicate (false, vector_mode, | |||
343 | target, | |||
344 | GEN_INT (val_broadcast)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (val_broadcast))); | |||
345 | gcc_assert (ok)((void)(!(ok) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 345, __FUNCTION__), 0 : 0)); | |||
346 | target = lowpart_subreg (mode, target, vector_mode); | |||
347 | return target; | |||
348 | } | |||
349 | ||||
350 | void | |||
351 | ix86_expand_move (machine_mode mode, rtx operands[]) | |||
352 | { | |||
353 | rtx op0, op1; | |||
354 | rtx tmp, addend = NULL_RTX(rtx) 0; | |||
355 | enum tls_model model; | |||
356 | ||||
357 | op0 = operands[0]; | |||
358 | op1 = operands[1]; | |||
359 | ||||
360 | /* Avoid complex sets of likely spilled hard registers before reload. */ | |||
361 | if (!ix86_hardreg_mov_ok (op0, op1)) | |||
362 | { | |||
363 | tmp = gen_reg_rtx (mode); | |||
364 | operands[0] = tmp; | |||
365 | ix86_expand_move (mode, operands); | |||
366 | operands[0] = op0; | |||
367 | operands[1] = tmp; | |||
368 | op1 = tmp; | |||
369 | } | |||
370 | ||||
371 | switch (GET_CODE (op1)((enum rtx_code) (op1)->code)) | |||
372 | { | |||
373 | case CONST: | |||
374 | tmp = XEXP (op1, 0)(((op1)->u.fld[0]).rt_rtx); | |||
375 | ||||
376 | if (GET_CODE (tmp)((enum rtx_code) (tmp)->code) != PLUS | |||
377 | || GET_CODE (XEXP (tmp, 0))((enum rtx_code) ((((tmp)->u.fld[0]).rt_rtx))->code) != SYMBOL_REF) | |||
378 | break; | |||
379 | ||||
380 | op1 = XEXP (tmp, 0)(((tmp)->u.fld[0]).rt_rtx); | |||
381 | addend = XEXP (tmp, 1)(((tmp)->u.fld[1]).rt_rtx); | |||
382 | /* FALLTHRU */ | |||
383 | ||||
384 | case SYMBOL_REF: | |||
385 | model = SYMBOL_REF_TLS_MODEL (op1)((enum tls_model) (((__extension__ ({ __typeof ((op1)) const _rtx = ((op1)); if (((enum rtx_code) (_rtx)->code) != SYMBOL_REF ) rtl_check_failed_flag ("SYMBOL_REF_FLAGS", _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 385, __FUNCTION__); _rtx; }) ->u2.symbol_ref_flags) >> 3) & 7)); | |||
386 | ||||
387 | if (model) | |||
388 | op1 = legitimize_tls_address (op1, model, true); | |||
389 | else if (ix86_force_load_from_GOT_p (op1)) | |||
390 | { | |||
391 | /* Load the external function address via GOT slot to avoid PLT. */ | |||
392 | op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op1),gen_rtx_fmt_Ei_stat ((UNSPEC), (((global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ((scalar_int_mode::from_int) E_DImode )) : (scalar_int_mode ((scalar_int_mode::from_int) E_SImode)) ))), ((gen_rtvec (1, op1))), (((((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? UNSPEC_GOTPCREL : UNSPEC_GOT ))) ) | |||
393 | (TARGET_64BITgen_rtx_fmt_Ei_stat ((UNSPEC), (((global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ((scalar_int_mode::from_int) E_DImode )) : (scalar_int_mode ((scalar_int_mode::from_int) E_SImode)) ))), ((gen_rtvec (1, op1))), (((((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? UNSPEC_GOTPCREL : UNSPEC_GOT ))) ) | |||
394 | ? UNSPEC_GOTPCRELgen_rtx_fmt_Ei_stat ((UNSPEC), (((global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ((scalar_int_mode::from_int) E_DImode )) : (scalar_int_mode ((scalar_int_mode::from_int) E_SImode)) ))), ((gen_rtvec (1, op1))), (((((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? UNSPEC_GOTPCREL : UNSPEC_GOT ))) ) | |||
395 | : UNSPEC_GOT))gen_rtx_fmt_Ei_stat ((UNSPEC), (((global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ((scalar_int_mode::from_int) E_DImode )) : (scalar_int_mode ((scalar_int_mode::from_int) E_SImode)) ))), ((gen_rtvec (1, op1))), (((((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? UNSPEC_GOTPCREL : UNSPEC_GOT ))) ); | |||
396 | op1 = gen_rtx_CONST (Pmode, op1)gen_rtx_fmt_e_stat ((CONST), (((global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ((scalar_int_mode::from_int) E_DImode )) : (scalar_int_mode ((scalar_int_mode::from_int) E_SImode)) ))), ((op1)) ); | |||
397 | op1 = gen_const_mem (Pmode(global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ( (scalar_int_mode::from_int) E_DImode)) : (scalar_int_mode ((scalar_int_mode ::from_int) E_SImode))), op1); | |||
398 | set_mem_alias_set (op1, ix86_GOT_alias_set ()); | |||
399 | } | |||
400 | else | |||
401 | { | |||
402 | tmp = legitimize_pe_coff_symbol (op1, addend != NULL_RTX(rtx) 0); | |||
403 | if (tmp) | |||
404 | { | |||
405 | op1 = tmp; | |||
406 | if (!addend) | |||
407 | break; | |||
408 | } | |||
409 | else | |||
410 | { | |||
411 | op1 = operands[1]; | |||
412 | break; | |||
413 | } | |||
414 | } | |||
415 | ||||
416 | if (addend) | |||
417 | { | |||
418 | op1 = force_operand (op1, NULL_RTX(rtx) 0); | |||
419 | op1 = expand_simple_binop (Pmode(global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ( (scalar_int_mode::from_int) E_DImode)) : (scalar_int_mode ((scalar_int_mode ::from_int) E_SImode))), PLUS, op1, addend, | |||
420 | op0, 1, OPTAB_DIRECT); | |||
421 | } | |||
422 | else | |||
423 | op1 = force_operand (op1, op0); | |||
424 | ||||
425 | if (op1 == op0) | |||
426 | return; | |||
427 | ||||
428 | op1 = convert_to_mode (mode, op1, 1); | |||
429 | ||||
430 | default: | |||
431 | break; | |||
432 | } | |||
433 | ||||
434 | if ((flag_picglobal_options.x_flag_pic || MACHOPIC_INDIRECT0) | |||
435 | && symbolic_operand (op1, mode)) | |||
436 | { | |||
437 | if (TARGET_MACHO0 && !TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 )) | |||
438 | { | |||
439 | #if TARGET_MACHO0 | |||
440 | /* dynamic-no-pic */ | |||
441 | if (MACHOPIC_INDIRECT0) | |||
442 | { | |||
443 | rtx temp = (op0 && REG_P (op0)(((enum rtx_code) (op0)->code) == REG) && mode == Pmode(global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ( (scalar_int_mode::from_int) E_DImode)) : (scalar_int_mode ((scalar_int_mode ::from_int) E_SImode)))) | |||
444 | ? op0 : gen_reg_rtx (Pmode(global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ( (scalar_int_mode::from_int) E_DImode)) : (scalar_int_mode ((scalar_int_mode ::from_int) E_SImode)))); | |||
445 | op1 = machopic_indirect_data_reference (op1, temp); | |||
446 | if (MACHOPIC_PURE0) | |||
447 | op1 = machopic_legitimize_pic_address (op1, mode, | |||
448 | temp == op1 ? 0 : temp); | |||
449 | } | |||
450 | if (op0 != op1 && GET_CODE (op0)((enum rtx_code) (op0)->code) != MEM) | |||
451 | { | |||
452 | rtx insn = gen_rtx_SET (op0, op1)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((op0)) , ((op1)) ); | |||
453 | emit_insn (insn); | |||
454 | return; | |||
455 | } | |||
456 | if (GET_CODE (op0)((enum rtx_code) (op0)->code) == MEM) | |||
457 | op1 = force_reg (Pmode(global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ( (scalar_int_mode::from_int) E_DImode)) : (scalar_int_mode ((scalar_int_mode ::from_int) E_SImode))), op1); | |||
458 | else | |||
459 | { | |||
460 | rtx temp = op0; | |||
461 | if (GET_CODE (temp)((enum rtx_code) (temp)->code) != REG) | |||
462 | temp = gen_reg_rtx (Pmode(global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ( (scalar_int_mode::from_int) E_DImode)) : (scalar_int_mode ((scalar_int_mode ::from_int) E_SImode)))); | |||
463 | temp = legitimize_pic_address (op1, temp); | |||
464 | if (temp == op0) | |||
465 | return; | |||
466 | op1 = temp; | |||
467 | } | |||
468 | /* dynamic-no-pic */ | |||
469 | #endif | |||
470 | } | |||
471 | else | |||
472 | { | |||
473 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM)) | |||
474 | op1 = force_reg (mode, op1); | |||
475 | else if (!(TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) && x86_64_movabs_operand (op1, DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode))))) | |||
476 | { | |||
477 | rtx reg = can_create_pseudo_p ()(!reload_in_progress && !reload_completed) ? NULL_RTX(rtx) 0 : op0; | |||
478 | op1 = legitimize_pic_address (op1, reg); | |||
479 | if (op0 == op1) | |||
480 | return; | |||
481 | op1 = convert_to_mode (mode, op1, 1); | |||
482 | } | |||
483 | } | |||
484 | } | |||
485 | else | |||
486 | { | |||
487 | if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | |||
488 | && (PUSH_ROUNDING (GET_MODE_SIZE (mode))ix86_push_rounding (((unsigned short) mode_to_bytes (mode).coeffs [0])) != GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) | |||
489 | || !push_operand (op0, mode)) | |||
490 | && MEM_P (op1)(((enum rtx_code) (op1)->code) == MEM)) | |||
491 | op1 = force_reg (mode, op1); | |||
492 | ||||
493 | if (push_operand (op0, mode) | |||
494 | && ! general_no_elim_operand (op1, mode)) | |||
495 | op1 = copy_to_mode_reg (mode, op1); | |||
496 | ||||
497 | /* Force large constants in 64bit compilation into register | |||
498 | to get them CSEed. */ | |||
499 | if (can_create_pseudo_p ()(!reload_in_progress && !reload_completed) | |||
500 | && (mode == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode))) && TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) | |||
501 | && immediate_operand (op1, mode) | |||
502 | && !x86_64_zext_immediate_operand (op1, VOIDmode((void) 0, E_VOIDmode)) | |||
503 | && !register_operand (op0, mode) | |||
504 | && optimizeglobal_options.x_optimize) | |||
505 | op1 = copy_to_mode_reg (mode, op1); | |||
506 | ||||
507 | if (can_create_pseudo_p ()(!reload_in_progress && !reload_completed)) | |||
508 | { | |||
509 | if (CONST_DOUBLE_P (op1)(((enum rtx_code) (op1)->code) == CONST_DOUBLE)) | |||
510 | { | |||
511 | /* If we are loading a floating point constant to a | |||
512 | register, force the value to memory now, since we'll | |||
513 | get better code out the back end. */ | |||
514 | ||||
515 | op1 = validize_mem (force_const_mem (mode, op1)); | |||
516 | if (!register_operand (op0, mode)) | |||
517 | { | |||
518 | rtx temp = gen_reg_rtx (mode); | |||
519 | emit_insn (gen_rtx_SET (temp, op1)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((temp) ), ((op1)) )); | |||
520 | emit_move_insn (op0, temp); | |||
521 | return; | |||
522 | } | |||
523 | } | |||
524 | else if (GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) >= 16) | |||
525 | { | |||
526 | rtx tmp = ix86_convert_const_wide_int_to_broadcast | |||
527 | (GET_MODE (op0)((machine_mode) (op0)->mode), op1); | |||
528 | if (tmp != nullptr) | |||
529 | op1 = tmp; | |||
530 | } | |||
531 | } | |||
532 | } | |||
533 | ||||
534 | emit_insn (gen_rtx_SET (op0, op1)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((op0)) , ((op1)) )); | |||
535 | } | |||
536 | ||||
537 | /* OP is a memref of CONST_VECTOR, return scalar constant mem | |||
538 | if CONST_VECTOR is a vec_duplicate, else return NULL. */ | |||
539 | static rtx | |||
540 | ix86_broadcast_from_constant (machine_mode mode, rtx op) | |||
541 | { | |||
542 | int nunits = GET_MODE_NUNITS (mode)(mode_to_nunits (mode).coeffs[0]); | |||
543 | if (nunits < 2) | |||
544 | return nullptr; | |||
545 | ||||
546 | /* Don't use integer vector broadcast if we can't move from GPR to SSE | |||
547 | register directly. */ | |||
548 | if (!TARGET_INTER_UNIT_MOVES_TO_VECix86_tune_features[X86_TUNE_INTER_UNIT_MOVES_TO_VEC] | |||
549 | && INTEGRAL_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_INT || ((enum mode_class ) mode_class[mode]) == MODE_PARTIAL_INT || ((enum mode_class) mode_class[mode]) == MODE_COMPLEX_INT || ((enum mode_class) mode_class [mode]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[ mode]) == MODE_VECTOR_INT)) | |||
550 | return nullptr; | |||
551 | ||||
552 | /* Convert CONST_VECTOR to a non-standard SSE constant integer | |||
553 | broadcast only if vector broadcast is available. */ | |||
554 | if (!(TARGET_AVX2((global_options.x_ix86_isa_flags & (1UL << 9)) != 0 ) | |||
555 | || (TARGET_AVX((global_options.x_ix86_isa_flags & (1UL << 8)) != 0 ) | |||
556 | && (GET_MODE_INNER (mode)(mode_to_inner (mode)) == SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)) | |||
557 | || GET_MODE_INNER (mode)(mode_to_inner (mode)) == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)))) | |||
558 | || FLOAT_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_DECIMAL_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_COMPLEX_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FLOAT)) | |||
559 | || standard_sse_constant_p (op, mode)) | |||
560 | return nullptr; | |||
561 | ||||
562 | /* Don't broadcast from a 64-bit integer constant in 32-bit mode. | |||
563 | We can still put 64-bit integer constant in memory when | |||
564 | avx512 embed broadcast is available. */ | |||
565 | if (GET_MODE_INNER (mode)(mode_to_inner (mode)) == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)) && !TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) | |||
566 | && (!TARGET_AVX512F((global_options.x_ix86_isa_flags & (1UL << 15)) != 0) | |||
567 | || (GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) < 64 && !TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0)))) | |||
568 | return nullptr; | |||
569 | ||||
570 | if (GET_MODE_INNER (mode)(mode_to_inner (mode)) == TImode(scalar_int_mode ((scalar_int_mode::from_int) E_TImode))) | |||
571 | return nullptr; | |||
572 | ||||
573 | rtx constant = get_pool_constant (XEXP (op, 0)(((op)->u.fld[0]).rt_rtx)); | |||
574 | if (GET_CODE (constant)((enum rtx_code) (constant)->code) != CONST_VECTOR) | |||
575 | return nullptr; | |||
576 | ||||
577 | /* There could be some rtx like | |||
578 | (mem/u/c:V16QI (symbol_ref/u:DI ("*.LC1"))) | |||
579 | but with "*.LC1" refer to V2DI constant vector. */ | |||
580 | if (GET_MODE (constant)((machine_mode) (constant)->mode) != mode) | |||
581 | { | |||
582 | constant = simplify_subreg (mode, constant, GET_MODE (constant)((machine_mode) (constant)->mode), | |||
583 | 0); | |||
584 | if (constant == nullptr || GET_CODE (constant)((enum rtx_code) (constant)->code) != CONST_VECTOR) | |||
585 | return nullptr; | |||
586 | } | |||
587 | ||||
588 | rtx first = XVECEXP (constant, 0, 0)(((((constant)->u.fld[0]).rt_rtvec))->elem[0]); | |||
589 | ||||
590 | for (int i = 1; i < nunits; ++i) | |||
591 | { | |||
592 | rtx tmp = XVECEXP (constant, 0, i)(((((constant)->u.fld[0]).rt_rtvec))->elem[i]); | |||
593 | /* Vector duplicate value. */ | |||
594 | if (!rtx_equal_p (tmp, first)) | |||
595 | return nullptr; | |||
596 | } | |||
597 | ||||
598 | return first; | |||
599 | } | |||
600 | ||||
601 | void | |||
602 | ix86_expand_vector_move (machine_mode mode, rtx operands[]) | |||
603 | { | |||
604 | rtx op0 = operands[0], op1 = operands[1]; | |||
605 | /* Use GET_MODE_BITSIZE instead of GET_MODE_ALIGNMENT for IA MCU | |||
606 | psABI since the biggest alignment is 4 byte for IA MCU psABI. */ | |||
607 | unsigned int align = (TARGET_IAMCU((global_options.x_target_flags & (1U << 12)) != 0) | |||
608 | ? GET_MODE_BITSIZE (mode)((unsigned short) mode_to_bits (mode).coeffs[0]) | |||
609 | : GET_MODE_ALIGNMENT (mode)get_mode_alignment (mode)); | |||
610 | ||||
611 | if (push_operand (op0, VOIDmode((void) 0, E_VOIDmode))) | |||
612 | op0 = emit_move_resolve_push (mode, op0); | |||
613 | ||||
614 | /* Force constants other than zero into memory. We do not know how | |||
615 | the instructions used to build constants modify the upper 64 bits | |||
616 | of the register, once we have that information we may be able | |||
617 | to handle some of them more efficiently. */ | |||
618 | if (can_create_pseudo_p ()(!reload_in_progress && !reload_completed) | |||
619 | && (CONSTANT_P (op1)((rtx_class[(int) (((enum rtx_code) (op1)->code))]) == RTX_CONST_OBJ ) | |||
620 | || (SUBREG_P (op1)(((enum rtx_code) (op1)->code) == SUBREG) | |||
621 | && CONSTANT_P (SUBREG_REG (op1))((rtx_class[(int) (((enum rtx_code) ((((op1)->u.fld[0]).rt_rtx ))->code))]) == RTX_CONST_OBJ))) | |||
622 | && ((register_operand (op0, mode) | |||
623 | && !standard_sse_constant_p (op1, mode)) | |||
624 | /* ix86_expand_vector_move_misalign() does not like constants. */ | |||
625 | || (SSE_REG_MODE_P (mode)((mode) == ((void) 0, E_V1TImode) || (mode) == (scalar_int_mode ((scalar_int_mode::from_int) E_TImode)) || (mode) == ((void) 0, E_V16QImode) || (mode) == (scalar_float_mode ((scalar_float_mode ::from_int) E_TFmode)) || (mode) == ((void) 0, E_V8HImode) || (mode) == ((void) 0, E_V2DFmode) || (mode) == ((void) 0, E_V2DImode ) || (mode) == ((void) 0, E_V4SFmode) || (mode) == ((void) 0, E_V4SImode) || (mode) == ((void) 0, E_V32QImode) || (mode) == ((void) 0, E_V16HImode) || (mode) == ((void) 0, E_V8SImode) || (mode) == ((void) 0, E_V4DImode) || (mode) == ((void) 0, E_V8SFmode ) || (mode) == ((void) 0, E_V4DFmode) || (mode) == ((void) 0, E_V2TImode) || (mode) == ((void) 0, E_V8DImode) || (mode) == ((void) 0, E_V64QImode) || (mode) == ((void) 0, E_V16SImode) || (mode) == ((void) 0, E_V32HImode) || (mode) == ((void) 0, E_V8DFmode) || (mode) == ((void) 0, E_V16SFmode) || (mode) == ((void) 0, E_V32HFmode) || (mode) == ((void) 0, E_V16HFmode) || (mode) == ((void) 0, E_V8HFmode) || (mode) == ((void) 0, E_V32BFmode ) || (mode) == ((void) 0, E_V16BFmode) || (mode) == ((void) 0 , E_V8BFmode)) | |||
626 | && MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | |||
627 | && MEM_ALIGN (op0)(get_mem_attrs (op0)->align) < align))) | |||
628 | { | |||
629 | if (SUBREG_P (op1)(((enum rtx_code) (op1)->code) == SUBREG)) | |||
630 | { | |||
631 | machine_mode imode = GET_MODE (SUBREG_REG (op1))((machine_mode) ((((op1)->u.fld[0]).rt_rtx))->mode); | |||
632 | rtx r = force_const_mem (imode, SUBREG_REG (op1)(((op1)->u.fld[0]).rt_rtx)); | |||
633 | if (r) | |||
634 | r = validize_mem (r); | |||
635 | else | |||
636 | r = force_reg (imode, SUBREG_REG (op1)(((op1)->u.fld[0]).rt_rtx)); | |||
637 | op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1)(((op1)->u.fld[1]).rt_subreg)); | |||
638 | } | |||
639 | else | |||
640 | { | |||
641 | machine_mode mode = GET_MODE (op0)((machine_mode) (op0)->mode); | |||
642 | rtx tmp = ix86_convert_const_wide_int_to_broadcast | |||
643 | (mode, op1); | |||
644 | if (tmp == nullptr) | |||
645 | op1 = validize_mem (force_const_mem (mode, op1)); | |||
646 | else | |||
647 | op1 = tmp; | |||
648 | } | |||
649 | } | |||
650 | ||||
651 | if (can_create_pseudo_p ()(!reload_in_progress && !reload_completed) | |||
652 | && GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) >= 16 | |||
653 | && VECTOR_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_VECTOR_BOOL || ( (enum mode_class) mode_class[mode]) == MODE_VECTOR_INT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_UACCUM) | |||
654 | && (MEM_P (op1)(((enum rtx_code) (op1)->code) == MEM) | |||
655 | && SYMBOL_REF_P (XEXP (op1, 0))(((enum rtx_code) ((((op1)->u.fld[0]).rt_rtx))->code) == SYMBOL_REF) | |||
656 | && CONSTANT_POOL_ADDRESS_P (XEXP (op1, 0))(__extension__ ({ __typeof (((((op1)->u.fld[0]).rt_rtx))) const _rtx = (((((op1)->u.fld[0]).rt_rtx))); if (((enum rtx_code ) (_rtx)->code) != SYMBOL_REF) rtl_check_failed_flag ("CONSTANT_POOL_ADDRESS_P" , _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 656, __FUNCTION__); _rtx; })->unchanging))) | |||
657 | { | |||
658 | rtx first = ix86_broadcast_from_constant (mode, op1); | |||
659 | if (first != nullptr) | |||
660 | { | |||
661 | /* Broadcast to XMM/YMM/ZMM register from an integer | |||
662 | constant or scalar mem. */ | |||
663 | op1 = gen_reg_rtx (mode); | |||
664 | if (FLOAT_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_DECIMAL_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_COMPLEX_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FLOAT) | |||
665 | || (!TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) && GET_MODE_INNER (mode)(mode_to_inner (mode)) == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)))) | |||
666 | first = force_const_mem (GET_MODE_INNER (mode)(mode_to_inner (mode)), first); | |||
667 | bool ok = ix86_expand_vector_init_duplicate (false, mode, | |||
668 | op1, first); | |||
669 | gcc_assert (ok)((void)(!(ok) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 669, __FUNCTION__), 0 : 0)); | |||
670 | emit_move_insn (op0, op1); | |||
671 | return; | |||
672 | } | |||
673 | } | |||
674 | ||||
675 | /* We need to check memory alignment for SSE mode since attribute | |||
676 | can make operands unaligned. */ | |||
677 | if (can_create_pseudo_p ()(!reload_in_progress && !reload_completed) | |||
678 | && SSE_REG_MODE_P (mode)((mode) == ((void) 0, E_V1TImode) || (mode) == (scalar_int_mode ((scalar_int_mode::from_int) E_TImode)) || (mode) == ((void) 0, E_V16QImode) || (mode) == (scalar_float_mode ((scalar_float_mode ::from_int) E_TFmode)) || (mode) == ((void) 0, E_V8HImode) || (mode) == ((void) 0, E_V2DFmode) || (mode) == ((void) 0, E_V2DImode ) || (mode) == ((void) 0, E_V4SFmode) || (mode) == ((void) 0, E_V4SImode) || (mode) == ((void) 0, E_V32QImode) || (mode) == ((void) 0, E_V16HImode) || (mode) == ((void) 0, E_V8SImode) || (mode) == ((void) 0, E_V4DImode) || (mode) == ((void) 0, E_V8SFmode ) || (mode) == ((void) 0, E_V4DFmode) || (mode) == ((void) 0, E_V2TImode) || (mode) == ((void) 0, E_V8DImode) || (mode) == ((void) 0, E_V64QImode) || (mode) == ((void) 0, E_V16SImode) || (mode) == ((void) 0, E_V32HImode) || (mode) == ((void) 0, E_V8DFmode) || (mode) == ((void) 0, E_V16SFmode) || (mode) == ((void) 0, E_V32HFmode) || (mode) == ((void) 0, E_V16HFmode) || (mode) == ((void) 0, E_V8HFmode) || (mode) == ((void) 0, E_V32BFmode ) || (mode) == ((void) 0, E_V16BFmode) || (mode) == ((void) 0 , E_V8BFmode)) | |||
679 | && ((MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) && (MEM_ALIGN (op0)(get_mem_attrs (op0)->align) < align)) | |||
680 | || (MEM_P (op1)(((enum rtx_code) (op1)->code) == MEM) && (MEM_ALIGN (op1)(get_mem_attrs (op1)->align) < align)))) | |||
681 | { | |||
682 | rtx tmp[2]; | |||
683 | ||||
684 | /* ix86_expand_vector_move_misalign() does not like both | |||
685 | arguments in memory. */ | |||
686 | if (!register_operand (op0, mode) | |||
687 | && !register_operand (op1, mode)) | |||
688 | { | |||
689 | rtx scratch = gen_reg_rtx (mode); | |||
690 | emit_move_insn (scratch, op1); | |||
691 | op1 = scratch; | |||
692 | } | |||
693 | ||||
694 | tmp[0] = op0; tmp[1] = op1; | |||
695 | ix86_expand_vector_move_misalign (mode, tmp); | |||
696 | return; | |||
697 | } | |||
698 | ||||
699 | /* Special case TImode to V1TImode conversions, via V2DI. */ | |||
700 | if (mode == V1TImode((void) 0, E_V1TImode) | |||
701 | && SUBREG_P (op1)(((enum rtx_code) (op1)->code) == SUBREG) | |||
702 | && GET_MODE (SUBREG_REG (op1))((machine_mode) ((((op1)->u.fld[0]).rt_rtx))->mode) == TImode(scalar_int_mode ((scalar_int_mode::from_int) E_TImode)) | |||
703 | && TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) && TARGET_SSE((global_options.x_ix86_isa_flags & (1UL << 50)) != 0) | |||
704 | && can_create_pseudo_p ()(!reload_in_progress && !reload_completed)) | |||
705 | { | |||
706 | rtx tmp = gen_reg_rtx (V2DImode((void) 0, E_V2DImode)); | |||
707 | rtx lo = gen_reg_rtx (DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode))); | |||
708 | rtx hi = gen_reg_rtx (DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode))); | |||
709 | emit_move_insn (lo, gen_lowpartrtl_hooks.gen_lowpart (DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)), SUBREG_REG (op1)(((op1)->u.fld[0]).rt_rtx))); | |||
710 | emit_move_insn (hi, gen_highpart (DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)), SUBREG_REG (op1)(((op1)->u.fld[0]).rt_rtx))); | |||
711 | emit_insn (gen_vec_concatv2di (tmp, lo, hi)); | |||
712 | emit_move_insn (op0, gen_lowpartrtl_hooks.gen_lowpart (V1TImode((void) 0, E_V1TImode), tmp)); | |||
713 | return; | |||
714 | } | |||
715 | ||||
716 | /* If operand0 is a hard register, make operand1 a pseudo. */ | |||
717 | if (can_create_pseudo_p ()(!reload_in_progress && !reload_completed) | |||
718 | && !ix86_hardreg_mov_ok (op0, op1)) | |||
719 | { | |||
720 | rtx tmp = gen_reg_rtx (GET_MODE (op0)((machine_mode) (op0)->mode)); | |||
721 | emit_move_insn (tmp, op1); | |||
722 | emit_move_insn (op0, tmp); | |||
723 | return; | |||
724 | } | |||
725 | ||||
726 | /* Make operand1 a register if it isn't already. */ | |||
727 | if (can_create_pseudo_p ()(!reload_in_progress && !reload_completed) | |||
728 | && !register_operand (op0, mode) | |||
729 | && !register_operand (op1, mode)) | |||
730 | { | |||
731 | rtx tmp = gen_reg_rtx (GET_MODE (op0)((machine_mode) (op0)->mode)); | |||
732 | emit_move_insn (tmp, op1); | |||
733 | emit_move_insn (op0, tmp); | |||
734 | return; | |||
735 | } | |||
736 | ||||
737 | emit_insn (gen_rtx_SET (op0, op1)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((op0)) , ((op1)) )); | |||
738 | } | |||
739 | ||||
740 | /* Split 32-byte AVX unaligned load and store if needed. */ | |||
741 | ||||
742 | static void | |||
743 | ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1) | |||
744 | { | |||
745 | rtx m; | |||
746 | rtx (*extract) (rtx, rtx, rtx); | |||
747 | machine_mode mode; | |||
748 | ||||
749 | if ((MEM_P (op1)(((enum rtx_code) (op1)->code) == MEM) && !TARGET_AVX256_SPLIT_UNALIGNED_LOAD((global_options.x_target_flags & (1U << 6)) != 0)) | |||
750 | || (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) && !TARGET_AVX256_SPLIT_UNALIGNED_STORE((global_options.x_target_flags & (1U << 7)) != 0))) | |||
751 | { | |||
752 | emit_insn (gen_rtx_SET (op0, op1)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((op0)) , ((op1)) )); | |||
753 | return; | |||
754 | } | |||
755 | ||||
756 | rtx orig_op0 = NULL_RTX(rtx) 0; | |||
757 | mode = GET_MODE (op0)((machine_mode) (op0)->mode); | |||
758 | switch (GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode])) | |||
759 | { | |||
760 | case MODE_VECTOR_INT: | |||
761 | case MODE_INT: | |||
762 | if (mode != V32QImode((void) 0, E_V32QImode)) | |||
763 | { | |||
764 | if (!MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM)) | |||
765 | { | |||
766 | orig_op0 = op0; | |||
767 | op0 = gen_reg_rtx (V32QImode((void) 0, E_V32QImode)); | |||
768 | } | |||
769 | else | |||
770 | op0 = gen_lowpartrtl_hooks.gen_lowpart (V32QImode((void) 0, E_V32QImode), op0); | |||
771 | op1 = gen_lowpartrtl_hooks.gen_lowpart (V32QImode((void) 0, E_V32QImode), op1); | |||
772 | mode = V32QImode((void) 0, E_V32QImode); | |||
773 | } | |||
774 | break; | |||
775 | case MODE_VECTOR_FLOAT: | |||
776 | break; | |||
777 | default: | |||
778 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 778, __FUNCTION__)); | |||
779 | } | |||
780 | ||||
781 | switch (mode) | |||
782 | { | |||
783 | default: | |||
784 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 784, __FUNCTION__)); | |||
785 | case E_V32QImode: | |||
786 | extract = gen_avx_vextractf128v32qi; | |||
787 | mode = V16QImode((void) 0, E_V16QImode); | |||
788 | break; | |||
789 | case E_V16BFmode: | |||
790 | extract = gen_avx_vextractf128v16bf; | |||
791 | mode = V8BFmode((void) 0, E_V8BFmode); | |||
792 | break; | |||
793 | case E_V16HFmode: | |||
794 | extract = gen_avx_vextractf128v16hf; | |||
795 | mode = V8HFmode((void) 0, E_V8HFmode); | |||
796 | break; | |||
797 | case E_V8SFmode: | |||
798 | extract = gen_avx_vextractf128v8sf; | |||
799 | mode = V4SFmode((void) 0, E_V4SFmode); | |||
800 | break; | |||
801 | case E_V4DFmode: | |||
802 | extract = gen_avx_vextractf128v4df; | |||
803 | mode = V2DFmode((void) 0, E_V2DFmode); | |||
804 | break; | |||
805 | } | |||
806 | ||||
807 | if (MEM_P (op1)(((enum rtx_code) (op1)->code) == MEM)) | |||
808 | { | |||
809 | rtx r = gen_reg_rtx (mode); | |||
810 | m = adjust_address (op1, mode, 0)adjust_address_1 (op1, mode, 0, 1, 1, 0, 0); | |||
811 | emit_move_insn (r, m); | |||
812 | m = adjust_address (op1, mode, 16)adjust_address_1 (op1, mode, 16, 1, 1, 0, 0); | |||
813 | r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m)gen_rtx_fmt_ee_stat ((VEC_CONCAT), ((((machine_mode) (op0)-> mode))), ((r)), ((m)) ); | |||
814 | emit_move_insn (op0, r); | |||
815 | } | |||
816 | else if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM)) | |||
817 | { | |||
818 | m = adjust_address (op0, mode, 0)adjust_address_1 (op0, mode, 0, 1, 1, 0, 0); | |||
819 | emit_insn (extract (m, op1, const0_rtx(const_int_rtx[64]))); | |||
820 | m = adjust_address (op0, mode, 16)adjust_address_1 (op0, mode, 16, 1, 1, 0, 0); | |||
821 | emit_insn (extract (m, copy_rtx (op1), const1_rtx(const_int_rtx[64 +1]))); | |||
822 | } | |||
823 | else | |||
824 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 824, __FUNCTION__)); | |||
825 | ||||
826 | if (orig_op0) | |||
827 | emit_move_insn (orig_op0, gen_lowpartrtl_hooks.gen_lowpart (GET_MODE (orig_op0)((machine_mode) (orig_op0)->mode), op0)); | |||
828 | } | |||
829 | ||||
830 | /* Implement the movmisalign patterns for SSE. Non-SSE modes go | |||
831 | straight to ix86_expand_vector_move. */ | |||
832 | /* Code generation for scalar reg-reg moves of single and double precision data: | |||
833 | if (x86_sse_partial_reg_dependency == true | x86_sse_split_regs == true) | |||
834 | movaps reg, reg | |||
835 | else | |||
836 | movss reg, reg | |||
837 | if (x86_sse_partial_reg_dependency == true) | |||
838 | movapd reg, reg | |||
839 | else | |||
840 | movsd reg, reg | |||
841 | ||||
842 | Code generation for scalar loads of double precision data: | |||
843 | if (x86_sse_split_regs == true) | |||
844 | movlpd mem, reg (gas syntax) | |||
845 | else | |||
846 | movsd mem, reg | |||
847 | ||||
848 | Code generation for unaligned packed loads of single precision data | |||
849 | (x86_sse_unaligned_move_optimal overrides x86_sse_partial_reg_dependency): | |||
850 | if (x86_sse_unaligned_move_optimal) | |||
851 | movups mem, reg | |||
852 | ||||
853 | if (x86_sse_partial_reg_dependency == true) | |||
854 | { | |||
855 | xorps reg, reg | |||
856 | movlps mem, reg | |||
857 | movhps mem+8, reg | |||
858 | } | |||
859 | else | |||
860 | { | |||
861 | movlps mem, reg | |||
862 | movhps mem+8, reg | |||
863 | } | |||
864 | ||||
865 | Code generation for unaligned packed loads of double precision data | |||
866 | (x86_sse_unaligned_move_optimal overrides x86_sse_split_regs): | |||
867 | if (x86_sse_unaligned_move_optimal) | |||
868 | movupd mem, reg | |||
869 | ||||
870 | if (x86_sse_split_regs == true) | |||
871 | { | |||
872 | movlpd mem, reg | |||
873 | movhpd mem+8, reg | |||
874 | } | |||
875 | else | |||
876 | { | |||
877 | movsd mem, reg | |||
878 | movhpd mem+8, reg | |||
879 | } | |||
880 | */ | |||
881 | ||||
882 | void | |||
883 | ix86_expand_vector_move_misalign (machine_mode mode, rtx operands[]) | |||
884 | { | |||
885 | rtx op0, op1, m; | |||
886 | ||||
887 | op0 = operands[0]; | |||
888 | op1 = operands[1]; | |||
889 | ||||
890 | /* Use unaligned load/store for AVX512 or when optimizing for size. */ | |||
891 | if (GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) == 64 || optimize_insn_for_size_p ()) | |||
892 | { | |||
893 | emit_insn (gen_rtx_SET (op0, op1)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((op0)) , ((op1)) )); | |||
894 | return; | |||
895 | } | |||
896 | ||||
897 | if (TARGET_AVX((global_options.x_ix86_isa_flags & (1UL << 8)) != 0 )) | |||
898 | { | |||
899 | if (GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) == 32) | |||
900 | ix86_avx256_split_vector_move_misalign (op0, op1); | |||
901 | else | |||
902 | /* Always use 128-bit mov<mode>_internal pattern for AVX. */ | |||
903 | emit_insn (gen_rtx_SET (op0, op1)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((op0)) , ((op1)) )); | |||
904 | return; | |||
905 | } | |||
906 | ||||
907 | if (TARGET_SSE_UNALIGNED_LOAD_OPTIMALix86_tune_features[X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL] | |||
908 | || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMALix86_tune_features[X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL]) | |||
909 | { | |||
910 | emit_insn (gen_rtx_SET (op0, op1)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((op0)) , ((op1)) )); | |||
911 | return; | |||
912 | } | |||
913 | ||||
914 | /* ??? If we have typed data, then it would appear that using | |||
915 | movdqu is the only way to get unaligned data loaded with | |||
916 | integer type. */ | |||
917 | if (TARGET_SSE2((global_options.x_ix86_isa_flags & (1UL << 51)) != 0) && GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_VECTOR_INT) | |||
918 | { | |||
919 | emit_insn (gen_rtx_SET (op0, op1)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((op0)) , ((op1)) )); | |||
920 | return; | |||
921 | } | |||
922 | ||||
923 | if (MEM_P (op1)(((enum rtx_code) (op1)->code) == MEM)) | |||
924 | { | |||
925 | if (TARGET_SSE2((global_options.x_ix86_isa_flags & (1UL << 51)) != 0) && mode == V2DFmode((void) 0, E_V2DFmode)) | |||
926 | { | |||
927 | rtx zero; | |||
928 | ||||
929 | /* When SSE registers are split into halves, we can avoid | |||
930 | writing to the top half twice. */ | |||
931 | if (TARGET_SSE_SPLIT_REGSix86_tune_features[X86_TUNE_SSE_SPLIT_REGS]) | |||
932 | { | |||
933 | emit_clobber (op0); | |||
934 | zero = op0; | |||
935 | } | |||
936 | else | |||
937 | { | |||
938 | /* ??? Not sure about the best option for the Intel chips. | |||
939 | The following would seem to satisfy; the register is | |||
940 | entirely cleared, breaking the dependency chain. We | |||
941 | then store to the upper half, with a dependency depth | |||
942 | of one. A rumor has it that Intel recommends two movsd | |||
943 | followed by an unpacklpd, but this is unconfirmed. And | |||
944 | given that the dependency depth of the unpacklpd would | |||
945 | still be one, I'm not sure why this would be better. */ | |||
946 | zero = CONST0_RTX (V2DFmode)(const_tiny_rtx[0][(int) (((void) 0, E_V2DFmode))]); | |||
947 | } | |||
948 | ||||
949 | m = adjust_address (op1, DFmode, 0)adjust_address_1 (op1, (scalar_float_mode ((scalar_float_mode ::from_int) E_DFmode)), 0, 1, 1, 0, 0); | |||
950 | emit_insn (gen_sse2_loadlpd (op0, zero, m)); | |||
951 | m = adjust_address (op1, DFmode, 8)adjust_address_1 (op1, (scalar_float_mode ((scalar_float_mode ::from_int) E_DFmode)), 8, 1, 1, 0, 0); | |||
952 | emit_insn (gen_sse2_loadhpd (op0, op0, m)); | |||
953 | } | |||
954 | else | |||
955 | { | |||
956 | rtx t; | |||
957 | ||||
958 | if (mode != V4SFmode((void) 0, E_V4SFmode)) | |||
959 | t = gen_reg_rtx (V4SFmode((void) 0, E_V4SFmode)); | |||
960 | else | |||
961 | t = op0; | |||
962 | ||||
963 | if (TARGET_SSE_PARTIAL_REG_DEPENDENCYix86_tune_features[X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY]) | |||
964 | emit_move_insn (t, CONST0_RTX (V4SFmode)(const_tiny_rtx[0][(int) (((void) 0, E_V4SFmode))])); | |||
965 | else | |||
966 | emit_clobber (t); | |||
967 | ||||
968 | m = adjust_address (op1, V2SFmode, 0)adjust_address_1 (op1, ((void) 0, E_V2SFmode), 0, 1, 1, 0, 0); | |||
969 | emit_insn (gen_sse_loadlps (t, t, m)); | |||
970 | m = adjust_address (op1, V2SFmode, 8)adjust_address_1 (op1, ((void) 0, E_V2SFmode), 8, 1, 1, 0, 0); | |||
971 | emit_insn (gen_sse_loadhps (t, t, m)); | |||
972 | if (mode != V4SFmode((void) 0, E_V4SFmode)) | |||
973 | emit_move_insn (op0, gen_lowpartrtl_hooks.gen_lowpart (mode, t)); | |||
974 | } | |||
975 | } | |||
976 | else if (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM)) | |||
977 | { | |||
978 | if (TARGET_SSE2((global_options.x_ix86_isa_flags & (1UL << 51)) != 0) && mode == V2DFmode((void) 0, E_V2DFmode)) | |||
979 | { | |||
980 | m = adjust_address (op0, DFmode, 0)adjust_address_1 (op0, (scalar_float_mode ((scalar_float_mode ::from_int) E_DFmode)), 0, 1, 1, 0, 0); | |||
981 | emit_insn (gen_sse2_storelpd (m, op1)); | |||
982 | m = adjust_address (op0, DFmode, 8)adjust_address_1 (op0, (scalar_float_mode ((scalar_float_mode ::from_int) E_DFmode)), 8, 1, 1, 0, 0); | |||
983 | emit_insn (gen_sse2_storehpd (m, op1)); | |||
984 | } | |||
985 | else | |||
986 | { | |||
987 | if (mode != V4SFmode((void) 0, E_V4SFmode)) | |||
988 | op1 = gen_lowpartrtl_hooks.gen_lowpart (V4SFmode((void) 0, E_V4SFmode), op1); | |||
989 | ||||
990 | m = adjust_address (op0, V2SFmode, 0)adjust_address_1 (op0, ((void) 0, E_V2SFmode), 0, 1, 1, 0, 0); | |||
991 | emit_insn (gen_sse_storelps (m, op1)); | |||
992 | m = adjust_address (op0, V2SFmode, 8)adjust_address_1 (op0, ((void) 0, E_V2SFmode), 8, 1, 1, 0, 0); | |||
993 | emit_insn (gen_sse_storehps (m, copy_rtx (op1))); | |||
994 | } | |||
995 | } | |||
996 | else | |||
997 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 997, __FUNCTION__)); | |||
998 | } | |||
999 | ||||
1000 | /* Move bits 64:95 to bits 32:63. */ | |||
1001 | ||||
1002 | void | |||
1003 | ix86_move_vector_high_sse_to_mmx (rtx op) | |||
1004 | { | |||
1005 | rtx mask = gen_rtx_PARALLEL (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0))))) ) | |||
1006 | gen_rtvec (4, GEN_INT (0), GEN_INT (2),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0))))) ) | |||
1007 | GEN_INT (0), GEN_INT (0)))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0))))) ); | |||
1008 | rtx dest = lowpart_subreg (V4SImode((void) 0, E_V4SImode), op, GET_MODE (op)((machine_mode) (op)->mode)); | |||
1009 | op = gen_rtx_VEC_SELECT (V4SImode, dest, mask)gen_rtx_fmt_ee_stat ((VEC_SELECT), ((((void) 0, E_V4SImode))) , ((dest)), ((mask)) ); | |||
1010 | rtx insn = gen_rtx_SET (dest, op)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((op)) ); | |||
1011 | emit_insn (insn); | |||
1012 | } | |||
1013 | ||||
1014 | /* Split MMX pack with signed/unsigned saturation with SSE/SSE2. */ | |||
1015 | ||||
1016 | void | |||
1017 | ix86_split_mmx_pack (rtx operands[], enum rtx_code code) | |||
1018 | { | |||
1019 | rtx op0 = operands[0]; | |||
1020 | rtx op1 = operands[1]; | |||
1021 | rtx op2 = operands[2]; | |||
1022 | ||||
1023 | machine_mode dmode = GET_MODE (op0)((machine_mode) (op0)->mode); | |||
1024 | machine_mode smode = GET_MODE (op1)((machine_mode) (op1)->mode); | |||
1025 | machine_mode inner_dmode = GET_MODE_INNER (dmode)(mode_to_inner (dmode)); | |||
1026 | machine_mode inner_smode = GET_MODE_INNER (smode)(mode_to_inner (smode)); | |||
1027 | ||||
1028 | /* Get the corresponding SSE mode for destination. */ | |||
1029 | int nunits = 16 / GET_MODE_SIZE (inner_dmode)((unsigned short) mode_to_bytes (inner_dmode).coeffs[0]); | |||
1030 | machine_mode sse_dmode = mode_for_vector (GET_MODE_INNER (dmode)(mode_to_inner (dmode)), | |||
1031 | nunits).require (); | |||
1032 | machine_mode sse_half_dmode = mode_for_vector (GET_MODE_INNER (dmode)(mode_to_inner (dmode)), | |||
1033 | nunits / 2).require (); | |||
1034 | ||||
1035 | /* Get the corresponding SSE mode for source. */ | |||
1036 | nunits = 16 / GET_MODE_SIZE (inner_smode)((unsigned short) mode_to_bytes (inner_smode).coeffs[0]); | |||
1037 | machine_mode sse_smode = mode_for_vector (GET_MODE_INNER (smode)(mode_to_inner (smode)), | |||
1038 | nunits).require (); | |||
1039 | ||||
1040 | /* Generate SSE pack with signed/unsigned saturation. */ | |||
1041 | rtx dest = lowpart_subreg (sse_dmode, op0, GET_MODE (op0)((machine_mode) (op0)->mode)); | |||
1042 | op1 = lowpart_subreg (sse_smode, op1, GET_MODE (op1)((machine_mode) (op1)->mode)); | |||
1043 | op2 = lowpart_subreg (sse_smode, op2, GET_MODE (op2)((machine_mode) (op2)->mode)); | |||
1044 | ||||
1045 | op1 = gen_rtx_fmt_e (code, sse_half_dmode, op1)gen_rtx_fmt_e_stat ((code), (sse_half_dmode), (op1) ); | |||
1046 | op2 = gen_rtx_fmt_e (code, sse_half_dmode, op2)gen_rtx_fmt_e_stat ((code), (sse_half_dmode), (op2) ); | |||
1047 | rtx insn = gen_rtx_SET (dest, gen_rtx_VEC_CONCAT (sse_dmode,gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((gen_rtx_fmt_ee_stat ((VEC_CONCAT), ((sse_dmode)), ((op1) ), ((op2)) ))) ) | |||
1048 | op1, op2))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((gen_rtx_fmt_ee_stat ((VEC_CONCAT), ((sse_dmode)), ((op1) ), ((op2)) ))) ); | |||
1049 | emit_insn (insn); | |||
1050 | ||||
1051 | ix86_move_vector_high_sse_to_mmx (op0); | |||
1052 | } | |||
1053 | ||||
1054 | /* Split MMX punpcklXX/punpckhXX with SSE punpcklXX. */ | |||
1055 | ||||
1056 | void | |||
1057 | ix86_split_mmx_punpck (rtx operands[], bool high_p) | |||
1058 | { | |||
1059 | rtx op0 = operands[0]; | |||
1060 | rtx op1 = operands[1]; | |||
1061 | rtx op2 = operands[2]; | |||
1062 | machine_mode mode = GET_MODE (op0)((machine_mode) (op0)->mode); | |||
1063 | rtx mask; | |||
1064 | /* The corresponding SSE mode. */ | |||
1065 | machine_mode sse_mode, double_sse_mode; | |||
1066 | ||||
1067 | switch (mode) | |||
1068 | { | |||
1069 | case E_V4QImode: | |||
1070 | case E_V8QImode: | |||
1071 | sse_mode = V16QImode((void) 0, E_V16QImode); | |||
1072 | double_sse_mode = V32QImode((void) 0, E_V32QImode); | |||
1073 | mask = gen_rtx_PARALLEL (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (16, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0 )), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (17)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (18)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (19)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (20)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (21)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (6)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (22)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (7)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (23))))) ) | |||
1074 | gen_rtvec (16,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (16, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0 )), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (17)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (18)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (19)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (20)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (21)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (6)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (22)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (7)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (23))))) ) | |||
1075 | GEN_INT (0), GEN_INT (16),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (16, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0 )), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (17)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (18)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (19)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (20)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (21)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (6)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (22)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (7)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (23))))) ) | |||
1076 | GEN_INT (1), GEN_INT (17),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (16, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0 )), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (17)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (18)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (19)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (20)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (21)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (6)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (22)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (7)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (23))))) ) | |||
1077 | GEN_INT (2), GEN_INT (18),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (16, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0 )), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (17)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (18)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (19)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (20)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (21)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (6)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (22)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (7)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (23))))) ) | |||
1078 | GEN_INT (3), GEN_INT (19),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (16, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0 )), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (17)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (18)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (19)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (20)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (21)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (6)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (22)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (7)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (23))))) ) | |||
1079 | GEN_INT (4), GEN_INT (20),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (16, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0 )), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (17)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (18)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (19)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (20)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (21)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (6)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (22)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (7)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (23))))) ) | |||
1080 | GEN_INT (5), GEN_INT (21),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (16, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0 )), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (17)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (18)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (19)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (20)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (21)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (6)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (22)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (7)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (23))))) ) | |||
1081 | GEN_INT (6), GEN_INT (22),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (16, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0 )), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (17)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (18)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (19)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (20)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (21)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (6)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (22)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (7)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (23))))) ) | |||
1082 | GEN_INT (7), GEN_INT (23)))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (16, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0 )), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (17)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (18)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (19)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (20)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (21)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (6)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (22)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (7)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (23))))) ); | |||
1083 | break; | |||
1084 | ||||
1085 | case E_V4HImode: | |||
1086 | case E_V2HImode: | |||
1087 | sse_mode = V8HImode((void) 0, E_V8HImode); | |||
1088 | double_sse_mode = V16HImode((void) 0, E_V16HImode); | |||
1089 | mask = gen_rtx_PARALLEL (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (8, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (8)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (9)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode) , (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (10)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (11))))) ) | |||
1090 | gen_rtvec (8,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (8, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (8)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (9)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode) , (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (10)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (11))))) ) | |||
1091 | GEN_INT (0), GEN_INT (8),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (8, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (8)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (9)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode) , (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (10)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (11))))) ) | |||
1092 | GEN_INT (1), GEN_INT (9),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (8, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (8)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (9)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode) , (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (10)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (11))))) ) | |||
1093 | GEN_INT (2), GEN_INT (10),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (8, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (8)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (9)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode) , (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (10)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (11))))) ) | |||
1094 | GEN_INT (3), GEN_INT (11)))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (8, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (8)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (9)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode) , (2)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (10)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (11))))) ); | |||
1095 | break; | |||
1096 | ||||
1097 | case E_V2SImode: | |||
1098 | sse_mode = V4SImode((void) 0, E_V4SImode); | |||
1099 | double_sse_mode = V8SImode((void) 0, E_V8SImode); | |||
1100 | mask = gen_rtx_PARALLEL (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5))))) ) | |||
1101 | gen_rtvec (4,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5))))) ) | |||
1102 | GEN_INT (0), GEN_INT (4),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5))))) ) | |||
1103 | GEN_INT (1), GEN_INT (5)))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5))))) ); | |||
1104 | break; | |||
1105 | ||||
1106 | case E_V2SFmode: | |||
1107 | sse_mode = V4SFmode((void) 0, E_V4SFmode); | |||
1108 | double_sse_mode = V8SFmode((void) 0, E_V8SFmode); | |||
1109 | mask = gen_rtx_PARALLEL (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5))))) ) | |||
1110 | gen_rtvec (4,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5))))) ) | |||
1111 | GEN_INT (0), GEN_INT (4),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5))))) ) | |||
1112 | GEN_INT (1), GEN_INT (5)))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5))))) ); | |||
1113 | break; | |||
1114 | ||||
1115 | default: | |||
1116 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 1116, __FUNCTION__)); | |||
1117 | } | |||
1118 | ||||
1119 | /* Generate SSE punpcklXX. */ | |||
1120 | rtx dest = lowpart_subreg (sse_mode, op0, GET_MODE (op0)((machine_mode) (op0)->mode)); | |||
1121 | op1 = lowpart_subreg (sse_mode, op1, GET_MODE (op1)((machine_mode) (op1)->mode)); | |||
1122 | op2 = lowpart_subreg (sse_mode, op2, GET_MODE (op2)((machine_mode) (op2)->mode)); | |||
1123 | ||||
1124 | op1 = gen_rtx_VEC_CONCAT (double_sse_mode, op1, op2)gen_rtx_fmt_ee_stat ((VEC_CONCAT), ((double_sse_mode)), ((op1 )), ((op2)) ); | |||
1125 | op2 = gen_rtx_VEC_SELECT (sse_mode, op1, mask)gen_rtx_fmt_ee_stat ((VEC_SELECT), ((sse_mode)), ((op1)), ((mask )) ); | |||
1126 | rtx insn = gen_rtx_SET (dest, op2)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((op2)) ); | |||
1127 | emit_insn (insn); | |||
1128 | ||||
1129 | /* Move high bits to low bits. */ | |||
1130 | if (high_p) | |||
1131 | { | |||
1132 | if (sse_mode == V4SFmode((void) 0, E_V4SFmode)) | |||
1133 | { | |||
1134 | mask = gen_rtx_PARALLEL (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (2) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5))))) ) | |||
1135 | gen_rtvec (4, GEN_INT (2), GEN_INT (3),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (2) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5))))) ) | |||
1136 | GEN_INT (4), GEN_INT (5)))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (2) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (4)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (5))))) ); | |||
1137 | op2 = gen_rtx_VEC_CONCAT (V8SFmode, dest, dest)gen_rtx_fmt_ee_stat ((VEC_CONCAT), ((((void) 0, E_V8SFmode))) , ((dest)), ((dest)) ); | |||
1138 | op1 = gen_rtx_VEC_SELECT (V4SFmode, op2, mask)gen_rtx_fmt_ee_stat ((VEC_SELECT), ((((void) 0, E_V4SFmode))) , ((op2)), ((mask)) ); | |||
1139 | } | |||
1140 | else | |||
1141 | { | |||
1142 | int sz = GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]); | |||
1143 | ||||
1144 | if (sz == 4) | |||
1145 | mask = gen_rtx_PARALLEL (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1))))) ) | |||
1146 | gen_rtvec (4, GEN_INT (1), GEN_INT (0),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1))))) ) | |||
1147 | GEN_INT (0), GEN_INT (1)))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1))))) ); | |||
1148 | else if (sz == 8) | |||
1149 | mask = gen_rtx_PARALLEL (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (2) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1))))) ) | |||
1150 | gen_rtvec (4, GEN_INT (2), GEN_INT (3),gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (2) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1))))) ) | |||
1151 | GEN_INT (0), GEN_INT (1)))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (4, gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (2) ), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0)), gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (1))))) ); | |||
1152 | else | |||
1153 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 1153, __FUNCTION__)); | |||
1154 | ||||
1155 | dest = lowpart_subreg (V4SImode((void) 0, E_V4SImode), dest, GET_MODE (dest)((machine_mode) (dest)->mode)); | |||
1156 | op1 = gen_rtx_VEC_SELECT (V4SImode, dest, mask)gen_rtx_fmt_ee_stat ((VEC_SELECT), ((((void) 0, E_V4SImode))) , ((dest)), ((mask)) ); | |||
1157 | } | |||
1158 | ||||
1159 | insn = gen_rtx_SET (dest, op1)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((op1)) ); | |||
1160 | emit_insn (insn); | |||
1161 | } | |||
1162 | } | |||
1163 | ||||
1164 | /* Helper function of ix86_fixup_binary_operands to canonicalize | |||
1165 | operand order. Returns true if the operands should be swapped. */ | |||
1166 | ||||
1167 | static bool | |||
1168 | ix86_swap_binary_operands_p (enum rtx_code code, machine_mode mode, | |||
1169 | rtx operands[]) | |||
1170 | { | |||
1171 | rtx dst = operands[0]; | |||
1172 | rtx src1 = operands[1]; | |||
1173 | rtx src2 = operands[2]; | |||
1174 | ||||
1175 | /* If the operation is not commutative, we can't do anything. */ | |||
1176 | if (GET_RTX_CLASS (code)(rtx_class[(int) (code)]) != RTX_COMM_ARITH | |||
1177 | && GET_RTX_CLASS (code)(rtx_class[(int) (code)]) != RTX_COMM_COMPARE) | |||
1178 | return false; | |||
1179 | ||||
1180 | /* Highest priority is that src1 should match dst. */ | |||
1181 | if (rtx_equal_p (dst, src1)) | |||
1182 | return false; | |||
1183 | if (rtx_equal_p (dst, src2)) | |||
1184 | return true; | |||
1185 | ||||
1186 | /* Next highest priority is that immediate constants come second. */ | |||
1187 | if (immediate_operand (src2, mode)) | |||
1188 | return false; | |||
1189 | if (immediate_operand (src1, mode)) | |||
1190 | return true; | |||
1191 | ||||
1192 | /* Lowest priority is that memory references should come second. */ | |||
1193 | if (MEM_P (src2)(((enum rtx_code) (src2)->code) == MEM)) | |||
1194 | return false; | |||
1195 | if (MEM_P (src1)(((enum rtx_code) (src1)->code) == MEM)) | |||
1196 | return true; | |||
1197 | ||||
1198 | return false; | |||
1199 | } | |||
1200 | ||||
1201 | ||||
1202 | /* Fix up OPERANDS to satisfy ix86_binary_operator_ok. Return the | |||
1203 | destination to use for the operation. If different from the true | |||
1204 | destination in operands[0], a copy operation will be required. */ | |||
1205 | ||||
1206 | rtx | |||
1207 | ix86_fixup_binary_operands (enum rtx_code code, machine_mode mode, | |||
1208 | rtx operands[]) | |||
1209 | { | |||
1210 | rtx dst = operands[0]; | |||
1211 | rtx src1 = operands[1]; | |||
1212 | rtx src2 = operands[2]; | |||
1213 | ||||
1214 | /* Canonicalize operand order. */ | |||
1215 | if (ix86_swap_binary_operands_p (code, mode, operands)) | |||
1216 | { | |||
1217 | /* It is invalid to swap operands of different modes. */ | |||
1218 | gcc_assert (GET_MODE (src1) == GET_MODE (src2))((void)(!(((machine_mode) (src1)->mode) == ((machine_mode) (src2)->mode)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 1218, __FUNCTION__), 0 : 0)); | |||
1219 | ||||
1220 | std::swap (src1, src2); | |||
1221 | } | |||
1222 | ||||
1223 | /* Both source operands cannot be in memory. */ | |||
1224 | if (MEM_P (src1)(((enum rtx_code) (src1)->code) == MEM) && MEM_P (src2)(((enum rtx_code) (src2)->code) == MEM)) | |||
1225 | { | |||
1226 | /* Optimization: Only read from memory once. */ | |||
1227 | if (rtx_equal_p (src1, src2)) | |||
1228 | { | |||
1229 | src2 = force_reg (mode, src2); | |||
1230 | src1 = src2; | |||
1231 | } | |||
1232 | else if (rtx_equal_p (dst, src1)) | |||
1233 | src2 = force_reg (mode, src2); | |||
1234 | else | |||
1235 | src1 = force_reg (mode, src1); | |||
1236 | } | |||
1237 | ||||
1238 | /* If the destination is memory, and we do not have matching source | |||
1239 | operands, do things in registers. */ | |||
1240 | if (MEM_P (dst)(((enum rtx_code) (dst)->code) == MEM) && !rtx_equal_p (dst, src1)) | |||
1241 | dst = gen_reg_rtx (mode); | |||
1242 | ||||
1243 | /* Source 1 cannot be a constant. */ | |||
1244 | if (CONSTANT_P (src1)((rtx_class[(int) (((enum rtx_code) (src1)->code))]) == RTX_CONST_OBJ )) | |||
1245 | src1 = force_reg (mode, src1); | |||
1246 | ||||
1247 | /* Source 1 cannot be a non-matching memory. */ | |||
1248 | if (MEM_P (src1)(((enum rtx_code) (src1)->code) == MEM) && !rtx_equal_p (dst, src1)) | |||
1249 | src1 = force_reg (mode, src1); | |||
1250 | ||||
1251 | /* Improve address combine. */ | |||
1252 | if (code == PLUS | |||
1253 | && GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_INT | |||
1254 | && MEM_P (src2)(((enum rtx_code) (src2)->code) == MEM)) | |||
1255 | src2 = force_reg (mode, src2); | |||
1256 | ||||
1257 | operands[1] = src1; | |||
1258 | operands[2] = src2; | |||
1259 | return dst; | |||
1260 | } | |||
1261 | ||||
1262 | /* Similarly, but assume that the destination has already been | |||
1263 | set up properly. */ | |||
1264 | ||||
1265 | void | |||
1266 | ix86_fixup_binary_operands_no_copy (enum rtx_code code, | |||
1267 | machine_mode mode, rtx operands[]) | |||
1268 | { | |||
1269 | rtx dst = ix86_fixup_binary_operands (code, mode, operands); | |||
1270 | gcc_assert (dst == operands[0])((void)(!(dst == operands[0]) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 1270, __FUNCTION__), 0 : 0)); | |||
1271 | } | |||
1272 | ||||
1273 | /* Attempt to expand a binary operator. Make the expansion closer to the | |||
1274 | actual machine, then just general_operand, which will allow 3 separate | |||
1275 | memory references (one output, two input) in a single insn. */ | |||
1276 | ||||
1277 | void | |||
1278 | ix86_expand_binary_operator (enum rtx_code code, machine_mode mode, | |||
1279 | rtx operands[]) | |||
1280 | { | |||
1281 | rtx src1, src2, dst, op, clob; | |||
1282 | ||||
1283 | dst = ix86_fixup_binary_operands (code, mode, operands); | |||
1284 | src1 = operands[1]; | |||
1285 | src2 = operands[2]; | |||
1286 | ||||
1287 | /* Emit the instruction. */ | |||
1288 | ||||
1289 | op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dst)) , ((gen_rtx_fmt_ee_stat ((code), (mode), (src1), (src2) ))) ); | |||
1290 | ||||
1291 | if (reload_completed | |||
1292 | && code == PLUS | |||
1293 | && !rtx_equal_p (dst, src1)) | |||
1294 | { | |||
1295 | /* This is going to be an LEA; avoid splitting it later. */ | |||
1296 | emit_insn (op); | |||
1297 | } | |||
1298 | else | |||
1299 | { | |||
1300 | clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG))gen_rtx_fmt_e_stat ((CLOBBER), ((((void) 0, E_VOIDmode))), (( gen_rtx_REG (((void) 0, E_CCmode), 17))) ); | |||
1301 | emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, op, clob))) )); | |||
1302 | } | |||
1303 | ||||
1304 | /* Fix up the destination if needed. */ | |||
1305 | if (dst != operands[0]) | |||
1306 | emit_move_insn (operands[0], dst); | |||
1307 | } | |||
1308 | ||||
1309 | /* Expand vector logical operation CODE (AND, IOR, XOR) in MODE with | |||
1310 | the given OPERANDS. */ | |||
1311 | ||||
1312 | void | |||
1313 | ix86_expand_vector_logical_operator (enum rtx_code code, machine_mode mode, | |||
1314 | rtx operands[]) | |||
1315 | { | |||
1316 | rtx op1 = NULL_RTX(rtx) 0, op2 = NULL_RTX(rtx) 0; | |||
1317 | if (SUBREG_P (operands[1])(((enum rtx_code) (operands[1])->code) == SUBREG)) | |||
1318 | { | |||
1319 | op1 = operands[1]; | |||
1320 | op2 = operands[2]; | |||
1321 | } | |||
1322 | else if (SUBREG_P (operands[2])(((enum rtx_code) (operands[2])->code) == SUBREG)) | |||
1323 | { | |||
1324 | op1 = operands[2]; | |||
1325 | op2 = operands[1]; | |||
1326 | } | |||
1327 | /* Optimize (__m128i) d | (__m128i) e and similar code | |||
1328 | when d and e are float vectors into float vector logical | |||
1329 | insn. In C/C++ without using intrinsics there is no other way | |||
1330 | to express vector logical operation on float vectors than | |||
1331 | to cast them temporarily to integer vectors. */ | |||
1332 | if (op1 | |||
1333 | && !TARGET_SSE_PACKED_SINGLE_INSN_OPTIMALix86_tune_features[X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL] | |||
1334 | && (SUBREG_P (op2)(((enum rtx_code) (op2)->code) == SUBREG) || GET_CODE (op2)((enum rtx_code) (op2)->code) == CONST_VECTOR) | |||
1335 | && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op1)))((enum mode_class) mode_class[((machine_mode) ((((op1)->u. fld[0]).rt_rtx))->mode)]) == MODE_VECTOR_FLOAT | |||
1336 | && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))((unsigned short) mode_to_bytes (((machine_mode) ((((op1)-> u.fld[0]).rt_rtx))->mode)).coeffs[0]) == GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) | |||
1337 | && SUBREG_BYTE (op1)(((op1)->u.fld[1]).rt_subreg) == 0 | |||
1338 | && (GET_CODE (op2)((enum rtx_code) (op2)->code) == CONST_VECTOR | |||
1339 | || (GET_MODE (SUBREG_REG (op1))((machine_mode) ((((op1)->u.fld[0]).rt_rtx))->mode) == GET_MODE (SUBREG_REG (op2))((machine_mode) ((((op2)->u.fld[0]).rt_rtx))->mode) | |||
1340 | && SUBREG_BYTE (op2)(((op2)->u.fld[1]).rt_subreg) == 0)) | |||
1341 | && can_create_pseudo_p ()(!reload_in_progress && !reload_completed)) | |||
1342 | { | |||
1343 | rtx dst; | |||
1344 | switch (GET_MODE (SUBREG_REG (op1))((machine_mode) ((((op1)->u.fld[0]).rt_rtx))->mode)) | |||
1345 | { | |||
1346 | case E_V4SFmode: | |||
1347 | case E_V8SFmode: | |||
1348 | case E_V16SFmode: | |||
1349 | case E_V2DFmode: | |||
1350 | case E_V4DFmode: | |||
1351 | case E_V8DFmode: | |||
1352 | dst = gen_reg_rtx (GET_MODE (SUBREG_REG (op1))((machine_mode) ((((op1)->u.fld[0]).rt_rtx))->mode)); | |||
1353 | if (GET_CODE (op2)((enum rtx_code) (op2)->code) == CONST_VECTOR) | |||
1354 | { | |||
1355 | op2 = gen_lowpartrtl_hooks.gen_lowpart (GET_MODE (dst)((machine_mode) (dst)->mode), op2); | |||
1356 | op2 = force_reg (GET_MODE (dst)((machine_mode) (dst)->mode), op2); | |||
1357 | } | |||
1358 | else | |||
1359 | { | |||
1360 | op1 = operands[1]; | |||
1361 | op2 = SUBREG_REG (operands[2])(((operands[2])->u.fld[0]).rt_rtx); | |||
1362 | if (!vector_operand (op2, GET_MODE (dst)((machine_mode) (dst)->mode))) | |||
1363 | op2 = force_reg (GET_MODE (dst)((machine_mode) (dst)->mode), op2); | |||
1364 | } | |||
1365 | op1 = SUBREG_REG (op1)(((op1)->u.fld[0]).rt_rtx); | |||
1366 | if (!vector_operand (op1, GET_MODE (dst)((machine_mode) (dst)->mode))) | |||
1367 | op1 = force_reg (GET_MODE (dst)((machine_mode) (dst)->mode), op1); | |||
1368 | emit_insn (gen_rtx_SET (dst,gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dst)) , ((gen_rtx_fmt_ee_stat ((code), (((machine_mode) (dst)->mode )), (op1), (op2) ))) ) | |||
1369 | gen_rtx_fmt_ee (code, GET_MODE (dst),gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dst)) , ((gen_rtx_fmt_ee_stat ((code), (((machine_mode) (dst)->mode )), (op1), (op2) ))) ) | |||
1370 | op1, op2))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dst)) , ((gen_rtx_fmt_ee_stat ((code), (((machine_mode) (dst)->mode )), (op1), (op2) ))) )); | |||
1371 | emit_move_insn (operands[0], gen_lowpartrtl_hooks.gen_lowpart (mode, dst)); | |||
1372 | return; | |||
1373 | default: | |||
1374 | break; | |||
1375 | } | |||
1376 | } | |||
1377 | if (!vector_operand (operands[1], mode)) | |||
1378 | operands[1] = force_reg (mode, operands[1]); | |||
1379 | if (!vector_operand (operands[2], mode)) | |||
1380 | operands[2] = force_reg (mode, operands[2]); | |||
1381 | ix86_fixup_binary_operands_no_copy (code, mode, operands); | |||
1382 | emit_insn (gen_rtx_SET (operands[0],gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((operands [0])), ((gen_rtx_fmt_ee_stat ((code), (mode), (operands[1]), ( operands[2]) ))) ) | |||
1383 | gen_rtx_fmt_ee (code, mode, operands[1],gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((operands [0])), ((gen_rtx_fmt_ee_stat ((code), (mode), (operands[1]), ( operands[2]) ))) ) | |||
1384 | operands[2]))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((operands [0])), ((gen_rtx_fmt_ee_stat ((code), (mode), (operands[1]), ( operands[2]) ))) )); | |||
1385 | } | |||
1386 | ||||
1387 | /* Return TRUE or FALSE depending on whether the binary operator meets the | |||
1388 | appropriate constraints. */ | |||
1389 | ||||
1390 | bool | |||
1391 | ix86_binary_operator_ok (enum rtx_code code, machine_mode mode, | |||
1392 | rtx operands[3]) | |||
1393 | { | |||
1394 | rtx dst = operands[0]; | |||
1395 | rtx src1 = operands[1]; | |||
1396 | rtx src2 = operands[2]; | |||
1397 | ||||
1398 | /* Both source operands cannot be in memory. */ | |||
1399 | if ((MEM_P (src1)(((enum rtx_code) (src1)->code) == MEM) || bcst_mem_operand (src1, mode)) | |||
1400 | && (MEM_P (src2)(((enum rtx_code) (src2)->code) == MEM) || bcst_mem_operand (src2, mode))) | |||
1401 | return false; | |||
1402 | ||||
1403 | /* Canonicalize operand order for commutative operators. */ | |||
1404 | if (ix86_swap_binary_operands_p (code, mode, operands)) | |||
1405 | std::swap (src1, src2); | |||
1406 | ||||
1407 | /* If the destination is memory, we must have a matching source operand. */ | |||
1408 | if (MEM_P (dst)(((enum rtx_code) (dst)->code) == MEM) && !rtx_equal_p (dst, src1)) | |||
1409 | return false; | |||
1410 | ||||
1411 | /* Source 1 cannot be a constant. */ | |||
1412 | if (CONSTANT_P (src1)((rtx_class[(int) (((enum rtx_code) (src1)->code))]) == RTX_CONST_OBJ )) | |||
1413 | return false; | |||
1414 | ||||
1415 | /* Source 1 cannot be a non-matching memory. */ | |||
1416 | if (MEM_P (src1)(((enum rtx_code) (src1)->code) == MEM) && !rtx_equal_p (dst, src1)) | |||
1417 | /* Support "andhi/andsi/anddi" as a zero-extending move. */ | |||
1418 | return (code == AND | |||
1419 | && (mode == HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode)) | |||
1420 | || mode == SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)) | |||
1421 | || (TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) && mode == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)))) | |||
1422 | && satisfies_constraint_L (src2)); | |||
1423 | ||||
1424 | return true; | |||
1425 | } | |||
1426 | ||||
1427 | /* Attempt to expand a unary operator. Make the expansion closer to the | |||
1428 | actual machine, then just general_operand, which will allow 2 separate | |||
1429 | memory references (one output, one input) in a single insn. */ | |||
1430 | ||||
1431 | void | |||
1432 | ix86_expand_unary_operator (enum rtx_code code, machine_mode mode, | |||
1433 | rtx operands[]) | |||
1434 | { | |||
1435 | bool matching_memory = false; | |||
1436 | rtx src, dst, op, clob; | |||
1437 | ||||
1438 | dst = operands[0]; | |||
1439 | src = operands[1]; | |||
1440 | ||||
1441 | /* If the destination is memory, and we do not have matching source | |||
1442 | operands, do things in registers. */ | |||
1443 | if (MEM_P (dst)(((enum rtx_code) (dst)->code) == MEM)) | |||
1444 | { | |||
1445 | if (rtx_equal_p (dst, src)) | |||
1446 | matching_memory = true; | |||
1447 | else | |||
1448 | dst = gen_reg_rtx (mode); | |||
1449 | } | |||
1450 | ||||
1451 | /* When source operand is memory, destination must match. */ | |||
1452 | if (MEM_P (src)(((enum rtx_code) (src)->code) == MEM) && !matching_memory) | |||
1453 | src = force_reg (mode, src); | |||
1454 | ||||
1455 | /* Emit the instruction. */ | |||
1456 | ||||
1457 | op = gen_rtx_SET (dst, gen_rtx_fmt_e (code, mode, src))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dst)) , ((gen_rtx_fmt_e_stat ((code), (mode), (src) ))) ); | |||
1458 | ||||
1459 | if (code == NOT) | |||
1460 | emit_insn (op); | |||
1461 | else | |||
1462 | { | |||
1463 | clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG))gen_rtx_fmt_e_stat ((CLOBBER), ((((void) 0, E_VOIDmode))), (( gen_rtx_REG (((void) 0, E_CCmode), 17))) ); | |||
1464 | emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, op, clob))) )); | |||
1465 | } | |||
1466 | ||||
1467 | /* Fix up the destination if needed. */ | |||
1468 | if (dst != operands[0]) | |||
1469 | emit_move_insn (operands[0], dst); | |||
1470 | } | |||
1471 | ||||
1472 | /* Predict just emitted jump instruction to be taken with probability PROB. */ | |||
1473 | ||||
1474 | static void | |||
1475 | predict_jump (int prob) | |||
1476 | { | |||
1477 | rtx_insn *insn = get_last_insn (); | |||
1478 | gcc_assert (JUMP_P (insn))((void)(!((((enum rtx_code) (insn)->code) == JUMP_INSN)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 1478, __FUNCTION__), 0 : 0)); | |||
1479 | add_reg_br_prob_note (insn, profile_probability::from_reg_br_prob_base (prob)); | |||
1480 | } | |||
1481 | ||||
1482 | /* Split 32bit/64bit divmod with 8bit unsigned divmod if dividend and | |||
1483 | divisor are within the range [0-255]. */ | |||
1484 | ||||
1485 | void | |||
1486 | ix86_split_idivmod (machine_mode mode, rtx operands[], | |||
1487 | bool unsigned_p) | |||
1488 | { | |||
1489 | rtx_code_label *end_label, *qimode_label; | |||
1490 | rtx div, mod; | |||
1491 | rtx_insn *insn; | |||
1492 | rtx scratch, tmp0, tmp1, tmp2; | |||
1493 | rtx (*gen_divmod4_1) (rtx, rtx, rtx, rtx); | |||
1494 | ||||
1495 | operands[2] = force_reg (mode, operands[2]); | |||
1496 | operands[3] = force_reg (mode, operands[3]); | |||
1497 | ||||
1498 | switch (mode) | |||
1499 | { | |||
1500 | case E_SImode: | |||
1501 | if (GET_MODE (operands[0])((machine_mode) (operands[0])->mode) == SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))) | |||
1502 | { | |||
1503 | if (GET_MODE (operands[1])((machine_mode) (operands[1])->mode) == SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))) | |||
1504 | gen_divmod4_1 = unsigned_p ? gen_udivmodsi4_1 : gen_divmodsi4_1; | |||
1505 | else | |||
1506 | gen_divmod4_1 | |||
1507 | = unsigned_p ? gen_udivmodsi4_zext_2 : gen_divmodsi4_zext_2; | |||
1508 | } | |||
1509 | else | |||
1510 | gen_divmod4_1 | |||
1511 | = unsigned_p ? gen_udivmodsi4_zext_1 : gen_divmodsi4_zext_1; | |||
1512 | break; | |||
1513 | ||||
1514 | case E_DImode: | |||
1515 | gen_divmod4_1 = unsigned_p ? gen_udivmoddi4_1 : gen_divmoddi4_1; | |||
1516 | break; | |||
1517 | ||||
1518 | default: | |||
1519 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 1519, __FUNCTION__)); | |||
1520 | } | |||
1521 | ||||
1522 | end_label = gen_label_rtx (); | |||
1523 | qimode_label = gen_label_rtx (); | |||
1524 | ||||
1525 | scratch = gen_reg_rtx (mode); | |||
1526 | ||||
1527 | /* Use 8bit unsigned divimod if dividend and divisor are within | |||
1528 | the range [0-255]. */ | |||
1529 | emit_move_insn (scratch, operands[2]); | |||
1530 | scratch = expand_simple_binop (mode, IOR, scratch, operands[3], | |||
1531 | scratch, 1, OPTAB_DIRECT); | |||
1532 | emit_insn (gen_test_ccno_1 (mode, scratch, GEN_INT (-0x100)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (-0x100)))); | |||
1533 | tmp0 = gen_rtx_REG (CCNOmode((void) 0, E_CCNOmode), FLAGS_REG17); | |||
1534 | tmp0 = gen_rtx_EQ (VOIDmode, tmp0, const0_rtx)gen_rtx_fmt_ee_stat ((EQ), ((((void) 0, E_VOIDmode))), ((tmp0 )), (((const_int_rtx[64]))) ); | |||
1535 | tmp0 = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp0,gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((tmp0)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0 , E_VOIDmode))), ((qimode_label)) ))), ((pc_rtx)) ) | |||
1536 | gen_rtx_LABEL_REF (VOIDmode, qimode_label),gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((tmp0)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0 , E_VOIDmode))), ((qimode_label)) ))), ((pc_rtx)) ) | |||
1537 | pc_rtx)gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((tmp0)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0 , E_VOIDmode))), ((qimode_label)) ))), ((pc_rtx)) ); | |||
1538 | insn = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp0)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((pc_rtx )), ((tmp0)) )); | |||
1539 | predict_jump (REG_BR_PROB_BASE10000 * 50 / 100); | |||
1540 | JUMP_LABEL (insn)(((insn)->u.fld[7]).rt_rtx) = qimode_label; | |||
1541 | ||||
1542 | /* Generate original signed/unsigned divimod. */ | |||
1543 | emit_insn (gen_divmod4_1 (operands[0], operands[1], | |||
1544 | operands[2], operands[3])); | |||
1545 | ||||
1546 | /* Branch to the end. */ | |||
1547 | emit_jump_insn (gen_jump (end_label)); | |||
1548 | emit_barrier (); | |||
1549 | ||||
1550 | /* Generate 8bit unsigned divide. */ | |||
1551 | emit_label (qimode_label); | |||
1552 | /* Don't use operands[0] for result of 8bit divide since not all | |||
1553 | registers support QImode ZERO_EXTRACT. */ | |||
1554 | tmp0 = lowpart_subreg (HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode)), scratch, mode); | |||
1555 | tmp1 = lowpart_subreg (HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode)), operands[2], mode); | |||
1556 | tmp2 = lowpart_subreg (QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)), operands[3], mode); | |||
1557 | emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, tmp2)); | |||
1558 | ||||
1559 | if (unsigned_p) | |||
1560 | { | |||
1561 | div = gen_rtx_UDIV (mode, operands[2], operands[3])gen_rtx_fmt_ee_stat ((UDIV), ((mode)), ((operands[2])), ((operands [3])) ); | |||
1562 | mod = gen_rtx_UMOD (mode, operands[2], operands[3])gen_rtx_fmt_ee_stat ((UMOD), ((mode)), ((operands[2])), ((operands [3])) ); | |||
1563 | } | |||
1564 | else | |||
1565 | { | |||
1566 | div = gen_rtx_DIV (mode, operands[2], operands[3])gen_rtx_fmt_ee_stat ((DIV), ((mode)), ((operands[2])), ((operands [3])) ); | |||
1567 | mod = gen_rtx_MOD (mode, operands[2], operands[3])gen_rtx_fmt_ee_stat ((MOD), ((mode)), ((operands[2])), ((operands [3])) ); | |||
1568 | } | |||
1569 | if (mode == SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))) | |||
1570 | { | |||
1571 | if (GET_MODE (operands[0])((machine_mode) (operands[0])->mode) != SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))) | |||
1572 | div = gen_rtx_ZERO_EXTEND (DImode, div)gen_rtx_fmt_e_stat ((ZERO_EXTEND), (((scalar_int_mode ((scalar_int_mode ::from_int) E_DImode)))), ((div)) ); | |||
1573 | if (GET_MODE (operands[1])((machine_mode) (operands[1])->mode) != SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))) | |||
1574 | mod = gen_rtx_ZERO_EXTEND (DImode, mod)gen_rtx_fmt_e_stat ((ZERO_EXTEND), (((scalar_int_mode ((scalar_int_mode ::from_int) E_DImode)))), ((mod)) ); | |||
1575 | } | |||
1576 | ||||
1577 | /* Extract remainder from AH. */ | |||
1578 | scratch = gen_lowpartrtl_hooks.gen_lowpart (GET_MODE (operands[1])((machine_mode) (operands[1])->mode), scratch); | |||
1579 | tmp1 = gen_rtx_ZERO_EXTRACT (GET_MODE (operands[1]), scratch,gen_rtx_fmt_eee_stat ((ZERO_EXTRACT), ((((machine_mode) (operands [1])->mode))), ((scratch)), ((gen_rtx_CONST_INT (((void) 0 , E_VOIDmode), (8)))), ((gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (8)))) ) | |||
1580 | GEN_INT (8), GEN_INT (8))gen_rtx_fmt_eee_stat ((ZERO_EXTRACT), ((((machine_mode) (operands [1])->mode))), ((scratch)), ((gen_rtx_CONST_INT (((void) 0 , E_VOIDmode), (8)))), ((gen_rtx_CONST_INT (((void) 0, E_VOIDmode ), (8)))) ); | |||
1581 | insn = emit_move_insn (operands[1], tmp1); | |||
1582 | set_unique_reg_note (insn, REG_EQUAL, mod); | |||
1583 | ||||
1584 | /* Zero extend quotient from AL. */ | |||
1585 | tmp1 = gen_lowpartrtl_hooks.gen_lowpart (QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)), tmp0); | |||
1586 | insn = emit_insn (gen_extend_insn | |||
1587 | (operands[0], tmp1, | |||
1588 | GET_MODE (operands[0])((machine_mode) (operands[0])->mode), QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)), 1)); | |||
1589 | set_unique_reg_note (insn, REG_EQUAL, div); | |||
1590 | ||||
1591 | emit_label (end_label); | |||
1592 | } | |||
1593 | ||||
1594 | /* Emit x86 binary operand CODE in mode MODE, where the first operand | |||
1595 | matches destination. RTX includes clobber of FLAGS_REG. */ | |||
1596 | ||||
1597 | void | |||
1598 | ix86_emit_binop (enum rtx_code code, machine_mode mode, | |||
1599 | rtx dst, rtx src) | |||
1600 | { | |||
1601 | rtx op, clob; | |||
1602 | ||||
1603 | op = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, dst, src))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dst)) , ((gen_rtx_fmt_ee_stat ((code), (mode), (dst), (src) ))) ); | |||
1604 | clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG))gen_rtx_fmt_e_stat ((CLOBBER), ((((void) 0, E_VOIDmode))), (( gen_rtx_REG (((void) 0, E_CCmode), 17))) ); | |||
1605 | ||||
1606 | emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, op, clob))) )); | |||
1607 | } | |||
1608 | ||||
1609 | /* Return true if regno1 def is nearest to the insn. */ | |||
1610 | ||||
1611 | static bool | |||
1612 | find_nearest_reg_def (rtx_insn *insn, int regno1, int regno2) | |||
1613 | { | |||
1614 | rtx_insn *prev = insn; | |||
1615 | rtx_insn *start = BB_HEAD (BLOCK_FOR_INSN (insn))(BLOCK_FOR_INSN (insn))->il.x.head_; | |||
1616 | ||||
1617 | if (insn == start) | |||
1618 | return false; | |||
1619 | while (prev && prev != start) | |||
1620 | { | |||
1621 | if (!INSN_P (prev)(((((enum rtx_code) (prev)->code) == INSN) || (((enum rtx_code ) (prev)->code) == JUMP_INSN) || (((enum rtx_code) (prev)-> code) == CALL_INSN)) || (((enum rtx_code) (prev)->code) == DEBUG_INSN)) || !NONDEBUG_INSN_P (prev)((((enum rtx_code) (prev)->code) == INSN) || (((enum rtx_code ) (prev)->code) == JUMP_INSN) || (((enum rtx_code) (prev)-> code) == CALL_INSN))) | |||
1622 | { | |||
1623 | prev = PREV_INSN (prev); | |||
1624 | continue; | |||
1625 | } | |||
1626 | if (insn_defines_reg (regno1, INVALID_REGNUM(~(unsigned int) 0), prev)) | |||
1627 | return true; | |||
1628 | else if (insn_defines_reg (regno2, INVALID_REGNUM(~(unsigned int) 0), prev)) | |||
1629 | return false; | |||
1630 | prev = PREV_INSN (prev); | |||
1631 | } | |||
1632 | ||||
1633 | /* None of the regs is defined in the bb. */ | |||
1634 | return false; | |||
1635 | } | |||
1636 | ||||
1637 | /* INSN_UID of the last insn emitted by zero store peephole2s. */ | |||
1638 | int ix86_last_zero_store_uid; | |||
1639 | ||||
1640 | /* Split lea instructions into a sequence of instructions | |||
1641 | which are executed on ALU to avoid AGU stalls. | |||
1642 | It is assumed that it is allowed to clobber flags register | |||
1643 | at lea position. */ | |||
1644 | ||||
1645 | void | |||
1646 | ix86_split_lea_for_addr (rtx_insn *insn, rtx operands[], machine_mode mode) | |||
1647 | { | |||
1648 | unsigned int regno0, regno1, regno2; | |||
1649 | struct ix86_address parts; | |||
1650 | rtx target, tmp; | |||
1651 | int ok, adds; | |||
1652 | ||||
1653 | ok = ix86_decompose_address (operands[1], &parts); | |||
1654 | gcc_assert (ok)((void)(!(ok) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 1654, __FUNCTION__), 0 : 0)); | |||
1655 | ||||
1656 | target = gen_lowpartrtl_hooks.gen_lowpart (mode, operands[0]); | |||
1657 | ||||
1658 | regno0 = true_regnum (target); | |||
1659 | regno1 = INVALID_REGNUM(~(unsigned int) 0); | |||
1660 | regno2 = INVALID_REGNUM(~(unsigned int) 0); | |||
1661 | ||||
1662 | if (parts.base) | |||
1663 | { | |||
1664 | parts.base = gen_lowpartrtl_hooks.gen_lowpart (mode, parts.base); | |||
1665 | regno1 = true_regnum (parts.base); | |||
1666 | } | |||
1667 | ||||
1668 | if (parts.index) | |||
1669 | { | |||
1670 | parts.index = gen_lowpartrtl_hooks.gen_lowpart (mode, parts.index); | |||
1671 | regno2 = true_regnum (parts.index); | |||
1672 | } | |||
1673 | ||||
1674 | if (parts.disp) | |||
1675 | parts.disp = gen_lowpartrtl_hooks.gen_lowpart (mode, parts.disp); | |||
1676 | ||||
1677 | if (parts.scale > 1) | |||
1678 | { | |||
1679 | /* Case r1 = r1 + ... */ | |||
1680 | if (regno1 == regno0) | |||
1681 | { | |||
1682 | /* If we have a case r1 = r1 + C * r2 then we | |||
1683 | should use multiplication which is very | |||
1684 | expensive. Assume cost model is wrong if we | |||
1685 | have such case here. */ | |||
1686 | gcc_assert (regno2 != regno0)((void)(!(regno2 != regno0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 1686, __FUNCTION__), 0 : 0)); | |||
1687 | ||||
1688 | for (adds = parts.scale; adds > 0; adds--) | |||
1689 | ix86_emit_binop (PLUS, mode, target, parts.index); | |||
1690 | } | |||
1691 | else | |||
1692 | { | |||
1693 | /* r1 = r2 + r3 * C case. Need to move r3 into r1. */ | |||
1694 | if (regno0 != regno2) | |||
1695 | emit_insn (gen_rtx_SET (target, parts.index)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((target )), ((parts.index)) )); | |||
1696 | ||||
1697 | /* Use shift for scaling, but emit it as MULT instead | |||
1698 | to avoid it being immediately peephole2 optimized back | |||
1699 | into lea. */ | |||
1700 | ix86_emit_binop (MULT, mode, target, GEN_INT (parts.scale)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (parts.scale))); | |||
1701 | ||||
1702 | if (parts.base) | |||
1703 | ix86_emit_binop (PLUS, mode, target, parts.base); | |||
1704 | ||||
1705 | if (parts.disp && parts.disp != const0_rtx(const_int_rtx[64])) | |||
1706 | ix86_emit_binop (PLUS, mode, target, parts.disp); | |||
1707 | } | |||
1708 | } | |||
1709 | else if (!parts.base && !parts.index) | |||
1710 | { | |||
1711 | gcc_assert(parts.disp)((void)(!(parts.disp) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 1711, __FUNCTION__), 0 : 0)); | |||
1712 | emit_insn (gen_rtx_SET (target, parts.disp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((target )), ((parts.disp)) )); | |||
1713 | } | |||
1714 | else | |||
1715 | { | |||
1716 | if (!parts.base) | |||
1717 | { | |||
1718 | if (regno0 != regno2) | |||
1719 | emit_insn (gen_rtx_SET (target, parts.index)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((target )), ((parts.index)) )); | |||
1720 | } | |||
1721 | else if (!parts.index) | |||
1722 | { | |||
1723 | if (regno0 != regno1) | |||
1724 | emit_insn (gen_rtx_SET (target, parts.base)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((target )), ((parts.base)) )); | |||
1725 | } | |||
1726 | else | |||
1727 | { | |||
1728 | if (regno0 == regno1) | |||
1729 | tmp = parts.index; | |||
1730 | else if (regno0 == regno2) | |||
1731 | tmp = parts.base; | |||
1732 | else | |||
1733 | { | |||
1734 | rtx tmp1; | |||
1735 | ||||
1736 | /* Find better operand for SET instruction, depending | |||
1737 | on which definition is farther from the insn. */ | |||
1738 | if (find_nearest_reg_def (insn, regno1, regno2)) | |||
1739 | tmp = parts.index, tmp1 = parts.base; | |||
1740 | else | |||
1741 | tmp = parts.base, tmp1 = parts.index; | |||
1742 | ||||
1743 | emit_insn (gen_rtx_SET (target, tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((target )), ((tmp)) )); | |||
1744 | ||||
1745 | if (parts.disp && parts.disp != const0_rtx(const_int_rtx[64])) | |||
1746 | ix86_emit_binop (PLUS, mode, target, parts.disp); | |||
1747 | ||||
1748 | ix86_emit_binop (PLUS, mode, target, tmp1); | |||
1749 | return; | |||
1750 | } | |||
1751 | ||||
1752 | ix86_emit_binop (PLUS, mode, target, tmp); | |||
1753 | } | |||
1754 | ||||
1755 | if (parts.disp && parts.disp != const0_rtx(const_int_rtx[64])) | |||
1756 | ix86_emit_binop (PLUS, mode, target, parts.disp); | |||
1757 | } | |||
1758 | } | |||
1759 | ||||
1760 | /* Post-reload splitter for converting an SF or DFmode value in an | |||
1761 | SSE register into an unsigned SImode. */ | |||
1762 | ||||
1763 | void | |||
1764 | ix86_split_convert_uns_si_sse (rtx operands[]) | |||
1765 | { | |||
1766 | machine_mode vecmode; | |||
1767 | rtx value, large, zero_or_two31, input, two31, x; | |||
1768 | ||||
1769 | large = operands[1]; | |||
1770 | zero_or_two31 = operands[2]; | |||
1771 | input = operands[3]; | |||
1772 | two31 = operands[4]; | |||
1773 | vecmode = GET_MODE (large)((machine_mode) (large)->mode); | |||
1774 | value = gen_rtx_REG (vecmode, REGNO (operands[0])(rhs_regno(operands[0]))); | |||
1775 | ||||
1776 | /* Load up the value into the low element. We must ensure that the other | |||
1777 | elements are valid floats -- zero is the easiest such value. */ | |||
1778 | if (MEM_P (input)(((enum rtx_code) (input)->code) == MEM)) | |||
1779 | { | |||
1780 | if (vecmode == V4SFmode((void) 0, E_V4SFmode)) | |||
1781 | emit_insn (gen_vec_setv4sf_0 (value, CONST0_RTX (V4SFmode)(const_tiny_rtx[0][(int) (((void) 0, E_V4SFmode))]), input)); | |||
1782 | else | |||
1783 | emit_insn (gen_sse2_loadlpd (value, CONST0_RTX (V2DFmode)(const_tiny_rtx[0][(int) (((void) 0, E_V2DFmode))]), input)); | |||
1784 | } | |||
1785 | else | |||
1786 | { | |||
1787 | input = gen_rtx_REG (vecmode, REGNO (input)(rhs_regno(input))); | |||
1788 | emit_move_insn (value, CONST0_RTX (vecmode)(const_tiny_rtx[0][(int) (vecmode)])); | |||
1789 | if (vecmode == V4SFmode((void) 0, E_V4SFmode)) | |||
1790 | emit_insn (gen_sse_movss_v4sf (value, value, input)); | |||
1791 | else | |||
1792 | emit_insn (gen_sse2_movsd_v2df (value, value, input)); | |||
1793 | } | |||
1794 | ||||
1795 | emit_move_insn (large, two31); | |||
1796 | emit_move_insn (zero_or_two31, MEM_P (two31)(((enum rtx_code) (two31)->code) == MEM) ? large : two31); | |||
1797 | ||||
1798 | x = gen_rtx_fmt_ee (LE, vecmode, large, value)gen_rtx_fmt_ee_stat ((LE), (vecmode), (large), (value) ); | |||
1799 | emit_insn (gen_rtx_SET (large, x)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((large )), ((x)) )); | |||
1800 | ||||
1801 | x = gen_rtx_AND (vecmode, zero_or_two31, large)gen_rtx_fmt_ee_stat ((AND), ((vecmode)), ((zero_or_two31)), ( (large)) ); | |||
1802 | emit_insn (gen_rtx_SET (zero_or_two31, x)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((zero_or_two31 )), ((x)) )); | |||
1803 | ||||
1804 | x = gen_rtx_MINUS (vecmode, value, zero_or_two31)gen_rtx_fmt_ee_stat ((MINUS), ((vecmode)), ((value)), ((zero_or_two31 )) ); | |||
1805 | emit_insn (gen_rtx_SET (value, x)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((value )), ((x)) )); | |||
1806 | ||||
1807 | large = gen_rtx_REG (V4SImode((void) 0, E_V4SImode), REGNO (large)(rhs_regno(large))); | |||
1808 | emit_insn (gen_ashlv4si3 (large, large, GEN_INT (31)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (31)))); | |||
1809 | ||||
1810 | x = gen_rtx_REG (V4SImode((void) 0, E_V4SImode), REGNO (value)(rhs_regno(value))); | |||
1811 | if (vecmode == V4SFmode((void) 0, E_V4SFmode)) | |||
1812 | emit_insn (gen_fix_truncv4sfv4si2 (x, value)); | |||
1813 | else | |||
1814 | emit_insn (gen_sse2_cvttpd2dq (x, value)); | |||
1815 | value = x; | |||
1816 | ||||
1817 | emit_insn (gen_xorv4si3 (value, value, large)); | |||
1818 | } | |||
1819 | ||||
1820 | static bool ix86_expand_vector_init_one_nonzero (bool mmx_ok, | |||
1821 | machine_mode mode, rtx target, | |||
1822 | rtx var, int one_var); | |||
1823 | ||||
1824 | /* Convert an unsigned DImode value into a DFmode, using only SSE. | |||
1825 | Expects the 64-bit DImode to be supplied in a pair of integral | |||
1826 | registers. Requires SSE2; will use SSE3 if available. For x86_32, | |||
1827 | -mfpmath=sse, !optimize_size only. */ | |||
1828 | ||||
1829 | void | |||
1830 | ix86_expand_convert_uns_didf_sse (rtx target, rtx input) | |||
1831 | { | |||
1832 | REAL_VALUE_TYPEstruct real_value bias_lo_rvt, bias_hi_rvt; | |||
1833 | rtx int_xmm, fp_xmm; | |||
1834 | rtx biases, exponents; | |||
1835 | rtx x; | |||
1836 | ||||
1837 | int_xmm = gen_reg_rtx (V4SImode((void) 0, E_V4SImode)); | |||
1838 | if (TARGET_INTER_UNIT_MOVES_TO_VECix86_tune_features[X86_TUNE_INTER_UNIT_MOVES_TO_VEC]) | |||
1839 | emit_insn (gen_movdi_to_sse (int_xmm, input)); | |||
1840 | else if (TARGET_SSE_SPLIT_REGSix86_tune_features[X86_TUNE_SSE_SPLIT_REGS]) | |||
1841 | { | |||
1842 | emit_clobber (int_xmm); | |||
1843 | emit_move_insn (gen_lowpartrtl_hooks.gen_lowpart (DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)), int_xmm), input); | |||
1844 | } | |||
1845 | else | |||
1846 | { | |||
1847 | x = gen_reg_rtx (V2DImode((void) 0, E_V2DImode)); | |||
1848 | ix86_expand_vector_init_one_nonzero (false, V2DImode((void) 0, E_V2DImode), x, input, 0); | |||
1849 | emit_move_insn (int_xmm, gen_lowpartrtl_hooks.gen_lowpart (V4SImode((void) 0, E_V4SImode), x)); | |||
1850 | } | |||
1851 | ||||
1852 | x = gen_rtx_CONST_VECTOR (V4SImode((void) 0, E_V4SImode), | |||
1853 | gen_rtvec (4, GEN_INT (0x43300000UL)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x43300000UL)), | |||
1854 | GEN_INT (0x45300000UL)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x45300000UL)), | |||
1855 | const0_rtx(const_int_rtx[64]), const0_rtx(const_int_rtx[64]))); | |||
1856 | exponents = validize_mem (force_const_mem (V4SImode((void) 0, E_V4SImode), x)); | |||
1857 | ||||
1858 | /* int_xmm = {0x45300000UL, fp_xmm/hi, 0x43300000, fp_xmm/lo } */ | |||
1859 | emit_insn (gen_vec_interleave_lowv4si (int_xmm, int_xmm, exponents)); | |||
1860 | ||||
1861 | /* Concatenating (juxtaposing) (0x43300000UL ## fp_value_low_xmm) | |||
1862 | yields a valid DF value equal to (0x1.0p52 + double(fp_value_lo_xmm)). | |||
1863 | Similarly (0x45300000UL ## fp_value_hi_xmm) yields | |||
1864 | (0x1.0p84 + double(fp_value_hi_xmm)). | |||
1865 | Note these exponents differ by 32. */ | |||
1866 | ||||
1867 | fp_xmm = copy_to_mode_reg (V2DFmode((void) 0, E_V2DFmode), gen_lowpartrtl_hooks.gen_lowpart (V2DFmode((void) 0, E_V2DFmode), int_xmm)); | |||
1868 | ||||
1869 | /* Subtract off those 0x1.0p52 and 0x1.0p84 biases, to produce values | |||
1870 | in [0,2**32-1] and [0]+[2**32,2**64-1] respectively. */ | |||
1871 | real_ldexp (&bias_lo_rvt, &dconst1, 52); | |||
1872 | real_ldexp (&bias_hi_rvt, &dconst1, 84); | |||
1873 | biases = const_double_from_real_value (bias_lo_rvt, DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode))); | |||
1874 | x = const_double_from_real_value (bias_hi_rvt, DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode))); | |||
1875 | biases = gen_rtx_CONST_VECTOR (V2DFmode((void) 0, E_V2DFmode), gen_rtvec (2, biases, x)); | |||
1876 | biases = validize_mem (force_const_mem (V2DFmode((void) 0, E_V2DFmode), biases)); | |||
1877 | emit_insn (gen_subv2df3 (fp_xmm, fp_xmm, biases)); | |||
1878 | ||||
1879 | /* Add the upper and lower DFmode values together. */ | |||
1880 | if (TARGET_SSE3((global_options.x_ix86_isa_flags & (1UL << 52)) != 0)) | |||
1881 | emit_insn (gen_sse3_haddv2df3 (fp_xmm, fp_xmm, fp_xmm)); | |||
1882 | else | |||
1883 | { | |||
1884 | x = copy_to_mode_reg (V2DFmode((void) 0, E_V2DFmode), fp_xmm); | |||
1885 | emit_insn (gen_vec_interleave_highv2df (fp_xmm, fp_xmm, fp_xmm)); | |||
1886 | emit_insn (gen_addv2df3 (fp_xmm, fp_xmm, x)); | |||
1887 | } | |||
1888 | ||||
1889 | ix86_expand_vector_extract (false, target, fp_xmm, 0); | |||
1890 | } | |||
1891 | ||||
1892 | /* Not used, but eases macroization of patterns. */ | |||
1893 | void | |||
1894 | ix86_expand_convert_uns_sixf_sse (rtx, rtx) | |||
1895 | { | |||
1896 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 1896, __FUNCTION__)); | |||
1897 | } | |||
1898 | ||||
1899 | static rtx ix86_expand_sse_fabs (rtx op0, rtx *smask); | |||
1900 | ||||
1901 | /* Convert an unsigned SImode value into a DFmode. Only currently used | |||
1902 | for SSE, but applicable anywhere. */ | |||
1903 | ||||
1904 | void | |||
1905 | ix86_expand_convert_uns_sidf_sse (rtx target, rtx input) | |||
1906 | { | |||
1907 | REAL_VALUE_TYPEstruct real_value TWO31r; | |||
1908 | rtx x, fp; | |||
1909 | ||||
1910 | x = expand_simple_binop (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), PLUS, input, GEN_INT (-2147483647 - 1)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (-2147483647 - 1)), | |||
1911 | NULL__null, 1, OPTAB_DIRECT); | |||
1912 | ||||
1913 | fp = gen_reg_rtx (DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode))); | |||
1914 | emit_insn (gen_floatsidf2 (fp, x)); | |||
1915 | ||||
1916 | real_ldexp (&TWO31r, &dconst1, 31); | |||
1917 | x = const_double_from_real_value (TWO31r, DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode))); | |||
1918 | ||||
1919 | x = expand_simple_binop (DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode)), PLUS, fp, x, target, 0, OPTAB_DIRECT); | |||
1920 | ||||
1921 | /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */ | |||
1922 | if (HONOR_SIGNED_ZEROS (DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode))) && flag_rounding_mathglobal_options.x_flag_rounding_math) | |||
1923 | x = ix86_expand_sse_fabs (x, NULL__null); | |||
1924 | ||||
1925 | if (x != target) | |||
1926 | emit_move_insn (target, x); | |||
1927 | } | |||
1928 | ||||
1929 | /* Convert a signed DImode value into a DFmode. Only used for SSE in | |||
1930 | 32-bit mode; otherwise we have a direct convert instruction. */ | |||
1931 | ||||
1932 | void | |||
1933 | ix86_expand_convert_sign_didf_sse (rtx target, rtx input) | |||
1934 | { | |||
1935 | REAL_VALUE_TYPEstruct real_value TWO32r; | |||
1936 | rtx fp_lo, fp_hi, x; | |||
1937 | ||||
1938 | fp_lo = gen_reg_rtx (DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode))); | |||
1939 | fp_hi = gen_reg_rtx (DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode))); | |||
1940 | ||||
1941 | emit_insn (gen_floatsidf2 (fp_hi, gen_highpart (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), input))); | |||
1942 | ||||
1943 | real_ldexp (&TWO32r, &dconst1, 32); | |||
1944 | x = const_double_from_real_value (TWO32r, DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode))); | |||
1945 | fp_hi = expand_simple_binop (DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode)), MULT, fp_hi, x, fp_hi, 0, OPTAB_DIRECT); | |||
1946 | ||||
1947 | ix86_expand_convert_uns_sidf_sse (fp_lo, gen_lowpartrtl_hooks.gen_lowpart (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), input)); | |||
1948 | ||||
1949 | x = expand_simple_binop (DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode)), PLUS, fp_hi, fp_lo, target, | |||
1950 | 0, OPTAB_DIRECT); | |||
1951 | if (x != target) | |||
1952 | emit_move_insn (target, x); | |||
1953 | } | |||
1954 | ||||
1955 | /* Convert an unsigned SImode value into a SFmode, using only SSE. | |||
1956 | For x86_32, -mfpmath=sse, !optimize_size only. */ | |||
1957 | void | |||
1958 | ix86_expand_convert_uns_sisf_sse (rtx target, rtx input) | |||
1959 | { | |||
1960 | REAL_VALUE_TYPEstruct real_value ONE16r; | |||
1961 | rtx fp_hi, fp_lo, int_hi, int_lo, x; | |||
1962 | ||||
1963 | real_ldexp (&ONE16r, &dconst1, 16); | |||
1964 | x = const_double_from_real_value (ONE16r, SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode))); | |||
1965 | int_lo = expand_simple_binop (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), AND, input, GEN_INT(0xffff)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0xffff)), | |||
1966 | NULL__null, 0, OPTAB_DIRECT); | |||
1967 | int_hi = expand_simple_binop (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), LSHIFTRT, input, GEN_INT(16)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), | |||
1968 | NULL__null, 0, OPTAB_DIRECT); | |||
1969 | fp_hi = gen_reg_rtx (SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode))); | |||
1970 | fp_lo = gen_reg_rtx (SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode))); | |||
1971 | emit_insn (gen_floatsisf2 (fp_hi, int_hi)); | |||
1972 | emit_insn (gen_floatsisf2 (fp_lo, int_lo)); | |||
1973 | if (TARGET_FMA((global_options.x_ix86_isa_flags & (1UL << 29)) != 0)) | |||
1974 | { | |||
1975 | x = validize_mem (force_const_mem (SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode)), x)); | |||
1976 | fp_hi = gen_rtx_FMA (SFmode, fp_hi, x, fp_lo)gen_rtx_fmt_eee_stat ((FMA), (((scalar_float_mode ((scalar_float_mode ::from_int) E_SFmode)))), ((fp_hi)), ((x)), ((fp_lo)) ); | |||
1977 | emit_move_insn (target, fp_hi); | |||
1978 | } | |||
1979 | else | |||
1980 | { | |||
1981 | fp_hi = expand_simple_binop (SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode)), MULT, fp_hi, x, fp_hi, | |||
1982 | 0, OPTAB_DIRECT); | |||
1983 | fp_hi = expand_simple_binop (SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode)), PLUS, fp_hi, fp_lo, target, | |||
1984 | 0, OPTAB_DIRECT); | |||
1985 | if (!rtx_equal_p (target, fp_hi)) | |||
1986 | emit_move_insn (target, fp_hi); | |||
1987 | } | |||
1988 | } | |||
1989 | ||||
1990 | /* floatunsv{4,8}siv{4,8}sf2 expander. Expand code to convert | |||
1991 | a vector of unsigned ints VAL to vector of floats TARGET. */ | |||
1992 | ||||
1993 | void | |||
1994 | ix86_expand_vector_convert_uns_vsivsf (rtx target, rtx val) | |||
1995 | { | |||
1996 | rtx tmp[8]; | |||
1997 | REAL_VALUE_TYPEstruct real_value TWO16r; | |||
1998 | machine_mode intmode = GET_MODE (val)((machine_mode) (val)->mode); | |||
1999 | machine_mode fltmode = GET_MODE (target)((machine_mode) (target)->mode); | |||
2000 | rtx (*cvt) (rtx, rtx); | |||
2001 | ||||
2002 | if (intmode == V4SImode((void) 0, E_V4SImode)) | |||
2003 | cvt = gen_floatv4siv4sf2; | |||
2004 | else | |||
2005 | cvt = gen_floatv8siv8sf2; | |||
2006 | tmp[0] = ix86_build_const_vector (intmode, 1, GEN_INT (0xffff)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0xffff))); | |||
2007 | tmp[0] = force_reg (intmode, tmp[0]); | |||
2008 | tmp[1] = expand_simple_binop (intmode, AND, val, tmp[0], NULL_RTX(rtx) 0, 1, | |||
2009 | OPTAB_DIRECT); | |||
2010 | tmp[2] = expand_simple_binop (intmode, LSHIFTRT, val, GEN_INT (16)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)), | |||
2011 | NULL_RTX(rtx) 0, 1, OPTAB_DIRECT); | |||
2012 | tmp[3] = gen_reg_rtx (fltmode); | |||
2013 | emit_insn (cvt (tmp[3], tmp[1])); | |||
2014 | tmp[4] = gen_reg_rtx (fltmode); | |||
2015 | emit_insn (cvt (tmp[4], tmp[2])); | |||
2016 | real_ldexp (&TWO16r, &dconst1, 16); | |||
2017 | tmp[5] = const_double_from_real_value (TWO16r, SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode))); | |||
2018 | tmp[5] = force_reg (fltmode, ix86_build_const_vector (fltmode, 1, tmp[5])); | |||
2019 | if (TARGET_FMA((global_options.x_ix86_isa_flags & (1UL << 29)) != 0)) | |||
2020 | { | |||
2021 | tmp[6] = gen_rtx_FMA (fltmode, tmp[4], tmp[5], tmp[3])gen_rtx_fmt_eee_stat ((FMA), ((fltmode)), ((tmp[4])), ((tmp[5 ])), ((tmp[3])) ); | |||
2022 | emit_move_insn (target, tmp[6]); | |||
2023 | } | |||
2024 | else | |||
2025 | { | |||
2026 | tmp[6] = expand_simple_binop (fltmode, MULT, tmp[4], tmp[5], | |||
2027 | NULL_RTX(rtx) 0, 1, OPTAB_DIRECT); | |||
2028 | tmp[7] = expand_simple_binop (fltmode, PLUS, tmp[3], tmp[6], | |||
2029 | target, 1, OPTAB_DIRECT); | |||
2030 | if (tmp[7] != target) | |||
2031 | emit_move_insn (target, tmp[7]); | |||
2032 | } | |||
2033 | } | |||
2034 | ||||
2035 | /* Adjust a V*SFmode/V*DFmode value VAL so that *sfix_trunc* resp. fix_trunc* | |||
2036 | pattern can be used on it instead of *ufix_trunc* resp. fixuns_trunc*. | |||
2037 | This is done by doing just signed conversion if < 0x1p31, and otherwise by | |||
2038 | subtracting 0x1p31 first and xoring in 0x80000000 from *XORP afterwards. */ | |||
2039 | ||||
2040 | rtx | |||
2041 | ix86_expand_adjust_ufix_to_sfix_si (rtx val, rtx *xorp) | |||
2042 | { | |||
2043 | REAL_VALUE_TYPEstruct real_value TWO31r; | |||
2044 | rtx two31r, tmp[4]; | |||
2045 | machine_mode mode = GET_MODE (val)((machine_mode) (val)->mode); | |||
2046 | machine_mode scalarmode = GET_MODE_INNER (mode)(mode_to_inner (mode)); | |||
2047 | machine_mode intmode = GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) == 32 ? V8SImode((void) 0, E_V8SImode) : V4SImode((void) 0, E_V4SImode); | |||
2048 | rtx (*cmp) (rtx, rtx, rtx, rtx); | |||
2049 | int i; | |||
2050 | ||||
2051 | for (i = 0; i < 3; i++) | |||
2052 | tmp[i] = gen_reg_rtx (mode); | |||
2053 | real_ldexp (&TWO31r, &dconst1, 31); | |||
2054 | two31r = const_double_from_real_value (TWO31r, scalarmode); | |||
2055 | two31r = ix86_build_const_vector (mode, 1, two31r); | |||
2056 | two31r = force_reg (mode, two31r); | |||
2057 | switch (mode) | |||
2058 | { | |||
2059 | case E_V8SFmode: cmp = gen_avx_maskcmpv8sf3; break; | |||
2060 | case E_V4SFmode: cmp = gen_sse_maskcmpv4sf3; break; | |||
2061 | case E_V4DFmode: cmp = gen_avx_maskcmpv4df3; break; | |||
2062 | case E_V2DFmode: cmp = gen_sse2_maskcmpv2df3; break; | |||
2063 | default: gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2063, __FUNCTION__)); | |||
2064 | } | |||
2065 | tmp[3] = gen_rtx_LE (mode, two31r, val)gen_rtx_fmt_ee_stat ((LE), ((mode)), ((two31r)), ((val)) ); | |||
2066 | emit_insn (cmp (tmp[0], two31r, val, tmp[3])); | |||
2067 | tmp[1] = expand_simple_binop (mode, AND, tmp[0], two31r, tmp[1], | |||
2068 | 0, OPTAB_DIRECT); | |||
2069 | if (intmode == V4SImode((void) 0, E_V4SImode) || TARGET_AVX2((global_options.x_ix86_isa_flags & (1UL << 9)) != 0 )) | |||
2070 | *xorp = expand_simple_binop (intmode, ASHIFT, | |||
2071 | gen_lowpartrtl_hooks.gen_lowpart (intmode, tmp[0]), | |||
2072 | GEN_INT (31)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (31)), NULL_RTX(rtx) 0, 0, | |||
2073 | OPTAB_DIRECT); | |||
2074 | else | |||
2075 | { | |||
2076 | rtx two31 = gen_int_mode (HOST_WIDE_INT_1U1UL << 31, SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))); | |||
2077 | two31 = ix86_build_const_vector (intmode, 1, two31); | |||
2078 | *xorp = expand_simple_binop (intmode, AND, | |||
2079 | gen_lowpartrtl_hooks.gen_lowpart (intmode, tmp[0]), | |||
2080 | two31, NULL_RTX(rtx) 0, 0, | |||
2081 | OPTAB_DIRECT); | |||
2082 | } | |||
2083 | return expand_simple_binop (mode, MINUS, val, tmp[1], tmp[2], | |||
2084 | 0, OPTAB_DIRECT); | |||
2085 | } | |||
2086 | ||||
2087 | /* Generate code for floating point ABS or NEG. */ | |||
2088 | ||||
2089 | void | |||
2090 | ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode, | |||
2091 | rtx operands[]) | |||
2092 | { | |||
2093 | rtx set, dst, src; | |||
2094 | bool use_sse = false; | |||
2095 | bool vector_mode = VECTOR_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_VECTOR_BOOL || ( (enum mode_class) mode_class[mode]) == MODE_VECTOR_INT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_UACCUM); | |||
2096 | machine_mode vmode = mode; | |||
2097 | rtvec par; | |||
2098 | ||||
2099 | if (vector_mode || mode == TFmode(scalar_float_mode ((scalar_float_mode::from_int) E_TFmode)) || mode == HFmode(scalar_float_mode ((scalar_float_mode::from_int) E_HFmode))) | |||
2100 | { | |||
2101 | use_sse = true; | |||
2102 | if (mode == HFmode(scalar_float_mode ((scalar_float_mode::from_int) E_HFmode))) | |||
2103 | vmode = V8HFmode((void) 0, E_V8HFmode); | |||
2104 | } | |||
2105 | else if (TARGET_SSE_MATH((global_options.x_ix86_fpmath & FPMATH_SSE) != 0)) | |||
2106 | { | |||
2107 | use_sse = SSE_FLOAT_MODE_P (mode)((((global_options.x_ix86_isa_flags & (1UL << 50)) != 0) && (mode) == (scalar_float_mode ((scalar_float_mode ::from_int) E_SFmode))) || (((global_options.x_ix86_isa_flags & (1UL << 51)) != 0) && (mode) == (scalar_float_mode ((scalar_float_mode::from_int) E_DFmode)))); | |||
2108 | if (mode == SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode))) | |||
2109 | vmode = V4SFmode((void) 0, E_V4SFmode); | |||
2110 | else if (mode == DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode))) | |||
2111 | vmode = V2DFmode((void) 0, E_V2DFmode); | |||
2112 | } | |||
2113 | ||||
2114 | dst = operands[0]; | |||
2115 | src = operands[1]; | |||
2116 | ||||
2117 | set = gen_rtx_fmt_e (code, mode, src)gen_rtx_fmt_e_stat ((code), (mode), (src) ); | |||
2118 | set = gen_rtx_SET (dst, set)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dst)) , ((set)) ); | |||
2119 | ||||
2120 | if (use_sse) | |||
2121 | { | |||
2122 | rtx mask, use, clob; | |||
2123 | ||||
2124 | /* NEG and ABS performed with SSE use bitwise mask operations. | |||
2125 | Create the appropriate mask now. */ | |||
2126 | mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS); | |||
2127 | use = gen_rtx_USE (VOIDmode, mask)gen_rtx_fmt_e_stat ((USE), ((((void) 0, E_VOIDmode))), ((mask )) ); | |||
2128 | if (vector_mode || mode == TFmode(scalar_float_mode ((scalar_float_mode::from_int) E_TFmode))) | |||
2129 | par = gen_rtvec (2, set, use); | |||
2130 | else | |||
2131 | { | |||
2132 | clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG))gen_rtx_fmt_e_stat ((CLOBBER), ((((void) 0, E_VOIDmode))), (( gen_rtx_REG (((void) 0, E_CCmode), 17))) ); | |||
2133 | par = gen_rtvec (3, set, use, clob); | |||
2134 | } | |||
2135 | } | |||
2136 | else | |||
2137 | { | |||
2138 | rtx clob; | |||
2139 | ||||
2140 | /* Changing of sign for FP values is doable using integer unit too. */ | |||
2141 | clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG))gen_rtx_fmt_e_stat ((CLOBBER), ((((void) 0, E_VOIDmode))), (( gen_rtx_REG (((void) 0, E_CCmode), 17))) ); | |||
2142 | par = gen_rtvec (2, set, clob); | |||
2143 | } | |||
2144 | ||||
2145 | emit_insn (gen_rtx_PARALLEL (VOIDmode, par)gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (par)) )); | |||
2146 | } | |||
2147 | ||||
2148 | /* Deconstruct a floating point ABS or NEG operation | |||
2149 | with integer registers into integer operations. */ | |||
2150 | ||||
2151 | void | |||
2152 | ix86_split_fp_absneg_operator (enum rtx_code code, machine_mode mode, | |||
2153 | rtx operands[]) | |||
2154 | { | |||
2155 | enum rtx_code absneg_op; | |||
2156 | rtx dst, set; | |||
2157 | ||||
2158 | gcc_assert (operands_match_p (operands[0], operands[1]))((void)(!(operands_match_p (operands[0], operands[1])) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2158, __FUNCTION__), 0 : 0)); | |||
2159 | ||||
2160 | switch (mode) | |||
2161 | { | |||
2162 | case E_SFmode: | |||
2163 | dst = gen_lowpartrtl_hooks.gen_lowpart (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), operands[0]); | |||
2164 | ||||
2165 | if (code == ABS) | |||
2166 | { | |||
2167 | set = gen_int_mode (0x7fffffff, SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))); | |||
2168 | absneg_op = AND; | |||
2169 | } | |||
2170 | else | |||
2171 | { | |||
2172 | set = gen_int_mode (0x80000000, SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))); | |||
2173 | absneg_op = XOR; | |||
2174 | } | |||
2175 | set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set)gen_rtx_fmt_ee_stat ((absneg_op), ((scalar_int_mode ((scalar_int_mode ::from_int) E_SImode))), (dst), (set) ); | |||
2176 | break; | |||
2177 | ||||
2178 | case E_DFmode: | |||
2179 | if (TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 )) | |||
2180 | { | |||
2181 | dst = gen_lowpartrtl_hooks.gen_lowpart (DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)), operands[0]); | |||
2182 | dst = gen_rtx_ZERO_EXTRACT (DImode, dst, const1_rtx, GEN_INT (63))gen_rtx_fmt_eee_stat ((ZERO_EXTRACT), (((scalar_int_mode ((scalar_int_mode ::from_int) E_DImode)))), ((dst)), (((const_int_rtx[64 +1]))) , ((gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (63)))) ); | |||
2183 | ||||
2184 | if (code == ABS) | |||
2185 | set = const0_rtx(const_int_rtx[64]); | |||
2186 | else | |||
2187 | set = gen_rtx_NOT (DImode, dst)gen_rtx_fmt_e_stat ((NOT), (((scalar_int_mode ((scalar_int_mode ::from_int) E_DImode)))), ((dst)) ); | |||
2188 | } | |||
2189 | else | |||
2190 | { | |||
2191 | dst = gen_highpart (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), operands[0]); | |||
2192 | ||||
2193 | if (code == ABS) | |||
2194 | { | |||
2195 | set = gen_int_mode (0x7fffffff, SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))); | |||
2196 | absneg_op = AND; | |||
2197 | } | |||
2198 | else | |||
2199 | { | |||
2200 | set = gen_int_mode (0x80000000, SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))); | |||
2201 | absneg_op = XOR; | |||
2202 | } | |||
2203 | set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set)gen_rtx_fmt_ee_stat ((absneg_op), ((scalar_int_mode ((scalar_int_mode ::from_int) E_SImode))), (dst), (set) ); | |||
2204 | } | |||
2205 | break; | |||
2206 | ||||
2207 | case E_XFmode: | |||
2208 | dst = gen_rtx_REG (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), | |||
2209 | REGNO (operands[0])(rhs_regno(operands[0])) + (TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) ? 1 : 2)); | |||
2210 | if (code == ABS) | |||
2211 | { | |||
2212 | set = GEN_INT (0x7fff)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x7fff)); | |||
2213 | absneg_op = AND; | |||
2214 | } | |||
2215 | else | |||
2216 | { | |||
2217 | set = GEN_INT (0x8000)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x8000)); | |||
2218 | absneg_op = XOR; | |||
2219 | } | |||
2220 | set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set)gen_rtx_fmt_ee_stat ((absneg_op), ((scalar_int_mode ((scalar_int_mode ::from_int) E_SImode))), (dst), (set) ); | |||
2221 | break; | |||
2222 | ||||
2223 | default: | |||
2224 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2224, __FUNCTION__)); | |||
2225 | } | |||
2226 | ||||
2227 | set = gen_rtx_SET (dst, set)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dst)) , ((set)) ); | |||
2228 | ||||
2229 | rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG))gen_rtx_fmt_e_stat ((CLOBBER), ((((void) 0, E_VOIDmode))), (( gen_rtx_REG (((void) 0, E_CCmode), 17))) ); | |||
2230 | rtvec par = gen_rtvec (2, set, clob); | |||
2231 | ||||
2232 | emit_insn (gen_rtx_PARALLEL (VOIDmode, par)gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (par)) )); | |||
2233 | } | |||
2234 | ||||
2235 | /* Expand a copysign operation. Special case operand 0 being a constant. */ | |||
2236 | ||||
2237 | void | |||
2238 | ix86_expand_copysign (rtx operands[]) | |||
2239 | { | |||
2240 | machine_mode mode, vmode; | |||
2241 | rtx dest, vdest, op0, op1, mask, op2, op3; | |||
2242 | ||||
2243 | mode = GET_MODE (operands[0])((machine_mode) (operands[0])->mode); | |||
2244 | ||||
2245 | if (mode == HFmode(scalar_float_mode ((scalar_float_mode::from_int) E_HFmode))) | |||
2246 | vmode = V8HFmode((void) 0, E_V8HFmode); | |||
2247 | else if (mode == SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode))) | |||
2248 | vmode = V4SFmode((void) 0, E_V4SFmode); | |||
2249 | else if (mode == DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode))) | |||
2250 | vmode = V2DFmode((void) 0, E_V2DFmode); | |||
2251 | else if (mode == TFmode(scalar_float_mode ((scalar_float_mode::from_int) E_TFmode))) | |||
2252 | vmode = mode; | |||
2253 | else | |||
2254 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2254, __FUNCTION__)); | |||
2255 | ||||
2256 | if (rtx_equal_p (operands[1], operands[2])) | |||
2257 | { | |||
2258 | emit_move_insn (operands[0], operands[1]); | |||
2259 | return; | |||
2260 | } | |||
2261 | ||||
2262 | dest = operands[0]; | |||
2263 | vdest = lowpart_subreg (vmode, dest, mode); | |||
2264 | if (vdest == NULL_RTX(rtx) 0) | |||
2265 | vdest = gen_reg_rtx (vmode); | |||
2266 | else | |||
2267 | dest = NULL_RTX(rtx) 0; | |||
2268 | op1 = lowpart_subreg (vmode, force_reg (mode, operands[2]), mode); | |||
2269 | mask = ix86_build_signbit_mask (vmode, 0, 0); | |||
2270 | ||||
2271 | if (CONST_DOUBLE_P (operands[1])(((enum rtx_code) (operands[1])->code) == CONST_DOUBLE)) | |||
2272 | { | |||
2273 | op0 = simplify_unary_operation (ABS, mode, operands[1], mode); | |||
2274 | /* Optimize for 0, simplify b = copy_signf (0.0f, a) to b = mask & a. */ | |||
2275 | if (op0 == CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)])) | |||
2276 | { | |||
2277 | emit_move_insn (vdest, gen_rtx_AND (vmode, mask, op1)gen_rtx_fmt_ee_stat ((AND), ((vmode)), ((mask)), ((op1)) )); | |||
2278 | if (dest) | |||
2279 | emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode)); | |||
2280 | return; | |||
2281 | } | |||
2282 | ||||
2283 | if (GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) < 16) | |||
2284 | op0 = ix86_build_const_vector (vmode, false, op0); | |||
2285 | op0 = force_reg (vmode, op0); | |||
2286 | } | |||
2287 | else | |||
2288 | op0 = lowpart_subreg (vmode, force_reg (mode, operands[1]), mode); | |||
2289 | ||||
2290 | op2 = gen_reg_rtx (vmode); | |||
2291 | op3 = gen_reg_rtx (vmode); | |||
2292 | emit_move_insn (op2, gen_rtx_AND (vmode,gen_rtx_fmt_ee_stat ((AND), ((vmode)), ((gen_rtx_fmt_e_stat ( (NOT), ((vmode)), ((mask)) ))), ((op0)) ) | |||
2293 | gen_rtx_NOT (vmode, mask),gen_rtx_fmt_ee_stat ((AND), ((vmode)), ((gen_rtx_fmt_e_stat ( (NOT), ((vmode)), ((mask)) ))), ((op0)) ) | |||
2294 | op0)gen_rtx_fmt_ee_stat ((AND), ((vmode)), ((gen_rtx_fmt_e_stat ( (NOT), ((vmode)), ((mask)) ))), ((op0)) )); | |||
2295 | emit_move_insn (op3, gen_rtx_AND (vmode, mask, op1)gen_rtx_fmt_ee_stat ((AND), ((vmode)), ((mask)), ((op1)) )); | |||
2296 | emit_move_insn (vdest, gen_rtx_IOR (vmode, op2, op3)gen_rtx_fmt_ee_stat ((IOR), ((vmode)), ((op2)), ((op3)) )); | |||
2297 | if (dest) | |||
2298 | emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode)); | |||
2299 | } | |||
2300 | ||||
2301 | /* Expand an xorsign operation. */ | |||
2302 | ||||
2303 | void | |||
2304 | ix86_expand_xorsign (rtx operands[]) | |||
2305 | { | |||
2306 | machine_mode mode, vmode; | |||
2307 | rtx dest, vdest, op0, op1, mask, x, temp; | |||
2308 | ||||
2309 | dest = operands[0]; | |||
2310 | op0 = operands[1]; | |||
2311 | op1 = operands[2]; | |||
2312 | ||||
2313 | mode = GET_MODE (dest)((machine_mode) (dest)->mode); | |||
2314 | ||||
2315 | if (mode == HFmode(scalar_float_mode ((scalar_float_mode::from_int) E_HFmode))) | |||
2316 | vmode = V8HFmode((void) 0, E_V8HFmode); | |||
2317 | else if (mode == SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode))) | |||
2318 | vmode = V4SFmode((void) 0, E_V4SFmode); | |||
2319 | else if (mode == DFmode(scalar_float_mode ((scalar_float_mode::from_int) E_DFmode))) | |||
2320 | vmode = V2DFmode((void) 0, E_V2DFmode); | |||
2321 | else | |||
2322 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2322, __FUNCTION__)); | |||
2323 | ||||
2324 | temp = gen_reg_rtx (vmode); | |||
2325 | mask = ix86_build_signbit_mask (vmode, 0, 0); | |||
2326 | ||||
2327 | op1 = lowpart_subreg (vmode, force_reg (mode, op1), mode); | |||
2328 | x = gen_rtx_AND (vmode, op1, mask)gen_rtx_fmt_ee_stat ((AND), ((vmode)), ((op1)), ((mask)) ); | |||
2329 | emit_insn (gen_rtx_SET (temp, x)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((temp) ), ((x)) )); | |||
2330 | ||||
2331 | op0 = lowpart_subreg (vmode, force_reg (mode, op0), mode); | |||
2332 | x = gen_rtx_XOR (vmode, temp, op0)gen_rtx_fmt_ee_stat ((XOR), ((vmode)), ((temp)), ((op0)) ); | |||
2333 | ||||
2334 | vdest = lowpart_subreg (vmode, dest, mode); | |||
2335 | if (vdest == NULL_RTX(rtx) 0) | |||
2336 | vdest = gen_reg_rtx (vmode); | |||
2337 | else | |||
2338 | dest = NULL_RTX(rtx) 0; | |||
2339 | emit_insn (gen_rtx_SET (vdest, x)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((vdest )), ((x)) )); | |||
2340 | ||||
2341 | if (dest) | |||
2342 | emit_move_insn (dest, lowpart_subreg (mode, vdest, vmode)); | |||
2343 | } | |||
2344 | ||||
2345 | static rtx ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1); | |||
2346 | ||||
2347 | void | |||
2348 | ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label) | |||
2349 | { | |||
2350 | machine_mode mode = GET_MODE (op0)((machine_mode) (op0)->mode); | |||
2351 | rtx tmp; | |||
2352 | ||||
2353 | /* Handle special case - vector comparsion with boolean result, transform | |||
2354 | it using ptest instruction. */ | |||
2355 | if (GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_VECTOR_INT | |||
2356 | || mode == OImode(scalar_int_mode ((scalar_int_mode::from_int) E_OImode))) | |||
2357 | { | |||
2358 | rtx flag = gen_rtx_REG (CCZmode((void) 0, E_CCZmode), FLAGS_REG17); | |||
2359 | machine_mode p_mode = GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) == 32 ? V4DImode((void) 0, E_V4DImode) : V2DImode((void) 0, E_V2DImode); | |||
2360 | ||||
2361 | gcc_assert (code == EQ || code == NE)((void)(!(code == EQ || code == NE) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2361, __FUNCTION__), 0 : 0)); | |||
2362 | ||||
2363 | if (mode == OImode(scalar_int_mode ((scalar_int_mode::from_int) E_OImode))) | |||
2364 | { | |||
2365 | op0 = lowpart_subreg (p_mode, force_reg (mode, op0), mode); | |||
2366 | op1 = lowpart_subreg (p_mode, force_reg (mode, op1), mode); | |||
2367 | mode = p_mode; | |||
2368 | } | |||
2369 | /* Generate XOR since we can't check that one operand is zero vector. */ | |||
2370 | tmp = gen_reg_rtx (mode); | |||
2371 | emit_insn (gen_rtx_SET (tmp, gen_rtx_XOR (mode, op0, op1))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((tmp)) , ((gen_rtx_fmt_ee_stat ((XOR), ((mode)), ((op0)), ((op1)) )) ) )); | |||
2372 | tmp = gen_lowpartrtl_hooks.gen_lowpart (p_mode, tmp); | |||
2373 | emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, FLAGS_REG),gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((gen_rtx_REG (((void) 0, E_CCmode), 17))), ((gen_rtx_fmt_Ei_stat ((UNSPEC ), ((((void) 0, E_CCmode))), ((gen_rtvec (2, tmp, tmp))), ((UNSPEC_PTEST )) ))) ) | |||
2374 | gen_rtx_UNSPEC (CCmode,gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((gen_rtx_REG (((void) 0, E_CCmode), 17))), ((gen_rtx_fmt_Ei_stat ((UNSPEC ), ((((void) 0, E_CCmode))), ((gen_rtvec (2, tmp, tmp))), ((UNSPEC_PTEST )) ))) ) | |||
2375 | gen_rtvec (2, tmp, tmp),gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((gen_rtx_REG (((void) 0, E_CCmode), 17))), ((gen_rtx_fmt_Ei_stat ((UNSPEC ), ((((void) 0, E_CCmode))), ((gen_rtvec (2, tmp, tmp))), ((UNSPEC_PTEST )) ))) ) | |||
2376 | UNSPEC_PTEST))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((gen_rtx_REG (((void) 0, E_CCmode), 17))), ((gen_rtx_fmt_Ei_stat ((UNSPEC ), ((((void) 0, E_CCmode))), ((gen_rtvec (2, tmp, tmp))), ((UNSPEC_PTEST )) ))) )); | |||
2377 | tmp = gen_rtx_fmt_ee (code, VOIDmode, flag, const0_rtx)gen_rtx_fmt_ee_stat ((code), (((void) 0, E_VOIDmode)), (flag) , ((const_int_rtx[64])) ); | |||
2378 | tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((tmp)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode))), ((label)) ))), ((pc_rtx)) ) | |||
2379 | gen_rtx_LABEL_REF (VOIDmode, label),gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((tmp)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode))), ((label)) ))), ((pc_rtx)) ) | |||
2380 | pc_rtx)gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((tmp)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode))), ((label)) ))), ((pc_rtx)) ); | |||
2381 | emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((pc_rtx )), ((tmp)) )); | |||
2382 | return; | |||
2383 | } | |||
2384 | ||||
2385 | switch (mode) | |||
2386 | { | |||
2387 | case E_HFmode: | |||
2388 | case E_SFmode: | |||
2389 | case E_DFmode: | |||
2390 | case E_XFmode: | |||
2391 | case E_QImode: | |||
2392 | case E_HImode: | |||
2393 | case E_SImode: | |||
2394 | simple: | |||
2395 | tmp = ix86_expand_compare (code, op0, op1); | |||
2396 | tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((tmp)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode))), ((label)) ))), ((pc_rtx)) ) | |||
2397 | gen_rtx_LABEL_REF (VOIDmode, label),gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((tmp)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode))), ((label)) ))), ((pc_rtx)) ) | |||
2398 | pc_rtx)gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((tmp)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode))), ((label)) ))), ((pc_rtx)) ); | |||
2399 | emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((pc_rtx )), ((tmp)) )); | |||
2400 | return; | |||
2401 | ||||
2402 | case E_DImode: | |||
2403 | if (TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 )) | |||
2404 | goto simple; | |||
2405 | /* FALLTHRU */ | |||
2406 | case E_TImode: | |||
2407 | /* DI and TI mode equality/inequality comparisons may be performed | |||
2408 | on SSE registers. Avoid splitting them, except when optimizing | |||
2409 | for size. */ | |||
2410 | if ((code == EQ || code == NE) | |||
2411 | && !optimize_insn_for_size_p ()) | |||
2412 | goto simple; | |||
2413 | ||||
2414 | /* Expand DImode branch into multiple compare+branch. */ | |||
2415 | { | |||
2416 | rtx lo[2], hi[2]; | |||
2417 | rtx_code_label *label2; | |||
2418 | enum rtx_code code1, code2, code3; | |||
2419 | machine_mode submode; | |||
2420 | ||||
2421 | if (CONSTANT_P (op0)((rtx_class[(int) (((enum rtx_code) (op0)->code))]) == RTX_CONST_OBJ ) && !CONSTANT_P (op1)((rtx_class[(int) (((enum rtx_code) (op1)->code))]) == RTX_CONST_OBJ )) | |||
2422 | { | |||
2423 | std::swap (op0, op1); | |||
2424 | code = swap_condition (code); | |||
2425 | } | |||
2426 | ||||
2427 | split_double_mode (mode, &op0, 1, lo+0, hi+0); | |||
2428 | split_double_mode (mode, &op1, 1, lo+1, hi+1); | |||
2429 | ||||
2430 | submode = mode == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)) ? SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)) : DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)); | |||
2431 | ||||
2432 | /* If we are doing less-than or greater-or-equal-than, | |||
2433 | op1 is a constant and the low word is zero, then we can just | |||
2434 | examine the high word. Similarly for low word -1 and | |||
2435 | less-or-equal-than or greater-than. */ | |||
2436 | ||||
2437 | if (CONST_INT_P (hi[1])(((enum rtx_code) (hi[1])->code) == CONST_INT)) | |||
2438 | switch (code) | |||
2439 | { | |||
2440 | case LT: case LTU: case GE: case GEU: | |||
2441 | if (lo[1] == const0_rtx(const_int_rtx[64])) | |||
2442 | { | |||
2443 | ix86_expand_branch (code, hi[0], hi[1], label); | |||
2444 | return; | |||
2445 | } | |||
2446 | break; | |||
2447 | case LE: case LEU: case GT: case GTU: | |||
2448 | if (lo[1] == constm1_rtx(const_int_rtx[64 -1])) | |||
2449 | { | |||
2450 | ix86_expand_branch (code, hi[0], hi[1], label); | |||
2451 | return; | |||
2452 | } | |||
2453 | break; | |||
2454 | default: | |||
2455 | break; | |||
2456 | } | |||
2457 | ||||
2458 | /* Emulate comparisons that do not depend on Zero flag with | |||
2459 | double-word subtraction. Note that only Overflow, Sign | |||
2460 | and Carry flags are valid, so swap arguments and condition | |||
2461 | of comparisons that would otherwise test Zero flag. */ | |||
2462 | ||||
2463 | switch (code) | |||
2464 | { | |||
2465 | case LE: case LEU: case GT: case GTU: | |||
2466 | std::swap (lo[0], lo[1]); | |||
2467 | std::swap (hi[0], hi[1]); | |||
2468 | code = swap_condition (code); | |||
2469 | /* FALLTHRU */ | |||
2470 | ||||
2471 | case LT: case LTU: case GE: case GEU: | |||
2472 | { | |||
2473 | bool uns = (code == LTU || code == GEU); | |||
2474 | rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx) | |||
2475 | = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz; | |||
2476 | ||||
2477 | if (!nonimmediate_operand (lo[0], submode)) | |||
2478 | lo[0] = force_reg (submode, lo[0]); | |||
2479 | if (!x86_64_general_operand (lo[1], submode)) | |||
2480 | lo[1] = force_reg (submode, lo[1]); | |||
2481 | ||||
2482 | if (!register_operand (hi[0], submode)) | |||
2483 | hi[0] = force_reg (submode, hi[0]); | |||
2484 | if ((uns && !nonimmediate_operand (hi[1], submode)) | |||
2485 | || (!uns && !x86_64_general_operand (hi[1], submode))) | |||
2486 | hi[1] = force_reg (submode, hi[1]); | |||
2487 | ||||
2488 | emit_insn (gen_cmp_1 (submode, lo[0], lo[1])); | |||
2489 | ||||
2490 | tmp = gen_rtx_SCRATCH (submode)gen_rtx_fmt__stat ((SCRATCH), ((submode)) ); | |||
2491 | emit_insn (sbb_insn (submode, tmp, hi[0], hi[1])); | |||
2492 | ||||
2493 | tmp = gen_rtx_REG (uns ? CCCmode((void) 0, E_CCCmode) : CCGZmode((void) 0, E_CCGZmode), FLAGS_REG17); | |||
2494 | ix86_expand_branch (code, tmp, const0_rtx(const_int_rtx[64]), label); | |||
2495 | return; | |||
2496 | } | |||
2497 | ||||
2498 | default: | |||
2499 | break; | |||
2500 | } | |||
2501 | ||||
2502 | /* Otherwise, we need two or three jumps. */ | |||
2503 | ||||
2504 | label2 = gen_label_rtx (); | |||
2505 | ||||
2506 | code1 = code; | |||
2507 | code2 = swap_condition (code); | |||
2508 | code3 = unsigned_condition (code); | |||
2509 | ||||
2510 | switch (code) | |||
2511 | { | |||
2512 | case LT: case GT: case LTU: case GTU: | |||
2513 | break; | |||
2514 | ||||
2515 | case LE: code1 = LT; code2 = GT; break; | |||
2516 | case GE: code1 = GT; code2 = LT; break; | |||
2517 | case LEU: code1 = LTU; code2 = GTU; break; | |||
2518 | case GEU: code1 = GTU; code2 = LTU; break; | |||
2519 | ||||
2520 | case EQ: code1 = UNKNOWN; code2 = NE; break; | |||
2521 | case NE: code2 = UNKNOWN; break; | |||
2522 | ||||
2523 | default: | |||
2524 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2524, __FUNCTION__)); | |||
2525 | } | |||
2526 | ||||
2527 | /* | |||
2528 | * a < b => | |||
2529 | * if (hi(a) < hi(b)) goto true; | |||
2530 | * if (hi(a) > hi(b)) goto false; | |||
2531 | * if (lo(a) < lo(b)) goto true; | |||
2532 | * false: | |||
2533 | */ | |||
2534 | ||||
2535 | if (code1 != UNKNOWN) | |||
2536 | ix86_expand_branch (code1, hi[0], hi[1], label); | |||
2537 | if (code2 != UNKNOWN) | |||
2538 | ix86_expand_branch (code2, hi[0], hi[1], label2); | |||
2539 | ||||
2540 | ix86_expand_branch (code3, lo[0], lo[1], label); | |||
2541 | ||||
2542 | if (code2 != UNKNOWN) | |||
2543 | emit_label (label2); | |||
2544 | return; | |||
2545 | } | |||
2546 | ||||
2547 | default: | |||
2548 | gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)((void)(!(((enum mode_class) mode_class[((machine_mode) (op0) ->mode)]) == MODE_CC) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2548, __FUNCTION__), 0 : 0)); | |||
2549 | goto simple; | |||
2550 | } | |||
2551 | } | |||
2552 | ||||
2553 | /* Figure out whether to use unordered fp comparisons. */ | |||
2554 | ||||
2555 | static bool | |||
2556 | ix86_unordered_fp_compare (enum rtx_code code) | |||
2557 | { | |||
2558 | if (!TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0)) | |||
2559 | return false; | |||
2560 | ||||
2561 | switch (code) | |||
2562 | { | |||
2563 | case LT: | |||
2564 | case LE: | |||
2565 | case GT: | |||
2566 | case GE: | |||
2567 | case LTGT: | |||
2568 | return false; | |||
2569 | ||||
2570 | case EQ: | |||
2571 | case NE: | |||
2572 | ||||
2573 | case UNORDERED: | |||
2574 | case ORDERED: | |||
2575 | case UNLT: | |||
2576 | case UNLE: | |||
2577 | case UNGT: | |||
2578 | case UNGE: | |||
2579 | case UNEQ: | |||
2580 | return true; | |||
2581 | ||||
2582 | default: | |||
2583 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2583, __FUNCTION__)); | |||
2584 | } | |||
2585 | } | |||
2586 | ||||
2587 | /* Return a comparison we can do and that it is equivalent to | |||
2588 | swap_condition (code) apart possibly from orderedness. | |||
2589 | But, never change orderedness if TARGET_IEEE_FP, returning | |||
2590 | UNKNOWN in that case if necessary. */ | |||
2591 | ||||
2592 | static enum rtx_code | |||
2593 | ix86_fp_swap_condition (enum rtx_code code) | |||
2594 | { | |||
2595 | switch (code) | |||
2596 | { | |||
2597 | case GT: /* GTU - CF=0 & ZF=0 */ | |||
2598 | return TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0) ? UNKNOWN : UNLT; | |||
2599 | case GE: /* GEU - CF=0 */ | |||
2600 | return TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0) ? UNKNOWN : UNLE; | |||
2601 | case UNLT: /* LTU - CF=1 */ | |||
2602 | return TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0) ? UNKNOWN : GT; | |||
2603 | case UNLE: /* LEU - CF=1 | ZF=1 */ | |||
2604 | return TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0) ? UNKNOWN : GE; | |||
2605 | default: | |||
2606 | return swap_condition (code); | |||
2607 | } | |||
2608 | } | |||
2609 | ||||
2610 | /* Return cost of comparison CODE using the best strategy for performance. | |||
2611 | All following functions do use number of instructions as a cost metrics. | |||
2612 | In future this should be tweaked to compute bytes for optimize_size and | |||
2613 | take into account performance of various instructions on various CPUs. */ | |||
2614 | ||||
2615 | static int | |||
2616 | ix86_fp_comparison_cost (enum rtx_code code) | |||
2617 | { | |||
2618 | int arith_cost; | |||
2619 | ||||
2620 | /* The cost of code using bit-twiddling on %ah. */ | |||
2621 | switch (code) | |||
2622 | { | |||
2623 | case UNLE: | |||
2624 | case UNLT: | |||
2625 | case LTGT: | |||
2626 | case GT: | |||
2627 | case GE: | |||
2628 | case UNORDERED: | |||
2629 | case ORDERED: | |||
2630 | case UNEQ: | |||
2631 | arith_cost = 4; | |||
2632 | break; | |||
2633 | case LT: | |||
2634 | case NE: | |||
2635 | case EQ: | |||
2636 | case UNGE: | |||
2637 | arith_cost = TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0) ? 5 : 4; | |||
2638 | break; | |||
2639 | case LE: | |||
2640 | case UNGT: | |||
2641 | arith_cost = TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0) ? 6 : 4; | |||
2642 | break; | |||
2643 | default: | |||
2644 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2644, __FUNCTION__)); | |||
2645 | } | |||
2646 | ||||
2647 | switch (ix86_fp_comparison_strategy (code)) | |||
2648 | { | |||
2649 | case IX86_FPCMP_COMI: | |||
2650 | return arith_cost > 4 ? 3 : 2; | |||
2651 | case IX86_FPCMP_SAHF: | |||
2652 | return arith_cost > 4 ? 4 : 3; | |||
2653 | default: | |||
2654 | return arith_cost; | |||
2655 | } | |||
2656 | } | |||
2657 | ||||
2658 | /* Swap, force into registers, or otherwise massage the two operands | |||
2659 | to a fp comparison. The operands are updated in place; the new | |||
2660 | comparison code is returned. */ | |||
2661 | ||||
2662 | static enum rtx_code | |||
2663 | ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1) | |||
2664 | { | |||
2665 | bool unordered_compare = ix86_unordered_fp_compare (code); | |||
2666 | rtx op0 = *pop0, op1 = *pop1; | |||
2667 | machine_mode op_mode = GET_MODE (op0)((machine_mode) (op0)->mode); | |||
2668 | bool is_sse = SSE_FLOAT_MODE_SSEMATH_OR_HF_P (op_mode)((((((global_options.x_ix86_isa_flags & (1UL << 50) ) != 0) && (op_mode) == (scalar_float_mode ((scalar_float_mode ::from_int) E_SFmode))) || (((global_options.x_ix86_isa_flags & (1UL << 51)) != 0) && (op_mode) == (scalar_float_mode ((scalar_float_mode::from_int) E_DFmode)))) && ((global_options .x_ix86_fpmath & FPMATH_SSE) != 0)) || (((global_options. x_ix86_isa_flags2 & (1UL << 7)) != 0) && (op_mode ) == (scalar_float_mode ((scalar_float_mode::from_int) E_HFmode )))); | |||
2669 | ||||
2670 | if (op_mode == BFmode(scalar_float_mode ((scalar_float_mode::from_int) E_BFmode))) | |||
2671 | { | |||
2672 | rtx op = gen_lowpartrtl_hooks.gen_lowpart (HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode)), op0); | |||
2673 | if (CONST_INT_P (op)(((enum rtx_code) (op)->code) == CONST_INT)) | |||
2674 | op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode)), | |||
2675 | op0, BFmode(scalar_float_mode ((scalar_float_mode::from_int) E_BFmode))); | |||
2676 | else | |||
2677 | { | |||
2678 | rtx t1 = gen_reg_rtx (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))); | |||
2679 | emit_insn (gen_zero_extendhisi2 (t1, op)); | |||
2680 | emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)))); | |||
2681 | op = gen_lowpartrtl_hooks.gen_lowpart (SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode)), t1); | |||
2682 | } | |||
2683 | *pop0 = op; | |||
2684 | op = gen_lowpartrtl_hooks.gen_lowpart (HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode)), op1); | |||
2685 | if (CONST_INT_P (op)(((enum rtx_code) (op)->code) == CONST_INT)) | |||
2686 | op = simplify_const_unary_operation (FLOAT_EXTEND, SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode)), | |||
2687 | op1, BFmode(scalar_float_mode ((scalar_float_mode::from_int) E_BFmode))); | |||
2688 | else | |||
2689 | { | |||
2690 | rtx t1 = gen_reg_rtx (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))); | |||
2691 | emit_insn (gen_zero_extendhisi2 (t1, op)); | |||
2692 | emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (16)))); | |||
2693 | op = gen_lowpartrtl_hooks.gen_lowpart (SFmode(scalar_float_mode ((scalar_float_mode::from_int) E_SFmode)), t1); | |||
2694 | } | |||
2695 | *pop1 = op; | |||
2696 | return ix86_prepare_fp_compare_args (code, pop0, pop1); | |||
2697 | } | |||
2698 | ||||
2699 | /* All of the unordered compare instructions only work on registers. | |||
2700 | The same is true of the fcomi compare instructions. The XFmode | |||
2701 | compare instructions require registers except when comparing | |||
2702 | against zero or when converting operand 1 from fixed point to | |||
2703 | floating point. */ | |||
2704 | ||||
2705 | if (!is_sse | |||
2706 | && (unordered_compare | |||
2707 | || (op_mode == XFmode(scalar_float_mode ((scalar_float_mode::from_int) E_XFmode)) | |||
2708 | && ! (standard_80387_constant_p (op0) == 1 | |||
2709 | || standard_80387_constant_p (op1) == 1) | |||
2710 | && GET_CODE (op1)((enum rtx_code) (op1)->code) != FLOAT) | |||
2711 | || ix86_fp_comparison_strategy (code) == IX86_FPCMP_COMI)) | |||
2712 | { | |||
2713 | op0 = force_reg (op_mode, op0); | |||
2714 | op1 = force_reg (op_mode, op1); | |||
2715 | } | |||
2716 | else | |||
2717 | { | |||
2718 | /* %%% We only allow op1 in memory; op0 must be st(0). So swap | |||
2719 | things around if they appear profitable, otherwise force op0 | |||
2720 | into a register. */ | |||
2721 | ||||
2722 | if (standard_80387_constant_p (op0) == 0 | |||
2723 | || (MEM_P (op0)(((enum rtx_code) (op0)->code) == MEM) | |||
2724 | && ! (standard_80387_constant_p (op1) == 0 | |||
2725 | || MEM_P (op1)(((enum rtx_code) (op1)->code) == MEM)))) | |||
2726 | { | |||
2727 | enum rtx_code new_code = ix86_fp_swap_condition (code); | |||
2728 | if (new_code != UNKNOWN) | |||
2729 | { | |||
2730 | std::swap (op0, op1); | |||
2731 | code = new_code; | |||
2732 | } | |||
2733 | } | |||
2734 | ||||
2735 | if (!REG_P (op0)(((enum rtx_code) (op0)->code) == REG)) | |||
2736 | op0 = force_reg (op_mode, op0); | |||
2737 | ||||
2738 | if (CONSTANT_P (op1)((rtx_class[(int) (((enum rtx_code) (op1)->code))]) == RTX_CONST_OBJ )) | |||
2739 | { | |||
2740 | int tmp = standard_80387_constant_p (op1); | |||
2741 | if (tmp == 0) | |||
2742 | op1 = validize_mem (force_const_mem (op_mode, op1)); | |||
2743 | else if (tmp == 1) | |||
2744 | { | |||
2745 | if (TARGET_CMOVE(ix86_arch_features[X86_ARCH_CMOV] || ((global_options.x_ix86_isa_flags & (1UL << 50)) != 0) || ((global_options.x_ix86_isa_flags & (1UL << 44)) != 0))) | |||
2746 | op1 = force_reg (op_mode, op1); | |||
2747 | } | |||
2748 | else | |||
2749 | op1 = force_reg (op_mode, op1); | |||
2750 | } | |||
2751 | } | |||
2752 | ||||
2753 | /* Try to rearrange the comparison to make it cheaper. */ | |||
2754 | if (ix86_fp_comparison_cost (code) | |||
2755 | > ix86_fp_comparison_cost (swap_condition (code)) | |||
2756 | && (REG_P (op1)(((enum rtx_code) (op1)->code) == REG) || can_create_pseudo_p ()(!reload_in_progress && !reload_completed))) | |||
2757 | { | |||
2758 | std::swap (op0, op1); | |||
2759 | code = swap_condition (code); | |||
2760 | if (!REG_P (op0)(((enum rtx_code) (op0)->code) == REG)) | |||
2761 | op0 = force_reg (op_mode, op0); | |||
2762 | } | |||
2763 | ||||
2764 | *pop0 = op0; | |||
2765 | *pop1 = op1; | |||
2766 | return code; | |||
2767 | } | |||
2768 | ||||
2769 | /* Generate insn patterns to do a floating point compare of OPERANDS. */ | |||
2770 | ||||
2771 | static rtx | |||
2772 | ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1) | |||
2773 | { | |||
2774 | bool unordered_compare = ix86_unordered_fp_compare (code); | |||
2775 | machine_mode cmp_mode; | |||
2776 | rtx tmp, scratch; | |||
2777 | ||||
2778 | code = ix86_prepare_fp_compare_args (code, &op0, &op1); | |||
2779 | ||||
2780 | tmp = gen_rtx_COMPARE (CCFPmode, op0, op1)gen_rtx_fmt_ee_stat ((COMPARE), ((((void) 0, E_CCFPmode))), ( (op0)), ((op1)) ); | |||
2781 | if (unordered_compare) | |||
2782 | tmp = gen_rtx_UNSPEC (CCFPmode, gen_rtvec (1, tmp), UNSPEC_NOTRAP)gen_rtx_fmt_Ei_stat ((UNSPEC), ((((void) 0, E_CCFPmode))), (( gen_rtvec (1, tmp))), ((UNSPEC_NOTRAP)) ); | |||
2783 | ||||
2784 | /* Do fcomi/sahf based test when profitable. */ | |||
2785 | switch (ix86_fp_comparison_strategy (code)) | |||
2786 | { | |||
2787 | case IX86_FPCMP_COMI: | |||
2788 | cmp_mode = CCFPmode((void) 0, E_CCFPmode); | |||
2789 | emit_insn (gen_rtx_SET (gen_rtx_REG (CCFPmode, FLAGS_REG), tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((gen_rtx_REG (((void) 0, E_CCFPmode), 17))), ((tmp)) )); | |||
2790 | break; | |||
2791 | ||||
2792 | case IX86_FPCMP_SAHF: | |||
2793 | cmp_mode = CCFPmode((void) 0, E_CCFPmode); | |||
2794 | tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW)gen_rtx_fmt_Ei_stat ((UNSPEC), (((scalar_int_mode ((scalar_int_mode ::from_int) E_HImode)))), ((gen_rtvec (1, tmp))), ((UNSPEC_FNSTSW )) ); | |||
2795 | scratch = gen_reg_rtx (HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode))); | |||
2796 | emit_insn (gen_rtx_SET (scratch, tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((scratch )), ((tmp)) )); | |||
2797 | emit_insn (gen_x86_sahf_1 (scratch)); | |||
2798 | break; | |||
2799 | ||||
2800 | case IX86_FPCMP_ARITH: | |||
2801 | cmp_mode = CCNOmode((void) 0, E_CCNOmode); | |||
2802 | tmp = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW)gen_rtx_fmt_Ei_stat ((UNSPEC), (((scalar_int_mode ((scalar_int_mode ::from_int) E_HImode)))), ((gen_rtvec (1, tmp))), ((UNSPEC_FNSTSW )) ); | |||
2803 | scratch = gen_reg_rtx (HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode))); | |||
2804 | emit_insn (gen_rtx_SET (scratch, tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((scratch )), ((tmp)) )); | |||
2805 | ||||
2806 | /* In the unordered case, we have to check C2 for NaN's, which | |||
2807 | doesn't happen to work out to anything nice combination-wise. | |||
2808 | So do some bit twiddling on the value we've got in AH to come | |||
2809 | up with an appropriate set of condition codes. */ | |||
2810 | ||||
2811 | switch (code) | |||
2812 | { | |||
2813 | case GT: | |||
2814 | case UNGT: | |||
2815 | if (code == GT || !TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0)) | |||
2816 | { | |||
2817 | emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x45)))); | |||
2818 | code = EQ; | |||
2819 | } | |||
2820 | else | |||
2821 | { | |||
2822 | emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x45)))); | |||
2823 | emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx(const_int_rtx[64 -1]))); | |||
2824 | emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x44)))); | |||
2825 | cmp_mode = CCmode((void) 0, E_CCmode); | |||
2826 | code = GEU; | |||
2827 | } | |||
2828 | break; | |||
2829 | case LT: | |||
2830 | case UNLT: | |||
2831 | if (code == LT && TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0)) | |||
2832 | { | |||
2833 | emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x45)))); | |||
2834 | emit_insn (gen_cmpqi_ext_3 (scratch, const1_rtx(const_int_rtx[64 +1]))); | |||
2835 | cmp_mode = CCmode((void) 0, E_CCmode); | |||
2836 | code = EQ; | |||
2837 | } | |||
2838 | else | |||
2839 | { | |||
2840 | emit_insn (gen_testqi_ext_1_ccno (scratch, const1_rtx(const_int_rtx[64 +1]))); | |||
2841 | code = NE; | |||
2842 | } | |||
2843 | break; | |||
2844 | case GE: | |||
2845 | case UNGE: | |||
2846 | if (code == GE || !TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0)) | |||
2847 | { | |||
2848 | emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x05)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x05)))); | |||
2849 | code = EQ; | |||
2850 | } | |||
2851 | else | |||
2852 | { | |||
2853 | emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x45)))); | |||
2854 | emit_insn (gen_xorqi_ext_1_cc (scratch, scratch, const1_rtx(const_int_rtx[64 +1]))); | |||
2855 | code = NE; | |||
2856 | } | |||
2857 | break; | |||
2858 | case LE: | |||
2859 | case UNLE: | |||
2860 | if (code == LE && TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0)) | |||
2861 | { | |||
2862 | emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x45)))); | |||
2863 | emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx(const_int_rtx[64 -1]))); | |||
2864 | emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x40)))); | |||
2865 | cmp_mode = CCmode((void) 0, E_CCmode); | |||
2866 | code = LTU; | |||
2867 | } | |||
2868 | else | |||
2869 | { | |||
2870 | emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x45)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x45)))); | |||
2871 | code = NE; | |||
2872 | } | |||
2873 | break; | |||
2874 | case EQ: | |||
2875 | case UNEQ: | |||
2876 | if (code == EQ && TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0)) | |||
2877 | { | |||
2878 | emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x45)))); | |||
2879 | emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x40)))); | |||
2880 | cmp_mode = CCmode((void) 0, E_CCmode); | |||
2881 | code = EQ; | |||
2882 | } | |||
2883 | else | |||
2884 | { | |||
2885 | emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x40)))); | |||
2886 | code = NE; | |||
2887 | } | |||
2888 | break; | |||
2889 | case NE: | |||
2890 | case LTGT: | |||
2891 | if (code == NE && TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0)) | |||
2892 | { | |||
2893 | emit_insn (gen_andqi_ext_1 (scratch, scratch, GEN_INT (0x45)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x45)))); | |||
2894 | emit_insn (gen_xorqi_ext_1_cc (scratch, scratch, | |||
2895 | GEN_INT (0x40)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x40)))); | |||
2896 | code = NE; | |||
2897 | } | |||
2898 | else | |||
2899 | { | |||
2900 | emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x40)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x40)))); | |||
2901 | code = EQ; | |||
2902 | } | |||
2903 | break; | |||
2904 | ||||
2905 | case UNORDERED: | |||
2906 | emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x04)))); | |||
2907 | code = NE; | |||
2908 | break; | |||
2909 | case ORDERED: | |||
2910 | emit_insn (gen_testqi_ext_1_ccno (scratch, GEN_INT (0x04)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (0x04)))); | |||
2911 | code = EQ; | |||
2912 | break; | |||
2913 | ||||
2914 | default: | |||
2915 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2915, __FUNCTION__)); | |||
2916 | } | |||
2917 | break; | |||
2918 | ||||
2919 | default: | |||
2920 | gcc_unreachable()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2920, __FUNCTION__)); | |||
2921 | } | |||
2922 | ||||
2923 | /* Return the test that should be put into the flags user, i.e. | |||
2924 | the bcc, scc, or cmov instruction. */ | |||
2925 | return gen_rtx_fmt_ee (code, VOIDmode,gen_rtx_fmt_ee_stat ((code), (((void) 0, E_VOIDmode)), (gen_rtx_REG (cmp_mode, 17)), ((const_int_rtx[64])) ) | |||
2926 | gen_rtx_REG (cmp_mode, FLAGS_REG),gen_rtx_fmt_ee_stat ((code), (((void) 0, E_VOIDmode)), (gen_rtx_REG (cmp_mode, 17)), ((const_int_rtx[64])) ) | |||
2927 | const0_rtx)gen_rtx_fmt_ee_stat ((code), (((void) 0, E_VOIDmode)), (gen_rtx_REG (cmp_mode, 17)), ((const_int_rtx[64])) ); | |||
2928 | } | |||
2929 | ||||
2930 | /* Generate insn patterns to do an integer compare of OPERANDS. */ | |||
2931 | ||||
2932 | static rtx | |||
2933 | ix86_expand_int_compare (enum rtx_code code, rtx op0, rtx op1) | |||
2934 | { | |||
2935 | machine_mode cmpmode; | |||
2936 | rtx tmp, flags; | |||
2937 | ||||
2938 | /* Swap operands to emit carry flag comparison. */ | |||
2939 | if ((code == GTU || code == LEU) | |||
2940 | && nonimmediate_operand (op1, VOIDmode((void) 0, E_VOIDmode))) | |||
2941 | { | |||
2942 | std::swap (op0, op1); | |||
2943 | code = swap_condition (code); | |||
2944 | } | |||
2945 | ||||
2946 | cmpmode = SELECT_CC_MODE (code, op0, op1)ix86_cc_mode ((code), (op0), (op1)); | |||
2947 | flags = gen_rtx_REG (cmpmode, FLAGS_REG17); | |||
2948 | ||||
2949 | /* This is very simple, but making the interface the same as in the | |||
2950 | FP case makes the rest of the code easier. */ | |||
2951 | tmp = gen_rtx_COMPARE (cmpmode, op0, op1)gen_rtx_fmt_ee_stat ((COMPARE), ((cmpmode)), ((op0)), ((op1)) ); | |||
2952 | emit_insn (gen_rtx_SET (flags, tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((flags )), ((tmp)) )); | |||
2953 | ||||
2954 | /* Return the test that should be put into the flags user, i.e. | |||
2955 | the bcc, scc, or cmov instruction. */ | |||
2956 | return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx)gen_rtx_fmt_ee_stat ((code), (((void) 0, E_VOIDmode)), (flags ), ((const_int_rtx[64])) ); | |||
2957 | } | |||
2958 | ||||
2959 | static rtx | |||
2960 | ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1) | |||
2961 | { | |||
2962 | rtx ret; | |||
2963 | ||||
2964 | if (GET_MODE_CLASS (GET_MODE (op0))((enum mode_class) mode_class[((machine_mode) (op0)->mode) ]) == MODE_CC) | |||
2965 | ret = gen_rtx_fmt_ee (code, VOIDmode, op0, op1)gen_rtx_fmt_ee_stat ((code), (((void) 0, E_VOIDmode)), (op0), (op1) ); | |||
2966 | ||||
2967 | else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0))(((enum mode_class) mode_class[((machine_mode) (op0)->mode )]) == MODE_FLOAT || ((enum mode_class) mode_class[((machine_mode ) (op0)->mode)]) == MODE_DECIMAL_FLOAT)) | |||
2968 | { | |||
2969 | gcc_assert (!DECIMAL_FLOAT_MODE_P (GET_MODE (op0)))((void)(!(!(((enum mode_class) mode_class[((machine_mode) (op0 )->mode)]) == MODE_DECIMAL_FLOAT)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2969, __FUNCTION__), 0 : 0)); | |||
2970 | ret = ix86_expand_fp_compare (code, op0, op1); | |||
2971 | } | |||
2972 | else | |||
2973 | ret = ix86_expand_int_compare (code, op0, op1); | |||
2974 | ||||
2975 | return ret; | |||
2976 | } | |||
2977 | ||||
2978 | void | |||
2979 | ix86_expand_setcc (rtx dest, enum rtx_code code, rtx op0, rtx op1) | |||
2980 | { | |||
2981 | rtx ret; | |||
2982 | ||||
2983 | gcc_assert (GET_MODE (dest) == QImode)((void)(!(((machine_mode) (dest)->mode) == (scalar_int_mode ((scalar_int_mode::from_int) E_QImode))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2983, __FUNCTION__), 0 : 0)); | |||
2984 | ||||
2985 | ret = ix86_expand_compare (code, op0, op1); | |||
2986 | PUT_MODE (ret, QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode))); | |||
2987 | emit_insn (gen_rtx_SET (dest, ret)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((ret)) )); | |||
2988 | } | |||
2989 | ||||
2990 | /* Expand floating point op0 <=> op1, i.e. | |||
2991 | dest = op0 == op1 ? 0 : op0 < op1 ? -1 : op0 > op1 ? 1 : 2. */ | |||
2992 | ||||
2993 | void | |||
2994 | ix86_expand_fp_spaceship (rtx dest, rtx op0, rtx op1) | |||
2995 | { | |||
2996 | gcc_checking_assert (ix86_fp_comparison_strategy (GT) != IX86_FPCMP_ARITH)((void)(!(ix86_fp_comparison_strategy (GT) != IX86_FPCMP_ARITH ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 2996, __FUNCTION__), 0 : 0)); | |||
2997 | rtx gt = ix86_expand_fp_compare (GT, op0, op1); | |||
2998 | rtx l0 = gen_label_rtx (); | |||
2999 | rtx l1 = gen_label_rtx (); | |||
3000 | rtx l2 = TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0) ? gen_label_rtx () : NULL_RTX(rtx) 0; | |||
3001 | rtx lend = gen_label_rtx (); | |||
3002 | rtx tmp; | |||
3003 | rtx_insn *jmp; | |||
3004 | if (l2) | |||
3005 | { | |||
3006 | rtx un = gen_rtx_fmt_ee (UNORDERED, VOIDmode,gen_rtx_fmt_ee_stat ((UNORDERED), (((void) 0, E_VOIDmode)), ( gen_rtx_REG (((void) 0, E_CCFPmode), 17)), ((const_int_rtx[64 ])) ) | |||
3007 | gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx)gen_rtx_fmt_ee_stat ((UNORDERED), (((void) 0, E_VOIDmode)), ( gen_rtx_REG (((void) 0, E_CCFPmode), 17)), ((const_int_rtx[64 ])) ); | |||
3008 | tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, un,gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((un)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode ))), ((l2)) ))), ((pc_rtx)) ) | |||
3009 | gen_rtx_LABEL_REF (VOIDmode, l2), pc_rtx)gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((un)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode ))), ((l2)) ))), ((pc_rtx)) ); | |||
3010 | jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((pc_rtx )), ((tmp)) )); | |||
3011 | add_reg_br_prob_note (jmp, profile_probability:: very_unlikely ()); | |||
3012 | } | |||
3013 | rtx eq = gen_rtx_fmt_ee (UNEQ, VOIDmode,gen_rtx_fmt_ee_stat ((UNEQ), (((void) 0, E_VOIDmode)), (gen_rtx_REG (((void) 0, E_CCFPmode), 17)), ((const_int_rtx[64])) ) | |||
3014 | gen_rtx_REG (CCFPmode, FLAGS_REG), const0_rtx)gen_rtx_fmt_ee_stat ((UNEQ), (((void) 0, E_VOIDmode)), (gen_rtx_REG (((void) 0, E_CCFPmode), 17)), ((const_int_rtx[64])) ); | |||
3015 | tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, eq,gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((eq)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode ))), ((l0)) ))), ((pc_rtx)) ) | |||
3016 | gen_rtx_LABEL_REF (VOIDmode, l0), pc_rtx)gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((eq)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode ))), ((l0)) ))), ((pc_rtx)) ); | |||
3017 | jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((pc_rtx )), ((tmp)) )); | |||
3018 | add_reg_br_prob_note (jmp, profile_probability::unlikely ()); | |||
3019 | tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, gt,gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((gt)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode ))), ((l1)) ))), ((pc_rtx)) ) | |||
3020 | gen_rtx_LABEL_REF (VOIDmode, l1), pc_rtx)gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((((void) 0, E_VOIDmode ))), ((gt)), ((gen_rtx_fmt_u_stat ((LABEL_REF), ((((void) 0, E_VOIDmode ))), ((l1)) ))), ((pc_rtx)) ); | |||
3021 | jmp = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((pc_rtx )), ((tmp)) )); | |||
3022 | add_reg_br_prob_note (jmp, profile_probability::even ()); | |||
3023 | emit_move_insn (dest, constm1_rtx(const_int_rtx[64 -1])); | |||
3024 | emit_jump (lend); | |||
3025 | emit_label (l0); | |||
3026 | emit_move_insn (dest, const0_rtx(const_int_rtx[64])); | |||
3027 | emit_jump (lend); | |||
3028 | emit_label (l1); | |||
3029 | emit_move_insn (dest, const1_rtx(const_int_rtx[64 +1])); | |||
3030 | emit_jump (lend); | |||
3031 | if (l2) | |||
3032 | { | |||
3033 | emit_label (l2); | |||
3034 | emit_move_insn (dest, const2_rtx(const_int_rtx[64 +2])); | |||
3035 | } | |||
3036 | emit_label (lend); | |||
3037 | } | |||
3038 | ||||
3039 | /* Expand comparison setting or clearing carry flag. Return true when | |||
3040 | successful and set pop for the operation. */ | |||
3041 | static bool | |||
3042 | ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop) | |||
3043 | { | |||
3044 | machine_mode mode | |||
3045 | = GET_MODE (op0)((machine_mode) (op0)->mode) != VOIDmode((void) 0, E_VOIDmode) ? GET_MODE (op0)((machine_mode) (op0)->mode) : GET_MODE (op1)((machine_mode) (op1)->mode); | |||
3046 | ||||
3047 | /* Do not handle double-mode compares that go through special path. */ | |||
3048 | if (mode == (TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) ? TImode(scalar_int_mode ((scalar_int_mode::from_int) E_TImode)) : DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)))) | |||
3049 | return false; | |||
3050 | ||||
3051 | if (SCALAR_FLOAT_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_DECIMAL_FLOAT)) | |||
3052 | { | |||
3053 | rtx compare_op; | |||
3054 | rtx_insn *compare_seq; | |||
3055 | ||||
3056 | gcc_assert (!DECIMAL_FLOAT_MODE_P (mode))((void)(!(!(((enum mode_class) mode_class[mode]) == MODE_DECIMAL_FLOAT )) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 3056, __FUNCTION__), 0 : 0)); | |||
3057 | ||||
3058 | /* Shortcut: following common codes never translate | |||
3059 | into carry flag compares. */ | |||
3060 | if (code == EQ || code == NE || code == UNEQ || code == LTGT | |||
3061 | || code == ORDERED || code == UNORDERED) | |||
3062 | return false; | |||
3063 | ||||
3064 | /* These comparisons require zero flag; swap operands so they won't. */ | |||
3065 | if ((code == GT || code == UNLE || code == LE || code == UNGT) | |||
3066 | && !TARGET_IEEE_FP((global_options.x_target_flags & (1U << 13)) != 0)) | |||
3067 | { | |||
3068 | std::swap (op0, op1); | |||
3069 | code = swap_condition (code); | |||
3070 | } | |||
3071 | ||||
3072 | /* Try to expand the comparison and verify that we end up with | |||
3073 | carry flag based comparison. This fails to be true only when | |||
3074 | we decide to expand comparison using arithmetic that is not | |||
3075 | too common scenario. */ | |||
3076 | start_sequence (); | |||
3077 | compare_op = ix86_expand_fp_compare (code, op0, op1); | |||
3078 | compare_seq = get_insns (); | |||
3079 | end_sequence (); | |||
3080 | ||||
3081 | if (GET_MODE (XEXP (compare_op, 0))((machine_mode) ((((compare_op)->u.fld[0]).rt_rtx))->mode ) == CCFPmode((void) 0, E_CCFPmode)) | |||
3082 | code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op)((enum rtx_code) (compare_op)->code)); | |||
3083 | else | |||
3084 | code = GET_CODE (compare_op)((enum rtx_code) (compare_op)->code); | |||
3085 | ||||
3086 | if (code != LTU && code != GEU) | |||
3087 | return false; | |||
3088 | ||||
3089 | emit_insn (compare_seq); | |||
3090 | *pop = compare_op; | |||
3091 | return true; | |||
3092 | } | |||
3093 | ||||
3094 | if (!INTEGRAL_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_INT || ((enum mode_class ) mode_class[mode]) == MODE_PARTIAL_INT || ((enum mode_class) mode_class[mode]) == MODE_COMPLEX_INT || ((enum mode_class) mode_class [mode]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[ mode]) == MODE_VECTOR_INT)) | |||
3095 | return false; | |||
3096 | ||||
3097 | switch (code) | |||
3098 | { | |||
3099 | case LTU: | |||
3100 | case GEU: | |||
3101 | break; | |||
3102 | ||||
3103 | /* Convert a==0 into (unsigned)a<1. */ | |||
3104 | case EQ: | |||
3105 | case NE: | |||
3106 | if (op1 != const0_rtx(const_int_rtx[64])) | |||
3107 | return false; | |||
3108 | op1 = const1_rtx(const_int_rtx[64 +1]); | |||
3109 | code = (code == EQ ? LTU : GEU); | |||
3110 | break; | |||
3111 | ||||
3112 | /* Convert a>b into b<a or a>=b-1. */ | |||
3113 | case GTU: | |||
3114 | case LEU: | |||
3115 | if (CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT)) | |||
3116 | { | |||
3117 | op1 = gen_int_mode (INTVAL (op1)((op1)->u.hwint[0]) + 1, GET_MODE (op0)((machine_mode) (op0)->mode)); | |||
3118 | /* Bail out on overflow. We still can swap operands but that | |||
3119 | would force loading of the constant into register. */ | |||
3120 | if (op1 == const0_rtx(const_int_rtx[64]) | |||
3121 | || !x86_64_immediate_operand (op1, GET_MODE (op1)((machine_mode) (op1)->mode))) | |||
3122 | return false; | |||
3123 | code = (code == GTU ? GEU : LTU); | |||
3124 | } | |||
3125 | else | |||
3126 | { | |||
3127 | std::swap (op0, op1); | |||
3128 | code = (code == GTU ? LTU : GEU); | |||
3129 | } | |||
3130 | break; | |||
3131 | ||||
3132 | /* Convert a>=0 into (unsigned)a<0x80000000. */ | |||
3133 | case LT: | |||
3134 | case GE: | |||
3135 | if (mode == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)) || op1 != const0_rtx(const_int_rtx[64])) | |||
3136 | return false; | |||
3137 | op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode)((unsigned short) mode_to_bits (mode).coeffs[0]) - 1), mode); | |||
3138 | code = (code == LT ? GEU : LTU); | |||
3139 | break; | |||
3140 | case LE: | |||
3141 | case GT: | |||
3142 | if (mode == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)) || op1 != constm1_rtx(const_int_rtx[64 -1])) | |||
3143 | return false; | |||
3144 | op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode)((unsigned short) mode_to_bits (mode).coeffs[0]) - 1), mode); | |||
3145 | code = (code == LE ? GEU : LTU); | |||
3146 | break; | |||
3147 | ||||
3148 | default: | |||
3149 | return false; | |||
3150 | } | |||
3151 | /* Swapping operands may cause constant to appear as first operand. */ | |||
3152 | if (!nonimmediate_operand (op0, VOIDmode((void) 0, E_VOIDmode))) | |||
3153 | { | |||
3154 | if (!can_create_pseudo_p ()(!reload_in_progress && !reload_completed)) | |||
3155 | return false; | |||
3156 | op0 = force_reg (mode, op0); | |||
3157 | } | |||
3158 | *pop = ix86_expand_compare (code, op0, op1); | |||
3159 | gcc_assert (GET_CODE (*pop) == LTU || GET_CODE (*pop) == GEU)((void)(!(((enum rtx_code) (*pop)->code) == LTU || ((enum rtx_code ) (*pop)->code) == GEU) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 3159, __FUNCTION__), 0 : 0)); | |||
3160 | return true; | |||
3161 | } | |||
3162 | ||||
3163 | /* Expand conditional increment or decrement using adb/sbb instructions. | |||
3164 | The default case using setcc followed by the conditional move can be | |||
3165 | done by generic code. */ | |||
3166 | bool | |||
3167 | ix86_expand_int_addcc (rtx operands[]) | |||
3168 | { | |||
3169 | enum rtx_code code = GET_CODE (operands[1])((enum rtx_code) (operands[1])->code); | |||
3170 | rtx flags; | |||
3171 | rtx (*insn) (machine_mode, rtx, rtx, rtx, rtx, rtx); | |||
3172 | rtx compare_op; | |||
3173 | rtx val = const0_rtx(const_int_rtx[64]); | |||
3174 | bool fpcmp = false; | |||
3175 | machine_mode mode; | |||
3176 | rtx op0 = XEXP (operands[1], 0)(((operands[1])->u.fld[0]).rt_rtx); | |||
3177 | rtx op1 = XEXP (operands[1], 1)(((operands[1])->u.fld[1]).rt_rtx); | |||
3178 | ||||
3179 | if (operands[3] != const1_rtx(const_int_rtx[64 +1]) | |||
3180 | && operands[3] != constm1_rtx(const_int_rtx[64 -1])) | |||
3181 | return false; | |||
3182 | if (!ix86_expand_carry_flag_compare (code, op0, op1, &compare_op)) | |||
3183 | return false; | |||
3184 | code = GET_CODE (compare_op)((enum rtx_code) (compare_op)->code); | |||
3185 | ||||
3186 | flags = XEXP (compare_op, 0)(((compare_op)->u.fld[0]).rt_rtx); | |||
3187 | ||||
3188 | if (GET_MODE (flags)((machine_mode) (flags)->mode) == CCFPmode((void) 0, E_CCFPmode)) | |||
3189 | { | |||
3190 | fpcmp = true; | |||
3191 | code = ix86_fp_compare_code_to_integer (code); | |||
3192 | } | |||
3193 | ||||
3194 | if (code != LTU) | |||
3195 | { | |||
3196 | val = constm1_rtx(const_int_rtx[64 -1]); | |||
3197 | if (fpcmp) | |||
3198 | PUT_CODE (compare_op,((compare_op)->code = (reverse_condition_maybe_unordered ( ((enum rtx_code) (compare_op)->code)))) | |||
3199 | reverse_condition_maybe_unordered((compare_op)->code = (reverse_condition_maybe_unordered ( ((enum rtx_code) (compare_op)->code)))) | |||
3200 | (GET_CODE (compare_op)))((compare_op)->code = (reverse_condition_maybe_unordered ( ((enum rtx_code) (compare_op)->code)))); | |||
3201 | else | |||
3202 | PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)))((compare_op)->code = (reverse_condition (((enum rtx_code) (compare_op)->code)))); | |||
3203 | } | |||
3204 | ||||
3205 | mode = GET_MODE (operands[0])((machine_mode) (operands[0])->mode); | |||
3206 | ||||
3207 | /* Construct either adc or sbb insn. */ | |||
3208 | if ((code == LTU) == (operands[3] == constm1_rtx(const_int_rtx[64 -1]))) | |||
3209 | insn = gen_sub3_carry; | |||
3210 | else | |||
3211 | insn = gen_add3_carry; | |||
3212 | ||||
3213 | emit_insn (insn (mode, operands[0], operands[2], val, flags, compare_op)); | |||
3214 | ||||
3215 | return true; | |||
3216 | } | |||
3217 | ||||
3218 | bool | |||
3219 | ix86_expand_int_movcc (rtx operands[]) | |||
3220 | { | |||
3221 | enum rtx_code code = GET_CODE (operands[1])((enum rtx_code) (operands[1])->code), compare_code; | |||
3222 | rtx_insn *compare_seq; | |||
3223 | rtx compare_op; | |||
3224 | machine_mode mode = GET_MODE (operands[0])((machine_mode) (operands[0])->mode); | |||
3225 | bool sign_bit_compare_p = false; | |||
3226 | bool negate_cc_compare_p = false; | |||
3227 | rtx op0 = XEXP (operands[1], 0)(((operands[1])->u.fld[0]).rt_rtx); | |||
3228 | rtx op1 = XEXP (operands[1], 1)(((operands[1])->u.fld[1]).rt_rtx); | |||
3229 | rtx op2 = operands[2]; | |||
3230 | rtx op3 = operands[3]; | |||
3231 | ||||
3232 | if (GET_MODE (op0)((machine_mode) (op0)->mode) == TImode(scalar_int_mode ((scalar_int_mode::from_int) E_TImode)) | |||
3233 | || (GET_MODE (op0)((machine_mode) (op0)->mode) == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)) | |||
3234 | && !TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ))) | |||
3235 | return false; | |||
3236 | ||||
3237 | if (GET_MODE (op0)((machine_mode) (op0)->mode) == BFmode(scalar_float_mode ((scalar_float_mode::from_int) E_BFmode)) | |||
3238 | && !ix86_fp_comparison_operator (operands[1], VOIDmode((void) 0, E_VOIDmode))) | |||
3239 | return false; | |||
3240 | ||||
3241 | start_sequence (); | |||
3242 | compare_op = ix86_expand_compare (code, op0, op1); | |||
3243 | compare_seq = get_insns (); | |||
3244 | end_sequence (); | |||
3245 | ||||
3246 | compare_code = GET_CODE (compare_op)((enum rtx_code) (compare_op)->code); | |||
3247 | ||||
3248 | if ((op1 == const0_rtx(const_int_rtx[64]) && (code == GE || code == LT)) | |||
3249 | || (op1 == constm1_rtx(const_int_rtx[64 -1]) && (code == GT || code == LE))) | |||
3250 | sign_bit_compare_p = true; | |||
3251 | ||||
3252 | /* op0 == op1 ? op0 : op3 is equivalent to op0 == op1 ? op1 : op3, | |||
3253 | but if op1 is a constant, the latter form allows more optimizations, | |||
3254 | either through the last 2 ops being constant handling, or the one | |||
3255 | constant and one variable cases. On the other side, for cmov the | |||
3256 | former might be better as we don't need to load the constant into | |||
3257 | another register. */ | |||
3258 | if (code == EQ && CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT) && rtx_equal_p (op0, op2)) | |||
3259 | op2 = op1; | |||
3260 | /* Similarly for op0 != op1 ? op2 : op0 and op0 != op1 ? op2 : op1. */ | |||
3261 | else if (code == NE && CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT) && rtx_equal_p (op0, op3)) | |||
3262 | op3 = op1; | |||
3263 | ||||
3264 | /* Don't attempt mode expansion here -- if we had to expand 5 or 6 | |||
3265 | HImode insns, we'd be swallowed in word prefix ops. */ | |||
3266 | ||||
3267 | if ((mode != HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode)) || TARGET_FAST_PREFIXix86_tune_features[X86_TUNE_FAST_PREFIX]) | |||
3268 | && (mode != (TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) ? TImode(scalar_int_mode ((scalar_int_mode::from_int) E_TImode)) : DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)))) | |||
3269 | && CONST_INT_P (op2)(((enum rtx_code) (op2)->code) == CONST_INT) | |||
3270 | && CONST_INT_P (op3)(((enum rtx_code) (op3)->code) == CONST_INT)) | |||
3271 | { | |||
3272 | rtx out = operands[0]; | |||
3273 | HOST_WIDE_INTlong ct = INTVAL (op2)((op2)->u.hwint[0]); | |||
3274 | HOST_WIDE_INTlong cf = INTVAL (op3)((op3)->u.hwint[0]); | |||
3275 | HOST_WIDE_INTlong diff; | |||
3276 | ||||
3277 | if ((mode == SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)) | |||
3278 | || (TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) && mode == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)))) | |||
3279 | && (GET_MODE (op0)((machine_mode) (op0)->mode) == SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)) | |||
3280 | || (TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ) && GET_MODE (op0)((machine_mode) (op0)->mode) == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode))))) | |||
3281 | { | |||
3282 | /* Special case x != 0 ? -1 : y. */ | |||
3283 | if (code == NE && op1 == const0_rtx(const_int_rtx[64]) && ct == -1) | |||
3284 | { | |||
3285 | negate_cc_compare_p = true; | |||
3286 | std::swap (ct, cf); | |||
3287 | code = EQ; | |||
3288 | } | |||
3289 | else if (code == EQ && op1 == const0_rtx(const_int_rtx[64]) && cf == -1) | |||
3290 | negate_cc_compare_p = true; | |||
3291 | } | |||
3292 | ||||
3293 | diff = ct - cf; | |||
3294 | /* Sign bit compares are better done using shifts than we do by using | |||
3295 | sbb. */ | |||
3296 | if (sign_bit_compare_p | |||
3297 | || negate_cc_compare_p | |||
3298 | || ix86_expand_carry_flag_compare (code, op0, op1, &compare_op)) | |||
3299 | { | |||
3300 | /* Detect overlap between destination and compare sources. */ | |||
3301 | rtx tmp = out; | |||
3302 | ||||
3303 | if (negate_cc_compare_p) | |||
3304 | { | |||
3305 | if (GET_MODE (op0)((machine_mode) (op0)->mode) == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode))) | |||
3306 | emit_insn (gen_x86_negdi_ccc (gen_reg_rtx (DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode))), op0)); | |||
3307 | else | |||
3308 | emit_insn (gen_x86_negsi_ccc (gen_reg_rtx (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode))), | |||
3309 | gen_lowpartrtl_hooks.gen_lowpart (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), op0))); | |||
3310 | ||||
3311 | tmp = gen_reg_rtx (mode); | |||
3312 | if (mode == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode))) | |||
3313 | emit_insn (gen_x86_movdicc_0_m1_neg (tmp)); | |||
3314 | else | |||
3315 | emit_insn (gen_x86_movsicc_0_m1_neg (gen_lowpartrtl_hooks.gen_lowpart (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), | |||
3316 | tmp))); | |||
3317 | } | |||
3318 | else if (!sign_bit_compare_p) | |||
3319 | { | |||
3320 | rtx flags; | |||
3321 | bool fpcmp = false; | |||
3322 | ||||
3323 | compare_code = GET_CODE (compare_op)((enum rtx_code) (compare_op)->code); | |||
3324 | ||||
3325 | flags = XEXP (compare_op, 0)(((compare_op)->u.fld[0]).rt_rtx); | |||
3326 | ||||
3327 | if (GET_MODE (flags)((machine_mode) (flags)->mode) == CCFPmode((void) 0, E_CCFPmode)) | |||
3328 | { | |||
3329 | fpcmp = true; | |||
3330 | compare_code | |||
3331 | = ix86_fp_compare_code_to_integer (compare_code); | |||
3332 | } | |||
3333 | ||||
3334 | /* To simplify rest of code, restrict to the GEU case. */ | |||
3335 | if (compare_code == LTU) | |||
3336 | { | |||
3337 | std::swap (ct, cf); | |||
3338 | compare_code = reverse_condition (compare_code); | |||
3339 | code = reverse_condition (code); | |||
3340 | } | |||
3341 | else | |||
3342 | { | |||
3343 | if (fpcmp) | |||
3344 | PUT_CODE (compare_op,((compare_op)->code = (reverse_condition_maybe_unordered ( ((enum rtx_code) (compare_op)->code)))) | |||
3345 | reverse_condition_maybe_unordered((compare_op)->code = (reverse_condition_maybe_unordered ( ((enum rtx_code) (compare_op)->code)))) | |||
3346 | (GET_CODE (compare_op)))((compare_op)->code = (reverse_condition_maybe_unordered ( ((enum rtx_code) (compare_op)->code)))); | |||
3347 | else | |||
3348 | PUT_CODE (compare_op,((compare_op)->code = (reverse_condition (((enum rtx_code) (compare_op)->code)))) | |||
3349 | reverse_condition (GET_CODE (compare_op)))((compare_op)->code = (reverse_condition (((enum rtx_code) (compare_op)->code)))); | |||
3350 | } | |||
3351 | diff = ct - cf; | |||
3352 | ||||
3353 | if (reg_overlap_mentioned_p (out, compare_op)) | |||
3354 | tmp = gen_reg_rtx (mode); | |||
3355 | ||||
3356 | if (mode == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode))) | |||
3357 | emit_insn (gen_x86_movdicc_0_m1 (tmp, flags, compare_op)); | |||
3358 | else | |||
3359 | emit_insn (gen_x86_movsicc_0_m1 (gen_lowpartrtl_hooks.gen_lowpart (SImode(scalar_int_mode ((scalar_int_mode::from_int) E_SImode)), tmp), | |||
3360 | flags, compare_op)); | |||
3361 | } | |||
3362 | else | |||
3363 | { | |||
3364 | if (code == GT || code == GE) | |||
3365 | code = reverse_condition (code); | |||
3366 | else | |||
3367 | { | |||
3368 | std::swap (ct, cf); | |||
3369 | diff = ct - cf; | |||
3370 | } | |||
3371 | tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode((void) 0, E_VOIDmode), 0, -1); | |||
3372 | } | |||
3373 | ||||
3374 | if (diff == 1) | |||
3375 | { | |||
3376 | /* | |||
3377 | * cmpl op0,op1 | |||
3378 | * sbbl dest,dest | |||
3379 | * [addl dest, ct] | |||
3380 | * | |||
3381 | * Size 5 - 8. | |||
3382 | */ | |||
3383 | if (ct) | |||
3384 | tmp = expand_simple_binop (mode, PLUS, | |||
3385 | tmp, GEN_INT (ct)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (ct)), | |||
3386 | copy_rtx (tmp), 1, OPTAB_DIRECT); | |||
3387 | } | |||
3388 | else if (cf == -1) | |||
3389 | { | |||
3390 | /* | |||
3391 | * cmpl op0,op1 | |||
3392 | * sbbl dest,dest | |||
3393 | * orl $ct, dest | |||
3394 | * | |||
3395 | * Size 8. | |||
3396 | */ | |||
3397 | tmp = expand_simple_binop (mode, IOR, | |||
3398 | tmp, GEN_INT (ct)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (ct)), | |||
3399 | copy_rtx (tmp), 1, OPTAB_DIRECT); | |||
3400 | } | |||
3401 | else if (diff == -1 && ct) | |||
3402 | { | |||
3403 | /* | |||
3404 | * cmpl op0,op1 | |||
3405 | * sbbl dest,dest | |||
3406 | * notl dest | |||
3407 | * [addl dest, cf] | |||
3408 | * | |||
3409 | * Size 8 - 11. | |||
3410 | */ | |||
3411 | tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1); | |||
3412 | if (cf) | |||
3413 | tmp = expand_simple_binop (mode, PLUS, | |||
3414 | copy_rtx (tmp), GEN_INT (cf)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (cf)), | |||
3415 | copy_rtx (tmp), 1, OPTAB_DIRECT); | |||
3416 | } | |||
3417 | else | |||
3418 | { | |||
3419 | /* | |||
3420 | * cmpl op0,op1 | |||
3421 | * sbbl dest,dest | |||
3422 | * [notl dest] | |||
3423 | * andl cf - ct, dest | |||
3424 | * [addl dest, ct] | |||
3425 | * | |||
3426 | * Size 8 - 11. | |||
3427 | */ | |||
3428 | ||||
3429 | if (cf == 0) | |||
3430 | { | |||
3431 | cf = ct; | |||
3432 | ct = 0; | |||
3433 | tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1); | |||
3434 | } | |||
3435 | ||||
3436 | tmp = expand_simple_binop (mode, AND, | |||
3437 | copy_rtx (tmp), | |||
3438 | gen_int_mode (cf - ct, mode), | |||
3439 | copy_rtx (tmp), 1, OPTAB_DIRECT); | |||
3440 | if (ct) | |||
3441 | tmp = expand_simple_binop (mode, PLUS, | |||
3442 | copy_rtx (tmp), GEN_INT (ct)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (ct)), | |||
3443 | copy_rtx (tmp), 1, OPTAB_DIRECT); | |||
3444 | } | |||
3445 | ||||
3446 | if (!rtx_equal_p (tmp, out)) | |||
3447 | emit_move_insn (copy_rtx (out), copy_rtx (tmp)); | |||
3448 | ||||
3449 | return true; | |||
3450 | } | |||
3451 | ||||
3452 | if (diff < 0) | |||
3453 | { | |||
3454 | machine_mode cmp_mode = GET_MODE (op0)((machine_mode) (op0)->mode); | |||
3455 | enum rtx_code new_code; | |||
3456 | ||||
3457 | if (SCALAR_FLOAT_MODE_P (cmp_mode)(((enum mode_class) mode_class[cmp_mode]) == MODE_FLOAT || (( enum mode_class) mode_class[cmp_mode]) == MODE_DECIMAL_FLOAT)) | |||
3458 | { | |||
3459 | gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode))((void)(!(!(((enum mode_class) mode_class[cmp_mode]) == MODE_DECIMAL_FLOAT )) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 3459, __FUNCTION__), 0 : 0)); | |||
3460 | ||||
3461 | /* We may be reversing a non-trapping | |||
3462 | comparison to a trapping comparison. */ | |||
3463 | if (HONOR_NANS (cmp_mode) && flag_trapping_mathglobal_options.x_flag_trapping_math | |||
3464 | && code != EQ && code != NE | |||
3465 | && code != ORDERED && code != UNORDERED) | |||
3466 | new_code = UNKNOWN; | |||
3467 | else | |||
3468 | new_code = reverse_condition_maybe_unordered (code); | |||
3469 | } | |||
3470 | else | |||
3471 | new_code = ix86_reverse_condition (code, cmp_mode); | |||
3472 | if (new_code != UNKNOWN) | |||
3473 | { | |||
3474 | std::swap (ct, cf); | |||
3475 | diff = -diff; | |||
3476 | code = new_code; | |||
3477 | } | |||
3478 | } | |||
3479 | ||||
3480 | compare_code = UNKNOWN; | |||
3481 | if (GET_MODE_CLASS (GET_MODE (op0))((enum mode_class) mode_class[((machine_mode) (op0)->mode) ]) == MODE_INT | |||
3482 | && CONST_INT_P (op1)(((enum rtx_code) (op1)->code) == CONST_INT)) | |||
3483 | { | |||
3484 | if (op1 == const0_rtx(const_int_rtx[64]) | |||
3485 | && (code == LT || code == GE)) | |||
3486 | compare_code = code; | |||
3487 | else if (op1 == constm1_rtx(const_int_rtx[64 -1])) | |||
3488 | { | |||
3489 | if (code == LE) | |||
3490 | compare_code = LT; | |||
3491 | else if (code == GT) | |||
3492 | compare_code = GE; | |||
3493 | } | |||
3494 | } | |||
3495 | ||||
3496 | /* Optimize dest = (op0 < 0) ? -1 : cf. */ | |||
3497 | if (compare_code != UNKNOWN | |||
3498 | && GET_MODE (op0)((machine_mode) (op0)->mode) == GET_MODE (out)((machine_mode) (out)->mode) | |||
3499 | && (cf == -1 || ct == -1)) | |||
3500 | { | |||
3501 | /* If lea code below could be used, only optimize | |||
3502 | if it results in a 2 insn sequence. */ | |||
3503 | ||||
3504 | if (! (diff == 1 || diff == 2 || diff == 4 || diff == 8 | |||
3505 | || diff == 3 || diff == 5 || diff == 9) | |||
3506 | || (compare_code == LT && ct == -1) | |||
3507 | || (compare_code == GE && cf == -1)) | |||
3508 | { | |||
3509 | /* | |||
3510 | * notl op1 (if necessary) | |||
3511 | * sarl $31, op1 | |||
3512 | * orl cf, op1 | |||
3513 | */ | |||
3514 | if (ct != -1) | |||
3515 | { | |||
3516 | cf = ct; | |||
3517 | ct = -1; | |||
3518 | code = reverse_condition (code); | |||
3519 | } | |||
3520 | ||||
3521 | out = emit_store_flag (out, code, op0, op1, VOIDmode((void) 0, E_VOIDmode), 0, -1); | |||
3522 | ||||
3523 | out = expand_simple_binop (mode, IOR, | |||
3524 | out, GEN_INT (cf)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (cf)), | |||
3525 | out, 1, OPTAB_DIRECT); | |||
3526 | if (out != operands[0]) | |||
3527 | emit_move_insn (operands[0], out); | |||
3528 | ||||
3529 | return true; | |||
3530 | } | |||
3531 | } | |||
3532 | ||||
3533 | ||||
3534 | if ((diff == 1 || diff == 2 || diff == 4 || diff == 8 | |||
3535 | || diff == 3 || diff == 5 || diff == 9) | |||
3536 | && ((mode != QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)) && mode != HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode))) || !TARGET_PARTIAL_REG_STALLix86_tune_features[X86_TUNE_PARTIAL_REG_STALL]) | |||
3537 | && (mode != DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)) | |||
3538 | || x86_64_immediate_operand (GEN_INT (cf)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (cf)), VOIDmode((void) 0, E_VOIDmode)))) | |||
3539 | { | |||
3540 | /* | |||
3541 | * xorl dest,dest | |||
3542 | * cmpl op1,op2 | |||
3543 | * setcc dest | |||
3544 | * lea cf(dest*(ct-cf)),dest | |||
3545 | * | |||
3546 | * Size 14. | |||
3547 | * | |||
3548 | * This also catches the degenerate setcc-only case. | |||
3549 | */ | |||
3550 | ||||
3551 | rtx tmp; | |||
3552 | int nops; | |||
3553 | ||||
3554 | out = emit_store_flag (out, code, op0, op1, VOIDmode((void) 0, E_VOIDmode), 0, 1); | |||
3555 | ||||
3556 | nops = 0; | |||
3557 | /* On x86_64 the lea instruction operates on Pmode, so we need | |||
3558 | to get arithmetics done in proper mode to match. */ | |||
3559 | if (diff == 1) | |||
3560 | tmp = copy_rtx (out); | |||
3561 | else | |||
3562 | { | |||
3563 | rtx out1; | |||
3564 | out1 = copy_rtx (out); | |||
3565 | tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1))gen_rtx_fmt_ee_stat ((MULT), ((mode)), ((out1)), ((gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (diff & ~1)))) ); | |||
3566 | nops++; | |||
3567 | if (diff & 1) | |||
3568 | { | |||
3569 | tmp = gen_rtx_PLUS (mode, tmp, out1)gen_rtx_fmt_ee_stat ((PLUS), ((mode)), ((tmp)), ((out1)) ); | |||
3570 | nops++; | |||
3571 | } | |||
3572 | } | |||
3573 | if (cf != 0) | |||
3574 | { | |||
3575 | tmp = plus_constant (mode, tmp, cf); | |||
3576 | nops++; | |||
3577 | } | |||
3578 | if (!rtx_equal_p (tmp, out)) | |||
3579 | { | |||
3580 | if (nops == 1) | |||
3581 | out = force_operand (tmp, copy_rtx (out)); | |||
3582 | else | |||
3583 | emit_insn (gen_rtx_SET (copy_rtx (out), copy_rtx (tmp))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((copy_rtx (out))), ((copy_rtx (tmp))) )); | |||
3584 | } | |||
3585 | if (!rtx_equal_p (out, operands[0])) | |||
3586 | emit_move_insn (operands[0], copy_rtx (out)); | |||
3587 | ||||
3588 | return true; | |||
3589 | } | |||
3590 | ||||
3591 | /* | |||
3592 | * General case: Jumpful: | |||
3593 | * xorl dest,dest cmpl op1, op2 | |||
3594 | * cmpl op1, op2 movl ct, dest | |||
3595 | * setcc dest jcc 1f | |||
3596 | * decl dest movl cf, dest | |||
3597 | * andl (cf-ct),dest 1: | |||
3598 | * addl ct,dest | |||
3599 | * | |||
3600 | * Size 20. Size 14. | |||
3601 | * | |||
3602 | * This is reasonably steep, but branch mispredict costs are | |||
3603 | * high on modern cpus, so consider failing only if optimizing | |||
3604 | * for space. | |||
3605 | */ | |||
3606 | ||||
3607 | if ((!TARGET_CMOVE(ix86_arch_features[X86_ARCH_CMOV] || ((global_options.x_ix86_isa_flags & (1UL << 50)) != 0) || ((global_options.x_ix86_isa_flags & (1UL << 44)) != 0)) || (mode == QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)) && TARGET_PARTIAL_REG_STALLix86_tune_features[X86_TUNE_PARTIAL_REG_STALL])) | |||
3608 | && BRANCH_COST (optimize_insn_for_speed_p (),(!(optimize_insn_for_speed_p ()) ? 2 : (false) ? 0 : global_options .x_ix86_branch_cost) | |||
3609 | false)(!(optimize_insn_for_speed_p ()) ? 2 : (false) ? 0 : global_options .x_ix86_branch_cost) >= 2) | |||
3610 | { | |||
3611 | if (cf == 0) | |||
3612 | { | |||
3613 | machine_mode cmp_mode = GET_MODE (op0)((machine_mode) (op0)->mode); | |||
3614 | enum rtx_code new_code; | |||
3615 | ||||
3616 | if (SCALAR_FLOAT_MODE_P (cmp_mode)(((enum mode_class) mode_class[cmp_mode]) == MODE_FLOAT || (( enum mode_class) mode_class[cmp_mode]) == MODE_DECIMAL_FLOAT)) | |||
3617 | { | |||
3618 | gcc_assert (!DECIMAL_FLOAT_MODE_P (cmp_mode))((void)(!(!(((enum mode_class) mode_class[cmp_mode]) == MODE_DECIMAL_FLOAT )) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 3618, __FUNCTION__), 0 : 0)); | |||
3619 | ||||
3620 | /* We may be reversing a non-trapping | |||
3621 | comparison to a trapping comparison. */ | |||
3622 | if (HONOR_NANS (cmp_mode) && flag_trapping_mathglobal_options.x_flag_trapping_math | |||
3623 | && code != EQ && code != NE | |||
3624 | && code != ORDERED && code != UNORDERED) | |||
3625 | new_code = UNKNOWN; | |||
3626 | else | |||
3627 | new_code = reverse_condition_maybe_unordered (code); | |||
3628 | ||||
3629 | } | |||
3630 | else | |||
3631 | { | |||
3632 | new_code = ix86_reverse_condition (code, cmp_mode); | |||
3633 | if (compare_code != UNKNOWN && new_code != UNKNOWN) | |||
3634 | compare_code = reverse_condition (compare_code); | |||
3635 | } | |||
3636 | ||||
3637 | if (new_code != UNKNOWN) | |||
3638 | { | |||
3639 | cf = ct; | |||
3640 | ct = 0; | |||
3641 | code = new_code; | |||
3642 | } | |||
3643 | } | |||
3644 | ||||
3645 | if (compare_code != UNKNOWN) | |||
3646 | { | |||
3647 | /* notl op1 (if needed) | |||
3648 | sarl $31, op1 | |||
3649 | andl (cf-ct), op1 | |||
3650 | addl ct, op1 | |||
3651 | ||||
3652 | For x < 0 (resp. x <= -1) there will be no notl, | |||
3653 | so if possible swap the constants to get rid of the | |||
3654 | complement. | |||
3655 | True/false will be -1/0 while code below (store flag | |||
3656 | followed by decrement) is 0/-1, so the constants need | |||
3657 | to be exchanged once more. */ | |||
3658 | ||||
3659 | if (compare_code == GE || !cf) | |||
3660 | { | |||
3661 | code = reverse_condition (code); | |||
3662 | compare_code = LT; | |||
3663 | } | |||
3664 | else | |||
3665 | std::swap (ct, cf); | |||
3666 | ||||
3667 | out = emit_store_flag (out, code, op0, op1, VOIDmode((void) 0, E_VOIDmode), 0, -1); | |||
3668 | } | |||
3669 | else | |||
3670 | { | |||
3671 | out = emit_store_flag (out, code, op0, op1, VOIDmode((void) 0, E_VOIDmode), 0, 1); | |||
3672 | ||||
3673 | out = expand_simple_binop (mode, PLUS, copy_rtx (out), | |||
3674 | constm1_rtx(const_int_rtx[64 -1]), | |||
3675 | copy_rtx (out), 1, OPTAB_DIRECT); | |||
3676 | } | |||
3677 | ||||
3678 | out = expand_simple_binop (mode, AND, copy_rtx (out), | |||
3679 | gen_int_mode (cf - ct, mode), | |||
3680 | copy_rtx (out), 1, OPTAB_DIRECT); | |||
3681 | if (ct) | |||
3682 | out = expand_simple_binop (mode, PLUS, copy_rtx (out), GEN_INT (ct)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (ct)), | |||
3683 | copy_rtx (out), 1, OPTAB_DIRECT); | |||
3684 | if (!rtx_equal_p (out, operands[0])) | |||
3685 | emit_move_insn (operands[0], copy_rtx (out)); | |||
3686 | ||||
3687 | return true; | |||
3688 | } | |||
3689 | } | |||
3690 | ||||
3691 | if (!TARGET_CMOVE(ix86_arch_features[X86_ARCH_CMOV] || ((global_options.x_ix86_isa_flags & (1UL << 50)) != 0) || ((global_options.x_ix86_isa_flags & (1UL << 44)) != 0)) || (mode == QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)) && TARGET_PARTIAL_REG_STALLix86_tune_features[X86_TUNE_PARTIAL_REG_STALL])) | |||
3692 | { | |||
3693 | /* Try a few things more with specific constants and a variable. */ | |||
3694 | ||||
3695 | optab op; | |||
3696 | rtx var, orig_out, out, tmp; | |||
3697 | ||||
3698 | if (BRANCH_COST (optimize_insn_for_speed_p (), false)(!(optimize_insn_for_speed_p ()) ? 2 : (false) ? 0 : global_options .x_ix86_branch_cost) <= 2) | |||
3699 | return false; | |||
3700 | ||||
3701 | operands[2] = op2; | |||
3702 | operands[3] = op3; | |||
3703 | ||||
3704 | /* If one of the two operands is an interesting constant, load a | |||
3705 | constant with the above and mask it in with a logical operation. */ | |||
3706 | ||||
3707 | if (CONST_INT_P (operands[2])(((enum rtx_code) (operands[2])->code) == CONST_INT)) | |||
3708 | { | |||
3709 | var = operands[3]; | |||
3710 | if (INTVAL (operands[2])((operands[2])->u.hwint[0]) == 0 && operands[3] != constm1_rtx(const_int_rtx[64 -1])) | |||
3711 | operands[3] = constm1_rtx(const_int_rtx[64 -1]), op = and_optab; | |||
3712 | else if (INTVAL (operands[2])((operands[2])->u.hwint[0]) == -1 && operands[3] != const0_rtx(const_int_rtx[64])) | |||
3713 | operands[3] = const0_rtx(const_int_rtx[64]), op = ior_optab; | |||
3714 | else | |||
3715 | return false; | |||
3716 | } | |||
3717 | else if (CONST_INT_P (operands[3])(((enum rtx_code) (operands[3])->code) == CONST_INT)) | |||
3718 | { | |||
3719 | var = operands[2]; | |||
3720 | if (INTVAL (operands[3])((operands[3])->u.hwint[0]) == 0 && operands[2] != constm1_rtx(const_int_rtx[64 -1])) | |||
3721 | { | |||
3722 | /* For smin (x, 0), expand as "x < 0 ? x : 0" instead of | |||
3723 | "x <= 0 ? x : 0" to enable sign_bit_compare_p. */ | |||
3724 | if (code == LE && op1 == const0_rtx(const_int_rtx[64]) && rtx_equal_p (op0, var)) | |||
3725 | operands[1] = simplify_gen_relational (LT, VOIDmode((void) 0, E_VOIDmode), | |||
3726 | GET_MODE (op0)((machine_mode) (op0)->mode), | |||
3727 | op0, const0_rtx(const_int_rtx[64])); | |||
3728 | ||||
3729 | operands[2] = constm1_rtx(const_int_rtx[64 -1]); | |||
3730 | op = and_optab; | |||
3731 | } | |||
3732 | else if (INTVAL (operands[3])((operands[3])->u.hwint[0]) == -1 && operands[3] != const0_rtx(const_int_rtx[64])) | |||
3733 | operands[2] = const0_rtx(const_int_rtx[64]), op = ior_optab; | |||
3734 | else | |||
3735 | return false; | |||
3736 | } | |||
3737 | else | |||
3738 | return false; | |||
3739 | ||||
3740 | orig_out = operands[0]; | |||
3741 | tmp = gen_reg_rtx (mode); | |||
3742 | operands[0] = tmp; | |||
3743 | ||||
3744 | /* Recurse to get the constant loaded. */ | |||
3745 | if (!ix86_expand_int_movcc (operands)) | |||
3746 | return false; | |||
3747 | ||||
3748 | /* Mask in the interesting variable. */ | |||
3749 | out = expand_binop (mode, op, var, tmp, orig_out, 0, | |||
3750 | OPTAB_WIDEN); | |||
3751 | if (!rtx_equal_p (out, orig_out)) | |||
3752 | emit_move_insn (copy_rtx (orig_out), copy_rtx (out)); | |||
3753 | ||||
3754 | return true; | |||
3755 | } | |||
3756 | ||||
3757 | /* | |||
3758 | * For comparison with above, | |||
3759 | * | |||
3760 | * movl cf,dest | |||
3761 | * movl ct,tmp | |||
3762 | * cmpl op1,op2 | |||
3763 | * cmovcc tmp,dest | |||
3764 | * | |||
3765 | * Size 15. | |||
3766 | */ | |||
3767 | ||||
3768 | if (! nonimmediate_operand (operands[2], mode)) | |||
3769 | operands[2] = force_reg (mode, operands[2]); | |||
3770 | if (! nonimmediate_operand (operands[3], mode)) | |||
3771 | operands[3] = force_reg (mode, operands[3]); | |||
3772 | ||||
3773 | if (! register_operand (operands[2], VOIDmode((void) 0, E_VOIDmode)) | |||
3774 | && (mode == QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)) | |||
3775 | || ! register_operand (operands[3], VOIDmode((void) 0, E_VOIDmode)))) | |||
3776 | operands[2] = force_reg (mode, operands[2]); | |||
3777 | ||||
3778 | if (mode == QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)) | |||
3779 | && ! register_operand (operands[3], VOIDmode((void) 0, E_VOIDmode))) | |||
3780 | operands[3] = force_reg (mode, operands[3]); | |||
3781 | ||||
3782 | emit_insn (compare_seq); | |||
3783 | emit_insn (gen_rtx_SET (operands[0],gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((operands [0])), ((gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((mode)), ((compare_op )), ((operands[2])), ((operands[3])) ))) ) | |||
3784 | gen_rtx_IF_THEN_ELSE (mode,gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((operands [0])), ((gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((mode)), ((compare_op )), ((operands[2])), ((operands[3])) ))) ) | |||
3785 | compare_op, operands[2],gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((operands [0])), ((gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((mode)), ((compare_op )), ((operands[2])), ((operands[3])) ))) ) | |||
3786 | operands[3]))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((operands [0])), ((gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((mode)), ((compare_op )), ((operands[2])), ((operands[3])) ))) )); | |||
3787 | return true; | |||
3788 | } | |||
3789 | ||||
3790 | /* Detect conditional moves that exactly match min/max operational | |||
3791 | semantics. Note that this is IEEE safe, as long as we don't | |||
3792 | interchange the operands. | |||
3793 | ||||
3794 | Returns FALSE if this conditional move doesn't match a MIN/MAX, | |||
3795 | and TRUE if the operation is successful and instructions are emitted. */ | |||
3796 | ||||
3797 | static bool | |||
3798 | ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0, | |||
3799 | rtx cmp_op1, rtx if_true, rtx if_false) | |||
3800 | { | |||
3801 | machine_mode mode; | |||
3802 | bool is_min; | |||
3803 | rtx tmp; | |||
3804 | ||||
3805 | if (code == LT) | |||
3806 | ; | |||
3807 | else if (code == UNGE) | |||
3808 | std::swap (if_true, if_false); | |||
3809 | else | |||
3810 | return false; | |||
3811 | ||||
3812 | if (rtx_equal_p (cmp_op0, if_true) && rtx_equal_p (cmp_op1, if_false)) | |||
3813 | is_min = true; | |||
3814 | else if (rtx_equal_p (cmp_op1, if_true) && rtx_equal_p (cmp_op0, if_false)) | |||
3815 | is_min = false; | |||
3816 | else | |||
3817 | return false; | |||
3818 | ||||
3819 | mode = GET_MODE (dest)((machine_mode) (dest)->mode); | |||
3820 | ||||
3821 | /* We want to check HONOR_NANS and HONOR_SIGNED_ZEROS here, | |||
3822 | but MODE may be a vector mode and thus not appropriate. */ | |||
3823 | if (!flag_finite_math_onlyglobal_options.x_flag_finite_math_only || flag_signed_zerosglobal_options.x_flag_signed_zeros) | |||
3824 | { | |||
3825 | int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX; | |||
3826 | rtvec v; | |||
3827 | ||||
3828 | if_true = force_reg (mode, if_true); | |||
3829 | v = gen_rtvec (2, if_true, if_false); | |||
3830 | tmp = gen_rtx_UNSPEC (mode, v, u)gen_rtx_fmt_Ei_stat ((UNSPEC), ((mode)), ((v)), ((u)) ); | |||
3831 | } | |||
3832 | else | |||
3833 | { | |||
3834 | code = is_min ? SMIN : SMAX; | |||
3835 | if (MEM_P (if_true)(((enum rtx_code) (if_true)->code) == MEM) && MEM_P (if_false)(((enum rtx_code) (if_false)->code) == MEM)) | |||
3836 | if_true = force_reg (mode, if_true); | |||
3837 | tmp = gen_rtx_fmt_ee (code, mode, if_true, if_false)gen_rtx_fmt_ee_stat ((code), (mode), (if_true), (if_false) ); | |||
3838 | } | |||
3839 | ||||
3840 | emit_insn (gen_rtx_SET (dest, tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((tmp)) )); | |||
3841 | return true; | |||
3842 | } | |||
3843 | ||||
3844 | /* Return true if MODE is valid for vector compare to mask register, | |||
3845 | Same result for conditionl vector move with mask register. */ | |||
3846 | static bool | |||
3847 | ix86_valid_mask_cmp_mode (machine_mode mode) | |||
3848 | { | |||
3849 | /* XOP has its own vector conditional movement. */ | |||
3850 | if (TARGET_XOP((global_options.x_ix86_isa_flags & (1UL << 59)) != 0) && !TARGET_AVX512F((global_options.x_ix86_isa_flags & (1UL << 15)) != 0)) | |||
3851 | return false; | |||
3852 | ||||
3853 | /* HFmode only supports vcmpsh whose dest is mask register. */ | |||
3854 | if (TARGET_AVX512FP16((global_options.x_ix86_isa_flags2 & (1UL << 7)) != 0) && mode == HFmode(scalar_float_mode ((scalar_float_mode::from_int) E_HFmode))) | |||
3855 | return true; | |||
3856 | ||||
3857 | /* AVX512F is needed for mask operation. */ | |||
3858 | if (!(TARGET_AVX512F((global_options.x_ix86_isa_flags & (1UL << 15)) != 0) && VECTOR_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_VECTOR_BOOL || ( (enum mode_class) mode_class[mode]) == MODE_VECTOR_INT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_UACCUM))) | |||
3859 | return false; | |||
3860 | ||||
3861 | /* AVX512BW is needed for vector QI/HImode, | |||
3862 | AVX512VL is needed for 128/256-bit vector. */ | |||
3863 | machine_mode inner_mode = GET_MODE_INNER (mode)(mode_to_inner (mode)); | |||
3864 | int vector_size = GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]); | |||
3865 | if ((inner_mode == QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode)) || inner_mode == HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode))) && !TARGET_AVX512BW((global_options.x_ix86_isa_flags & (1UL << 11)) != 0)) | |||
3866 | return false; | |||
3867 | ||||
3868 | return vector_size == 64 || TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0); | |||
3869 | } | |||
3870 | ||||
3871 | /* Return true if integer mask comparison should be used. */ | |||
3872 | static bool | |||
3873 | ix86_use_mask_cmp_p (machine_mode mode, machine_mode cmp_mode, | |||
3874 | rtx op_true, rtx op_false) | |||
3875 | { | |||
3876 | int vector_size = GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]); | |||
3877 | ||||
3878 | if (cmp_mode == HFmode(scalar_float_mode ((scalar_float_mode::from_int) E_HFmode))) | |||
3879 | return true; | |||
3880 | else if (vector_size < 16) | |||
3881 | return false; | |||
3882 | else if (vector_size == 64) | |||
3883 | return true; | |||
3884 | else if (GET_MODE_INNER (cmp_mode)(mode_to_inner (cmp_mode)) == HFmode(scalar_float_mode ((scalar_float_mode::from_int) E_HFmode))) | |||
3885 | return true; | |||
3886 | ||||
3887 | /* When op_true is NULL, op_false must be NULL, or vice versa. */ | |||
3888 | gcc_assert (!op_true == !op_false)((void)(!(!op_true == !op_false) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 3888, __FUNCTION__), 0 : 0)); | |||
3889 | ||||
3890 | /* When op_true/op_false is NULL or cmp_mode is not valid mask cmp mode, | |||
3891 | vector dest is required. */ | |||
3892 | if (!op_true || !ix86_valid_mask_cmp_mode (cmp_mode)) | |||
3893 | return false; | |||
3894 | ||||
3895 | /* Exclude those that could be optimized in ix86_expand_sse_movcc. */ | |||
3896 | if (op_false == CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)]) | |||
3897 | || op_true == CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)]) | |||
3898 | || (INTEGRAL_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_INT || ((enum mode_class ) mode_class[mode]) == MODE_PARTIAL_INT || ((enum mode_class) mode_class[mode]) == MODE_COMPLEX_INT || ((enum mode_class) mode_class [mode]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[ mode]) == MODE_VECTOR_INT) | |||
3899 | && (op_true == CONSTM1_RTX (mode)(const_tiny_rtx[3][(int) (mode)]) | |||
3900 | || op_false == CONSTM1_RTX (mode)(const_tiny_rtx[3][(int) (mode)])))) | |||
3901 | return false; | |||
3902 | ||||
3903 | return true; | |||
3904 | } | |||
3905 | ||||
3906 | /* Expand an SSE comparison. Return the register with the result. */ | |||
3907 | ||||
3908 | static rtx | |||
3909 | ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1, | |||
3910 | rtx op_true, rtx op_false) | |||
3911 | { | |||
3912 | machine_mode mode = GET_MODE (dest)((machine_mode) (dest)->mode); | |||
3913 | machine_mode cmp_ops_mode = GET_MODE (cmp_op0)((machine_mode) (cmp_op0)->mode); | |||
3914 | ||||
3915 | /* In general case result of comparison can differ from operands' type. */ | |||
3916 | machine_mode cmp_mode; | |||
3917 | ||||
3918 | /* In AVX512F the result of comparison is an integer mask. */ | |||
3919 | bool maskcmp = false; | |||
3920 | rtx x; | |||
3921 | ||||
3922 | if (ix86_use_mask_cmp_p (mode, cmp_ops_mode, op_true, op_false)) | |||
3923 | { | |||
3924 | unsigned int nbits = GET_MODE_NUNITS (cmp_ops_mode)(mode_to_nunits (cmp_ops_mode).coeffs[0]); | |||
3925 | maskcmp = true; | |||
3926 | cmp_mode = nbits > 8 ? int_mode_for_size (nbits, 0).require () : E_QImode; | |||
3927 | } | |||
3928 | else | |||
3929 | cmp_mode = cmp_ops_mode; | |||
3930 | ||||
3931 | cmp_op0 = force_reg (cmp_ops_mode, cmp_op0); | |||
3932 | ||||
3933 | bool (*op1_predicate)(rtx, machine_mode) | |||
3934 | = VECTOR_MODE_P (cmp_ops_mode)(((enum mode_class) mode_class[cmp_ops_mode]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[cmp_ops_mode]) == MODE_VECTOR_INT || ((enum mode_class) mode_class[cmp_ops_mode]) == MODE_VECTOR_FLOAT || ((enum mode_class) mode_class[cmp_ops_mode]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[cmp_ops_mode]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[cmp_ops_mode]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[cmp_ops_mode]) == MODE_VECTOR_UACCUM ) ? vector_operand : nonimmediate_operand; | |||
3935 | ||||
3936 | if (!op1_predicate (cmp_op1, cmp_ops_mode)) | |||
3937 | cmp_op1 = force_reg (cmp_ops_mode, cmp_op1); | |||
3938 | ||||
3939 | if (optimizeglobal_options.x_optimize | |||
3940 | || (maskcmp && cmp_mode != mode) | |||
3941 | || (op_true && reg_overlap_mentioned_p (dest, op_true)) | |||
3942 | || (op_false && reg_overlap_mentioned_p (dest, op_false))) | |||
3943 | dest = gen_reg_rtx (maskcmp ? cmp_mode : mode); | |||
3944 | ||||
3945 | if (maskcmp) | |||
3946 | { | |||
3947 | bool ok = ix86_expand_mask_vec_cmp (dest, code, cmp_op0, cmp_op1); | |||
3948 | gcc_assert (ok)((void)(!(ok) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 3948, __FUNCTION__), 0 : 0)); | |||
3949 | return dest; | |||
3950 | } | |||
3951 | ||||
3952 | x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1)gen_rtx_fmt_ee_stat ((code), (cmp_mode), (cmp_op0), (cmp_op1) ); | |||
3953 | ||||
3954 | if (cmp_mode != mode) | |||
3955 | { | |||
3956 | x = force_reg (cmp_ops_mode, x); | |||
3957 | convert_move (dest, x, false); | |||
3958 | } | |||
3959 | else | |||
3960 | emit_insn (gen_rtx_SET (dest, x)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((x)) )); | |||
3961 | ||||
3962 | return dest; | |||
3963 | } | |||
3964 | ||||
3965 | /* Emit x86 binary operand CODE in mode MODE for SSE vector | |||
3966 | instructions that can be performed using GP registers. */ | |||
3967 | ||||
3968 | static void | |||
3969 | ix86_emit_vec_binop (enum rtx_code code, machine_mode mode, | |||
3970 | rtx dst, rtx src1, rtx src2) | |||
3971 | { | |||
3972 | rtx tmp; | |||
3973 | ||||
3974 | tmp = gen_rtx_SET (dst, gen_rtx_fmt_ee (code, mode, src1, src2))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dst)) , ((gen_rtx_fmt_ee_stat ((code), (mode), (src1), (src2) ))) ); | |||
3975 | ||||
3976 | if (GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) <= GET_MODE_SIZE (SImode)((unsigned short) mode_to_bytes ((scalar_int_mode ((scalar_int_mode ::from_int) E_SImode))).coeffs[0]) | |||
3977 | && GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_VECTOR_INT) | |||
3978 | { | |||
3979 | rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG))gen_rtx_fmt_e_stat ((CLOBBER), ((((void) 0, E_VOIDmode))), (( gen_rtx_REG (((void) 0, E_CCmode), 17))) ); | |||
3980 | tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, tmp, clob))) ); | |||
3981 | } | |||
3982 | ||||
3983 | emit_insn (tmp); | |||
3984 | } | |||
3985 | ||||
3986 | /* Expand DEST = CMP ? OP_TRUE : OP_FALSE into a sequence of logical | |||
3987 | operations. This is used for both scalar and vector conditional moves. */ | |||
3988 | ||||
3989 | void | |||
3990 | ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false) | |||
3991 | { | |||
3992 | machine_mode mode = GET_MODE (dest)((machine_mode) (dest)->mode); | |||
3993 | machine_mode cmpmode = GET_MODE (cmp)((machine_mode) (cmp)->mode); | |||
3994 | rtx x; | |||
3995 | ||||
3996 | /* Simplify trivial VEC_COND_EXPR to avoid ICE in pr97506. */ | |||
3997 | if (rtx_equal_p (op_true, op_false)) | |||
3998 | { | |||
3999 | emit_move_insn (dest, op_true); | |||
4000 | return; | |||
4001 | } | |||
4002 | ||||
4003 | /* If we have an integer mask and FP value then we need | |||
4004 | to cast mask to FP mode. */ | |||
4005 | if (mode != cmpmode && VECTOR_MODE_P (cmpmode)(((enum mode_class) mode_class[cmpmode]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[cmpmode]) == MODE_VECTOR_INT || ((enum mode_class) mode_class[cmpmode]) == MODE_VECTOR_FLOAT || ((enum mode_class) mode_class[cmpmode]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[cmpmode]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[cmpmode]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[cmpmode]) == MODE_VECTOR_UACCUM )) | |||
4006 | { | |||
4007 | cmp = force_reg (cmpmode, cmp); | |||
4008 | cmp = gen_rtx_SUBREG (mode, cmp, 0); | |||
4009 | } | |||
4010 | ||||
4011 | /* In AVX512F the result of comparison is an integer mask. */ | |||
4012 | if (mode != cmpmode | |||
4013 | && GET_MODE_CLASS (cmpmode)((enum mode_class) mode_class[cmpmode]) == MODE_INT) | |||
4014 | { | |||
4015 | gcc_assert (ix86_valid_mask_cmp_mode (mode))((void)(!(ix86_valid_mask_cmp_mode (mode)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 4015, __FUNCTION__), 0 : 0)); | |||
4016 | /* Using scalar/vector move with mask register. */ | |||
4017 | cmp = force_reg (cmpmode, cmp); | |||
4018 | /* Optimize for mask zero. */ | |||
4019 | op_true = (op_true != CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)]) | |||
4020 | ? force_reg (mode, op_true) : op_true); | |||
4021 | op_false = (op_false != CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)]) | |||
4022 | ? force_reg (mode, op_false) : op_false); | |||
4023 | if (op_true == CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)])) | |||
4024 | { | |||
4025 | if (cmpmode == E_DImode && !TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 )) | |||
4026 | { | |||
4027 | x = gen_reg_rtx (cmpmode); | |||
4028 | emit_insn (gen_knotdi (x, cmp)); | |||
4029 | } | |||
4030 | else | |||
4031 | x = expand_simple_unop (cmpmode, NOT, cmp, NULL__null, 1); | |||
4032 | cmp = x; | |||
4033 | /* Reverse op_true op_false. */ | |||
4034 | std::swap (op_true, op_false); | |||
4035 | } | |||
4036 | ||||
4037 | if (mode == HFmode(scalar_float_mode ((scalar_float_mode::from_int) E_HFmode))) | |||
4038 | emit_insn (gen_movhf_mask (dest, op_true, op_false, cmp)); | |||
4039 | else | |||
4040 | emit_insn (gen_rtx_SET (dest,gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((gen_rtx_fmt_eee_stat ((VEC_MERGE), ((mode)), ((op_true)) , ((op_false)), ((cmp)) ))) ) | |||
4041 | gen_rtx_VEC_MERGE (mode,gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((gen_rtx_fmt_eee_stat ((VEC_MERGE), ((mode)), ((op_true)) , ((op_false)), ((cmp)) ))) ) | |||
4042 | op_true, op_false, cmp))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((gen_rtx_fmt_eee_stat ((VEC_MERGE), ((mode)), ((op_true)) , ((op_false)), ((cmp)) ))) )); | |||
4043 | return; | |||
4044 | } | |||
4045 | ||||
4046 | if (vector_all_ones_operand (op_true, mode) | |||
4047 | && op_false == CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)])) | |||
4048 | { | |||
4049 | emit_move_insn (dest, cmp); | |||
4050 | return; | |||
4051 | } | |||
4052 | else if (op_false == CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)])) | |||
4053 | { | |||
4054 | x = expand_simple_binop (mode, AND, cmp, op_true, | |||
4055 | dest, 1, OPTAB_DIRECT); | |||
4056 | if (x != dest) | |||
4057 | emit_move_insn (dest, x); | |||
4058 | return; | |||
4059 | } | |||
4060 | else if (op_true == CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)])) | |||
4061 | { | |||
4062 | op_false = force_reg (mode, op_false); | |||
4063 | x = gen_rtx_NOT (mode, cmp)gen_rtx_fmt_e_stat ((NOT), ((mode)), ((cmp)) ); | |||
4064 | ix86_emit_vec_binop (AND, mode, dest, x, op_false); | |||
4065 | return; | |||
4066 | } | |||
4067 | else if (vector_all_ones_operand (op_true, mode)) | |||
4068 | { | |||
4069 | x = expand_simple_binop (mode, IOR, cmp, op_false, | |||
4070 | dest, 1, OPTAB_DIRECT); | |||
4071 | if (x != dest) | |||
4072 | emit_move_insn (dest, x); | |||
4073 | return; | |||
4074 | } | |||
4075 | ||||
4076 | if (TARGET_XOP((global_options.x_ix86_isa_flags & (1UL << 59)) != 0)) | |||
4077 | { | |||
4078 | op_true = force_reg (mode, op_true); | |||
4079 | ||||
4080 | if (GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) < 16 | |||
4081 | || !nonimmediate_operand (op_false, mode)) | |||
4082 | op_false = force_reg (mode, op_false); | |||
4083 | ||||
4084 | emit_insn (gen_rtx_SET (dest,gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((mode)), ((cmp)), ((op_true)), ((op_false)) ))) ) | |||
4085 | gen_rtx_IF_THEN_ELSE (mode, cmp,gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((mode)), ((cmp)), ((op_true)), ((op_false)) ))) ) | |||
4086 | op_true, op_false))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((mode)), ((cmp)), ((op_true)), ((op_false)) ))) )); | |||
4087 | return; | |||
4088 | } | |||
4089 | ||||
4090 | rtx (*gen) (rtx, rtx, rtx, rtx) = NULL__null; | |||
4091 | machine_mode blend_mode = mode; | |||
4092 | ||||
4093 | if (GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) < 16 | |||
4094 | || !vector_operand (op_true, mode)) | |||
4095 | op_true = force_reg (mode, op_true); | |||
4096 | ||||
4097 | op_false = force_reg (mode, op_false); | |||
4098 | ||||
4099 | switch (mode) | |||
4100 | { | |||
4101 | case E_V2SFmode: | |||
4102 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4103 | gen = gen_mmx_blendvps; | |||
4104 | break; | |||
4105 | case E_V4SFmode: | |||
4106 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4107 | gen = gen_sse4_1_blendvps; | |||
4108 | break; | |||
4109 | case E_V2DFmode: | |||
4110 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4111 | gen = gen_sse4_1_blendvpd; | |||
4112 | break; | |||
4113 | case E_SFmode: | |||
4114 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4115 | gen = gen_sse4_1_blendvss; | |||
4116 | break; | |||
4117 | case E_DFmode: | |||
4118 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4119 | gen = gen_sse4_1_blendvsd; | |||
4120 | break; | |||
4121 | case E_V8QImode: | |||
4122 | case E_V4HImode: | |||
4123 | case E_V2SImode: | |||
4124 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4125 | { | |||
4126 | gen = gen_mmx_pblendvb_v8qi; | |||
4127 | blend_mode = V8QImode((void) 0, E_V8QImode); | |||
4128 | } | |||
4129 | break; | |||
4130 | case E_V4QImode: | |||
4131 | case E_V2HImode: | |||
4132 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4133 | { | |||
4134 | gen = gen_mmx_pblendvb_v4qi; | |||
4135 | blend_mode = V4QImode((void) 0, E_V4QImode); | |||
4136 | } | |||
4137 | break; | |||
4138 | case E_V2QImode: | |||
4139 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4140 | gen = gen_mmx_pblendvb_v2qi; | |||
4141 | break; | |||
4142 | case E_V16QImode: | |||
4143 | case E_V8HImode: | |||
4144 | case E_V8HFmode: | |||
4145 | case E_V8BFmode: | |||
4146 | case E_V4SImode: | |||
4147 | case E_V2DImode: | |||
4148 | case E_V1TImode: | |||
4149 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4150 | { | |||
4151 | gen = gen_sse4_1_pblendvb; | |||
4152 | blend_mode = V16QImode((void) 0, E_V16QImode); | |||
4153 | } | |||
4154 | break; | |||
4155 | case E_V8SFmode: | |||
4156 | if (TARGET_AVX((global_options.x_ix86_isa_flags & (1UL << 8)) != 0 )) | |||
4157 | gen = gen_avx_blendvps256; | |||
4158 | break; | |||
4159 | case E_V4DFmode: | |||
4160 | if (TARGET_AVX((global_options.x_ix86_isa_flags & (1UL << 8)) != 0 )) | |||
4161 | gen = gen_avx_blendvpd256; | |||
4162 | break; | |||
4163 | case E_V32QImode: | |||
4164 | case E_V16HImode: | |||
4165 | case E_V16HFmode: | |||
4166 | case E_V16BFmode: | |||
4167 | case E_V8SImode: | |||
4168 | case E_V4DImode: | |||
4169 | if (TARGET_AVX2((global_options.x_ix86_isa_flags & (1UL << 9)) != 0 )) | |||
4170 | { | |||
4171 | gen = gen_avx2_pblendvb; | |||
4172 | blend_mode = V32QImode((void) 0, E_V32QImode); | |||
4173 | } | |||
4174 | break; | |||
4175 | ||||
4176 | case E_V64QImode: | |||
4177 | gen = gen_avx512bw_blendmv64qi; | |||
4178 | break; | |||
4179 | case E_V32HImode: | |||
4180 | gen = gen_avx512bw_blendmv32hi; | |||
4181 | break; | |||
4182 | case E_V32HFmode: | |||
4183 | gen = gen_avx512bw_blendmv32hf; | |||
4184 | break; | |||
4185 | case E_V32BFmode: | |||
4186 | gen = gen_avx512bw_blendmv32bf; | |||
4187 | break; | |||
4188 | case E_V16SImode: | |||
4189 | gen = gen_avx512f_blendmv16si; | |||
4190 | break; | |||
4191 | case E_V8DImode: | |||
4192 | gen = gen_avx512f_blendmv8di; | |||
4193 | break; | |||
4194 | case E_V8DFmode: | |||
4195 | gen = gen_avx512f_blendmv8df; | |||
4196 | break; | |||
4197 | case E_V16SFmode: | |||
4198 | gen = gen_avx512f_blendmv16sf; | |||
4199 | break; | |||
4200 | ||||
4201 | default: | |||
4202 | break; | |||
4203 | } | |||
4204 | ||||
4205 | if (gen != NULL__null) | |||
4206 | { | |||
4207 | if (blend_mode == mode) | |||
4208 | x = dest; | |||
4209 | else | |||
4210 | { | |||
4211 | x = gen_reg_rtx (blend_mode); | |||
4212 | op_false = gen_lowpartrtl_hooks.gen_lowpart (blend_mode, op_false); | |||
4213 | op_true = gen_lowpartrtl_hooks.gen_lowpart (blend_mode, op_true); | |||
4214 | cmp = gen_lowpartrtl_hooks.gen_lowpart (blend_mode, cmp); | |||
4215 | } | |||
4216 | ||||
4217 | emit_insn (gen (x, op_false, op_true, cmp)); | |||
4218 | ||||
4219 | if (x != dest) | |||
4220 | emit_move_insn (dest, gen_lowpartrtl_hooks.gen_lowpart (mode, x)); | |||
4221 | } | |||
4222 | else | |||
4223 | { | |||
4224 | rtx t2, t3; | |||
4225 | ||||
4226 | t2 = expand_simple_binop (mode, AND, op_true, cmp, | |||
4227 | NULL__null, 1, OPTAB_DIRECT); | |||
4228 | ||||
4229 | t3 = gen_reg_rtx (mode); | |||
4230 | x = gen_rtx_NOT (mode, cmp)gen_rtx_fmt_e_stat ((NOT), ((mode)), ((cmp)) ); | |||
4231 | ix86_emit_vec_binop (AND, mode, t3, x, op_false); | |||
4232 | ||||
4233 | x = expand_simple_binop (mode, IOR, t3, t2, | |||
4234 | dest, 1, OPTAB_DIRECT); | |||
4235 | if (x != dest) | |||
4236 | emit_move_insn (dest, x); | |||
4237 | } | |||
4238 | } | |||
4239 | ||||
4240 | /* Swap, force into registers, or otherwise massage the two operands | |||
4241 | to an sse comparison with a mask result. Thus we differ a bit from | |||
4242 | ix86_prepare_fp_compare_args which expects to produce a flags result. | |||
4243 | ||||
4244 | The DEST operand exists to help determine whether to commute commutative | |||
4245 | operators. The POP0/POP1 operands are updated in place. The new | |||
4246 | comparison code is returned, or UNKNOWN if not implementable. */ | |||
4247 | ||||
4248 | static enum rtx_code | |||
4249 | ix86_prepare_sse_fp_compare_args (rtx dest, enum rtx_code code, | |||
4250 | rtx *pop0, rtx *pop1) | |||
4251 | { | |||
4252 | switch (code) | |||
4253 | { | |||
4254 | case LTGT: | |||
4255 | case UNEQ: | |||
4256 | /* AVX supports all the needed comparisons. */ | |||
4257 | if (TARGET_AVX((global_options.x_ix86_isa_flags & (1UL << 8)) != 0 )) | |||
4258 | break; | |||
4259 | /* We have no LTGT as an operator. We could implement it with | |||
4260 | NE & ORDERED, but this requires an extra temporary. It's | |||
4261 | not clear that it's worth it. */ | |||
4262 | return UNKNOWN; | |||
4263 | ||||
4264 | case LT: | |||
4265 | case LE: | |||
4266 | case UNGT: | |||
4267 | case UNGE: | |||
4268 | /* These are supported directly. */ | |||
4269 | break; | |||
4270 | ||||
4271 | case EQ: | |||
4272 | case NE: | |||
4273 | case UNORDERED: | |||
4274 | case ORDERED: | |||
4275 | /* AVX has 3 operand comparisons, no need to swap anything. */ | |||
4276 | if (TARGET_AVX((global_options.x_ix86_isa_flags & (1UL << 8)) != 0 )) | |||
4277 | break; | |||
4278 | /* For commutative operators, try to canonicalize the destination | |||
4279 | operand to be first in the comparison - this helps reload to | |||
4280 | avoid extra moves. */ | |||
4281 | if (!dest || !rtx_equal_p (dest, *pop1)) | |||
4282 | break; | |||
4283 | /* FALLTHRU */ | |||
4284 | ||||
4285 | case GE: | |||
4286 | case GT: | |||
4287 | case UNLE: | |||
4288 | case UNLT: | |||
4289 | /* These are not supported directly before AVX, and furthermore | |||
4290 | ix86_expand_sse_fp_minmax only optimizes LT/UNGE. Swap the | |||
4291 | comparison operands to transform into something that is | |||
4292 | supported. */ | |||
4293 | std::swap (*pop0, *pop1); | |||
4294 | code = swap_condition (code); | |||
4295 | break; | |||
4296 | ||||
4297 | default: | |||
4298 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 4298, __FUNCTION__)); | |||
4299 | } | |||
4300 | ||||
4301 | return code; | |||
4302 | } | |||
4303 | ||||
4304 | /* Expand a floating-point conditional move. Return true if successful. */ | |||
4305 | ||||
4306 | bool | |||
4307 | ix86_expand_fp_movcc (rtx operands[]) | |||
4308 | { | |||
4309 | machine_mode mode = GET_MODE (operands[0])((machine_mode) (operands[0])->mode); | |||
4310 | enum rtx_code code = GET_CODE (operands[1])((enum rtx_code) (operands[1])->code); | |||
4311 | rtx tmp, compare_op; | |||
4312 | rtx op0 = XEXP (operands[1], 0)(((operands[1])->u.fld[0]).rt_rtx); | |||
4313 | rtx op1 = XEXP (operands[1], 1)(((operands[1])->u.fld[1]).rt_rtx); | |||
4314 | ||||
4315 | if (GET_MODE (op0)((machine_mode) (op0)->mode) == BFmode(scalar_float_mode ((scalar_float_mode::from_int) E_BFmode)) | |||
4316 | && !ix86_fp_comparison_operator (operands[1], VOIDmode((void) 0, E_VOIDmode))) | |||
4317 | return false; | |||
4318 | ||||
4319 | if (SSE_FLOAT_MODE_SSEMATH_OR_HF_P (mode)((((((global_options.x_ix86_isa_flags & (1UL << 50) ) != 0) && (mode) == (scalar_float_mode ((scalar_float_mode ::from_int) E_SFmode))) || (((global_options.x_ix86_isa_flags & (1UL << 51)) != 0) && (mode) == (scalar_float_mode ((scalar_float_mode::from_int) E_DFmode)))) && ((global_options .x_ix86_fpmath & FPMATH_SSE) != 0)) || (((global_options. x_ix86_isa_flags2 & (1UL << 7)) != 0) && (mode ) == (scalar_float_mode ((scalar_float_mode::from_int) E_HFmode ))))) | |||
4320 | { | |||
4321 | machine_mode cmode; | |||
4322 | ||||
4323 | /* Since we've no cmove for sse registers, don't force bad register | |||
4324 | allocation just to gain access to it. Deny movcc when the | |||
4325 | comparison mode doesn't match the move mode. */ | |||
4326 | cmode = GET_MODE (op0)((machine_mode) (op0)->mode); | |||
4327 | if (cmode == VOIDmode((void) 0, E_VOIDmode)) | |||
4328 | cmode = GET_MODE (op1)((machine_mode) (op1)->mode); | |||
4329 | if (cmode != mode) | |||
4330 | return false; | |||
4331 | ||||
4332 | code = ix86_prepare_sse_fp_compare_args (operands[0], code, &op0, &op1); | |||
4333 | if (code == UNKNOWN) | |||
4334 | return false; | |||
4335 | ||||
4336 | if (ix86_expand_sse_fp_minmax (operands[0], code, op0, op1, | |||
4337 | operands[2], operands[3])) | |||
4338 | return true; | |||
4339 | ||||
4340 | tmp = ix86_expand_sse_cmp (operands[0], code, op0, op1, | |||
4341 | operands[2], operands[3]); | |||
4342 | ix86_expand_sse_movcc (operands[0], tmp, operands[2], operands[3]); | |||
4343 | return true; | |||
4344 | } | |||
4345 | ||||
4346 | if (GET_MODE (op0)((machine_mode) (op0)->mode) == TImode(scalar_int_mode ((scalar_int_mode::from_int) E_TImode)) | |||
4347 | || (GET_MODE (op0)((machine_mode) (op0)->mode) == DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)) | |||
4348 | && !TARGET_64BIT((global_options.x_ix86_isa_flags & (1UL << 1)) != 0 ))) | |||
4349 | return false; | |||
4350 | ||||
4351 | /* The floating point conditional move instructions don't directly | |||
4352 | support conditions resulting from a signed integer comparison. */ | |||
4353 | ||||
4354 | compare_op = ix86_expand_compare (code, op0, op1); | |||
4355 | if (!fcmov_comparison_operator (compare_op, VOIDmode((void) 0, E_VOIDmode))) | |||
4356 | { | |||
4357 | tmp = gen_reg_rtx (QImode(scalar_int_mode ((scalar_int_mode::from_int) E_QImode))); | |||
4358 | ix86_expand_setcc (tmp, code, op0, op1); | |||
4359 | ||||
4360 | compare_op = ix86_expand_compare (NE, tmp, const0_rtx(const_int_rtx[64])); | |||
4361 | } | |||
4362 | ||||
4363 | emit_insn (gen_rtx_SET (operands[0],gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((operands [0])), ((gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((mode)), ((compare_op )), ((operands[2])), ((operands[3])) ))) ) | |||
4364 | gen_rtx_IF_THEN_ELSE (mode, compare_op,gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((operands [0])), ((gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((mode)), ((compare_op )), ((operands[2])), ((operands[3])) ))) ) | |||
4365 | operands[2], operands[3]))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((operands [0])), ((gen_rtx_fmt_eee_stat ((IF_THEN_ELSE), ((mode)), ((compare_op )), ((operands[2])), ((operands[3])) ))) )); | |||
4366 | ||||
4367 | return true; | |||
4368 | } | |||
4369 | ||||
4370 | /* Helper for ix86_cmp_code_to_pcmp_immediate for int modes. */ | |||
4371 | ||||
4372 | static int | |||
4373 | ix86_int_cmp_code_to_pcmp_immediate (enum rtx_code code) | |||
4374 | { | |||
4375 | switch (code) | |||
4376 | { | |||
4377 | case EQ: | |||
4378 | return 0; | |||
4379 | case LT: | |||
4380 | case LTU: | |||
4381 | return 1; | |||
4382 | case LE: | |||
4383 | case LEU: | |||
4384 | return 2; | |||
4385 | case NE: | |||
4386 | return 4; | |||
4387 | case GE: | |||
4388 | case GEU: | |||
4389 | return 5; | |||
4390 | case GT: | |||
4391 | case GTU: | |||
4392 | return 6; | |||
4393 | default: | |||
4394 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 4394, __FUNCTION__)); | |||
4395 | } | |||
4396 | } | |||
4397 | ||||
4398 | /* Helper for ix86_cmp_code_to_pcmp_immediate for fp modes. */ | |||
4399 | ||||
4400 | static int | |||
4401 | ix86_fp_cmp_code_to_pcmp_immediate (enum rtx_code code) | |||
4402 | { | |||
4403 | switch (code) | |||
4404 | { | |||
4405 | case EQ: | |||
4406 | return 0x00; | |||
4407 | case NE: | |||
4408 | return 0x04; | |||
4409 | case GT: | |||
4410 | return 0x0e; | |||
4411 | case LE: | |||
4412 | return 0x02; | |||
4413 | case GE: | |||
4414 | return 0x0d; | |||
4415 | case LT: | |||
4416 | return 0x01; | |||
4417 | case UNLE: | |||
4418 | return 0x0a; | |||
4419 | case UNLT: | |||
4420 | return 0x09; | |||
4421 | case UNGE: | |||
4422 | return 0x05; | |||
4423 | case UNGT: | |||
4424 | return 0x06; | |||
4425 | case UNEQ: | |||
4426 | return 0x18; | |||
4427 | case LTGT: | |||
4428 | return 0x0c; | |||
4429 | case ORDERED: | |||
4430 | return 0x07; | |||
4431 | case UNORDERED: | |||
4432 | return 0x03; | |||
4433 | default: | |||
4434 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 4434, __FUNCTION__)); | |||
4435 | } | |||
4436 | } | |||
4437 | ||||
4438 | /* Return immediate value to be used in UNSPEC_PCMP | |||
4439 | for comparison CODE in MODE. */ | |||
4440 | ||||
4441 | static int | |||
4442 | ix86_cmp_code_to_pcmp_immediate (enum rtx_code code, machine_mode mode) | |||
4443 | { | |||
4444 | if (FLOAT_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_DECIMAL_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_COMPLEX_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FLOAT)) | |||
4445 | return ix86_fp_cmp_code_to_pcmp_immediate (code); | |||
4446 | return ix86_int_cmp_code_to_pcmp_immediate (code); | |||
4447 | } | |||
4448 | ||||
4449 | /* Expand AVX-512 vector comparison. */ | |||
4450 | ||||
4451 | bool | |||
4452 | ix86_expand_mask_vec_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1) | |||
4453 | { | |||
4454 | machine_mode mask_mode = GET_MODE (dest)((machine_mode) (dest)->mode); | |||
4455 | machine_mode cmp_mode = GET_MODE (cmp_op0)((machine_mode) (cmp_op0)->mode); | |||
4456 | rtx imm = GEN_INT (ix86_cmp_code_to_pcmp_immediate (code, cmp_mode))gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (ix86_cmp_code_to_pcmp_immediate (code, cmp_mode))); | |||
4457 | int unspec_code; | |||
4458 | rtx unspec; | |||
4459 | ||||
4460 | switch (code) | |||
4461 | { | |||
4462 | case LEU: | |||
4463 | case GTU: | |||
4464 | case GEU: | |||
4465 | case LTU: | |||
4466 | unspec_code = UNSPEC_UNSIGNED_PCMP; | |||
4467 | break; | |||
4468 | ||||
4469 | default: | |||
4470 | unspec_code = UNSPEC_PCMP; | |||
4471 | } | |||
4472 | ||||
4473 | unspec = gen_rtx_UNSPEC (mask_mode, gen_rtvec (3, cmp_op0, cmp_op1, imm),gen_rtx_fmt_Ei_stat ((UNSPEC), ((mask_mode)), ((gen_rtvec (3, cmp_op0, cmp_op1, imm))), ((unspec_code)) ) | |||
4474 | unspec_code)gen_rtx_fmt_Ei_stat ((UNSPEC), ((mask_mode)), ((gen_rtvec (3, cmp_op0, cmp_op1, imm))), ((unspec_code)) ); | |||
4475 | emit_insn (gen_rtx_SET (dest, unspec)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((dest) ), ((unspec)) )); | |||
4476 | ||||
4477 | return true; | |||
4478 | } | |||
4479 | ||||
4480 | /* Expand fp vector comparison. */ | |||
4481 | ||||
4482 | bool | |||
4483 | ix86_expand_fp_vec_cmp (rtx operands[]) | |||
4484 | { | |||
4485 | enum rtx_code code = GET_CODE (operands[1])((enum rtx_code) (operands[1])->code); | |||
4486 | rtx cmp; | |||
4487 | ||||
4488 | code = ix86_prepare_sse_fp_compare_args (operands[0], code, | |||
4489 | &operands[2], &operands[3]); | |||
4490 | if (code == UNKNOWN) | |||
4491 | { | |||
4492 | rtx temp; | |||
4493 | switch (GET_CODE (operands[1])((enum rtx_code) (operands[1])->code)) | |||
4494 | { | |||
4495 | case LTGT: | |||
4496 | temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[2], | |||
4497 | operands[3], NULL__null, NULL__null); | |||
4498 | cmp = ix86_expand_sse_cmp (operands[0], NE, operands[2], | |||
4499 | operands[3], NULL__null, NULL__null); | |||
4500 | code = AND; | |||
4501 | break; | |||
4502 | case UNEQ: | |||
4503 | temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[2], | |||
4504 | operands[3], NULL__null, NULL__null); | |||
4505 | cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[2], | |||
4506 | operands[3], NULL__null, NULL__null); | |||
4507 | code = IOR; | |||
4508 | break; | |||
4509 | default: | |||
4510 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 4510, __FUNCTION__)); | |||
4511 | } | |||
4512 | cmp = expand_simple_binop (GET_MODE (cmp)((machine_mode) (cmp)->mode), code, temp, cmp, cmp, 1, | |||
4513 | OPTAB_DIRECT); | |||
4514 | } | |||
4515 | else | |||
4516 | cmp = ix86_expand_sse_cmp (operands[0], code, operands[2], operands[3], | |||
4517 | NULL__null, NULL__null); | |||
4518 | ||||
4519 | if (operands[0] != cmp) | |||
4520 | emit_move_insn (operands[0], cmp); | |||
4521 | ||||
4522 | return true; | |||
4523 | } | |||
4524 | ||||
4525 | static rtx | |||
4526 | ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1, | |||
4527 | rtx op_true, rtx op_false, bool *negate) | |||
4528 | { | |||
4529 | machine_mode data_mode = GET_MODE (dest)((machine_mode) (dest)->mode); | |||
4530 | machine_mode mode = GET_MODE (cop0)((machine_mode) (cop0)->mode); | |||
4531 | rtx x; | |||
4532 | ||||
4533 | *negate = false; | |||
4534 | ||||
4535 | /* XOP supports all of the comparisons on all 128-bit vector int types. */ | |||
4536 | if (TARGET_XOP((global_options.x_ix86_isa_flags & (1UL << 59)) != 0) | |||
4537 | && GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_VECTOR_INT | |||
4538 | && GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) <= 16) | |||
4539 | ; | |||
4540 | /* AVX512F supports all of the comparsions | |||
4541 | on all 128/256/512-bit vector int types. */ | |||
4542 | else if (ix86_use_mask_cmp_p (data_mode, mode, op_true, op_false)) | |||
4543 | ; | |||
4544 | else | |||
4545 | { | |||
4546 | /* Canonicalize the comparison to EQ, GT, GTU. */ | |||
4547 | switch (code) | |||
4548 | { | |||
4549 | case EQ: | |||
4550 | case GT: | |||
4551 | case GTU: | |||
4552 | break; | |||
4553 | ||||
4554 | case LE: | |||
4555 | case LEU: | |||
4556 | /* x <= cst can be handled as x < cst + 1 unless there is | |||
4557 | wrap around in cst + 1. */ | |||
4558 | if (GET_CODE (cop1)((enum rtx_code) (cop1)->code) == CONST_VECTOR | |||
4559 | && GET_MODE_INNER (mode)(mode_to_inner (mode)) != TImode(scalar_int_mode ((scalar_int_mode::from_int) E_TImode))) | |||
4560 | { | |||
4561 | unsigned int n_elts = GET_MODE_NUNITS (mode)(mode_to_nunits (mode).coeffs[0]), i; | |||
4562 | machine_mode eltmode = GET_MODE_INNER (mode)(mode_to_inner (mode)); | |||
4563 | for (i = 0; i < n_elts; ++i) | |||
4564 | { | |||
4565 | rtx elt = CONST_VECTOR_ELT (cop1, i)const_vector_elt (cop1, i); | |||
4566 | if (!CONST_INT_P (elt)(((enum rtx_code) (elt)->code) == CONST_INT)) | |||
4567 | break; | |||
4568 | if (code == GE) | |||
4569 | { | |||
4570 | /* For LE punt if some element is signed maximum. */ | |||
4571 | if ((INTVAL (elt)((elt)->u.hwint[0]) & (GET_MODE_MASK (eltmode)mode_mask_array[eltmode] >> 1)) | |||
4572 | == (GET_MODE_MASK (eltmode)mode_mask_array[eltmode] >> 1)) | |||
4573 | break; | |||
4574 | } | |||
4575 | /* For LEU punt if some element is unsigned maximum. */ | |||
4576 | else if (elt == constm1_rtx(const_int_rtx[64 -1])) | |||
4577 | break; | |||
4578 | } | |||
4579 | if (i == n_elts) | |||
4580 | { | |||
4581 | rtvec v = rtvec_alloc (n_elts); | |||
4582 | for (i = 0; i < n_elts; ++i) | |||
4583 | RTVEC_ELT (v, i)((v)->elem[i]) | |||
4584 | = gen_int_mode (INTVAL (CONST_VECTOR_ELT (cop1, i))((const_vector_elt (cop1, i))->u.hwint[0]) + 1, | |||
4585 | eltmode); | |||
4586 | cop1 = gen_rtx_CONST_VECTOR (mode, v); | |||
4587 | std::swap (cop0, cop1); | |||
4588 | code = code == LE ? GT : GTU; | |||
4589 | break; | |||
4590 | } | |||
4591 | } | |||
4592 | /* FALLTHRU */ | |||
4593 | case NE: | |||
4594 | code = reverse_condition (code); | |||
4595 | *negate = true; | |||
4596 | break; | |||
4597 | ||||
4598 | case GE: | |||
4599 | case GEU: | |||
4600 | /* x >= cst can be handled as x > cst - 1 unless there is | |||
4601 | wrap around in cst - 1. */ | |||
4602 | if (GET_CODE (cop1)((enum rtx_code) (cop1)->code) == CONST_VECTOR | |||
4603 | && GET_MODE_INNER (mode)(mode_to_inner (mode)) != TImode(scalar_int_mode ((scalar_int_mode::from_int) E_TImode))) | |||
4604 | { | |||
4605 | unsigned int n_elts = GET_MODE_NUNITS (mode)(mode_to_nunits (mode).coeffs[0]), i; | |||
4606 | machine_mode eltmode = GET_MODE_INNER (mode)(mode_to_inner (mode)); | |||
4607 | for (i = 0; i < n_elts; ++i) | |||
4608 | { | |||
4609 | rtx elt = CONST_VECTOR_ELT (cop1, i)const_vector_elt (cop1, i); | |||
4610 | if (!CONST_INT_P (elt)(((enum rtx_code) (elt)->code) == CONST_INT)) | |||
4611 | break; | |||
4612 | if (code == GE) | |||
4613 | { | |||
4614 | /* For GE punt if some element is signed minimum. */ | |||
4615 | if (INTVAL (elt)((elt)->u.hwint[0]) < 0 | |||
4616 | && ((INTVAL (elt)((elt)->u.hwint[0]) & (GET_MODE_MASK (eltmode)mode_mask_array[eltmode] >> 1)) | |||
4617 | == 0)) | |||
4618 | break; | |||
4619 | } | |||
4620 | /* For GEU punt if some element is zero. */ | |||
4621 | else if (elt == const0_rtx(const_int_rtx[64])) | |||
4622 | break; | |||
4623 | } | |||
4624 | if (i == n_elts) | |||
4625 | { | |||
4626 | rtvec v = rtvec_alloc (n_elts); | |||
4627 | for (i = 0; i < n_elts; ++i) | |||
4628 | RTVEC_ELT (v, i)((v)->elem[i]) | |||
4629 | = gen_int_mode (INTVAL (CONST_VECTOR_ELT (cop1, i))((const_vector_elt (cop1, i))->u.hwint[0]) - 1, | |||
4630 | eltmode); | |||
4631 | cop1 = gen_rtx_CONST_VECTOR (mode, v); | |||
4632 | code = code == GE ? GT : GTU; | |||
4633 | break; | |||
4634 | } | |||
4635 | } | |||
4636 | code = reverse_condition (code); | |||
4637 | *negate = true; | |||
4638 | /* FALLTHRU */ | |||
4639 | ||||
4640 | case LT: | |||
4641 | case LTU: | |||
4642 | std::swap (cop0, cop1); | |||
4643 | code = swap_condition (code); | |||
4644 | break; | |||
4645 | ||||
4646 | default: | |||
4647 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 4647, __FUNCTION__)); | |||
4648 | } | |||
4649 | ||||
4650 | /* Only SSE4.1/SSE4.2 supports V2DImode. */ | |||
4651 | if (mode == V2DImode((void) 0, E_V2DImode)) | |||
4652 | { | |||
4653 | switch (code) | |||
4654 | { | |||
4655 | case EQ: | |||
4656 | /* SSE4.1 supports EQ. */ | |||
4657 | if (!TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4658 | return NULL__null; | |||
4659 | break; | |||
4660 | ||||
4661 | case GT: | |||
4662 | case GTU: | |||
4663 | /* SSE4.2 supports GT/GTU. */ | |||
4664 | if (!TARGET_SSE4_2((global_options.x_ix86_isa_flags & (1UL << 53)) != 0)) | |||
4665 | return NULL__null; | |||
4666 | break; | |||
4667 | ||||
4668 | default: | |||
4669 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 4669, __FUNCTION__)); | |||
4670 | } | |||
4671 | } | |||
4672 | ||||
4673 | if (GET_CODE (cop0)((enum rtx_code) (cop0)->code) == CONST_VECTOR) | |||
4674 | cop0 = force_reg (mode, cop0); | |||
4675 | else if (GET_CODE (cop1)((enum rtx_code) (cop1)->code) == CONST_VECTOR) | |||
4676 | cop1 = force_reg (mode, cop1); | |||
4677 | ||||
4678 | rtx optrue = op_true ? op_true : CONSTM1_RTX (data_mode)(const_tiny_rtx[3][(int) (data_mode)]); | |||
4679 | rtx opfalse = op_false ? op_false : CONST0_RTX (data_mode)(const_tiny_rtx[0][(int) (data_mode)]); | |||
4680 | if (*negate) | |||
4681 | std::swap (optrue, opfalse); | |||
4682 | ||||
4683 | /* Transform x > y ? 0 : -1 (i.e. x <= y ? -1 : 0 or x <= y) when | |||
4684 | not using integer masks into min (x, y) == x ? -1 : 0 (i.e. | |||
4685 | min (x, y) == x). While we add one instruction (the minimum), | |||
4686 | we remove the need for two instructions in the negation, as the | |||
4687 | result is done this way. | |||
4688 | When using masks, do it for SI/DImode element types, as it is shorter | |||
4689 | than the two subtractions. */ | |||
4690 | if ((code != EQ | |||
4691 | && GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) != 64 | |||
4692 | && vector_all_ones_operand (opfalse, data_mode) | |||
4693 | && optrue == CONST0_RTX (data_mode)(const_tiny_rtx[0][(int) (data_mode)])) | |||
4694 | || (code == GTU | |||
4695 | && GET_MODE_SIZE (GET_MODE_INNER (mode))((unsigned short) mode_to_bytes ((mode_to_inner (mode))).coeffs [0]) >= 4 | |||
4696 | /* Don't do it if not using integer masks and we'd end up with | |||
4697 | the right values in the registers though. */ | |||
4698 | && (GET_MODE_SIZE (mode)((unsigned short) mode_to_bytes (mode).coeffs[0]) == 64 | |||
4699 | || !vector_all_ones_operand (optrue, data_mode) | |||
4700 | || opfalse != CONST0_RTX (data_mode)(const_tiny_rtx[0][(int) (data_mode)])))) | |||
4701 | { | |||
4702 | rtx (*gen) (rtx, rtx, rtx) = NULL__null; | |||
4703 | ||||
4704 | switch (mode) | |||
4705 | { | |||
4706 | case E_V16SImode: | |||
4707 | gen = (code == GTU) ? gen_uminv16si3 : gen_sminv16si3; | |||
4708 | break; | |||
4709 | case E_V8DImode: | |||
4710 | gen = (code == GTU) ? gen_uminv8di3 : gen_sminv8di3; | |||
4711 | cop0 = force_reg (mode, cop0); | |||
4712 | cop1 = force_reg (mode, cop1); | |||
4713 | break; | |||
4714 | case E_V32QImode: | |||
4715 | if (TARGET_AVX2((global_options.x_ix86_isa_flags & (1UL << 9)) != 0 )) | |||
4716 | gen = (code == GTU) ? gen_uminv32qi3 : gen_sminv32qi3; | |||
4717 | break; | |||
4718 | case E_V16HImode: | |||
4719 | if (TARGET_AVX2((global_options.x_ix86_isa_flags & (1UL << 9)) != 0 )) | |||
4720 | gen = (code == GTU) ? gen_uminv16hi3 : gen_sminv16hi3; | |||
4721 | break; | |||
4722 | case E_V8SImode: | |||
4723 | if (TARGET_AVX2((global_options.x_ix86_isa_flags & (1UL << 9)) != 0 )) | |||
4724 | gen = (code == GTU) ? gen_uminv8si3 : gen_sminv8si3; | |||
4725 | break; | |||
4726 | case E_V4DImode: | |||
4727 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0)) | |||
4728 | { | |||
4729 | gen = (code == GTU) ? gen_uminv4di3 : gen_sminv4di3; | |||
4730 | cop0 = force_reg (mode, cop0); | |||
4731 | cop1 = force_reg (mode, cop1); | |||
4732 | } | |||
4733 | break; | |||
4734 | case E_V16QImode: | |||
4735 | if (code == GTU && TARGET_SSE2((global_options.x_ix86_isa_flags & (1UL << 51)) != 0)) | |||
4736 | gen = gen_uminv16qi3; | |||
4737 | else if (code == GT && TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4738 | gen = gen_sminv16qi3; | |||
4739 | break; | |||
4740 | case E_V8QImode: | |||
4741 | if (code == GTU && TARGET_SSE2((global_options.x_ix86_isa_flags & (1UL << 51)) != 0)) | |||
4742 | gen = gen_uminv8qi3; | |||
4743 | else if (code == GT && TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4744 | gen = gen_sminv8qi3; | |||
4745 | break; | |||
4746 | case E_V4QImode: | |||
4747 | if (code == GTU && TARGET_SSE2((global_options.x_ix86_isa_flags & (1UL << 51)) != 0)) | |||
4748 | gen = gen_uminv4qi3; | |||
4749 | else if (code == GT && TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4750 | gen = gen_sminv4qi3; | |||
4751 | break; | |||
4752 | case E_V2QImode: | |||
4753 | if (code == GTU && TARGET_SSE2((global_options.x_ix86_isa_flags & (1UL << 51)) != 0)) | |||
4754 | gen = gen_uminv2qi3; | |||
4755 | else if (code == GT && TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4756 | gen = gen_sminv2qi3; | |||
4757 | break; | |||
4758 | case E_V8HImode: | |||
4759 | if (code == GTU && TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4760 | gen = gen_uminv8hi3; | |||
4761 | else if (code == GT && TARGET_SSE2((global_options.x_ix86_isa_flags & (1UL << 51)) != 0)) | |||
4762 | gen = gen_sminv8hi3; | |||
4763 | break; | |||
4764 | case E_V4HImode: | |||
4765 | if (code == GTU && TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4766 | gen = gen_uminv4hi3; | |||
4767 | else if (code == GT && TARGET_SSE2((global_options.x_ix86_isa_flags & (1UL << 51)) != 0)) | |||
4768 | gen = gen_sminv4hi3; | |||
4769 | break; | |||
4770 | case E_V2HImode: | |||
4771 | if (code == GTU && TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4772 | gen = gen_uminv2hi3; | |||
4773 | else if (code == GT && TARGET_SSE2((global_options.x_ix86_isa_flags & (1UL << 51)) != 0)) | |||
4774 | gen = gen_sminv2hi3; | |||
4775 | break; | |||
4776 | case E_V4SImode: | |||
4777 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4778 | gen = (code == GTU) ? gen_uminv4si3 : gen_sminv4si3; | |||
4779 | break; | |||
4780 | case E_V2SImode: | |||
4781 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
4782 | gen = (code == GTU) ? gen_uminv2si3 : gen_sminv2si3; | |||
4783 | break; | |||
4784 | case E_V2DImode: | |||
4785 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0)) | |||
4786 | { | |||
4787 | gen = (code == GTU) ? gen_uminv2di3 : gen_sminv2di3; | |||
4788 | cop0 = force_reg (mode, cop0); | |||
4789 | cop1 = force_reg (mode, cop1); | |||
4790 | } | |||
4791 | break; | |||
4792 | default: | |||
4793 | break; | |||
4794 | } | |||
4795 | ||||
4796 | if (gen) | |||
4797 | { | |||
4798 | rtx tem = gen_reg_rtx (mode); | |||
4799 | if (!vector_operand (cop0, mode)) | |||
4800 | cop0 = force_reg (mode, cop0); | |||
4801 | if (!vector_operand (cop1, mode)) | |||
4802 | cop1 = force_reg (mode, cop1); | |||
4803 | *negate = !*negate; | |||
4804 | emit_insn (gen (tem, cop0, cop1)); | |||
4805 | cop1 = tem; | |||
4806 | code = EQ; | |||
4807 | } | |||
4808 | } | |||
4809 | ||||
4810 | /* Unsigned parallel compare is not supported by the hardware. | |||
4811 | Play some tricks to turn this into a signed comparison | |||
4812 | against 0. */ | |||
4813 | if (code == GTU) | |||
4814 | { | |||
4815 | cop0 = force_reg (mode, cop0); | |||
4816 | ||||
4817 | switch (mode) | |||
4818 | { | |||
4819 | case E_V16SImode: | |||
4820 | case E_V8DImode: | |||
4821 | case E_V8SImode: | |||
4822 | case E_V4DImode: | |||
4823 | case E_V4SImode: | |||
4824 | case E_V2SImode: | |||
4825 | case E_V2DImode: | |||
4826 | { | |||
4827 | rtx t1, t2, mask; | |||
4828 | ||||
4829 | /* Subtract (-(INT MAX) - 1) from both operands to make | |||
4830 | them signed. */ | |||
4831 | mask = ix86_build_signbit_mask (mode, true, false); | |||
4832 | t1 = gen_reg_rtx (mode); | |||
4833 | emit_insn (gen_sub3_insn (t1, cop0, mask)); | |||
4834 | ||||
4835 | t2 = gen_reg_rtx (mode); | |||
4836 | emit_insn (gen_sub3_insn (t2, cop1, mask)); | |||
4837 | ||||
4838 | cop0 = t1; | |||
4839 | cop1 = t2; | |||
4840 | code = GT; | |||
4841 | } | |||
4842 | break; | |||
4843 | ||||
4844 | case E_V64QImode: | |||
4845 | case E_V32HImode: | |||
4846 | case E_V32QImode: | |||
4847 | case E_V16HImode: | |||
4848 | case E_V16QImode: | |||
4849 | case E_V8QImode: | |||
4850 | case E_V4QImode: | |||
4851 | case E_V2QImode: | |||
4852 | case E_V8HImode: | |||
4853 | case E_V4HImode: | |||
4854 | case E_V2HImode: | |||
4855 | /* Perform a parallel unsigned saturating subtraction. */ | |||
4856 | x = gen_reg_rtx (mode); | |||
4857 | emit_insn (gen_rtx_SETgen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((x)), ( (gen_rtx_fmt_ee_stat ((US_MINUS), ((mode)), ((cop0)), ((cop1) ) ))) ) | |||
4858 | (x, gen_rtx_US_MINUS (mode, cop0, cop1))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((x)), ( (gen_rtx_fmt_ee_stat ((US_MINUS), ((mode)), ((cop0)), ((cop1) ) ))) )); | |||
4859 | cop0 = x; | |||
4860 | cop1 = CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)]); | |||
4861 | code = EQ; | |||
4862 | *negate = !*negate; | |||
4863 | break; | |||
4864 | ||||
4865 | default: | |||
4866 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 4866, __FUNCTION__)); | |||
4867 | } | |||
4868 | } | |||
4869 | } | |||
4870 | ||||
4871 | if (*negate) | |||
4872 | std::swap (op_true, op_false); | |||
4873 | ||||
4874 | if (GET_CODE (cop1)((enum rtx_code) (cop1)->code) == CONST_VECTOR) | |||
4875 | cop1 = force_reg (mode, cop1); | |||
4876 | ||||
4877 | /* Allow the comparison to be done in one mode, but the movcc to | |||
4878 | happen in another mode. */ | |||
4879 | if (data_mode == mode) | |||
4880 | x = ix86_expand_sse_cmp (dest, code, cop0, cop1, op_true, op_false); | |||
4881 | else | |||
4882 | { | |||
4883 | gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode))((void)(!(((unsigned short) mode_to_bytes (data_mode).coeffs[ 0]) == ((unsigned short) mode_to_bytes (mode).coeffs[0])) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 4883, __FUNCTION__), 0 : 0)); | |||
4884 | x = ix86_expand_sse_cmp (gen_reg_rtx (mode), code, cop0, cop1, | |||
4885 | op_true, op_false); | |||
4886 | if (GET_MODE (x)((machine_mode) (x)->mode) == mode) | |||
4887 | x = gen_lowpartrtl_hooks.gen_lowpart (data_mode, x); | |||
4888 | } | |||
4889 | ||||
4890 | return x; | |||
4891 | } | |||
4892 | ||||
4893 | /* Expand integer vector comparison. */ | |||
4894 | ||||
4895 | bool | |||
4896 | ix86_expand_int_vec_cmp (rtx operands[]) | |||
4897 | { | |||
4898 | rtx_code code = GET_CODE (operands[1])((enum rtx_code) (operands[1])->code); | |||
4899 | bool negate = false; | |||
4900 | rtx cmp = ix86_expand_int_sse_cmp (operands[0], code, operands[2], | |||
4901 | operands[3], NULL__null, NULL__null, &negate); | |||
4902 | ||||
4903 | if (!cmp) | |||
4904 | return false; | |||
4905 | ||||
4906 | if (negate) | |||
4907 | cmp = ix86_expand_int_sse_cmp (operands[0], EQ, cmp, | |||
4908 | CONST0_RTX (GET_MODE (cmp))(const_tiny_rtx[0][(int) (((machine_mode) (cmp)->mode))]), | |||
4909 | NULL__null, NULL__null, &negate); | |||
4910 | ||||
4911 | gcc_assert (!negate)((void)(!(!negate) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 4911, __FUNCTION__), 0 : 0)); | |||
4912 | ||||
4913 | if (operands[0] != cmp) | |||
4914 | emit_move_insn (operands[0], cmp); | |||
4915 | ||||
4916 | return true; | |||
4917 | } | |||
4918 | ||||
4919 | /* Expand a floating-point vector conditional move; a vcond operation | |||
4920 | rather than a movcc operation. */ | |||
4921 | ||||
4922 | bool | |||
4923 | ix86_expand_fp_vcond (rtx operands[]) | |||
4924 | { | |||
4925 | enum rtx_code code = GET_CODE (operands[3])((enum rtx_code) (operands[3])->code); | |||
4926 | rtx cmp; | |||
4927 | ||||
4928 | code = ix86_prepare_sse_fp_compare_args (operands[0], code, | |||
4929 | &operands[4], &operands[5]); | |||
4930 | if (code == UNKNOWN) | |||
4931 | { | |||
4932 | rtx temp; | |||
4933 | switch (GET_CODE (operands[3])((enum rtx_code) (operands[3])->code)) | |||
4934 | { | |||
4935 | case LTGT: | |||
4936 | temp = ix86_expand_sse_cmp (operands[0], ORDERED, operands[4], | |||
4937 | operands[5], operands[0], operands[0]); | |||
4938 | cmp = ix86_expand_sse_cmp (operands[0], NE, operands[4], | |||
4939 | operands[5], operands[1], operands[2]); | |||
4940 | code = AND; | |||
4941 | break; | |||
4942 | case UNEQ: | |||
4943 | temp = ix86_expand_sse_cmp (operands[0], UNORDERED, operands[4], | |||
4944 | operands[5], operands[0], operands[0]); | |||
4945 | cmp = ix86_expand_sse_cmp (operands[0], EQ, operands[4], | |||
4946 | operands[5], operands[1], operands[2]); | |||
4947 | code = IOR; | |||
4948 | break; | |||
4949 | default: | |||
4950 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 4950, __FUNCTION__)); | |||
4951 | } | |||
4952 | cmp = expand_simple_binop (GET_MODE (cmp)((machine_mode) (cmp)->mode), code, temp, cmp, cmp, 1, | |||
4953 | OPTAB_DIRECT); | |||
4954 | ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]); | |||
4955 | return true; | |||
4956 | } | |||
4957 | ||||
4958 | if (ix86_expand_sse_fp_minmax (operands[0], code, operands[4], | |||
4959 | operands[5], operands[1], operands[2])) | |||
4960 | return true; | |||
4961 | ||||
4962 | cmp = ix86_expand_sse_cmp (operands[0], code, operands[4], operands[5], | |||
4963 | operands[1], operands[2]); | |||
4964 | ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]); | |||
4965 | return true; | |||
4966 | } | |||
4967 | ||||
4968 | /* Expand a signed/unsigned integral vector conditional move. */ | |||
4969 | ||||
4970 | bool | |||
4971 | ix86_expand_int_vcond (rtx operands[]) | |||
4972 | { | |||
4973 | machine_mode data_mode = GET_MODE (operands[0])((machine_mode) (operands[0])->mode); | |||
4974 | machine_mode mode = GET_MODE (operands[4])((machine_mode) (operands[4])->mode); | |||
4975 | enum rtx_code code = GET_CODE (operands[3])((enum rtx_code) (operands[3])->code); | |||
4976 | bool negate = false; | |||
4977 | rtx x, cop0, cop1; | |||
4978 | ||||
4979 | cop0 = operands[4]; | |||
4980 | cop1 = operands[5]; | |||
4981 | ||||
4982 | /* Try to optimize x < 0 ? -1 : 0 into (signed) x >> 31 | |||
4983 | and x < 0 ? 1 : 0 into (unsigned) x >> 31. */ | |||
4984 | if ((code == LT || code == GE) | |||
4985 | && data_mode == mode | |||
4986 | && cop1 == CONST0_RTX (mode)(const_tiny_rtx[0][(int) (mode)]) | |||
4987 | && operands[1 + (code == LT)] == CONST0_RTX (data_mode)(const_tiny_rtx[0][(int) (data_mode)]) | |||
4988 | && GET_MODE_UNIT_SIZE (data_mode)mode_to_unit_size (data_mode) > 1 | |||
4989 | && GET_MODE_UNIT_SIZE (data_mode)mode_to_unit_size (data_mode) <= 8 | |||
4990 | && (GET_MODE_SIZE (data_mode)((unsigned short) mode_to_bytes (data_mode).coeffs[0]) == 16 | |||
4991 | || (TARGET_AVX2((global_options.x_ix86_isa_flags & (1UL << 9)) != 0 ) && GET_MODE_SIZE (data_mode)((unsigned short) mode_to_bytes (data_mode).coeffs[0]) == 32))) | |||
4992 | { | |||
4993 | rtx negop = operands[2 - (code == LT)]; | |||
4994 | int shift = GET_MODE_UNIT_BITSIZE (data_mode)((unsigned short) (mode_to_unit_size (data_mode) * (8))) - 1; | |||
4995 | if (negop == CONST1_RTX (data_mode)(const_tiny_rtx[1][(int) (data_mode)])) | |||
4996 | { | |||
4997 | rtx res = expand_simple_binop (mode, LSHIFTRT, cop0, GEN_INT (shift)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (shift)), | |||
4998 | operands[0], 1, OPTAB_DIRECT); | |||
4999 | if (res != operands[0]) | |||
5000 | emit_move_insn (operands[0], res); | |||
5001 | return true; | |||
5002 | } | |||
5003 | else if (GET_MODE_INNER (data_mode)(mode_to_inner (data_mode)) != DImode(scalar_int_mode ((scalar_int_mode::from_int) E_DImode)) | |||
5004 | && vector_all_ones_operand (negop, data_mode)) | |||
5005 | { | |||
5006 | rtx res = expand_simple_binop (mode, ASHIFTRT, cop0, GEN_INT (shift)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (shift)), | |||
5007 | operands[0], 0, OPTAB_DIRECT); | |||
5008 | if (res != operands[0]) | |||
5009 | emit_move_insn (operands[0], res); | |||
5010 | return true; | |||
5011 | } | |||
5012 | } | |||
5013 | ||||
5014 | if (!nonimmediate_operand (cop1, mode)) | |||
5015 | cop1 = force_reg (mode, cop1); | |||
5016 | if (!general_operand (operands[1], data_mode)) | |||
5017 | operands[1] = force_reg (data_mode, operands[1]); | |||
5018 | if (!general_operand (operands[2], data_mode)) | |||
5019 | operands[2] = force_reg (data_mode, operands[2]); | |||
5020 | ||||
5021 | x = ix86_expand_int_sse_cmp (operands[0], code, cop0, cop1, | |||
5022 | operands[1], operands[2], &negate); | |||
5023 | ||||
5024 | if (!x) | |||
5025 | return false; | |||
5026 | ||||
5027 | ix86_expand_sse_movcc (operands[0], x, operands[1+negate], | |||
5028 | operands[2-negate]); | |||
5029 | return true; | |||
5030 | } | |||
5031 | ||||
5032 | static bool | |||
5033 | ix86_expand_vec_perm_vpermt2 (rtx target, rtx mask, rtx op0, rtx op1, | |||
5034 | struct expand_vec_perm_d *d) | |||
5035 | { | |||
5036 | /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const | |||
5037 | expander, so args are either in d, or in op0, op1 etc. */ | |||
5038 | machine_mode mode = GET_MODE (d ? d->op0 : op0)((machine_mode) (d ? d->op0 : op0)->mode); | |||
5039 | machine_mode maskmode = mode; | |||
5040 | rtx (*gen) (rtx, rtx, rtx, rtx) = NULL__null; | |||
5041 | ||||
5042 | switch (mode) | |||
5043 | { | |||
5044 | case E_V16QImode: | |||
5045 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0) && TARGET_AVX512VBMI((global_options.x_ix86_isa_flags & (1UL << 18)) != 0)) | |||
5046 | gen = gen_avx512vl_vpermt2varv16qi3; | |||
5047 | break; | |||
5048 | case E_V32QImode: | |||
5049 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0) && TARGET_AVX512VBMI((global_options.x_ix86_isa_flags & (1UL << 18)) != 0)) | |||
5050 | gen = gen_avx512vl_vpermt2varv32qi3; | |||
5051 | break; | |||
5052 | case E_V64QImode: | |||
5053 | if (TARGET_AVX512VBMI((global_options.x_ix86_isa_flags & (1UL << 18)) != 0)) | |||
5054 | gen = gen_avx512bw_vpermt2varv64qi3; | |||
5055 | break; | |||
5056 | case E_V8HImode: | |||
5057 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0) && TARGET_AVX512BW((global_options.x_ix86_isa_flags & (1UL << 11)) != 0)) | |||
5058 | gen = gen_avx512vl_vpermt2varv8hi3; | |||
5059 | break; | |||
5060 | case E_V16HImode: | |||
5061 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0) && TARGET_AVX512BW((global_options.x_ix86_isa_flags & (1UL << 11)) != 0)) | |||
5062 | gen = gen_avx512vl_vpermt2varv16hi3; | |||
5063 | break; | |||
5064 | case E_V32HImode: | |||
5065 | if (TARGET_AVX512BW((global_options.x_ix86_isa_flags & (1UL << 11)) != 0)) | |||
5066 | gen = gen_avx512bw_vpermt2varv32hi3; | |||
5067 | break; | |||
5068 | case E_V4SImode: | |||
5069 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0)) | |||
5070 | gen = gen_avx512vl_vpermt2varv4si3; | |||
5071 | break; | |||
5072 | case E_V8SImode: | |||
5073 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0)) | |||
5074 | gen = gen_avx512vl_vpermt2varv8si3; | |||
5075 | break; | |||
5076 | case E_V16SImode: | |||
5077 | if (TARGET_AVX512F((global_options.x_ix86_isa_flags & (1UL << 15)) != 0)) | |||
5078 | gen = gen_avx512f_vpermt2varv16si3; | |||
5079 | break; | |||
5080 | case E_V4SFmode: | |||
5081 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0)) | |||
5082 | { | |||
5083 | gen = gen_avx512vl_vpermt2varv4sf3; | |||
5084 | maskmode = V4SImode((void) 0, E_V4SImode); | |||
5085 | } | |||
5086 | break; | |||
5087 | case E_V8SFmode: | |||
5088 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0)) | |||
5089 | { | |||
5090 | gen = gen_avx512vl_vpermt2varv8sf3; | |||
5091 | maskmode = V8SImode((void) 0, E_V8SImode); | |||
5092 | } | |||
5093 | break; | |||
5094 | case E_V16SFmode: | |||
5095 | if (TARGET_AVX512F((global_options.x_ix86_isa_flags & (1UL << 15)) != 0)) | |||
5096 | { | |||
5097 | gen = gen_avx512f_vpermt2varv16sf3; | |||
5098 | maskmode = V16SImode((void) 0, E_V16SImode); | |||
5099 | } | |||
5100 | break; | |||
5101 | case E_V2DImode: | |||
5102 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0)) | |||
5103 | gen = gen_avx512vl_vpermt2varv2di3; | |||
5104 | break; | |||
5105 | case E_V4DImode: | |||
5106 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0)) | |||
5107 | gen = gen_avx512vl_vpermt2varv4di3; | |||
5108 | break; | |||
5109 | case E_V8DImode: | |||
5110 | if (TARGET_AVX512F((global_options.x_ix86_isa_flags & (1UL << 15)) != 0)) | |||
5111 | gen = gen_avx512f_vpermt2varv8di3; | |||
5112 | break; | |||
5113 | case E_V2DFmode: | |||
5114 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0)) | |||
5115 | { | |||
5116 | gen = gen_avx512vl_vpermt2varv2df3; | |||
5117 | maskmode = V2DImode((void) 0, E_V2DImode); | |||
5118 | } | |||
5119 | break; | |||
5120 | case E_V4DFmode: | |||
5121 | if (TARGET_AVX512VL((global_options.x_ix86_isa_flags & (1UL << 20)) != 0)) | |||
5122 | { | |||
5123 | gen = gen_avx512vl_vpermt2varv4df3; | |||
5124 | maskmode = V4DImode((void) 0, E_V4DImode); | |||
5125 | } | |||
5126 | break; | |||
5127 | case E_V8DFmode: | |||
5128 | if (TARGET_AVX512F((global_options.x_ix86_isa_flags & (1UL << 15)) != 0)) | |||
5129 | { | |||
5130 | gen = gen_avx512f_vpermt2varv8df3; | |||
5131 | maskmode = V8DImode((void) 0, E_V8DImode); | |||
5132 | } | |||
5133 | break; | |||
5134 | default: | |||
5135 | break; | |||
5136 | } | |||
5137 | ||||
5138 | if (gen == NULL__null) | |||
5139 | return false; | |||
5140 | ||||
5141 | /* ix86_expand_vec_perm_vpermt2 is called from both const and non-const | |||
5142 | expander, so args are either in d, or in op0, op1 etc. */ | |||
5143 | if (d) | |||
5144 | { | |||
5145 | rtx vec[64]; | |||
5146 | target = d->target; | |||
5147 | op0 = d->op0; | |||
5148 | op1 = d->op1; | |||
5149 | for (int i = 0; i < d->nelt; ++i) | |||
5150 | vec[i] = GEN_INT (d->perm[i])gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (d->perm[i])); | |||
5151 | mask = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (d->nelt, vec)); | |||
5152 | } | |||
5153 | ||||
5154 | emit_insn (gen (target, force_reg (maskmode, mask), op0, op1)); | |||
5155 | return true; | |||
5156 | } | |||
5157 | ||||
5158 | /* Expand a variable vector permutation. */ | |||
5159 | ||||
5160 | void | |||
5161 | ix86_expand_vec_perm (rtx operands[]) | |||
5162 | { | |||
5163 | rtx target = operands[0]; | |||
5164 | rtx op0 = operands[1]; | |||
5165 | rtx op1 = operands[2]; | |||
5166 | rtx mask = operands[3]; | |||
5167 | rtx t1, t2, t3, t4, t5, t6, t7, t8, vt, vt2, vec[32]; | |||
5168 | machine_mode mode = GET_MODE (op0)((machine_mode) (op0)->mode); | |||
5169 | machine_mode maskmode = GET_MODE (mask)((machine_mode) (mask)->mode); | |||
5170 | int w, e, i; | |||
5171 | bool one_operand_shuffle = rtx_equal_p (op0, op1); | |||
5172 | ||||
5173 | /* Number of elements in the vector. */ | |||
5174 | w = GET_MODE_NUNITS (mode)(mode_to_nunits (mode).coeffs[0]); | |||
5175 | e = GET_MODE_UNIT_SIZE (mode)mode_to_unit_size (mode); | |||
5176 | gcc_assert (w <= 64)((void)(!(w <= 64) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 5176, __FUNCTION__), 0 : 0)); | |||
5177 | ||||
5178 | /* For HF mode vector, convert it to HI using subreg. */ | |||
5179 | if (GET_MODE_INNER (mode)(mode_to_inner (mode)) == HFmode(scalar_float_mode ((scalar_float_mode::from_int) E_HFmode))) | |||
5180 | { | |||
5181 | machine_mode orig_mode = mode; | |||
5182 | mode = mode_for_vector (HImode(scalar_int_mode ((scalar_int_mode::from_int) E_HImode)), w).require (); | |||
5183 | target = lowpart_subreg (mode, target, orig_mode); | |||
5184 | op0 = lowpart_subreg (mode, op0, orig_mode); | |||
5185 | op1 = lowpart_subreg (mode, op1, orig_mode); | |||
5186 | } | |||
5187 | ||||
5188 | if (TARGET_AVX512F((global_options.x_ix86_isa_flags & (1UL << 15)) != 0) && one_operand_shuffle) | |||
5189 | { | |||
5190 | rtx (*gen) (rtx, rtx, rtx) = NULL__null; | |||
5191 | switch (mode) | |||
5192 | { | |||
5193 | case E_V16SImode: | |||
5194 | gen =gen_avx512f_permvarv16si; | |||
5195 | break; | |||
5196 | case E_V16SFmode: | |||
5197 | gen = gen_avx512f_permvarv16sf; | |||
5198 | break; | |||
5199 | case E_V8DImode: | |||
5200 | gen = gen_avx512f_permvarv8di; | |||
5201 | break; | |||
5202 | case E_V8DFmode: | |||
5203 | gen = gen_avx512f_permvarv8df; | |||
5204 | break; | |||
5205 | default: | |||
5206 | break; | |||
5207 | } | |||
5208 | if (gen != NULL__null) | |||
5209 | { | |||
5210 | emit_insn (gen (target, op0, mask)); | |||
5211 | return; | |||
5212 | } | |||
5213 | } | |||
5214 | ||||
5215 | if (ix86_expand_vec_perm_vpermt2 (target, mask, op0, op1, NULL__null)) | |||
5216 | return; | |||
5217 | ||||
5218 | if (TARGET_AVX2((global_options.x_ix86_isa_flags & (1UL << 9)) != 0 )) | |||
5219 | { | |||
5220 | if (mode == V4DImode((void) 0, E_V4DImode) || mode == V4DFmode((void) 0, E_V4DFmode) || mode == V16HImode((void) 0, E_V16HImode)) | |||
5221 | { | |||
5222 | /* Unfortunately, the VPERMQ and VPERMPD instructions only support | |||
5223 | an constant shuffle operand. With a tiny bit of effort we can | |||
5224 | use VPERMD instead. A re-interpretation stall for V4DFmode is | |||
5225 | unfortunate but there's no avoiding it. | |||
5226 | Similarly for V16HImode we don't have instructions for variable | |||
5227 | shuffling, while for V32QImode we can use after preparing suitable | |||
5228 | masks vpshufb; vpshufb; vpermq; vpor. */ | |||
5229 | ||||
5230 | if (mode == V16HImode((void) 0, E_V16HImode)) | |||
5231 | { | |||
5232 | maskmode = mode = V32QImode((void) 0, E_V32QImode); | |||
5233 | w = 32; | |||
5234 | e = 1; | |||
5235 | } | |||
5236 | else | |||
5237 | { | |||
5238 | maskmode = mode = V8SImode((void) 0, E_V8SImode); | |||
5239 | w = 8; | |||
5240 | e = 4; | |||
5241 | } | |||
5242 | t1 = gen_reg_rtx (maskmode); | |||
5243 | ||||
5244 | /* Replicate the low bits of the V4DImode mask into V8SImode: | |||
5245 | mask = { A B C D } | |||
5246 | t1 = { A A B B C C D D }. */ | |||
5247 | for (i = 0; i < w / 2; ++i) | |||
5248 | vec[i*2 + 1] = vec[i*2] = GEN_INT (i * 2)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (i * 2)); | |||
5249 | vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec)); | |||
5250 | vt = force_reg (maskmode, vt); | |||
5251 | mask = gen_lowpartrtl_hooks.gen_lowpart (maskmode, mask); | |||
5252 | if (maskmode == V8SImode((void) 0, E_V8SImode)) | |||
5253 | emit_insn (gen_avx2_permvarv8si (t1, mask, vt)); | |||
5254 | else | |||
5255 | emit_insn (gen_avx2_pshufbv32qi3 (t1, mask, vt)); | |||
5256 | ||||
5257 | /* Multiply the shuffle indicies by two. */ | |||
5258 | t1 = expand_simple_binop (maskmode, PLUS, t1, t1, t1, 1, | |||
5259 | OPTAB_DIRECT); | |||
5260 | ||||
5261 | /* Add one to the odd shuffle indicies: | |||
5262 | t1 = { A*2, A*2+1, B*2, B*2+1, ... }. */ | |||
5263 | for (i = 0; i < w / 2; ++i) | |||
5264 | { | |||
5265 | vec[i * 2] = const0_rtx(const_int_rtx[64]); | |||
5266 | vec[i * 2 + 1] = const1_rtx(const_int_rtx[64 +1]); | |||
5267 | } | |||
5268 | vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec)); | |||
5269 | vt = validize_mem (force_const_mem (maskmode, vt)); | |||
5270 | t1 = expand_simple_binop (maskmode, PLUS, t1, vt, t1, 1, | |||
5271 | OPTAB_DIRECT); | |||
5272 | ||||
5273 | /* Continue as if V8SImode (resp. V32QImode) was used initially. */ | |||
5274 | operands[3] = mask = t1; | |||
5275 | target = gen_reg_rtx (mode); | |||
5276 | op0 = gen_lowpartrtl_hooks.gen_lowpart (mode, op0); | |||
5277 | op1 = gen_lowpartrtl_hooks.gen_lowpart (mode, op1); | |||
5278 | } | |||
5279 | ||||
5280 | switch (mode) | |||
5281 | { | |||
5282 | case E_V8SImode: | |||
5283 | /* The VPERMD and VPERMPS instructions already properly ignore | |||
5284 | the high bits of the shuffle elements. No need for us to | |||
5285 | perform an AND ourselves. */ | |||
5286 | if (one_operand_shuffle) | |||
5287 | { | |||
5288 | emit_insn (gen_avx2_permvarv8si (target, op0, mask)); | |||
5289 | if (target != operands[0]) | |||
5290 | emit_move_insn (operands[0], | |||
5291 | gen_lowpartrtl_hooks.gen_lowpart (GET_MODE (operands[0])((machine_mode) (operands[0])->mode), target)); | |||
5292 | } | |||
5293 | else | |||
5294 | { | |||
5295 | t1 = gen_reg_rtx (V8SImode((void) 0, E_V8SImode)); | |||
5296 | t2 = gen_reg_rtx (V8SImode((void) 0, E_V8SImode)); | |||
5297 | emit_insn (gen_avx2_permvarv8si (t1, op0, mask)); | |||
5298 | emit_insn (gen_avx2_permvarv8si (t2, op1, mask)); | |||
5299 | goto merge_two; | |||
5300 | } | |||
5301 | return; | |||
5302 | ||||
5303 | case E_V8SFmode: | |||
5304 | mask = gen_lowpartrtl_hooks.gen_lowpart (V8SImode((void) 0, E_V8SImode), mask); | |||
5305 | if (one_operand_shuffle) | |||
5306 | emit_insn (gen_avx2_permvarv8sf (target, op0, mask)); | |||
5307 | else | |||
5308 | { | |||
5309 | t1 = gen_reg_rtx (V8SFmode((void) 0, E_V8SFmode)); | |||
5310 | t2 = gen_reg_rtx (V8SFmode((void) 0, E_V8SFmode)); | |||
5311 | emit_insn (gen_avx2_permvarv8sf (t1, op0, mask)); | |||
5312 | emit_insn (gen_avx2_permvarv8sf (t2, op1, mask)); | |||
5313 | goto merge_two; | |||
5314 | } | |||
5315 | return; | |||
5316 | ||||
5317 | case E_V4SImode: | |||
5318 | /* By combining the two 128-bit input vectors into one 256-bit | |||
5319 | input vector, we can use VPERMD and VPERMPS for the full | |||
5320 | two-operand shuffle. */ | |||
5321 | t1 = gen_reg_rtx (V8SImode((void) 0, E_V8SImode)); | |||
5322 | t2 = gen_reg_rtx (V8SImode((void) 0, E_V8SImode)); | |||
5323 | emit_insn (gen_avx_vec_concatv8si (t1, op0, op1)); | |||
5324 | emit_insn (gen_avx_vec_concatv8si (t2, mask, mask)); | |||
5325 | emit_insn (gen_avx2_permvarv8si (t1, t1, t2)); | |||
5326 | emit_insn (gen_avx_vextractf128v8si (target, t1, const0_rtx(const_int_rtx[64]))); | |||
5327 | return; | |||
5328 | ||||
5329 | case E_V4SFmode: | |||
5330 | t1 = gen_reg_rtx (V8SFmode((void) 0, E_V8SFmode)); | |||
5331 | t2 = gen_reg_rtx (V8SImode((void) 0, E_V8SImode)); | |||
5332 | mask = gen_lowpartrtl_hooks.gen_lowpart (V4SImode((void) 0, E_V4SImode), mask); | |||
5333 | emit_insn (gen_avx_vec_concatv8sf (t1, op0, op1)); | |||
5334 | emit_insn (gen_avx_vec_concatv8si (t2, mask, mask)); | |||
5335 | emit_insn (gen_avx2_permvarv8sf (t1, t1, t2)); | |||
5336 | emit_insn (gen_avx_vextractf128v8sf (target, t1, const0_rtx(const_int_rtx[64]))); | |||
5337 | return; | |||
5338 | ||||
5339 | case E_V32QImode: | |||
5340 | t1 = gen_reg_rtx (V32QImode((void) 0, E_V32QImode)); | |||
5341 | t2 = gen_reg_rtx (V32QImode((void) 0, E_V32QImode)); | |||
5342 | t3 = gen_reg_rtx (V32QImode((void) 0, E_V32QImode)); | |||
5343 | vt2 = GEN_INT (-128)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (-128)); | |||
5344 | vt = gen_const_vec_duplicate (V32QImode((void) 0, E_V32QImode), vt2); | |||
5345 | vt = force_reg (V32QImode((void) 0, E_V32QImode), vt); | |||
5346 | for (i = 0; i < 32; i++) | |||
5347 | vec[i] = i < 16 ? vt2 : const0_rtx(const_int_rtx[64]); | |||
5348 | vt2 = gen_rtx_CONST_VECTOR (V32QImode((void) 0, E_V32QImode), gen_rtvec_v (32, vec)); | |||
5349 | vt2 = force_reg (V32QImode((void) 0, E_V32QImode), vt2); | |||
5350 | /* From mask create two adjusted masks, which contain the same | |||
5351 | bits as mask in the low 7 bits of each vector element. | |||
5352 | The first mask will have the most significant bit clear | |||
5353 | if it requests element from the same 128-bit lane | |||
5354 | and MSB set if it requests element from the other 128-bit lane. | |||
5355 | The second mask will have the opposite values of the MSB, | |||
5356 | and additionally will have its 128-bit lanes swapped. | |||
5357 | E.g. { 07 12 1e 09 ... | 17 19 05 1f ... } mask vector will have | |||
5358 | t1 { 07 92 9e 09 ... | 17 19 85 1f ... } and | |||
5359 | t3 { 97 99 05 9f ... | 87 12 1e 89 ... } where each ... | |||
5360 | stands for other 12 bytes. */ | |||
5361 | /* The bit whether element is from the same lane or the other | |||
5362 | lane is bit 4, so shift it up by 3 to the MSB position. */ | |||
5363 | t5 = gen_reg_rtx (V4DImode((void) 0, E_V4DImode)); | |||
5364 | emit_insn (gen_ashlv4di3 (t5, gen_lowpartrtl_hooks.gen_lowpart (V4DImode((void) 0, E_V4DImode), mask), | |||
5365 | GEN_INT (3)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)))); | |||
5366 | /* Clear MSB bits from the mask just in case it had them set. */ | |||
5367 | emit_insn (gen_avx2_andnotv32qi3 (t2, vt, mask)); | |||
5368 | /* After this t1 will have MSB set for elements from other lane. */ | |||
5369 | emit_insn (gen_xorv32qi3 (t1, gen_lowpartrtl_hooks.gen_lowpart (V32QImode((void) 0, E_V32QImode), t5), vt2)); | |||
5370 | /* Clear bits other than MSB. */ | |||
5371 | emit_insn (gen_andv32qi3 (t1, t1, vt)); | |||
5372 | /* Or in the lower bits from mask into t3. */ | |||
5373 | emit_insn (gen_iorv32qi3 (t3, t1, t2)); | |||
5374 | /* And invert MSB bits in t1, so MSB is set for elements from the same | |||
5375 | lane. */ | |||
5376 | emit_insn (gen_xorv32qi3 (t1, t1, vt)); | |||
5377 | /* Swap 128-bit lanes in t3. */ | |||
5378 | t6 = gen_reg_rtx (V4DImode((void) 0, E_V4DImode)); | |||
5379 | emit_insn (gen_avx2_permv4di_1 (t6, gen_lowpartrtl_hooks.gen_lowpart (V4DImode((void) 0, E_V4DImode), t3), | |||
5380 | const2_rtx(const_int_rtx[64 +2]), GEN_INT (3)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), | |||
5381 | const0_rtx(const_int_rtx[64]), const1_rtx(const_int_rtx[64 +1]))); | |||
5382 | /* And or in the lower bits from mask into t1. */ | |||
5383 | emit_insn (gen_iorv32qi3 (t1, t1, t2)); | |||
5384 | if (one_operand_shuffle) | |||
5385 | { | |||
5386 | /* Each of these shuffles will put 0s in places where | |||
5387 | element from the other 128-bit lane is needed, otherwise | |||
5388 | will shuffle in the requested value. */ | |||
5389 | emit_insn (gen_avx2_pshufbv32qi3 (t3, op0, | |||
5390 | gen_lowpartrtl_hooks.gen_lowpart (V32QImode((void) 0, E_V32QImode), t6))); | |||
5391 | emit_insn (gen_avx2_pshufbv32qi3 (t1, op0, t1)); | |||
5392 | /* For t3 the 128-bit lanes are swapped again. */ | |||
5393 | t7 = gen_reg_rtx (V4DImode((void) 0, E_V4DImode)); | |||
5394 | emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpartrtl_hooks.gen_lowpart (V4DImode((void) 0, E_V4DImode), t3), | |||
5395 | const2_rtx(const_int_rtx[64 +2]), GEN_INT (3)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), | |||
5396 | const0_rtx(const_int_rtx[64]), const1_rtx(const_int_rtx[64 +1]))); | |||
5397 | /* And oring both together leads to the result. */ | |||
5398 | emit_insn (gen_iorv32qi3 (target, t1, | |||
5399 | gen_lowpartrtl_hooks.gen_lowpart (V32QImode((void) 0, E_V32QImode), t7))); | |||
5400 | if (target != operands[0]) | |||
5401 | emit_move_insn (operands[0], | |||
5402 | gen_lowpartrtl_hooks.gen_lowpart (GET_MODE (operands[0])((machine_mode) (operands[0])->mode), target)); | |||
5403 | return; | |||
5404 | } | |||
5405 | ||||
5406 | t4 = gen_reg_rtx (V32QImode((void) 0, E_V32QImode)); | |||
5407 | /* Similarly to the above one_operand_shuffle code, | |||
5408 | just for repeated twice for each operand. merge_two: | |||
5409 | code will merge the two results together. */ | |||
5410 | emit_insn (gen_avx2_pshufbv32qi3 (t4, op0, | |||
5411 | gen_lowpartrtl_hooks.gen_lowpart (V32QImode((void) 0, E_V32QImode), t6))); | |||
5412 | emit_insn (gen_avx2_pshufbv32qi3 (t3, op1, | |||
5413 | gen_lowpartrtl_hooks.gen_lowpart (V32QImode((void) 0, E_V32QImode), t6))); | |||
5414 | emit_insn (gen_avx2_pshufbv32qi3 (t2, op0, t1)); | |||
5415 | emit_insn (gen_avx2_pshufbv32qi3 (t1, op1, t1)); | |||
5416 | t7 = gen_reg_rtx (V4DImode((void) 0, E_V4DImode)); | |||
5417 | emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpartrtl_hooks.gen_lowpart (V4DImode((void) 0, E_V4DImode), t4), | |||
5418 | const2_rtx(const_int_rtx[64 +2]), GEN_INT (3)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), | |||
5419 | const0_rtx(const_int_rtx[64]), const1_rtx(const_int_rtx[64 +1]))); | |||
5420 | t8 = gen_reg_rtx (V4DImode((void) 0, E_V4DImode)); | |||
5421 | emit_insn (gen_avx2_permv4di_1 (t8, gen_lowpartrtl_hooks.gen_lowpart (V4DImode((void) 0, E_V4DImode), t3), | |||
5422 | const2_rtx(const_int_rtx[64 +2]), GEN_INT (3)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (3)), | |||
5423 | const0_rtx(const_int_rtx[64]), const1_rtx(const_int_rtx[64 +1]))); | |||
5424 | emit_insn (gen_iorv32qi3 (t4, t2, gen_lowpartrtl_hooks.gen_lowpart (V32QImode((void) 0, E_V32QImode), t7))); | |||
5425 | emit_insn (gen_iorv32qi3 (t3, t1, gen_lowpartrtl_hooks.gen_lowpart (V32QImode((void) 0, E_V32QImode), t8))); | |||
5426 | t1 = t4; | |||
5427 | t2 = t3; | |||
5428 | goto merge_two; | |||
5429 | ||||
5430 | default: | |||
5431 | gcc_assert (GET_MODE_SIZE (mode) <= 16)((void)(!(((unsigned short) mode_to_bytes (mode).coeffs[0]) <= 16) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 5431, __FUNCTION__), 0 : 0)); | |||
5432 | break; | |||
5433 | } | |||
5434 | } | |||
5435 | ||||
5436 | if (TARGET_XOP((global_options.x_ix86_isa_flags & (1UL << 59)) != 0)) | |||
5437 | { | |||
5438 | /* The XOP VPPERM insn supports three inputs. By ignoring the | |||
5439 | one_operand_shuffle special case, we avoid creating another | |||
5440 | set of constant vectors in memory. */ | |||
5441 | one_operand_shuffle = false; | |||
5442 | ||||
5443 | /* mask = mask & {2*w-1, ...} */ | |||
5444 | vt = GEN_INT (2*w - 1)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (2*w - 1)); | |||
5445 | } | |||
5446 | else | |||
5447 | { | |||
5448 | /* mask = mask & {w-1, ...} */ | |||
5449 | vt = GEN_INT (w - 1)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (w - 1)); | |||
5450 | } | |||
5451 | ||||
5452 | vt = gen_const_vec_duplicate (maskmode, vt); | |||
5453 | mask = expand_simple_binop (maskmode, AND, mask, vt, | |||
5454 | NULL_RTX(rtx) 0, 0, OPTAB_DIRECT); | |||
5455 | ||||
5456 | /* For non-QImode operations, convert the word permutation control | |||
5457 | into a byte permutation control. */ | |||
5458 | if (mode != V16QImode((void) 0, E_V16QImode)) | |||
5459 | { | |||
5460 | mask = expand_simple_binop (maskmode, ASHIFT, mask, | |||
5461 | GEN_INT (exact_log2 (e))gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (exact_log2 (e))), | |||
5462 | NULL_RTX(rtx) 0, 0, OPTAB_DIRECT); | |||
5463 | ||||
5464 | /* Convert mask to vector of chars. */ | |||
5465 | mask = force_reg (V16QImode((void) 0, E_V16QImode), gen_lowpartrtl_hooks.gen_lowpart (V16QImode((void) 0, E_V16QImode), mask)); | |||
5466 | ||||
5467 | /* Replicate each of the input bytes into byte positions: | |||
5468 | (v2di) --> {0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8} | |||
5469 | (v4si) --> {0,0,0,0, 4,4,4,4, 8,8,8,8, 12,12,12,12} | |||
5470 | (v8hi) --> {0,0, 2,2, 4,4, 6,6, ...}. */ | |||
5471 | for (i = 0; i < 16; ++i) | |||
5472 | vec[i] = GEN_INT (i/e * e)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (i/e * e)); | |||
5473 | vt = gen_rtx_CONST_VECTOR (V16QImode((void) 0, E_V16QImode), gen_rtvec_v (16, vec)); | |||
5474 | vt = validize_mem (force_const_mem (V16QImode((void) 0, E_V16QImode), vt)); | |||
5475 | if (TARGET_XOP((global_options.x_ix86_isa_flags & (1UL << 59)) != 0)) | |||
5476 | emit_insn (gen_xop_pperm (mask, mask, mask, vt)); | |||
5477 | else | |||
5478 | emit_insn (gen_ssse3_pshufbv16qi3 (mask, mask, vt)); | |||
5479 | ||||
5480 | /* Convert it into the byte positions by doing | |||
5481 | mask = mask + {0,1,..,16/w, 0,1,..,16/w, ...} */ | |||
5482 | for (i = 0; i < 16; ++i) | |||
5483 | vec[i] = GEN_INT (i % e)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (i % e)); | |||
5484 | vt = gen_rtx_CONST_VECTOR (V16QImode((void) 0, E_V16QImode), gen_rtvec_v (16, vec)); | |||
5485 | vt = validize_mem (force_const_mem (V16QImode((void) 0, E_V16QImode), vt)); | |||
5486 | emit_insn (gen_addv16qi3 (mask, mask, vt)); | |||
5487 | } | |||
5488 | ||||
5489 | /* The actual shuffle operations all operate on V16QImode. */ | |||
5490 | op0 = gen_lowpartrtl_hooks.gen_lowpart (V16QImode((void) 0, E_V16QImode), op0); | |||
5491 | op1 = gen_lowpartrtl_hooks.gen_lowpart (V16QImode((void) 0, E_V16QImode), op1); | |||
5492 | ||||
5493 | if (TARGET_XOP((global_options.x_ix86_isa_flags & (1UL << 59)) != 0)) | |||
5494 | { | |||
5495 | if (GET_MODE (target)((machine_mode) (target)->mode) != V16QImode((void) 0, E_V16QImode)) | |||
5496 | target = gen_reg_rtx (V16QImode((void) 0, E_V16QImode)); | |||
5497 | emit_insn (gen_xop_pperm (target, op0, op1, mask)); | |||
5498 | if (target != operands[0]) | |||
5499 | emit_move_insn (operands[0], | |||
5500 | gen_lowpartrtl_hooks.gen_lowpart (GET_MODE (operands[0])((machine_mode) (operands[0])->mode), target)); | |||
5501 | } | |||
5502 | else if (one_operand_shuffle) | |||
5503 | { | |||
5504 | if (GET_MODE (target)((machine_mode) (target)->mode) != V16QImode((void) 0, E_V16QImode)) | |||
5505 | target = gen_reg_rtx (V16QImode((void) 0, E_V16QImode)); | |||
5506 | emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, mask)); | |||
5507 | if (target != operands[0]) | |||
5508 | emit_move_insn (operands[0], | |||
5509 | gen_lowpartrtl_hooks.gen_lowpart (GET_MODE (operands[0])((machine_mode) (operands[0])->mode), target)); | |||
5510 | } | |||
5511 | else | |||
5512 | { | |||
5513 | rtx xops[6]; | |||
5514 | bool ok; | |||
5515 | ||||
5516 | /* Shuffle the two input vectors independently. */ | |||
5517 | t1 = gen_reg_rtx (V16QImode((void) 0, E_V16QImode)); | |||
5518 | t2 = gen_reg_rtx (V16QImode((void) 0, E_V16QImode)); | |||
5519 | emit_insn (gen_ssse3_pshufbv16qi3 (t1, op0, mask)); | |||
5520 | emit_insn (gen_ssse3_pshufbv16qi3 (t2, op1, mask)); | |||
5521 | ||||
5522 | merge_two: | |||
5523 | /* Then merge them together. The key is whether any given control | |||
5524 | element contained a bit set that indicates the second word. */ | |||
5525 | mask = operands[3]; | |||
5526 | vt = GEN_INT (w)gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (w)); | |||
5527 | if (maskmode == V2DImode((void) 0, E_V2DImode) && !TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
5528 | { | |||
5529 | /* Without SSE4.1, we don't have V2DImode EQ. Perform one | |||
5530 | more shuffle to convert the V2DI input mask into a V4SI | |||
5531 | input mask. At which point the masking that expand_int_vcond | |||
5532 | will work as desired. */ | |||
5533 | rtx t3 = gen_reg_rtx (V4SImode((void) 0, E_V4SImode)); | |||
5534 | emit_insn (gen_sse2_pshufd_1 (t3, gen_lowpartrtl_hooks.gen_lowpart (V4SImode((void) 0, E_V4SImode), mask), | |||
5535 | const0_rtx(const_int_rtx[64]), const0_rtx(const_int_rtx[64]), | |||
5536 | const2_rtx(const_int_rtx[64 +2]), const2_rtx(const_int_rtx[64 +2]))); | |||
5537 | mask = t3; | |||
5538 | maskmode = V4SImode((void) 0, E_V4SImode); | |||
5539 | e = w = 4; | |||
5540 | } | |||
5541 | ||||
5542 | vt = gen_const_vec_duplicate (maskmode, vt); | |||
5543 | vt = force_reg (maskmode, vt); | |||
5544 | mask = expand_simple_binop (maskmode, AND, mask, vt, | |||
5545 | NULL_RTX(rtx) 0, 0, OPTAB_DIRECT); | |||
5546 | ||||
5547 | if (GET_MODE (target)((machine_mode) (target)->mode) != mode) | |||
5548 | target = gen_reg_rtx (mode); | |||
5549 | xops[0] = target; | |||
5550 | xops[1] = gen_lowpartrtl_hooks.gen_lowpart (mode, t2); | |||
5551 | xops[2] = gen_lowpartrtl_hooks.gen_lowpart (mode, t1); | |||
5552 | xops[3] = gen_rtx_EQ (maskmode, mask, vt)gen_rtx_fmt_ee_stat ((EQ), ((maskmode)), ((mask)), ((vt)) ); | |||
5553 | xops[4] = mask; | |||
5554 | xops[5] = vt; | |||
5555 | ok = ix86_expand_int_vcond (xops); | |||
5556 | gcc_assert (ok)((void)(!(ok) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/config/i386/i386-expand.cc" , 5556, __FUNCTION__), 0 : 0)); | |||
5557 | if (target != operands[0]) | |||
5558 | emit_move_insn (operands[0], | |||
5559 | gen_lowpartrtl_hooks.gen_lowpart (GET_MODE (operands[0])((machine_mode) (operands[0])->mode), target)); | |||
5560 | } | |||
5561 | } | |||
5562 | ||||
5563 | /* Unpack OP[1] into the next wider integer vector type. UNSIGNED_P is | |||
5564 | true if we should do zero extension, else sign extension. HIGH_P is | |||
5565 | true if we want the N/2 high elements, else the low elements. */ | |||
5566 | ||||
5567 | void | |||
5568 | ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p) | |||
5569 | { | |||
5570 | machine_mode imode = GET_MODE (src)((machine_mode) (src)->mode); | |||
5571 | rtx tmp; | |||
5572 | ||||
5573 | if (TARGET_SSE4_1((global_options.x_ix86_isa_flags & (1UL << 38)) != 0)) | |||
| ||||
5574 | { | |||
5575 | rtx (*unpack)(rtx, rtx); | |||
5576 | rtx (*extract)(rtx, rtx) = NULL__null; | |||
5577 | machine_mode halfmode = BLKmode((void) 0, E_BLKmode); | |||
5578 | ||||
5579 | switch (imode) | |||
5580 | { | |||
5581 | case E_V64QImode: | |||
5582 | if (unsigned_p) | |||
5583 | unpack = gen_avx512bw_zero_extendv32qiv32hi2; | |||
5584 | else | |||
5585 | unpack = gen_avx512bw_sign_extendv32qiv32hi2; | |||
5586 | halfmode = V32QImode((void) 0, E_V32QImode); | |||
5587 | extract | |||
5588 | = high_p ? gen_vec_extract_hi_v64qi : gen_vec_extract_lo_v64qi; | |||
5589 | break; | |||
5590 | case E_V32QImode: | |||
5591 | if (unsigned_p) | |||
5592 | unpack = gen_avx2_zero_extendv16qiv16hi2; | |||
5593 | else | |||
5594 | unpack = gen_avx2_sign_extendv16qiv16hi2; | |||
5595 | halfmode = V16QImode((void) 0, E_V16QImode); | |||
5596 | extract | |||
5597 | = high_p ? gen_vec_extract_hi_v32qi : gen_vec_extract_lo_v32qi; | |||
5598 | break; | |||
5599 | case E_V32HImode: | |||
5600 | if (unsigned_p) | |||
5601 | unpack = gen_avx512f_zero_extendv16hiv16si2; | |||
5602 | else | |||
5603 | unpack = gen_avx512f_sign_extendv16hiv16si2; | |||
5604 | halfmode = V16HImode((void) 0, E_V16HImode); | |||
5605 | extract | |||
5606 | = high_p ? gen_vec_extract_hi_v32hi : gen_vec_extract_lo_v32hi; | |||
5607 | break; | |||
5608 | case E_V16HImode: | |||
5609 | if (unsigned_p) | |||
5610 | unpack = gen_avx2_zero_extendv8hiv8si2; | |||
5611 | else | |||
5612 | unpack = gen_avx2_sign_extendv8hiv8si2; | |||
5613 | halfmode = V8HImode((void) 0, E_V8HImode); | |||
5614 | extract | |||
5615 | = high_p ? gen_vec_extract_hi_v16hi : gen_vec_extract_lo_v16hi; | |||
5616 | break; | |||
5617 | case E_V16SImode: | |||
5618 | if (unsigned_p) | |||
5619 | unpack = gen_avx512f_zero_extendv8siv8di2; | |||
5620 | else | |||
5621 | unpack = gen_avx512f_sign_extendv8siv8di2; | |||
5622 | halfmode = V8SImode((void) 0, E_V8SImode); | |||
5623 | extract | |||
5624 | = high_p ? gen |