File: | build/gcc/config/i386/i386-expand.cc |
Warning: | line 24210, column 16 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_vec_extract_hi_v16si : gen_vec_extract_lo_v16si; |
5625 | break; |
5626 | case E_V8SImode: |
5627 | if (unsigned_p) |
5628 | unpack = gen_avx2_zero_extendv4siv4di2; |
5629 | else |