File: | build/gcc/config/i386/i386-expand.c |
Warning: | line 5032, column 15 Called function pointer is null (null dereference) |
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; | |||
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 |