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