]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/internal-fn.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / internal-fn.cc
1 /* Internal functions.
2 Copyright (C) 2011-2024 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "backend.h"
24 #include "target.h"
25 #include "rtl.h"
26 #include "tree.h"
27 #include "gimple.h"
28 #include "predict.h"
29 #include "stringpool.h"
30 #include "tree-vrp.h"
31 #include "tree-ssanames.h"
32 #include "expmed.h"
33 #include "memmodel.h"
34 #include "optabs.h"
35 #include "emit-rtl.h"
36 #include "diagnostic-core.h"
37 #include "fold-const.h"
38 #include "internal-fn.h"
39 #include "stor-layout.h"
40 #include "dojump.h"
41 #include "expr.h"
42 #include "stringpool.h"
43 #include "attribs.h"
44 #include "asan.h"
45 #include "ubsan.h"
46 #include "recog.h"
47 #include "builtins.h"
48 #include "optabs-tree.h"
49 #include "gimple-ssa.h"
50 #include "tree-phinodes.h"
51 #include "ssa-iterators.h"
52 #include "explow.h"
53 #include "rtl-iter.h"
54 #include "gimple-range.h"
55
56 /* For lang_hooks.types.type_for_mode. */
57 #include "langhooks.h"
58
59 /* The names of each internal function, indexed by function number. */
60 const char *const internal_fn_name_array[] = {
61 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
62 #include "internal-fn.def"
63 "<invalid-fn>"
64 };
65
66 /* The ECF_* flags of each internal function, indexed by function number. */
67 const int internal_fn_flags_array[] = {
68 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
69 #include "internal-fn.def"
70 0
71 };
72
73 /* Return the internal function called NAME, or IFN_LAST if there's
74 no such function. */
75
76 internal_fn
77 lookup_internal_fn (const char *name)
78 {
79 typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
80 static name_to_fn_map_type *name_to_fn_map;
81
82 if (!name_to_fn_map)
83 {
84 name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
85 for (unsigned int i = 0; i < IFN_LAST; ++i)
86 name_to_fn_map->put (internal_fn_name (internal_fn (i)),
87 internal_fn (i));
88 }
89 internal_fn *entry = name_to_fn_map->get (name);
90 return entry ? *entry : IFN_LAST;
91 }
92
93 /* Geven an internal_fn IFN that is a widening function, return its
94 corresponding LO and HI internal_fns. */
95
96 extern void
97 lookup_hilo_internal_fn (internal_fn ifn, internal_fn *lo, internal_fn *hi)
98 {
99 gcc_assert (widening_fn_p (ifn));
100
101 switch (ifn)
102 {
103 default:
104 gcc_unreachable ();
105 #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
106 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
107 case IFN_##NAME: \
108 *lo = internal_fn (IFN_##NAME##_LO); \
109 *hi = internal_fn (IFN_##NAME##_HI); \
110 break;
111 #include "internal-fn.def"
112 }
113 }
114
115 /* Given an internal_fn IFN that is a widening function, return its
116 corresponding _EVEN and _ODD internal_fns in *EVEN and *ODD. */
117
118 extern void
119 lookup_evenodd_internal_fn (internal_fn ifn, internal_fn *even,
120 internal_fn *odd)
121 {
122 gcc_assert (widening_fn_p (ifn));
123
124 switch (ifn)
125 {
126 default:
127 gcc_unreachable ();
128 #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
129 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
130 case IFN_##NAME: \
131 *even = internal_fn (IFN_##NAME##_EVEN); \
132 *odd = internal_fn (IFN_##NAME##_ODD); \
133 break;
134 #include "internal-fn.def"
135 }
136 }
137
138
139 /* Fnspec of each internal function, indexed by function number. */
140 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
141
142 void
143 init_internal_fns ()
144 {
145 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
146 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
147 build_string ((int) sizeof (FNSPEC) - 1, FNSPEC ? FNSPEC : "");
148 #include "internal-fn.def"
149 internal_fn_fnspec_array[IFN_LAST] = 0;
150 }
151
152 /* Create static initializers for the information returned by
153 direct_internal_fn. */
154 #define not_direct { -2, -2, false }
155 #define mask_load_direct { -1, 2, false }
156 #define load_lanes_direct { -1, -1, false }
157 #define mask_load_lanes_direct { -1, -1, false }
158 #define gather_load_direct { 3, 1, false }
159 #define len_load_direct { -1, -1, false }
160 #define mask_len_load_direct { -1, 4, false }
161 #define mask_store_direct { 3, 2, false }
162 #define store_lanes_direct { 0, 0, false }
163 #define mask_store_lanes_direct { 0, 0, false }
164 #define vec_cond_mask_direct { 1, 0, false }
165 #define vec_cond_mask_len_direct { 1, 1, false }
166 #define vec_cond_direct { 2, 0, false }
167 #define scatter_store_direct { 3, 1, false }
168 #define len_store_direct { 3, 3, false }
169 #define mask_len_store_direct { 4, 5, false }
170 #define vec_set_direct { 3, 3, false }
171 #define vec_extract_direct { 0, -1, false }
172 #define unary_direct { 0, 0, true }
173 #define unary_convert_direct { -1, 0, true }
174 #define binary_direct { 0, 0, true }
175 #define ternary_direct { 0, 0, true }
176 #define cond_unary_direct { 1, 1, true }
177 #define cond_binary_direct { 1, 1, true }
178 #define cond_ternary_direct { 1, 1, true }
179 #define cond_len_unary_direct { 1, 1, true }
180 #define cond_len_binary_direct { 1, 1, true }
181 #define cond_len_ternary_direct { 1, 1, true }
182 #define while_direct { 0, 2, false }
183 #define fold_extract_direct { 2, 2, false }
184 #define fold_len_extract_direct { 2, 2, false }
185 #define fold_left_direct { 1, 1, false }
186 #define mask_fold_left_direct { 1, 1, false }
187 #define mask_len_fold_left_direct { 1, 1, false }
188 #define check_ptrs_direct { 0, 0, false }
189
190 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
191 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
192 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
193 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
194 UNSIGNED_OPTAB, TYPE) TYPE##_direct,
195 #include "internal-fn.def"
196 not_direct
197 };
198
199 /* Expand STMT using instruction ICODE. The instruction has NOUTPUTS
200 output operands and NINPUTS input operands, where NOUTPUTS is either
201 0 or 1. The output operand (if any) comes first, followed by the
202 NINPUTS input operands. */
203
204 static void
205 expand_fn_using_insn (gcall *stmt, insn_code icode, unsigned int noutputs,
206 unsigned int ninputs)
207 {
208 gcc_assert (icode != CODE_FOR_nothing);
209
210 expand_operand *ops = XALLOCAVEC (expand_operand, noutputs + ninputs);
211 unsigned int opno = 0;
212 rtx lhs_rtx = NULL_RTX;
213 tree lhs = gimple_call_lhs (stmt);
214
215 if (noutputs)
216 {
217 gcc_assert (noutputs == 1);
218 if (lhs)
219 lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
220
221 /* Do not assign directly to a promoted subreg, since there is no
222 guarantee that the instruction will leave the upper bits of the
223 register in the state required by SUBREG_PROMOTED_SIGN. */
224 rtx dest = lhs_rtx;
225 if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
226 dest = NULL_RTX;
227 create_output_operand (&ops[opno], dest,
228 insn_data[icode].operand[opno].mode);
229 opno += 1;
230 }
231 else
232 gcc_assert (!lhs);
233
234 for (unsigned int i = 0; i < ninputs; ++i)
235 {
236 tree rhs = gimple_call_arg (stmt, i);
237 tree rhs_type = TREE_TYPE (rhs);
238 rtx rhs_rtx = expand_normal (rhs);
239 if (INTEGRAL_TYPE_P (rhs_type))
240 create_convert_operand_from (&ops[opno], rhs_rtx,
241 TYPE_MODE (rhs_type),
242 TYPE_UNSIGNED (rhs_type));
243 else if (TREE_CODE (rhs) == SSA_NAME
244 && SSA_NAME_IS_DEFAULT_DEF (rhs)
245 && VAR_P (SSA_NAME_VAR (rhs)))
246 create_undefined_input_operand (&ops[opno], TYPE_MODE (rhs_type));
247 else
248 create_input_operand (&ops[opno], rhs_rtx, TYPE_MODE (rhs_type));
249 opno += 1;
250 }
251
252 gcc_assert (opno == noutputs + ninputs);
253 expand_insn (icode, opno, ops);
254 if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
255 {
256 /* If the return value has an integral type, convert the instruction
257 result to that type. This is useful for things that return an
258 int regardless of the size of the input. If the instruction result
259 is smaller than required, assume that it is signed.
260
261 If the return value has a nonintegral type, its mode must match
262 the instruction result. */
263 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
264 {
265 /* If this is a scalar in a register that is stored in a wider
266 mode than the declared mode, compute the result into its
267 declared mode and then convert to the wider mode. */
268 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
269 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
270 convert_move (SUBREG_REG (lhs_rtx), tmp,
271 SUBREG_PROMOTED_SIGN (lhs_rtx));
272 }
273 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
274 emit_move_insn (lhs_rtx, ops[0].value);
275 else
276 {
277 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
278 convert_move (lhs_rtx, ops[0].value, 0);
279 }
280 }
281 }
282
283 /* ARRAY_TYPE is an array of vector modes. Return the associated insn
284 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
285
286 static enum insn_code
287 get_multi_vector_move (tree array_type, convert_optab optab)
288 {
289 machine_mode imode;
290 machine_mode vmode;
291
292 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
293 imode = TYPE_MODE (array_type);
294 vmode = TYPE_MODE (TREE_TYPE (array_type));
295
296 return convert_optab_handler (optab, imode, vmode);
297 }
298
299 /* Add mask and len arguments according to the STMT. */
300
301 static unsigned int
302 add_mask_and_len_args (expand_operand *ops, unsigned int opno, gcall *stmt)
303 {
304 internal_fn ifn = gimple_call_internal_fn (stmt);
305 int len_index = internal_fn_len_index (ifn);
306 /* BIAS is always consecutive next of LEN. */
307 int bias_index = len_index + 1;
308 int mask_index = internal_fn_mask_index (ifn);
309 /* The order of arguments are always {len,bias,mask}. */
310 if (mask_index >= 0)
311 {
312 tree mask = gimple_call_arg (stmt, mask_index);
313 rtx mask_rtx = expand_normal (mask);
314 create_input_operand (&ops[opno++], mask_rtx,
315 TYPE_MODE (TREE_TYPE (mask)));
316 }
317 if (len_index >= 0)
318 {
319 tree len = gimple_call_arg (stmt, len_index);
320 rtx len_rtx = expand_normal (len);
321 create_convert_operand_from (&ops[opno++], len_rtx,
322 TYPE_MODE (TREE_TYPE (len)),
323 TYPE_UNSIGNED (TREE_TYPE (len)));
324 tree biast = gimple_call_arg (stmt, bias_index);
325 rtx bias = expand_normal (biast);
326 create_input_operand (&ops[opno++], bias, QImode);
327 }
328 return opno;
329 }
330
331 /* Expand LOAD_LANES call STMT using optab OPTAB. */
332
333 static void
334 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
335 {
336 class expand_operand ops[2];
337 tree type, lhs, rhs;
338 rtx target, mem;
339
340 lhs = gimple_call_lhs (stmt);
341 rhs = gimple_call_arg (stmt, 0);
342 type = TREE_TYPE (lhs);
343
344 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
345 mem = expand_normal (rhs);
346
347 gcc_assert (MEM_P (mem));
348 PUT_MODE (mem, TYPE_MODE (type));
349
350 create_output_operand (&ops[0], target, TYPE_MODE (type));
351 create_fixed_operand (&ops[1], mem);
352 expand_insn (get_multi_vector_move (type, optab), 2, ops);
353 if (!rtx_equal_p (target, ops[0].value))
354 emit_move_insn (target, ops[0].value);
355 }
356
357 /* Expand STORE_LANES call STMT using optab OPTAB. */
358
359 static void
360 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
361 {
362 class expand_operand ops[2];
363 tree type, lhs, rhs;
364 rtx target, reg;
365
366 lhs = gimple_call_lhs (stmt);
367 rhs = gimple_call_arg (stmt, 0);
368 type = TREE_TYPE (rhs);
369
370 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
371 reg = expand_normal (rhs);
372
373 gcc_assert (MEM_P (target));
374 PUT_MODE (target, TYPE_MODE (type));
375
376 create_fixed_operand (&ops[0], target);
377 create_input_operand (&ops[1], reg, TYPE_MODE (type));
378 expand_insn (get_multi_vector_move (type, optab), 2, ops);
379 }
380
381 static void
382 expand_ANNOTATE (internal_fn, gcall *)
383 {
384 gcc_unreachable ();
385 }
386
387 /* This should get expanded in omp_device_lower pass. */
388
389 static void
390 expand_GOMP_USE_SIMT (internal_fn, gcall *)
391 {
392 gcc_unreachable ();
393 }
394
395 /* This should get expanded in omp_device_lower pass. */
396
397 static void
398 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
399 {
400 gcc_unreachable ();
401 }
402
403 /* Allocate per-lane storage and begin non-uniform execution region. */
404
405 static void
406 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
407 {
408 rtx target;
409 tree lhs = gimple_call_lhs (stmt);
410 if (lhs)
411 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
412 else
413 target = gen_reg_rtx (Pmode);
414 rtx size = expand_normal (gimple_call_arg (stmt, 0));
415 rtx align = expand_normal (gimple_call_arg (stmt, 1));
416 class expand_operand ops[3];
417 create_output_operand (&ops[0], target, Pmode);
418 create_input_operand (&ops[1], size, Pmode);
419 create_input_operand (&ops[2], align, Pmode);
420 gcc_assert (targetm.have_omp_simt_enter ());
421 expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
422 if (!rtx_equal_p (target, ops[0].value))
423 emit_move_insn (target, ops[0].value);
424 }
425
426 /* Deallocate per-lane storage and leave non-uniform execution region. */
427
428 static void
429 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
430 {
431 gcc_checking_assert (!gimple_call_lhs (stmt));
432 rtx arg = expand_normal (gimple_call_arg (stmt, 0));
433 class expand_operand ops[1];
434 create_input_operand (&ops[0], arg, Pmode);
435 gcc_assert (targetm.have_omp_simt_exit ());
436 expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
437 }
438
439 /* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
440 without SIMT execution this should be expanded in omp_device_lower pass. */
441
442 static void
443 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
444 {
445 tree lhs = gimple_call_lhs (stmt);
446 if (!lhs)
447 return;
448
449 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
450 gcc_assert (targetm.have_omp_simt_lane ());
451 emit_insn (targetm.gen_omp_simt_lane (target));
452 }
453
454 /* This should get expanded in omp_device_lower pass. */
455
456 static void
457 expand_GOMP_SIMT_VF (internal_fn, gcall *)
458 {
459 gcc_unreachable ();
460 }
461
462 /* This should get expanded in omp_device_lower pass. */
463
464 static void
465 expand_GOMP_TARGET_REV (internal_fn, gcall *)
466 {
467 gcc_unreachable ();
468 }
469
470 /* Lane index of the first SIMT lane that supplies a non-zero argument.
471 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
472 lane that executed the last iteration for handling OpenMP lastprivate. */
473
474 static void
475 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
476 {
477 tree lhs = gimple_call_lhs (stmt);
478 if (!lhs)
479 return;
480
481 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
482 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
483 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
484 class expand_operand ops[2];
485 create_output_operand (&ops[0], target, mode);
486 create_input_operand (&ops[1], cond, mode);
487 gcc_assert (targetm.have_omp_simt_last_lane ());
488 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
489 if (!rtx_equal_p (target, ops[0].value))
490 emit_move_insn (target, ops[0].value);
491 }
492
493 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
494
495 static void
496 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
497 {
498 tree lhs = gimple_call_lhs (stmt);
499 if (!lhs)
500 return;
501
502 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
503 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
504 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
505 class expand_operand ops[2];
506 create_output_operand (&ops[0], target, mode);
507 create_input_operand (&ops[1], ctr, mode);
508 gcc_assert (targetm.have_omp_simt_ordered ());
509 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
510 if (!rtx_equal_p (target, ops[0].value))
511 emit_move_insn (target, ops[0].value);
512 }
513
514 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
515 any lane supplies a non-zero argument. */
516
517 static void
518 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
519 {
520 tree lhs = gimple_call_lhs (stmt);
521 if (!lhs)
522 return;
523
524 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
525 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
526 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
527 class expand_operand ops[2];
528 create_output_operand (&ops[0], target, mode);
529 create_input_operand (&ops[1], cond, mode);
530 gcc_assert (targetm.have_omp_simt_vote_any ());
531 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
532 if (!rtx_equal_p (target, ops[0].value))
533 emit_move_insn (target, ops[0].value);
534 }
535
536 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
537 is destination lane index XOR given offset. */
538
539 static void
540 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
541 {
542 tree lhs = gimple_call_lhs (stmt);
543 if (!lhs)
544 return;
545
546 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
547 rtx src = expand_normal (gimple_call_arg (stmt, 0));
548 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
549 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
550 class expand_operand ops[3];
551 create_output_operand (&ops[0], target, mode);
552 create_input_operand (&ops[1], src, mode);
553 create_input_operand (&ops[2], idx, SImode);
554 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
555 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
556 if (!rtx_equal_p (target, ops[0].value))
557 emit_move_insn (target, ops[0].value);
558 }
559
560 /* Exchange between SIMT lanes according to given source lane index. */
561
562 static void
563 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
564 {
565 tree lhs = gimple_call_lhs (stmt);
566 if (!lhs)
567 return;
568
569 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
570 rtx src = expand_normal (gimple_call_arg (stmt, 0));
571 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
572 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
573 class expand_operand ops[3];
574 create_output_operand (&ops[0], target, mode);
575 create_input_operand (&ops[1], src, mode);
576 create_input_operand (&ops[2], idx, SImode);
577 gcc_assert (targetm.have_omp_simt_xchg_idx ());
578 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
579 if (!rtx_equal_p (target, ops[0].value))
580 emit_move_insn (target, ops[0].value);
581 }
582
583 /* This should get expanded in adjust_simduid_builtins. */
584
585 static void
586 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
587 {
588 gcc_unreachable ();
589 }
590
591 /* This should get expanded in adjust_simduid_builtins. */
592
593 static void
594 expand_GOMP_SIMD_VF (internal_fn, gcall *)
595 {
596 gcc_unreachable ();
597 }
598
599 /* This should get expanded in adjust_simduid_builtins. */
600
601 static void
602 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
603 {
604 gcc_unreachable ();
605 }
606
607 /* This should get expanded in adjust_simduid_builtins. */
608
609 static void
610 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
611 {
612 gcc_unreachable ();
613 }
614
615 /* This should get expanded in adjust_simduid_builtins. */
616
617 static void
618 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
619 {
620 gcc_unreachable ();
621 }
622
623 /* This should get expanded in the sanopt pass. */
624
625 static void
626 expand_UBSAN_NULL (internal_fn, gcall *)
627 {
628 gcc_unreachable ();
629 }
630
631 /* This should get expanded in the sanopt pass. */
632
633 static void
634 expand_UBSAN_BOUNDS (internal_fn, gcall *)
635 {
636 gcc_unreachable ();
637 }
638
639 /* This should get expanded in the sanopt pass. */
640
641 static void
642 expand_UBSAN_VPTR (internal_fn, gcall *)
643 {
644 gcc_unreachable ();
645 }
646
647 /* This should get expanded in the sanopt pass. */
648
649 static void
650 expand_UBSAN_PTR (internal_fn, gcall *)
651 {
652 gcc_unreachable ();
653 }
654
655 /* This should get expanded in the sanopt pass. */
656
657 static void
658 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
659 {
660 gcc_unreachable ();
661 }
662
663 /* This should get expanded in the sanopt pass. */
664
665 static void
666 expand_HWASAN_CHECK (internal_fn, gcall *)
667 {
668 gcc_unreachable ();
669 }
670
671 /* For hwasan stack tagging:
672 Clear tags on the dynamically allocated space.
673 For use after an object dynamically allocated on the stack goes out of
674 scope. */
675 static void
676 expand_HWASAN_ALLOCA_UNPOISON (internal_fn, gcall *gc)
677 {
678 gcc_assert (Pmode == ptr_mode);
679 tree restored_position = gimple_call_arg (gc, 0);
680 rtx restored_rtx = expand_expr (restored_position, NULL_RTX, VOIDmode,
681 EXPAND_NORMAL);
682 rtx func = init_one_libfunc ("__hwasan_tag_memory");
683 rtx off = expand_simple_binop (Pmode, MINUS, restored_rtx,
684 stack_pointer_rtx, NULL_RTX, 0,
685 OPTAB_WIDEN);
686 emit_library_call_value (func, NULL_RTX, LCT_NORMAL, VOIDmode,
687 virtual_stack_dynamic_rtx, Pmode,
688 HWASAN_STACK_BACKGROUND, QImode,
689 off, Pmode);
690 }
691
692 /* For hwasan stack tagging:
693 Return a tag to be used for a dynamic allocation. */
694 static void
695 expand_HWASAN_CHOOSE_TAG (internal_fn, gcall *gc)
696 {
697 tree tag = gimple_call_lhs (gc);
698 rtx target = expand_expr (tag, NULL_RTX, VOIDmode, EXPAND_NORMAL);
699 machine_mode mode = GET_MODE (target);
700 gcc_assert (mode == QImode);
701
702 rtx base_tag = targetm.memtag.extract_tag (hwasan_frame_base (), NULL_RTX);
703 gcc_assert (base_tag);
704 rtx tag_offset = gen_int_mode (hwasan_current_frame_tag (), QImode);
705 rtx chosen_tag = expand_simple_binop (QImode, PLUS, base_tag, tag_offset,
706 target, /* unsignedp = */1,
707 OPTAB_WIDEN);
708 chosen_tag = hwasan_truncate_to_tag_size (chosen_tag, target);
709
710 /* Really need to put the tag into the `target` RTX. */
711 if (chosen_tag != target)
712 {
713 rtx temp = chosen_tag;
714 gcc_assert (GET_MODE (chosen_tag) == mode);
715 emit_move_insn (target, temp);
716 }
717
718 hwasan_increment_frame_tag ();
719 }
720
721 /* For hwasan stack tagging:
722 Tag a region of space in the shadow stack according to the base pointer of
723 an object on the stack. N.b. the length provided in the internal call is
724 required to be aligned to HWASAN_TAG_GRANULE_SIZE. */
725 static void
726 expand_HWASAN_MARK (internal_fn, gcall *gc)
727 {
728 gcc_assert (ptr_mode == Pmode);
729 HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (gc, 0));
730 bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
731
732 tree base = gimple_call_arg (gc, 1);
733 gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
734 rtx base_rtx = expand_normal (base);
735
736 rtx tag = is_poison ? HWASAN_STACK_BACKGROUND
737 : targetm.memtag.extract_tag (base_rtx, NULL_RTX);
738 rtx address = targetm.memtag.untagged_pointer (base_rtx, NULL_RTX);
739
740 tree len = gimple_call_arg (gc, 2);
741 rtx r_len = expand_normal (len);
742
743 rtx func = init_one_libfunc ("__hwasan_tag_memory");
744 emit_library_call (func, LCT_NORMAL, VOIDmode, address, Pmode,
745 tag, QImode, r_len, Pmode);
746 }
747
748 /* For hwasan stack tagging:
749 Store a tag into a pointer. */
750 static void
751 expand_HWASAN_SET_TAG (internal_fn, gcall *gc)
752 {
753 gcc_assert (ptr_mode == Pmode);
754 tree g_target = gimple_call_lhs (gc);
755 tree g_ptr = gimple_call_arg (gc, 0);
756 tree g_tag = gimple_call_arg (gc, 1);
757
758 rtx ptr = expand_normal (g_ptr);
759 rtx tag = expand_expr (g_tag, NULL_RTX, QImode, EXPAND_NORMAL);
760 rtx target = expand_normal (g_target);
761
762 rtx untagged = targetm.memtag.untagged_pointer (ptr, target);
763 rtx tagged_value = targetm.memtag.set_tag (untagged, tag, target);
764 if (tagged_value != target)
765 emit_move_insn (target, tagged_value);
766 }
767
768 /* This should get expanded in the sanopt pass. */
769
770 static void
771 expand_ASAN_CHECK (internal_fn, gcall *)
772 {
773 gcc_unreachable ();
774 }
775
776 /* This should get expanded in the sanopt pass. */
777
778 static void
779 expand_ASAN_MARK (internal_fn, gcall *)
780 {
781 gcc_unreachable ();
782 }
783
784 /* This should get expanded in the sanopt pass. */
785
786 static void
787 expand_ASAN_POISON (internal_fn, gcall *)
788 {
789 gcc_unreachable ();
790 }
791
792 /* This should get expanded in the sanopt pass. */
793
794 static void
795 expand_ASAN_POISON_USE (internal_fn, gcall *)
796 {
797 gcc_unreachable ();
798 }
799
800 /* This should get expanded in the tsan pass. */
801
802 static void
803 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
804 {
805 gcc_unreachable ();
806 }
807
808 /* This should get expanded in the lower pass. */
809
810 static void
811 expand_FALLTHROUGH (internal_fn, gcall *call)
812 {
813 error_at (gimple_location (call),
814 "invalid use of attribute %<fallthrough%>");
815 }
816
817 /* Return minimum precision needed to represent all values
818 of ARG in SIGNed integral type. */
819
820 static int
821 get_min_precision (tree arg, signop sign)
822 {
823 int prec = TYPE_PRECISION (TREE_TYPE (arg));
824 int cnt = 0;
825 signop orig_sign = sign;
826 if (TREE_CODE (arg) == INTEGER_CST)
827 {
828 int p;
829 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
830 {
831 widest_int w = wi::to_widest (arg);
832 w = wi::ext (w, prec, sign);
833 p = wi::min_precision (w, sign);
834 }
835 else
836 p = wi::min_precision (wi::to_wide (arg), sign);
837 return MIN (p, prec);
838 }
839 while (CONVERT_EXPR_P (arg)
840 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
841 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
842 {
843 arg = TREE_OPERAND (arg, 0);
844 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
845 {
846 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
847 sign = UNSIGNED;
848 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
849 return prec + (orig_sign != sign);
850 prec = TYPE_PRECISION (TREE_TYPE (arg));
851 }
852 if (++cnt > 30)
853 return prec + (orig_sign != sign);
854 }
855 if (CONVERT_EXPR_P (arg)
856 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
857 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) > prec)
858 {
859 /* We have e.g. (unsigned short) y_2 where int y_2 = (int) x_1(D);
860 If y_2's min precision is smaller than prec, return that. */
861 int oprec = get_min_precision (TREE_OPERAND (arg, 0), sign);
862 if (oprec < prec)
863 return oprec + (orig_sign != sign);
864 }
865 if (TREE_CODE (arg) != SSA_NAME)
866 return prec + (orig_sign != sign);
867 value_range r;
868 while (!get_global_range_query ()->range_of_expr (r, arg)
869 || r.varying_p ()
870 || r.undefined_p ())
871 {
872 gimple *g = SSA_NAME_DEF_STMT (arg);
873 if (is_gimple_assign (g)
874 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
875 {
876 tree t = gimple_assign_rhs1 (g);
877 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
878 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
879 {
880 arg = t;
881 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
882 {
883 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
884 sign = UNSIGNED;
885 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
886 return prec + (orig_sign != sign);
887 prec = TYPE_PRECISION (TREE_TYPE (arg));
888 }
889 if (++cnt > 30)
890 return prec + (orig_sign != sign);
891 continue;
892 }
893 }
894 return prec + (orig_sign != sign);
895 }
896 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
897 {
898 int p1 = wi::min_precision (r.lower_bound (), sign);
899 int p2 = wi::min_precision (r.upper_bound (), sign);
900 p1 = MAX (p1, p2);
901 prec = MIN (prec, p1);
902 }
903 else if (sign == UNSIGNED && !wi::neg_p (r.lower_bound (), SIGNED))
904 {
905 int p = wi::min_precision (r.upper_bound (), UNSIGNED);
906 prec = MIN (prec, p);
907 }
908 return prec + (orig_sign != sign);
909 }
910
911 /* Helper for expand_*_overflow. Set the __imag__ part to true
912 (1 except for signed:1 type, in which case store -1). */
913
914 static void
915 expand_arith_set_overflow (tree lhs, rtx target)
916 {
917 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
918 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
919 write_complex_part (target, constm1_rtx, true, false);
920 else
921 write_complex_part (target, const1_rtx, true, false);
922 }
923
924 /* Helper for expand_*_overflow. Store RES into the __real__ part
925 of TARGET. If RES has larger MODE than __real__ part of TARGET,
926 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
927 if LHS has smaller precision than its mode. */
928
929 static void
930 expand_arith_overflow_result_store (tree lhs, rtx target,
931 scalar_int_mode mode, rtx res)
932 {
933 scalar_int_mode tgtmode
934 = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
935 rtx lres = res;
936 if (tgtmode != mode)
937 {
938 rtx_code_label *done_label = gen_label_rtx ();
939 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
940 lres = convert_modes (tgtmode, mode, res, uns);
941 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
942 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
943 EQ, true, mode, NULL_RTX, NULL, done_label,
944 profile_probability::very_likely ());
945 expand_arith_set_overflow (lhs, target);
946 emit_label (done_label);
947 }
948 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
949 int tgtprec = GET_MODE_PRECISION (tgtmode);
950 if (prec < tgtprec)
951 {
952 rtx_code_label *done_label = gen_label_rtx ();
953 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
954 res = lres;
955 if (uns)
956 {
957 rtx mask
958 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
959 tgtmode);
960 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
961 true, OPTAB_LIB_WIDEN);
962 }
963 else
964 {
965 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
966 NULL_RTX, 1);
967 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
968 NULL_RTX, 0);
969 }
970 do_compare_rtx_and_jump (res, lres,
971 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
972 profile_probability::very_likely ());
973 expand_arith_set_overflow (lhs, target);
974 emit_label (done_label);
975 }
976 write_complex_part (target, lres, false, false);
977 }
978
979 /* Helper for expand_*_overflow. Store RES into TARGET. */
980
981 static void
982 expand_ubsan_result_store (tree lhs, rtx target, scalar_int_mode mode,
983 rtx res, rtx_code_label *do_error)
984 {
985 if (TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE
986 && TYPE_PRECISION (TREE_TYPE (lhs)) < GET_MODE_PRECISION (mode))
987 {
988 int uns = TYPE_UNSIGNED (TREE_TYPE (lhs));
989 int prec = TYPE_PRECISION (TREE_TYPE (lhs));
990 int tgtprec = GET_MODE_PRECISION (mode);
991 rtx resc = gen_reg_rtx (mode), lres;
992 emit_move_insn (resc, res);
993 if (uns)
994 {
995 rtx mask
996 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
997 mode);
998 lres = expand_simple_binop (mode, AND, res, mask, NULL_RTX,
999 true, OPTAB_LIB_WIDEN);
1000 }
1001 else
1002 {
1003 lres = expand_shift (LSHIFT_EXPR, mode, res, tgtprec - prec,
1004 NULL_RTX, 1);
1005 lres = expand_shift (RSHIFT_EXPR, mode, lres, tgtprec - prec,
1006 NULL_RTX, 0);
1007 }
1008 if (lres != res)
1009 emit_move_insn (res, lres);
1010 do_compare_rtx_and_jump (res, resc,
1011 NE, true, mode, NULL_RTX, NULL, do_error,
1012 profile_probability::very_unlikely ());
1013 }
1014 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
1015 /* If this is a scalar in a register that is stored in a wider mode
1016 than the declared mode, compute the result into its declared mode
1017 and then convert to the wider mode. Our value is the computed
1018 expression. */
1019 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
1020 else
1021 emit_move_insn (target, res);
1022 }
1023
1024 /* Add sub/add overflow checking to the statement STMT.
1025 CODE says whether the operation is +, or -. */
1026
1027 void
1028 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
1029 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
1030 bool uns1_p, bool is_ubsan, tree *datap)
1031 {
1032 rtx res, target = NULL_RTX;
1033 tree fn;
1034 rtx_code_label *done_label = gen_label_rtx ();
1035 rtx_code_label *do_error = gen_label_rtx ();
1036 do_pending_stack_adjust ();
1037 rtx op0 = expand_normal (arg0);
1038 rtx op1 = expand_normal (arg1);
1039 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1040 int prec = GET_MODE_PRECISION (mode);
1041 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1042 bool do_xor = false;
1043
1044 if (is_ubsan)
1045 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1046
1047 if (lhs)
1048 {
1049 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1050 if (!is_ubsan)
1051 write_complex_part (target, const0_rtx, true, false);
1052 }
1053
1054 /* We assume both operands and result have the same precision
1055 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1056 with that precision, U for unsigned type with that precision,
1057 sgn for unsigned most significant bit in that precision.
1058 s1 is signed first operand, u1 is unsigned first operand,
1059 s2 is signed second operand, u2 is unsigned second operand,
1060 sr is signed result, ur is unsigned result and the following
1061 rules say how to compute result (which is always result of
1062 the operands as if both were unsigned, cast to the right
1063 signedness) and how to compute whether operation overflowed.
1064
1065 s1 + s2 -> sr
1066 res = (S) ((U) s1 + (U) s2)
1067 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
1068 s1 - s2 -> sr
1069 res = (S) ((U) s1 - (U) s2)
1070 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
1071 u1 + u2 -> ur
1072 res = u1 + u2
1073 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
1074 u1 - u2 -> ur
1075 res = u1 - u2
1076 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
1077 s1 + u2 -> sr
1078 res = (S) ((U) s1 + u2)
1079 ovf = ((U) res ^ sgn) < u2
1080 s1 + u2 -> ur
1081 t1 = (S) (u2 ^ sgn)
1082 t2 = s1 + t1
1083 res = (U) t2 ^ sgn
1084 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
1085 s1 - u2 -> sr
1086 res = (S) ((U) s1 - u2)
1087 ovf = u2 > ((U) s1 ^ sgn)
1088 s1 - u2 -> ur
1089 res = (U) s1 - u2
1090 ovf = s1 < 0 || u2 > (U) s1
1091 u1 - s2 -> sr
1092 res = u1 - (U) s2
1093 ovf = u1 >= ((U) s2 ^ sgn)
1094 u1 - s2 -> ur
1095 t1 = u1 ^ sgn
1096 t2 = t1 - (U) s2
1097 res = t2 ^ sgn
1098 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
1099 s1 + s2 -> ur
1100 res = (U) s1 + (U) s2
1101 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
1102 u1 + u2 -> sr
1103 res = (S) (u1 + u2)
1104 ovf = (U) res < u2 || res < 0
1105 u1 - u2 -> sr
1106 res = (S) (u1 - u2)
1107 ovf = u1 >= u2 ? res < 0 : res >= 0
1108 s1 - s2 -> ur
1109 res = (U) s1 - (U) s2
1110 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
1111
1112 if (code == PLUS_EXPR && uns0_p && !uns1_p)
1113 {
1114 /* PLUS_EXPR is commutative, if operand signedness differs,
1115 canonicalize to the first operand being signed and second
1116 unsigned to simplify following code. */
1117 std::swap (op0, op1);
1118 std::swap (arg0, arg1);
1119 uns0_p = false;
1120 uns1_p = true;
1121 }
1122
1123 /* u1 +- u2 -> ur */
1124 if (uns0_p && uns1_p && unsr_p)
1125 {
1126 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
1127 : usubv4_optab, mode);
1128 if (icode != CODE_FOR_nothing)
1129 {
1130 class expand_operand ops[4];
1131 rtx_insn *last = get_last_insn ();
1132
1133 res = gen_reg_rtx (mode);
1134 create_output_operand (&ops[0], res, mode);
1135 create_input_operand (&ops[1], op0, mode);
1136 create_input_operand (&ops[2], op1, mode);
1137 create_fixed_operand (&ops[3], do_error);
1138 if (maybe_expand_insn (icode, 4, ops))
1139 {
1140 last = get_last_insn ();
1141 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1142 && JUMP_P (last)
1143 && any_condjump_p (last)
1144 && !find_reg_note (last, REG_BR_PROB, 0))
1145 add_reg_br_prob_note (last,
1146 profile_probability::very_unlikely ());
1147 emit_jump (done_label);
1148 goto do_error_label;
1149 }
1150
1151 delete_insns_since (last);
1152 }
1153
1154 /* Compute the operation. On RTL level, the addition is always
1155 unsigned. */
1156 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1157 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1158 rtx tem = op0;
1159 /* For PLUS_EXPR, the operation is commutative, so we can pick
1160 operand to compare against. For prec <= BITS_PER_WORD, I think
1161 preferring REG operand is better over CONST_INT, because
1162 the CONST_INT might enlarge the instruction or CSE would need
1163 to figure out we'd already loaded it into a register before.
1164 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
1165 as then the multi-word comparison can be perhaps simplified. */
1166 if (code == PLUS_EXPR
1167 && (prec <= BITS_PER_WORD
1168 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
1169 : CONST_SCALAR_INT_P (op1)))
1170 tem = op1;
1171 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
1172 true, mode, NULL_RTX, NULL, done_label,
1173 profile_probability::very_likely ());
1174 goto do_error_label;
1175 }
1176
1177 /* s1 +- u2 -> sr */
1178 if (!uns0_p && uns1_p && !unsr_p)
1179 {
1180 /* Compute the operation. On RTL level, the addition is always
1181 unsigned. */
1182 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1183 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1184 rtx tem = expand_binop (mode, add_optab,
1185 code == PLUS_EXPR ? res : op0, sgn,
1186 NULL_RTX, false, OPTAB_LIB_WIDEN);
1187 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
1188 done_label, profile_probability::very_likely ());
1189 goto do_error_label;
1190 }
1191
1192 /* s1 + u2 -> ur */
1193 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
1194 {
1195 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1196 OPTAB_LIB_WIDEN);
1197 /* As we've changed op1, we have to avoid using the value range
1198 for the original argument. */
1199 arg1 = error_mark_node;
1200 do_xor = true;
1201 goto do_signed;
1202 }
1203
1204 /* u1 - s2 -> ur */
1205 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
1206 {
1207 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
1208 OPTAB_LIB_WIDEN);
1209 /* As we've changed op0, we have to avoid using the value range
1210 for the original argument. */
1211 arg0 = error_mark_node;
1212 do_xor = true;
1213 goto do_signed;
1214 }
1215
1216 /* s1 - u2 -> ur */
1217 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
1218 {
1219 /* Compute the operation. On RTL level, the addition is always
1220 unsigned. */
1221 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1222 OPTAB_LIB_WIDEN);
1223 int pos_neg = get_range_pos_neg (arg0);
1224 if (pos_neg == 2)
1225 /* If ARG0 is known to be always negative, this is always overflow. */
1226 emit_jump (do_error);
1227 else if (pos_neg == 3)
1228 /* If ARG0 is not known to be always positive, check at runtime. */
1229 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
1230 NULL, do_error, profile_probability::very_unlikely ());
1231 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
1232 done_label, profile_probability::very_likely ());
1233 goto do_error_label;
1234 }
1235
1236 /* u1 - s2 -> sr */
1237 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
1238 {
1239 /* Compute the operation. On RTL level, the addition is always
1240 unsigned. */
1241 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1242 OPTAB_LIB_WIDEN);
1243 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1244 OPTAB_LIB_WIDEN);
1245 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
1246 done_label, profile_probability::very_likely ());
1247 goto do_error_label;
1248 }
1249
1250 /* u1 + u2 -> sr */
1251 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
1252 {
1253 /* Compute the operation. On RTL level, the addition is always
1254 unsigned. */
1255 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
1256 OPTAB_LIB_WIDEN);
1257 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1258 NULL, do_error, profile_probability::very_unlikely ());
1259 rtx tem = op1;
1260 /* The operation is commutative, so we can pick operand to compare
1261 against. For prec <= BITS_PER_WORD, I think preferring REG operand
1262 is better over CONST_INT, because the CONST_INT might enlarge the
1263 instruction or CSE would need to figure out we'd already loaded it
1264 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
1265 might be more beneficial, as then the multi-word comparison can be
1266 perhaps simplified. */
1267 if (prec <= BITS_PER_WORD
1268 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
1269 : CONST_SCALAR_INT_P (op0))
1270 tem = op0;
1271 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
1272 done_label, profile_probability::very_likely ());
1273 goto do_error_label;
1274 }
1275
1276 /* s1 +- s2 -> ur */
1277 if (!uns0_p && !uns1_p && unsr_p)
1278 {
1279 /* Compute the operation. On RTL level, the addition is always
1280 unsigned. */
1281 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1282 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1283 int pos_neg = get_range_pos_neg (arg1);
1284 if (code == PLUS_EXPR)
1285 {
1286 int pos_neg0 = get_range_pos_neg (arg0);
1287 if (pos_neg0 != 3 && pos_neg == 3)
1288 {
1289 std::swap (op0, op1);
1290 pos_neg = pos_neg0;
1291 }
1292 }
1293 rtx tem;
1294 if (pos_neg != 3)
1295 {
1296 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
1297 ? and_optab : ior_optab,
1298 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
1299 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
1300 NULL, done_label, profile_probability::very_likely ());
1301 }
1302 else
1303 {
1304 rtx_code_label *do_ior_label = gen_label_rtx ();
1305 do_compare_rtx_and_jump (op1, const0_rtx,
1306 code == MINUS_EXPR ? GE : LT, false, mode,
1307 NULL_RTX, NULL, do_ior_label,
1308 profile_probability::even ());
1309 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
1310 OPTAB_LIB_WIDEN);
1311 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1312 NULL, done_label, profile_probability::very_likely ());
1313 emit_jump (do_error);
1314 emit_label (do_ior_label);
1315 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
1316 OPTAB_LIB_WIDEN);
1317 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1318 NULL, done_label, profile_probability::very_likely ());
1319 }
1320 goto do_error_label;
1321 }
1322
1323 /* u1 - u2 -> sr */
1324 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
1325 {
1326 /* Compute the operation. On RTL level, the addition is always
1327 unsigned. */
1328 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1329 OPTAB_LIB_WIDEN);
1330 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
1331 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
1332 op0_geu_op1, profile_probability::even ());
1333 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1334 NULL, done_label, profile_probability::very_likely ());
1335 emit_jump (do_error);
1336 emit_label (op0_geu_op1);
1337 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1338 NULL, done_label, profile_probability::very_likely ());
1339 goto do_error_label;
1340 }
1341
1342 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
1343
1344 /* s1 +- s2 -> sr */
1345 do_signed:
1346 {
1347 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
1348 : subv4_optab, mode);
1349 if (icode != CODE_FOR_nothing)
1350 {
1351 class expand_operand ops[4];
1352 rtx_insn *last = get_last_insn ();
1353
1354 res = gen_reg_rtx (mode);
1355 create_output_operand (&ops[0], res, mode);
1356 create_input_operand (&ops[1], op0, mode);
1357 create_input_operand (&ops[2], op1, mode);
1358 create_fixed_operand (&ops[3], do_error);
1359 if (maybe_expand_insn (icode, 4, ops))
1360 {
1361 last = get_last_insn ();
1362 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1363 && JUMP_P (last)
1364 && any_condjump_p (last)
1365 && !find_reg_note (last, REG_BR_PROB, 0))
1366 add_reg_br_prob_note (last,
1367 profile_probability::very_unlikely ());
1368 emit_jump (done_label);
1369 goto do_error_label;
1370 }
1371
1372 delete_insns_since (last);
1373 }
1374
1375 /* Compute the operation. On RTL level, the addition is always
1376 unsigned. */
1377 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1378 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1379
1380 /* If we can prove that one of the arguments (for MINUS_EXPR only
1381 the second operand, as subtraction is not commutative) is always
1382 non-negative or always negative, we can do just one comparison
1383 and conditional jump. */
1384 int pos_neg = get_range_pos_neg (arg1);
1385 if (code == PLUS_EXPR)
1386 {
1387 int pos_neg0 = get_range_pos_neg (arg0);
1388 if (pos_neg0 != 3 && pos_neg == 3)
1389 {
1390 std::swap (op0, op1);
1391 pos_neg = pos_neg0;
1392 }
1393 }
1394
1395 /* Addition overflows if and only if the two operands have the same sign,
1396 and the result has the opposite sign. Subtraction overflows if and
1397 only if the two operands have opposite sign, and the subtrahend has
1398 the same sign as the result. Here 0 is counted as positive. */
1399 if (pos_neg == 3)
1400 {
1401 /* Compute op0 ^ op1 (operands have opposite sign). */
1402 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1403 OPTAB_LIB_WIDEN);
1404
1405 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1406 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1407 OPTAB_LIB_WIDEN);
1408
1409 rtx tem;
1410 if (code == PLUS_EXPR)
1411 {
1412 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1413 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1414 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1415 OPTAB_LIB_WIDEN);
1416 }
1417 else
1418 {
1419 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1420 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1421 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1422 OPTAB_LIB_WIDEN);
1423 }
1424
1425 /* No overflow if the result has bit sign cleared. */
1426 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1427 NULL, done_label, profile_probability::very_likely ());
1428 }
1429
1430 /* Compare the result of the operation with the first operand.
1431 No overflow for addition if second operand is positive and result
1432 is larger or second operand is negative and result is smaller.
1433 Likewise for subtraction with sign of second operand flipped. */
1434 else
1435 do_compare_rtx_and_jump (res, op0,
1436 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1437 false, mode, NULL_RTX, NULL, done_label,
1438 profile_probability::very_likely ());
1439 }
1440
1441 do_error_label:
1442 emit_label (do_error);
1443 if (is_ubsan)
1444 {
1445 /* Expand the ubsan builtin call. */
1446 push_temp_slots ();
1447 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1448 arg0, arg1, datap);
1449 expand_normal (fn);
1450 pop_temp_slots ();
1451 do_pending_stack_adjust ();
1452 }
1453 else if (lhs)
1454 expand_arith_set_overflow (lhs, target);
1455
1456 /* We're done. */
1457 emit_label (done_label);
1458
1459 if (lhs)
1460 {
1461 if (is_ubsan)
1462 expand_ubsan_result_store (lhs, target, mode, res, do_error);
1463 else
1464 {
1465 if (do_xor)
1466 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1467 OPTAB_LIB_WIDEN);
1468
1469 expand_arith_overflow_result_store (lhs, target, mode, res);
1470 }
1471 }
1472 }
1473
1474 /* Add negate overflow checking to the statement STMT. */
1475
1476 static void
1477 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1478 tree *datap)
1479 {
1480 rtx res, op1;
1481 tree fn;
1482 rtx_code_label *done_label, *do_error;
1483 rtx target = NULL_RTX;
1484
1485 done_label = gen_label_rtx ();
1486 do_error = gen_label_rtx ();
1487
1488 do_pending_stack_adjust ();
1489 op1 = expand_normal (arg1);
1490
1491 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
1492 if (lhs)
1493 {
1494 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1495 if (!is_ubsan)
1496 write_complex_part (target, const0_rtx, true, false);
1497 }
1498
1499 enum insn_code icode = optab_handler (negv3_optab, mode);
1500 if (icode != CODE_FOR_nothing)
1501 {
1502 class expand_operand ops[3];
1503 rtx_insn *last = get_last_insn ();
1504
1505 res = gen_reg_rtx (mode);
1506 create_output_operand (&ops[0], res, mode);
1507 create_input_operand (&ops[1], op1, mode);
1508 create_fixed_operand (&ops[2], do_error);
1509 if (maybe_expand_insn (icode, 3, ops))
1510 {
1511 last = get_last_insn ();
1512 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1513 && JUMP_P (last)
1514 && any_condjump_p (last)
1515 && !find_reg_note (last, REG_BR_PROB, 0))
1516 add_reg_br_prob_note (last,
1517 profile_probability::very_unlikely ());
1518 emit_jump (done_label);
1519 }
1520 else
1521 {
1522 delete_insns_since (last);
1523 icode = CODE_FOR_nothing;
1524 }
1525 }
1526
1527 if (icode == CODE_FOR_nothing)
1528 {
1529 /* Compute the operation. On RTL level, the addition is always
1530 unsigned. */
1531 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1532
1533 /* Compare the operand with the most negative value. */
1534 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1535 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1536 done_label, profile_probability::very_likely ());
1537 }
1538
1539 emit_label (do_error);
1540 if (is_ubsan)
1541 {
1542 /* Expand the ubsan builtin call. */
1543 push_temp_slots ();
1544 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1545 arg1, NULL_TREE, datap);
1546 expand_normal (fn);
1547 pop_temp_slots ();
1548 do_pending_stack_adjust ();
1549 }
1550 else if (lhs)
1551 expand_arith_set_overflow (lhs, target);
1552
1553 /* We're done. */
1554 emit_label (done_label);
1555
1556 if (lhs)
1557 {
1558 if (is_ubsan)
1559 expand_ubsan_result_store (lhs, target, mode, res, do_error);
1560 else
1561 expand_arith_overflow_result_store (lhs, target, mode, res);
1562 }
1563 }
1564
1565 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1566 mode MODE can be expanded without using a libcall. */
1567
1568 static bool
1569 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1570 rtx op0, rtx op1, bool uns)
1571 {
1572 if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1573 != CODE_FOR_nothing)
1574 return true;
1575
1576 if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1577 != CODE_FOR_nothing)
1578 return true;
1579
1580 rtx_insn *last = get_last_insn ();
1581 if (CONSTANT_P (op0))
1582 op0 = convert_modes (wmode, mode, op0, uns);
1583 else
1584 op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1585 if (CONSTANT_P (op1))
1586 op1 = convert_modes (wmode, mode, op1, uns);
1587 else
1588 op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1589 rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1590 delete_insns_since (last);
1591 return ret != NULL_RTX;
1592 }
1593
1594 /* Add mul overflow checking to the statement STMT. */
1595
1596 static void
1597 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1598 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1599 tree *datap)
1600 {
1601 rtx res, op0, op1;
1602 tree fn, type;
1603 rtx_code_label *done_label, *do_error;
1604 rtx target = NULL_RTX;
1605 signop sign;
1606 enum insn_code icode;
1607
1608 done_label = gen_label_rtx ();
1609 do_error = gen_label_rtx ();
1610
1611 do_pending_stack_adjust ();
1612 op0 = expand_normal (arg0);
1613 op1 = expand_normal (arg1);
1614
1615 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1616 bool uns = unsr_p;
1617 if (lhs)
1618 {
1619 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1620 if (!is_ubsan)
1621 write_complex_part (target, const0_rtx, true, false);
1622 }
1623
1624 if (is_ubsan)
1625 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1626
1627 /* We assume both operands and result have the same precision
1628 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1629 with that precision, U for unsigned type with that precision,
1630 sgn for unsigned most significant bit in that precision.
1631 s1 is signed first operand, u1 is unsigned first operand,
1632 s2 is signed second operand, u2 is unsigned second operand,
1633 sr is signed result, ur is unsigned result and the following
1634 rules say how to compute result (which is always result of
1635 the operands as if both were unsigned, cast to the right
1636 signedness) and how to compute whether operation overflowed.
1637 main_ovf (false) stands for jump on signed multiplication
1638 overflow or the main algorithm with uns == false.
1639 main_ovf (true) stands for jump on unsigned multiplication
1640 overflow or the main algorithm with uns == true.
1641
1642 s1 * s2 -> sr
1643 res = (S) ((U) s1 * (U) s2)
1644 ovf = main_ovf (false)
1645 u1 * u2 -> ur
1646 res = u1 * u2
1647 ovf = main_ovf (true)
1648 s1 * u2 -> ur
1649 res = (U) s1 * u2
1650 ovf = (s1 < 0 && u2) || main_ovf (true)
1651 u1 * u2 -> sr
1652 res = (S) (u1 * u2)
1653 ovf = res < 0 || main_ovf (true)
1654 s1 * u2 -> sr
1655 res = (S) ((U) s1 * u2)
1656 ovf = (S) u2 >= 0 ? main_ovf (false)
1657 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1658 s1 * s2 -> ur
1659 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1660 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1661 res = t1 * t2
1662 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1663
1664 if (uns0_p && !uns1_p)
1665 {
1666 /* Multiplication is commutative, if operand signedness differs,
1667 canonicalize to the first operand being signed and second
1668 unsigned to simplify following code. */
1669 std::swap (op0, op1);
1670 std::swap (arg0, arg1);
1671 uns0_p = false;
1672 uns1_p = true;
1673 }
1674
1675 int pos_neg0 = get_range_pos_neg (arg0);
1676 int pos_neg1 = get_range_pos_neg (arg1);
1677 /* Unsigned types with smaller than mode precision, even if they have most
1678 significant bit set, are still zero-extended. */
1679 if (uns0_p && TYPE_PRECISION (TREE_TYPE (arg0)) < GET_MODE_PRECISION (mode))
1680 pos_neg0 = 1;
1681 if (uns1_p && TYPE_PRECISION (TREE_TYPE (arg1)) < GET_MODE_PRECISION (mode))
1682 pos_neg1 = 1;
1683
1684 /* s1 * u2 -> ur */
1685 if (!uns0_p && uns1_p && unsr_p)
1686 {
1687 switch (pos_neg0)
1688 {
1689 case 1:
1690 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1691 goto do_main;
1692 case 2:
1693 /* If s1 is negative, avoid the main code, just multiply and
1694 signal overflow if op1 is not 0. */
1695 struct separate_ops ops;
1696 ops.code = MULT_EXPR;
1697 ops.type = TREE_TYPE (arg1);
1698 ops.op0 = make_tree (ops.type, op0);
1699 ops.op1 = make_tree (ops.type, op1);
1700 ops.op2 = NULL_TREE;
1701 ops.location = loc;
1702 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1703 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1704 NULL, done_label, profile_probability::very_likely ());
1705 goto do_error_label;
1706 case 3:
1707 if (get_min_precision (arg1, UNSIGNED)
1708 + get_min_precision (arg0, SIGNED) <= GET_MODE_PRECISION (mode))
1709 {
1710 /* If the first operand is sign extended from narrower type, the
1711 second operand is zero extended from narrower type and
1712 the sum of the two precisions is smaller or equal to the
1713 result precision: if the first argument is at runtime
1714 non-negative, maximum result will be 0x7e81 or 0x7f..fe80..01
1715 and there will be no overflow, if the first argument is
1716 negative and the second argument zero, the result will be
1717 0 and there will be no overflow, if the first argument is
1718 negative and the second argument positive, the result when
1719 treated as signed will be negative (minimum -0x7f80 or
1720 -0x7f..f80..0) there will be always overflow. So, do
1721 res = (U) (s1 * u2)
1722 ovf = (S) res < 0 */
1723 struct separate_ops ops;
1724 ops.code = MULT_EXPR;
1725 ops.type
1726 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1727 1);
1728 ops.op0 = make_tree (ops.type, op0);
1729 ops.op1 = make_tree (ops.type, op1);
1730 ops.op2 = NULL_TREE;
1731 ops.location = loc;
1732 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1733 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1734 mode, NULL_RTX, NULL, done_label,
1735 profile_probability::very_likely ());
1736 goto do_error_label;
1737 }
1738 rtx_code_label *do_main_label;
1739 do_main_label = gen_label_rtx ();
1740 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1741 NULL, do_main_label, profile_probability::very_likely ());
1742 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1743 NULL, do_main_label, profile_probability::very_likely ());
1744 expand_arith_set_overflow (lhs, target);
1745 emit_label (do_main_label);
1746 goto do_main;
1747 default:
1748 gcc_unreachable ();
1749 }
1750 }
1751
1752 /* u1 * u2 -> sr */
1753 if (uns0_p && uns1_p && !unsr_p)
1754 {
1755 if ((pos_neg0 | pos_neg1) == 1)
1756 {
1757 /* If both arguments are zero extended from narrower types,
1758 the MSB will be clear on both and so we can pretend it is
1759 a normal s1 * s2 -> sr multiplication. */
1760 uns0_p = false;
1761 uns1_p = false;
1762 }
1763 else
1764 uns = true;
1765 /* Rest of handling of this case after res is computed. */
1766 goto do_main;
1767 }
1768
1769 /* s1 * u2 -> sr */
1770 if (!uns0_p && uns1_p && !unsr_p)
1771 {
1772 switch (pos_neg1)
1773 {
1774 case 1:
1775 goto do_main;
1776 case 2:
1777 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1778 avoid the main code, just multiply and signal overflow
1779 unless 0 * u2 or -1 * ((U) Smin). */
1780 struct separate_ops ops;
1781 ops.code = MULT_EXPR;
1782 ops.type = TREE_TYPE (arg1);
1783 ops.op0 = make_tree (ops.type, op0);
1784 ops.op1 = make_tree (ops.type, op1);
1785 ops.op2 = NULL_TREE;
1786 ops.location = loc;
1787 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1788 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1789 NULL, done_label, profile_probability::very_likely ());
1790 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1791 NULL, do_error, profile_probability::very_unlikely ());
1792 int prec;
1793 prec = GET_MODE_PRECISION (mode);
1794 rtx sgn;
1795 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1796 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1797 NULL, done_label, profile_probability::very_likely ());
1798 goto do_error_label;
1799 case 3:
1800 /* Rest of handling of this case after res is computed. */
1801 goto do_main;
1802 default:
1803 gcc_unreachable ();
1804 }
1805 }
1806
1807 /* s1 * s2 -> ur */
1808 if (!uns0_p && !uns1_p && unsr_p)
1809 {
1810 rtx tem;
1811 switch (pos_neg0 | pos_neg1)
1812 {
1813 case 1: /* Both operands known to be non-negative. */
1814 goto do_main;
1815 case 2: /* Both operands known to be negative. */
1816 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1817 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1818 /* Avoid looking at arg0/arg1 ranges, as we've changed
1819 the arguments. */
1820 arg0 = error_mark_node;
1821 arg1 = error_mark_node;
1822 goto do_main;
1823 case 3:
1824 if ((pos_neg0 ^ pos_neg1) == 3)
1825 {
1826 /* If one operand is known to be negative and the other
1827 non-negative, this overflows always, unless the non-negative
1828 one is 0. Just do normal multiply and set overflow
1829 unless one of the operands is 0. */
1830 struct separate_ops ops;
1831 ops.code = MULT_EXPR;
1832 ops.type
1833 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1834 1);
1835 ops.op0 = make_tree (ops.type, op0);
1836 ops.op1 = make_tree (ops.type, op1);
1837 ops.op2 = NULL_TREE;
1838 ops.location = loc;
1839 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1840 do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
1841 true, mode, NULL_RTX, NULL, done_label,
1842 profile_probability::very_likely ());
1843 goto do_error_label;
1844 }
1845 if (get_min_precision (arg0, SIGNED)
1846 + get_min_precision (arg1, SIGNED) <= GET_MODE_PRECISION (mode))
1847 {
1848 /* If both operands are sign extended from narrower types and
1849 the sum of the two precisions is smaller or equal to the
1850 result precision: if both arguments are at runtime
1851 non-negative, maximum result will be 0x3f01 or 0x3f..f0..01
1852 and there will be no overflow, if both arguments are negative,
1853 maximum result will be 0x40..00 and there will be no overflow
1854 either, if one argument is positive and the other argument
1855 negative, the result when treated as signed will be negative
1856 and there will be always overflow, and if one argument is
1857 zero and the other negative the result will be zero and no
1858 overflow. So, do
1859 res = (U) (s1 * s2)
1860 ovf = (S) res < 0 */
1861 struct separate_ops ops;
1862 ops.code = MULT_EXPR;
1863 ops.type
1864 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1865 1);
1866 ops.op0 = make_tree (ops.type, op0);
1867 ops.op1 = make_tree (ops.type, op1);
1868 ops.op2 = NULL_TREE;
1869 ops.location = loc;
1870 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1871 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1872 mode, NULL_RTX, NULL, done_label,
1873 profile_probability::very_likely ());
1874 goto do_error_label;
1875 }
1876 /* The general case, do all the needed comparisons at runtime. */
1877 rtx_code_label *do_main_label, *after_negate_label;
1878 rtx rop0, rop1;
1879 rop0 = gen_reg_rtx (mode);
1880 rop1 = gen_reg_rtx (mode);
1881 emit_move_insn (rop0, op0);
1882 emit_move_insn (rop1, op1);
1883 op0 = rop0;
1884 op1 = rop1;
1885 do_main_label = gen_label_rtx ();
1886 after_negate_label = gen_label_rtx ();
1887 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1888 OPTAB_LIB_WIDEN);
1889 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1890 NULL, after_negate_label, profile_probability::very_likely ());
1891 /* Both arguments negative here, negate them and continue with
1892 normal unsigned overflow checking multiplication. */
1893 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1894 NULL_RTX, false));
1895 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1896 NULL_RTX, false));
1897 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1898 the arguments. */
1899 arg0 = error_mark_node;
1900 arg1 = error_mark_node;
1901 emit_jump (do_main_label);
1902 emit_label (after_negate_label);
1903 tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1904 OPTAB_LIB_WIDEN);
1905 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1906 NULL, do_main_label,
1907 profile_probability::very_likely ());
1908 /* One argument is negative here, the other positive. This
1909 overflows always, unless one of the arguments is 0. But
1910 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1911 is, thus we can keep do_main code oring in overflow as is. */
1912 if (pos_neg0 != 2)
1913 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1914 NULL, do_main_label,
1915 profile_probability::very_unlikely ());
1916 if (pos_neg1 != 2)
1917 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1918 NULL, do_main_label,
1919 profile_probability::very_unlikely ());
1920 expand_arith_set_overflow (lhs, target);
1921 emit_label (do_main_label);
1922 goto do_main;
1923 default:
1924 gcc_unreachable ();
1925 }
1926 }
1927
1928 do_main:
1929 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1930 sign = uns ? UNSIGNED : SIGNED;
1931 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1932 if (uns
1933 && (integer_pow2p (arg0) || integer_pow2p (arg1))
1934 && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1935 {
1936 /* Optimize unsigned multiplication by power of 2 constant
1937 using 2 shifts, one for result, one to extract the shifted
1938 out bits to see if they are all zero.
1939 Don't do this if optimizing for size and we have umulv4_optab,
1940 in that case assume multiplication will be shorter.
1941 This is heuristics based on the single target that provides
1942 umulv4 right now (i?86/x86_64), if further targets add it, this
1943 might need to be revisited.
1944 Cases where both operands are constant should be folded already
1945 during GIMPLE, and cases where one operand is constant but not
1946 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1947 below can be done without multiplication, just by shifts and adds,
1948 or we'd need to divide the result (and hope it actually doesn't
1949 really divide nor multiply) and compare the result of the division
1950 with the original operand. */
1951 rtx opn0 = op0;
1952 rtx opn1 = op1;
1953 tree argn0 = arg0;
1954 tree argn1 = arg1;
1955 if (integer_pow2p (arg0))
1956 {
1957 std::swap (opn0, opn1);
1958 std::swap (argn0, argn1);
1959 }
1960 int cnt = tree_log2 (argn1);
1961 if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1962 {
1963 rtx upper = const0_rtx;
1964 res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1965 if (cnt != 0)
1966 upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1967 GET_MODE_PRECISION (mode) - cnt,
1968 NULL_RTX, uns);
1969 do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1970 NULL_RTX, NULL, done_label,
1971 profile_probability::very_likely ());
1972 goto do_error_label;
1973 }
1974 }
1975 if (icode != CODE_FOR_nothing)
1976 {
1977 class expand_operand ops[4];
1978 rtx_insn *last = get_last_insn ();
1979
1980 res = gen_reg_rtx (mode);
1981 create_output_operand (&ops[0], res, mode);
1982 create_input_operand (&ops[1], op0, mode);
1983 create_input_operand (&ops[2], op1, mode);
1984 create_fixed_operand (&ops[3], do_error);
1985 if (maybe_expand_insn (icode, 4, ops))
1986 {
1987 last = get_last_insn ();
1988 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1989 && JUMP_P (last)
1990 && any_condjump_p (last)
1991 && !find_reg_note (last, REG_BR_PROB, 0))
1992 add_reg_br_prob_note (last,
1993 profile_probability::very_unlikely ());
1994 emit_jump (done_label);
1995 }
1996 else
1997 {
1998 delete_insns_since (last);
1999 icode = CODE_FOR_nothing;
2000 }
2001 }
2002
2003 if (icode == CODE_FOR_nothing)
2004 {
2005 struct separate_ops ops;
2006 int prec = GET_MODE_PRECISION (mode);
2007 scalar_int_mode hmode, wmode;
2008 ops.op0 = make_tree (type, op0);
2009 ops.op1 = make_tree (type, op1);
2010 ops.op2 = NULL_TREE;
2011 ops.location = loc;
2012
2013 /* Optimize unsigned overflow check where we don't use the
2014 multiplication result, just whether overflow happened.
2015 If we can do MULT_HIGHPART_EXPR, that followed by
2016 comparison of the result against zero is cheapest.
2017 We'll still compute res, but it should be DCEd later. */
2018 use_operand_p use;
2019 gimple *use_stmt;
2020 if (!is_ubsan
2021 && lhs
2022 && uns
2023 && !(uns0_p && uns1_p && !unsr_p)
2024 && can_mult_highpart_p (mode, uns) == 1
2025 && single_imm_use (lhs, &use, &use_stmt)
2026 && is_gimple_assign (use_stmt)
2027 && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
2028 goto highpart;
2029
2030 if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
2031 && targetm.scalar_mode_supported_p (wmode)
2032 && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
2033 {
2034 twoxwider:
2035 ops.code = WIDEN_MULT_EXPR;
2036 ops.type
2037 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
2038
2039 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
2040 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
2041 NULL_RTX, uns);
2042 hipart = convert_modes (mode, wmode, hipart, uns);
2043 res = convert_modes (mode, wmode, res, uns);
2044 if (uns)
2045 /* For the unsigned multiplication, there was overflow if
2046 HIPART is non-zero. */
2047 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
2048 NULL_RTX, NULL, done_label,
2049 profile_probability::very_likely ());
2050 else
2051 {
2052 /* RES is used more than once, place it in a pseudo. */
2053 res = force_reg (mode, res);
2054
2055 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
2056 NULL_RTX, 0);
2057 /* RES is low half of the double width result, HIPART
2058 the high half. There was overflow if
2059 HIPART is different from RES < 0 ? -1 : 0. */
2060 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
2061 NULL_RTX, NULL, done_label,
2062 profile_probability::very_likely ());
2063 }
2064 }
2065 else if (can_mult_highpart_p (mode, uns) == 1)
2066 {
2067 highpart:
2068 ops.code = MULT_HIGHPART_EXPR;
2069 ops.type = type;
2070
2071 rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
2072 EXPAND_NORMAL);
2073 ops.code = MULT_EXPR;
2074 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2075 if (uns)
2076 /* For the unsigned multiplication, there was overflow if
2077 HIPART is non-zero. */
2078 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
2079 NULL_RTX, NULL, done_label,
2080 profile_probability::very_likely ());
2081 else
2082 {
2083 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
2084 NULL_RTX, 0);
2085 /* RES is low half of the double width result, HIPART
2086 the high half. There was overflow if
2087 HIPART is different from RES < 0 ? -1 : 0. */
2088 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
2089 NULL_RTX, NULL, done_label,
2090 profile_probability::very_likely ());
2091 }
2092
2093 }
2094 else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
2095 && 2 * GET_MODE_PRECISION (hmode) == prec)
2096 {
2097 rtx_code_label *large_op0 = gen_label_rtx ();
2098 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
2099 rtx_code_label *one_small_one_large = gen_label_rtx ();
2100 rtx_code_label *both_ops_large = gen_label_rtx ();
2101 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
2102 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
2103 rtx_code_label *do_overflow = gen_label_rtx ();
2104 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
2105
2106 unsigned int hprec = GET_MODE_PRECISION (hmode);
2107 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
2108 NULL_RTX, uns);
2109 hipart0 = convert_modes (hmode, mode, hipart0, uns);
2110 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
2111 rtx signbit0 = const0_rtx;
2112 if (!uns)
2113 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
2114 NULL_RTX, 0);
2115 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
2116 NULL_RTX, uns);
2117 hipart1 = convert_modes (hmode, mode, hipart1, uns);
2118 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
2119 rtx signbit1 = const0_rtx;
2120 if (!uns)
2121 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
2122 NULL_RTX, 0);
2123
2124 res = gen_reg_rtx (mode);
2125
2126 /* True if op0 resp. op1 are known to be in the range of
2127 halfstype. */
2128 bool op0_small_p = false;
2129 bool op1_small_p = false;
2130 /* True if op0 resp. op1 are known to have all zeros or all ones
2131 in the upper half of bits, but are not known to be
2132 op{0,1}_small_p. */
2133 bool op0_medium_p = false;
2134 bool op1_medium_p = false;
2135 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
2136 nonnegative, 1 if unknown. */
2137 int op0_sign = 1;
2138 int op1_sign = 1;
2139
2140 if (pos_neg0 == 1)
2141 op0_sign = 0;
2142 else if (pos_neg0 == 2)
2143 op0_sign = -1;
2144 if (pos_neg1 == 1)
2145 op1_sign = 0;
2146 else if (pos_neg1 == 2)
2147 op1_sign = -1;
2148
2149 unsigned int mprec0 = prec;
2150 if (arg0 != error_mark_node)
2151 mprec0 = get_min_precision (arg0, sign);
2152 if (mprec0 <= hprec)
2153 op0_small_p = true;
2154 else if (!uns && mprec0 <= hprec + 1)
2155 op0_medium_p = true;
2156 unsigned int mprec1 = prec;
2157 if (arg1 != error_mark_node)
2158 mprec1 = get_min_precision (arg1, sign);
2159 if (mprec1 <= hprec)
2160 op1_small_p = true;
2161 else if (!uns && mprec1 <= hprec + 1)
2162 op1_medium_p = true;
2163
2164 int smaller_sign = 1;
2165 int larger_sign = 1;
2166 if (op0_small_p)
2167 {
2168 smaller_sign = op0_sign;
2169 larger_sign = op1_sign;
2170 }
2171 else if (op1_small_p)
2172 {
2173 smaller_sign = op1_sign;
2174 larger_sign = op0_sign;
2175 }
2176 else if (op0_sign == op1_sign)
2177 {
2178 smaller_sign = op0_sign;
2179 larger_sign = op0_sign;
2180 }
2181
2182 if (!op0_small_p)
2183 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
2184 NULL_RTX, NULL, large_op0,
2185 profile_probability::unlikely ());
2186
2187 if (!op1_small_p)
2188 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2189 NULL_RTX, NULL, small_op0_large_op1,
2190 profile_probability::unlikely ());
2191
2192 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
2193 hmode to mode, the multiplication will never overflow. We can
2194 do just one hmode x hmode => mode widening multiplication. */
2195 tree halfstype = build_nonstandard_integer_type (hprec, uns);
2196 ops.op0 = make_tree (halfstype, lopart0);
2197 ops.op1 = make_tree (halfstype, lopart1);
2198 ops.code = WIDEN_MULT_EXPR;
2199 ops.type = type;
2200 rtx thisres
2201 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2202 emit_move_insn (res, thisres);
2203 emit_jump (done_label);
2204
2205 emit_label (small_op0_large_op1);
2206
2207 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
2208 but op1 is not, just swap the arguments and handle it as op1
2209 sign/zero extended, op0 not. */
2210 rtx larger = gen_reg_rtx (mode);
2211 rtx hipart = gen_reg_rtx (hmode);
2212 rtx lopart = gen_reg_rtx (hmode);
2213 emit_move_insn (larger, op1);
2214 emit_move_insn (hipart, hipart1);
2215 emit_move_insn (lopart, lopart0);
2216 emit_jump (one_small_one_large);
2217
2218 emit_label (large_op0);
2219
2220 if (!op1_small_p)
2221 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2222 NULL_RTX, NULL, both_ops_large,
2223 profile_probability::unlikely ());
2224
2225 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
2226 but op0 is not, prepare larger, hipart and lopart pseudos and
2227 handle it together with small_op0_large_op1. */
2228 emit_move_insn (larger, op0);
2229 emit_move_insn (hipart, hipart0);
2230 emit_move_insn (lopart, lopart1);
2231
2232 emit_label (one_small_one_large);
2233
2234 /* lopart is the low part of the operand that is sign extended
2235 to mode, larger is the other operand, hipart is the
2236 high part of larger and lopart0 and lopart1 are the low parts
2237 of both operands.
2238 We perform lopart0 * lopart1 and lopart * hipart widening
2239 multiplications. */
2240 tree halfutype = build_nonstandard_integer_type (hprec, 1);
2241 ops.op0 = make_tree (halfutype, lopart0);
2242 ops.op1 = make_tree (halfutype, lopart1);
2243 rtx lo0xlo1
2244 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2245
2246 ops.op0 = make_tree (halfutype, lopart);
2247 ops.op1 = make_tree (halfutype, hipart);
2248 rtx loxhi = gen_reg_rtx (mode);
2249 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2250 emit_move_insn (loxhi, tem);
2251
2252 if (!uns)
2253 {
2254 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
2255 if (larger_sign == 0)
2256 emit_jump (after_hipart_neg);
2257 else if (larger_sign != -1)
2258 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
2259 NULL_RTX, NULL, after_hipart_neg,
2260 profile_probability::even ());
2261
2262 tem = convert_modes (mode, hmode, lopart, 1);
2263 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
2264 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
2265 1, OPTAB_WIDEN);
2266 emit_move_insn (loxhi, tem);
2267
2268 emit_label (after_hipart_neg);
2269
2270 /* if (lopart < 0) loxhi -= larger; */
2271 if (smaller_sign == 0)
2272 emit_jump (after_lopart_neg);
2273 else if (smaller_sign != -1)
2274 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
2275 NULL_RTX, NULL, after_lopart_neg,
2276 profile_probability::even ());
2277
2278 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
2279 1, OPTAB_WIDEN);
2280 emit_move_insn (loxhi, tem);
2281
2282 emit_label (after_lopart_neg);
2283 }
2284
2285 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
2286 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
2287 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
2288 1, OPTAB_WIDEN);
2289 emit_move_insn (loxhi, tem);
2290
2291 /* if (loxhi >> (bitsize / 2)
2292 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
2293 if (loxhi >> (bitsize / 2) == 0 (if uns). */
2294 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
2295 NULL_RTX, 0);
2296 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
2297 rtx signbitloxhi = const0_rtx;
2298 if (!uns)
2299 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
2300 convert_modes (hmode, mode,
2301 loxhi, 0),
2302 hprec - 1, NULL_RTX, 0);
2303
2304 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
2305 NULL_RTX, NULL, do_overflow,
2306 profile_probability::very_unlikely ());
2307
2308 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
2309 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
2310 NULL_RTX, 1);
2311 tem = convert_modes (mode, hmode,
2312 convert_modes (hmode, mode, lo0xlo1, 1), 1);
2313
2314 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
2315 1, OPTAB_WIDEN);
2316 if (tem != res)
2317 emit_move_insn (res, tem);
2318 emit_jump (done_label);
2319
2320 emit_label (both_ops_large);
2321
2322 /* If both operands are large (not sign (!uns) or zero (uns)
2323 extended from hmode), then perform the full multiplication
2324 which will be the result of the operation.
2325 The only cases which don't overflow are for signed multiplication
2326 some cases where both hipart0 and highpart1 are 0 or -1.
2327 For unsigned multiplication when high parts are both non-zero
2328 this overflows always. */
2329 ops.code = MULT_EXPR;
2330 ops.op0 = make_tree (type, op0);
2331 ops.op1 = make_tree (type, op1);
2332 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2333 emit_move_insn (res, tem);
2334
2335 if (!uns)
2336 {
2337 if (!op0_medium_p)
2338 {
2339 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
2340 NULL_RTX, 1, OPTAB_WIDEN);
2341 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2342 NULL_RTX, NULL, do_error,
2343 profile_probability::very_unlikely ());
2344 }
2345
2346 if (!op1_medium_p)
2347 {
2348 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
2349 NULL_RTX, 1, OPTAB_WIDEN);
2350 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2351 NULL_RTX, NULL, do_error,
2352 profile_probability::very_unlikely ());
2353 }
2354
2355 /* At this point hipart{0,1} are both in [-1, 0]. If they are
2356 the same, overflow happened if res is non-positive, if they
2357 are different, overflow happened if res is positive. */
2358 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
2359 emit_jump (hipart_different);
2360 else if (op0_sign == 1 || op1_sign == 1)
2361 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
2362 NULL_RTX, NULL, hipart_different,
2363 profile_probability::even ());
2364
2365 do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
2366 NULL_RTX, NULL, do_error,
2367 profile_probability::very_unlikely ());
2368 emit_jump (done_label);
2369
2370 emit_label (hipart_different);
2371
2372 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
2373 NULL_RTX, NULL, do_error,
2374 profile_probability::very_unlikely ());
2375 emit_jump (done_label);
2376 }
2377
2378 emit_label (do_overflow);
2379
2380 /* Overflow, do full multiplication and fallthru into do_error. */
2381 ops.op0 = make_tree (type, op0);
2382 ops.op1 = make_tree (type, op1);
2383 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2384 emit_move_insn (res, tem);
2385 }
2386 else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
2387 && targetm.scalar_mode_supported_p (wmode))
2388 /* Even emitting a libcall is better than not detecting overflow
2389 at all. */
2390 goto twoxwider;
2391 else
2392 {
2393 gcc_assert (!is_ubsan);
2394 ops.code = MULT_EXPR;
2395 ops.type = type;
2396 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2397 emit_jump (done_label);
2398 }
2399 }
2400
2401 do_error_label:
2402 emit_label (do_error);
2403 if (is_ubsan)
2404 {
2405 /* Expand the ubsan builtin call. */
2406 push_temp_slots ();
2407 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
2408 arg0, arg1, datap);
2409 expand_normal (fn);
2410 pop_temp_slots ();
2411 do_pending_stack_adjust ();
2412 }
2413 else if (lhs)
2414 expand_arith_set_overflow (lhs, target);
2415
2416 /* We're done. */
2417 emit_label (done_label);
2418
2419 /* u1 * u2 -> sr */
2420 if (uns0_p && uns1_p && !unsr_p)
2421 {
2422 rtx_code_label *all_done_label = gen_label_rtx ();
2423 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
2424 NULL, all_done_label, profile_probability::very_likely ());
2425 expand_arith_set_overflow (lhs, target);
2426 emit_label (all_done_label);
2427 }
2428
2429 /* s1 * u2 -> sr */
2430 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
2431 {
2432 rtx_code_label *all_done_label = gen_label_rtx ();
2433 rtx_code_label *set_noovf = gen_label_rtx ();
2434 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
2435 NULL, all_done_label, profile_probability::very_likely ());
2436 expand_arith_set_overflow (lhs, target);
2437 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
2438 NULL, set_noovf, profile_probability::very_likely ());
2439 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
2440 NULL, all_done_label, profile_probability::very_unlikely ());
2441 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
2442 all_done_label, profile_probability::very_unlikely ());
2443 emit_label (set_noovf);
2444 write_complex_part (target, const0_rtx, true, false);
2445 emit_label (all_done_label);
2446 }
2447
2448 if (lhs)
2449 {
2450 if (is_ubsan)
2451 expand_ubsan_result_store (lhs, target, mode, res, do_error);
2452 else
2453 expand_arith_overflow_result_store (lhs, target, mode, res);
2454 }
2455 }
2456
2457 /* Expand UBSAN_CHECK_* internal function if it has vector operands. */
2458
2459 static void
2460 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2461 tree arg0, tree arg1)
2462 {
2463 poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2464 rtx_code_label *loop_lab = NULL;
2465 rtx cntvar = NULL_RTX;
2466 tree cntv = NULL_TREE;
2467 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2468 tree sz = TYPE_SIZE (eltype);
2469 tree data = NULL_TREE;
2470 tree resv = NULL_TREE;
2471 rtx lhsr = NULL_RTX;
2472 rtx resvr = NULL_RTX;
2473 unsigned HOST_WIDE_INT const_cnt = 0;
2474 bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
2475
2476 if (lhs)
2477 {
2478 optab op;
2479 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2480 if (!VECTOR_MODE_P (GET_MODE (lhsr))
2481 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2482 optab_default)) == unknown_optab
2483 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2484 == CODE_FOR_nothing))
2485 {
2486 if (MEM_P (lhsr))
2487 resv = make_tree (TREE_TYPE (lhs), lhsr);
2488 else
2489 {
2490 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2491 resv = make_tree (TREE_TYPE (lhs), resvr);
2492 }
2493 }
2494 }
2495 if (use_loop_p)
2496 {
2497 do_pending_stack_adjust ();
2498 loop_lab = gen_label_rtx ();
2499 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2500 cntv = make_tree (sizetype, cntvar);
2501 emit_move_insn (cntvar, const0_rtx);
2502 emit_label (loop_lab);
2503 }
2504 if (TREE_CODE (arg0) != VECTOR_CST)
2505 {
2506 rtx arg0r = expand_normal (arg0);
2507 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2508 }
2509 if (TREE_CODE (arg1) != VECTOR_CST)
2510 {
2511 rtx arg1r = expand_normal (arg1);
2512 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2513 }
2514 for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
2515 {
2516 tree op0, op1, res = NULL_TREE;
2517 if (use_loop_p)
2518 {
2519 tree atype = build_array_type_nelts (eltype, cnt);
2520 op0 = uniform_vector_p (arg0);
2521 if (op0 == NULL_TREE)
2522 {
2523 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2524 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2525 NULL_TREE, NULL_TREE);
2526 }
2527 op1 = uniform_vector_p (arg1);
2528 if (op1 == NULL_TREE)
2529 {
2530 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2531 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2532 NULL_TREE, NULL_TREE);
2533 }
2534 if (resv)
2535 {
2536 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2537 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2538 NULL_TREE, NULL_TREE);
2539 }
2540 }
2541 else
2542 {
2543 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2544 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2545 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2546 if (resv)
2547 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2548 bitpos);
2549 }
2550 switch (code)
2551 {
2552 case PLUS_EXPR:
2553 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2554 false, false, false, true, &data);
2555 break;
2556 case MINUS_EXPR:
2557 if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
2558 expand_neg_overflow (loc, res, op1, true, &data);
2559 else
2560 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2561 false, false, false, true, &data);
2562 break;
2563 case MULT_EXPR:
2564 expand_mul_overflow (loc, res, op0, op1, false, false, false,
2565 true, &data);
2566 break;
2567 default:
2568 gcc_unreachable ();
2569 }
2570 }
2571 if (use_loop_p)
2572 {
2573 struct separate_ops ops;
2574 ops.code = PLUS_EXPR;
2575 ops.type = TREE_TYPE (cntv);
2576 ops.op0 = cntv;
2577 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2578 ops.op2 = NULL_TREE;
2579 ops.location = loc;
2580 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2581 EXPAND_NORMAL);
2582 if (ret != cntvar)
2583 emit_move_insn (cntvar, ret);
2584 rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2585 do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
2586 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2587 profile_probability::very_likely ());
2588 }
2589 if (lhs && resv == NULL_TREE)
2590 {
2591 struct separate_ops ops;
2592 ops.code = code;
2593 ops.type = TREE_TYPE (arg0);
2594 ops.op0 = arg0;
2595 ops.op1 = arg1;
2596 ops.op2 = NULL_TREE;
2597 ops.location = loc;
2598 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2599 EXPAND_NORMAL);
2600 if (ret != lhsr)
2601 emit_move_insn (lhsr, ret);
2602 }
2603 else if (resvr)
2604 emit_move_insn (lhsr, resvr);
2605 }
2606
2607 /* Expand UBSAN_CHECK_ADD call STMT. */
2608
2609 static void
2610 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2611 {
2612 location_t loc = gimple_location (stmt);
2613 tree lhs = gimple_call_lhs (stmt);
2614 tree arg0 = gimple_call_arg (stmt, 0);
2615 tree arg1 = gimple_call_arg (stmt, 1);
2616 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2617 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2618 else
2619 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2620 false, false, false, true, NULL);
2621 }
2622
2623 /* Expand UBSAN_CHECK_SUB call STMT. */
2624
2625 static void
2626 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2627 {
2628 location_t loc = gimple_location (stmt);
2629 tree lhs = gimple_call_lhs (stmt);
2630 tree arg0 = gimple_call_arg (stmt, 0);
2631 tree arg1 = gimple_call_arg (stmt, 1);
2632 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2633 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2634 else if (integer_zerop (arg0))
2635 expand_neg_overflow (loc, lhs, arg1, true, NULL);
2636 else
2637 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2638 false, false, false, true, NULL);
2639 }
2640
2641 /* Expand UBSAN_CHECK_MUL call STMT. */
2642
2643 static void
2644 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2645 {
2646 location_t loc = gimple_location (stmt);
2647 tree lhs = gimple_call_lhs (stmt);
2648 tree arg0 = gimple_call_arg (stmt, 0);
2649 tree arg1 = gimple_call_arg (stmt, 1);
2650 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2651 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2652 else
2653 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2654 NULL);
2655 }
2656
2657 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2658
2659 static void
2660 expand_arith_overflow (enum tree_code code, gimple *stmt)
2661 {
2662 tree lhs = gimple_call_lhs (stmt);
2663 if (lhs == NULL_TREE)
2664 return;
2665 tree arg0 = gimple_call_arg (stmt, 0);
2666 tree arg1 = gimple_call_arg (stmt, 1);
2667 tree type = TREE_TYPE (TREE_TYPE (lhs));
2668 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2669 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2670 int unsr_p = TYPE_UNSIGNED (type);
2671 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2672 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2673 int precres = TYPE_PRECISION (type);
2674 location_t loc = gimple_location (stmt);
2675 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2676 uns0_p = true;
2677 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2678 uns1_p = true;
2679 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2680 prec0 = MIN (prec0, pr);
2681 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2682 prec1 = MIN (prec1, pr);
2683
2684 /* If uns0_p && uns1_p, precop is minimum needed precision
2685 of unsigned type to hold the exact result, otherwise
2686 precop is minimum needed precision of signed type to
2687 hold the exact result. */
2688 int precop;
2689 if (code == MULT_EXPR)
2690 precop = prec0 + prec1 + (uns0_p != uns1_p);
2691 else
2692 {
2693 if (uns0_p == uns1_p)
2694 precop = MAX (prec0, prec1) + 1;
2695 else if (uns0_p)
2696 precop = MAX (prec0 + 1, prec1) + 1;
2697 else
2698 precop = MAX (prec0, prec1 + 1) + 1;
2699 }
2700 int orig_precres = precres;
2701
2702 do
2703 {
2704 if ((uns0_p && uns1_p)
2705 ? ((precop + !unsr_p) <= precres
2706 /* u1 - u2 -> ur can overflow, no matter what precision
2707 the result has. */
2708 && (code != MINUS_EXPR || !unsr_p))
2709 : (!unsr_p && precop <= precres))
2710 {
2711 /* The infinity precision result will always fit into result. */
2712 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2713 write_complex_part (target, const0_rtx, true, false);
2714 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2715 struct separate_ops ops;
2716 ops.code = code;
2717 ops.type = type;
2718 ops.op0 = fold_convert_loc (loc, type, arg0);
2719 ops.op1 = fold_convert_loc (loc, type, arg1);
2720 ops.op2 = NULL_TREE;
2721 ops.location = loc;
2722 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2723 expand_arith_overflow_result_store (lhs, target, mode, tem);
2724 return;
2725 }
2726
2727 /* For operations with low precision, if target doesn't have them, start
2728 with precres widening right away, otherwise do it only if the most
2729 simple cases can't be used. */
2730 const int min_precision = targetm.min_arithmetic_precision ();
2731 if (orig_precres == precres && precres < min_precision)
2732 ;
2733 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2734 && prec1 <= precres)
2735 || ((!uns0_p || !uns1_p) && !unsr_p
2736 && prec0 + uns0_p <= precres
2737 && prec1 + uns1_p <= precres))
2738 {
2739 arg0 = fold_convert_loc (loc, type, arg0);
2740 arg1 = fold_convert_loc (loc, type, arg1);
2741 switch (code)
2742 {
2743 case MINUS_EXPR:
2744 if (integer_zerop (arg0) && !unsr_p)
2745 {
2746 expand_neg_overflow (loc, lhs, arg1, false, NULL);
2747 return;
2748 }
2749 /* FALLTHRU */
2750 case PLUS_EXPR:
2751 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2752 unsr_p, unsr_p, false, NULL);
2753 return;
2754 case MULT_EXPR:
2755 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2756 unsr_p, unsr_p, false, NULL);
2757 return;
2758 default:
2759 gcc_unreachable ();
2760 }
2761 }
2762
2763 /* For sub-word operations, retry with a wider type first. */
2764 if (orig_precres == precres && precop <= BITS_PER_WORD)
2765 {
2766 int p = MAX (min_precision, precop);
2767 scalar_int_mode m = smallest_int_mode_for_size (p);
2768 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2769 uns0_p && uns1_p
2770 && unsr_p);
2771 p = TYPE_PRECISION (optype);
2772 if (p > precres)
2773 {
2774 precres = p;
2775 unsr_p = TYPE_UNSIGNED (optype);
2776 type = optype;
2777 continue;
2778 }
2779 }
2780
2781 if (prec0 <= precres && prec1 <= precres)
2782 {
2783 tree types[2];
2784 if (unsr_p)
2785 {
2786 types[0] = build_nonstandard_integer_type (precres, 0);
2787 types[1] = type;
2788 }
2789 else
2790 {
2791 types[0] = type;
2792 types[1] = build_nonstandard_integer_type (precres, 1);
2793 }
2794 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2795 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2796 if (code != MULT_EXPR)
2797 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2798 uns0_p, uns1_p, false, NULL);
2799 else
2800 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2801 uns0_p, uns1_p, false, NULL);
2802 return;
2803 }
2804
2805 /* Retry with a wider type. */
2806 if (orig_precres == precres)
2807 {
2808 int p = MAX (prec0, prec1);
2809 scalar_int_mode m = smallest_int_mode_for_size (p);
2810 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2811 uns0_p && uns1_p
2812 && unsr_p);
2813 p = TYPE_PRECISION (optype);
2814 if (p > precres)
2815 {
2816 precres = p;
2817 unsr_p = TYPE_UNSIGNED (optype);
2818 type = optype;
2819 continue;
2820 }
2821 }
2822
2823 gcc_unreachable ();
2824 }
2825 while (1);
2826 }
2827
2828 /* Expand ADD_OVERFLOW STMT. */
2829
2830 static void
2831 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2832 {
2833 expand_arith_overflow (PLUS_EXPR, stmt);
2834 }
2835
2836 /* Expand SUB_OVERFLOW STMT. */
2837
2838 static void
2839 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2840 {
2841 expand_arith_overflow (MINUS_EXPR, stmt);
2842 }
2843
2844 /* Expand MUL_OVERFLOW STMT. */
2845
2846 static void
2847 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2848 {
2849 expand_arith_overflow (MULT_EXPR, stmt);
2850 }
2851
2852 /* Expand UADDC STMT. */
2853
2854 static void
2855 expand_UADDC (internal_fn ifn, gcall *stmt)
2856 {
2857 tree lhs = gimple_call_lhs (stmt);
2858 tree arg1 = gimple_call_arg (stmt, 0);
2859 tree arg2 = gimple_call_arg (stmt, 1);
2860 tree arg3 = gimple_call_arg (stmt, 2);
2861 tree type = TREE_TYPE (arg1);
2862 machine_mode mode = TYPE_MODE (type);
2863 insn_code icode = optab_handler (ifn == IFN_UADDC
2864 ? uaddc5_optab : usubc5_optab, mode);
2865 rtx op1 = expand_normal (arg1);
2866 rtx op2 = expand_normal (arg2);
2867 rtx op3 = expand_normal (arg3);
2868 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2869 rtx re = gen_reg_rtx (mode);
2870 rtx im = gen_reg_rtx (mode);
2871 class expand_operand ops[5];
2872 create_output_operand (&ops[0], re, mode);
2873 create_output_operand (&ops[1], im, mode);
2874 create_input_operand (&ops[2], op1, mode);
2875 create_input_operand (&ops[3], op2, mode);
2876 create_input_operand (&ops[4], op3, mode);
2877 expand_insn (icode, 5, ops);
2878 write_complex_part (target, re, false, false);
2879 write_complex_part (target, im, true, false);
2880 }
2881
2882 /* Expand USUBC STMT. */
2883
2884 static void
2885 expand_USUBC (internal_fn ifn, gcall *stmt)
2886 {
2887 expand_UADDC (ifn, stmt);
2888 }
2889
2890 /* This should get folded in tree-vectorizer.cc. */
2891
2892 static void
2893 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2894 {
2895 gcc_unreachable ();
2896 }
2897
2898 /* This should get folded in tree-vectorizer.cc. */
2899
2900 static void
2901 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2902 {
2903 gcc_unreachable ();
2904 }
2905
2906 /* Return a memory reference of type TYPE for argument INDEX of STMT.
2907 Use argument INDEX + 1 to derive the second (TBAA) operand. */
2908
2909 static tree
2910 expand_call_mem_ref (tree type, gcall *stmt, int index)
2911 {
2912 tree addr = gimple_call_arg (stmt, index);
2913 tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2914 unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2915 if (TYPE_ALIGN (type) != align)
2916 type = build_aligned_type (type, align);
2917
2918 tree tmp = addr;
2919 if (TREE_CODE (tmp) == SSA_NAME)
2920 {
2921 gimple *def = SSA_NAME_DEF_STMT (tmp);
2922 if (gimple_assign_single_p (def))
2923 tmp = gimple_assign_rhs1 (def);
2924 }
2925
2926 if (TREE_CODE (tmp) == ADDR_EXPR)
2927 {
2928 tree mem = TREE_OPERAND (tmp, 0);
2929 if (TREE_CODE (mem) == TARGET_MEM_REF
2930 && types_compatible_p (TREE_TYPE (mem), type))
2931 {
2932 tree offset = TMR_OFFSET (mem);
2933 if (type != TREE_TYPE (mem)
2934 || alias_ptr_type != TREE_TYPE (offset)
2935 || !integer_zerop (offset))
2936 {
2937 mem = copy_node (mem);
2938 TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2939 wi::to_poly_wide (offset));
2940 TREE_TYPE (mem) = type;
2941 }
2942 return mem;
2943 }
2944 }
2945
2946 return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2947 }
2948
2949 /* Expand MASK_LOAD{,_LANES}, MASK_LEN_LOAD or LEN_LOAD call STMT using optab
2950 * OPTAB. */
2951
2952 static void
2953 expand_partial_load_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
2954 {
2955 int i = 0;
2956 class expand_operand ops[5];
2957 tree type, lhs, rhs, maskt;
2958 rtx mem, target;
2959 insn_code icode;
2960
2961 maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
2962 lhs = gimple_call_lhs (stmt);
2963 if (lhs == NULL_TREE)
2964 return;
2965 type = TREE_TYPE (lhs);
2966 rhs = expand_call_mem_ref (type, stmt, 0);
2967
2968 if (optab == vec_mask_load_lanes_optab
2969 || optab == vec_mask_len_load_lanes_optab)
2970 icode = get_multi_vector_move (type, optab);
2971 else if (optab == len_load_optab)
2972 icode = direct_optab_handler (optab, TYPE_MODE (type));
2973 else
2974 icode = convert_optab_handler (optab, TYPE_MODE (type),
2975 TYPE_MODE (TREE_TYPE (maskt)));
2976
2977 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2978 gcc_assert (MEM_P (mem));
2979 /* The built MEM_REF does not accurately reflect that the load
2980 is only partial. Clear it. */
2981 set_mem_expr (mem, NULL_TREE);
2982 clear_mem_offset (mem);
2983 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2984 create_output_operand (&ops[i++], target, TYPE_MODE (type));
2985 create_fixed_operand (&ops[i++], mem);
2986 i = add_mask_and_len_args (ops, i, stmt);
2987 expand_insn (icode, i, ops);
2988
2989 if (!rtx_equal_p (target, ops[0].value))
2990 emit_move_insn (target, ops[0].value);
2991 }
2992
2993 #define expand_mask_load_optab_fn expand_partial_load_optab_fn
2994 #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
2995 #define expand_len_load_optab_fn expand_partial_load_optab_fn
2996 #define expand_mask_len_load_optab_fn expand_partial_load_optab_fn
2997
2998 /* Expand MASK_STORE{,_LANES}, MASK_LEN_STORE or LEN_STORE call STMT using optab
2999 * OPTAB. */
3000
3001 static void
3002 expand_partial_store_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
3003 {
3004 int i = 0;
3005 class expand_operand ops[5];
3006 tree type, lhs, rhs, maskt;
3007 rtx mem, reg;
3008 insn_code icode;
3009
3010 maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
3011 rhs = gimple_call_arg (stmt, internal_fn_stored_value_index (ifn));
3012 type = TREE_TYPE (rhs);
3013 lhs = expand_call_mem_ref (type, stmt, 0);
3014
3015 if (optab == vec_mask_store_lanes_optab
3016 || optab == vec_mask_len_store_lanes_optab)
3017 icode = get_multi_vector_move (type, optab);
3018 else if (optab == len_store_optab)
3019 icode = direct_optab_handler (optab, TYPE_MODE (type));
3020 else
3021 icode = convert_optab_handler (optab, TYPE_MODE (type),
3022 TYPE_MODE (TREE_TYPE (maskt)));
3023
3024 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3025 gcc_assert (MEM_P (mem));
3026 /* The built MEM_REF does not accurately reflect that the store
3027 is only partial. Clear it. */
3028 set_mem_expr (mem, NULL_TREE);
3029 clear_mem_offset (mem);
3030 reg = expand_normal (rhs);
3031 create_fixed_operand (&ops[i++], mem);
3032 create_input_operand (&ops[i++], reg, TYPE_MODE (type));
3033 i = add_mask_and_len_args (ops, i, stmt);
3034 expand_insn (icode, i, ops);
3035 }
3036
3037 #define expand_mask_store_optab_fn expand_partial_store_optab_fn
3038 #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
3039 #define expand_len_store_optab_fn expand_partial_store_optab_fn
3040 #define expand_mask_len_store_optab_fn expand_partial_store_optab_fn
3041
3042 /* Expand VCOND, VCONDU and VCONDEQ optab internal functions.
3043 The expansion of STMT happens based on OPTAB table associated. */
3044
3045 static void
3046 expand_vec_cond_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3047 {
3048 class expand_operand ops[6];
3049 insn_code icode;
3050 tree lhs = gimple_call_lhs (stmt);
3051 tree op0a = gimple_call_arg (stmt, 0);
3052 tree op0b = gimple_call_arg (stmt, 1);
3053 tree op1 = gimple_call_arg (stmt, 2);
3054 tree op2 = gimple_call_arg (stmt, 3);
3055 enum tree_code tcode = (tree_code) int_cst_value (gimple_call_arg (stmt, 4));
3056
3057 tree vec_cond_type = TREE_TYPE (lhs);
3058 tree op_mode = TREE_TYPE (op0a);
3059 bool unsignedp = TYPE_UNSIGNED (op_mode);
3060
3061 machine_mode mode = TYPE_MODE (vec_cond_type);
3062 machine_mode cmp_op_mode = TYPE_MODE (op_mode);
3063
3064 icode = convert_optab_handler (optab, mode, cmp_op_mode);
3065 rtx comparison
3066 = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp, icode, 4);
3067 /* vector_compare_rtx legitimizes operands, preserve equality when
3068 expanding op1/op2. */
3069 rtx rtx_op1, rtx_op2;
3070 if (operand_equal_p (op1, op0a))
3071 rtx_op1 = XEXP (comparison, 0);
3072 else if (operand_equal_p (op1, op0b))
3073 rtx_op1 = XEXP (comparison, 1);
3074 else
3075 rtx_op1 = expand_normal (op1);
3076 if (operand_equal_p (op2, op0a))
3077 rtx_op2 = XEXP (comparison, 0);
3078 else if (operand_equal_p (op2, op0b))
3079 rtx_op2 = XEXP (comparison, 1);
3080 else
3081 rtx_op2 = expand_normal (op2);
3082
3083 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3084 create_output_operand (&ops[0], target, mode);
3085 create_input_operand (&ops[1], rtx_op1, mode);
3086 create_input_operand (&ops[2], rtx_op2, mode);
3087 create_fixed_operand (&ops[3], comparison);
3088 create_fixed_operand (&ops[4], XEXP (comparison, 0));
3089 create_fixed_operand (&ops[5], XEXP (comparison, 1));
3090 expand_insn (icode, 6, ops);
3091 if (!rtx_equal_p (ops[0].value, target))
3092 emit_move_insn (target, ops[0].value);
3093 }
3094
3095 /* Expand VCOND_MASK optab internal function.
3096 The expansion of STMT happens based on OPTAB table associated. */
3097
3098 static void
3099 expand_vec_cond_mask_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3100 {
3101 class expand_operand ops[4];
3102
3103 tree lhs = gimple_call_lhs (stmt);
3104 tree op0 = gimple_call_arg (stmt, 0);
3105 tree op1 = gimple_call_arg (stmt, 1);
3106 tree op2 = gimple_call_arg (stmt, 2);
3107 tree vec_cond_type = TREE_TYPE (lhs);
3108
3109 machine_mode mode = TYPE_MODE (vec_cond_type);
3110 machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
3111 enum insn_code icode = convert_optab_handler (optab, mode, mask_mode);
3112 rtx mask, rtx_op1, rtx_op2;
3113
3114 gcc_assert (icode != CODE_FOR_nothing);
3115
3116 mask = expand_normal (op0);
3117 rtx_op1 = expand_normal (op1);
3118 rtx_op2 = expand_normal (op2);
3119
3120 mask = force_reg (mask_mode, mask);
3121 rtx_op1 = force_reg (mode, rtx_op1);
3122
3123 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3124 create_output_operand (&ops[0], target, mode);
3125 create_input_operand (&ops[1], rtx_op1, mode);
3126 create_input_operand (&ops[2], rtx_op2, mode);
3127 create_input_operand (&ops[3], mask, mask_mode);
3128 expand_insn (icode, 4, ops);
3129 if (!rtx_equal_p (ops[0].value, target))
3130 emit_move_insn (target, ops[0].value);
3131 }
3132
3133 /* Expand VEC_SET internal functions. */
3134
3135 static void
3136 expand_vec_set_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3137 {
3138 tree lhs = gimple_call_lhs (stmt);
3139 tree op0 = gimple_call_arg (stmt, 0);
3140 tree op1 = gimple_call_arg (stmt, 1);
3141 tree op2 = gimple_call_arg (stmt, 2);
3142 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3143 rtx src = expand_normal (op0);
3144
3145 machine_mode outermode = TYPE_MODE (TREE_TYPE (op0));
3146 scalar_mode innermode = GET_MODE_INNER (outermode);
3147
3148 rtx value = expand_normal (op1);
3149 rtx pos = expand_normal (op2);
3150
3151 class expand_operand ops[3];
3152 enum insn_code icode = optab_handler (optab, outermode);
3153
3154 if (icode != CODE_FOR_nothing)
3155 {
3156 rtx temp = gen_reg_rtx (outermode);
3157 emit_move_insn (temp, src);
3158
3159 create_fixed_operand (&ops[0], temp);
3160 create_input_operand (&ops[1], value, innermode);
3161 create_convert_operand_from (&ops[2], pos, TYPE_MODE (TREE_TYPE (op2)),
3162 true);
3163 if (maybe_expand_insn (icode, 3, ops))
3164 {
3165 emit_move_insn (target, temp);
3166 return;
3167 }
3168 }
3169 gcc_unreachable ();
3170 }
3171
3172 static void
3173 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
3174 {
3175 }
3176
3177 static void
3178 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
3179 {
3180 /* When guessing was done, the hints should be already stripped away. */
3181 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
3182
3183 rtx target;
3184 tree lhs = gimple_call_lhs (stmt);
3185 if (lhs)
3186 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3187 else
3188 target = const0_rtx;
3189 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
3190 if (lhs && val != target)
3191 emit_move_insn (target, val);
3192 }
3193
3194 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
3195 should never be called. */
3196
3197 static void
3198 expand_VA_ARG (internal_fn, gcall *)
3199 {
3200 gcc_unreachable ();
3201 }
3202
3203 /* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector. So this
3204 dummy function should never be called. */
3205
3206 static void
3207 expand_VEC_CONVERT (internal_fn, gcall *)
3208 {
3209 gcc_unreachable ();
3210 }
3211
3212 /* Expand IFN_RAWMEMCHR internal function. */
3213
3214 void
3215 expand_RAWMEMCHR (internal_fn, gcall *stmt)
3216 {
3217 expand_operand ops[3];
3218
3219 tree lhs = gimple_call_lhs (stmt);
3220 if (!lhs)
3221 return;
3222 machine_mode lhs_mode = TYPE_MODE (TREE_TYPE (lhs));
3223 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3224 create_output_operand (&ops[0], lhs_rtx, lhs_mode);
3225
3226 tree mem = gimple_call_arg (stmt, 0);
3227 rtx mem_rtx = get_memory_rtx (mem, NULL);
3228 create_fixed_operand (&ops[1], mem_rtx);
3229
3230 tree pattern = gimple_call_arg (stmt, 1);
3231 machine_mode mode = TYPE_MODE (TREE_TYPE (pattern));
3232 rtx pattern_rtx = expand_normal (pattern);
3233 create_input_operand (&ops[2], pattern_rtx, mode);
3234
3235 insn_code icode = direct_optab_handler (rawmemchr_optab, mode);
3236
3237 expand_insn (icode, 3, ops);
3238 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3239 emit_move_insn (lhs_rtx, ops[0].value);
3240 }
3241
3242 /* Expand the IFN_UNIQUE function according to its first argument. */
3243
3244 static void
3245 expand_UNIQUE (internal_fn, gcall *stmt)
3246 {
3247 rtx pattern = NULL_RTX;
3248 enum ifn_unique_kind kind
3249 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
3250
3251 switch (kind)
3252 {
3253 default:
3254 gcc_unreachable ();
3255
3256 case IFN_UNIQUE_UNSPEC:
3257 if (targetm.have_unique ())
3258 pattern = targetm.gen_unique ();
3259 break;
3260
3261 case IFN_UNIQUE_OACC_FORK:
3262 case IFN_UNIQUE_OACC_JOIN:
3263 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
3264 {
3265 tree lhs = gimple_call_lhs (stmt);
3266 rtx target = const0_rtx;
3267
3268 if (lhs)
3269 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3270
3271 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
3272 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
3273
3274 if (kind == IFN_UNIQUE_OACC_FORK)
3275 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
3276 else
3277 pattern = targetm.gen_oacc_join (target, data_dep, axis);
3278 }
3279 else
3280 gcc_unreachable ();
3281 break;
3282 }
3283
3284 if (pattern)
3285 emit_insn (pattern);
3286 }
3287
3288 /* Expand the IFN_DEFERRED_INIT function:
3289 LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL);
3290
3291 Initialize the LHS with zero/pattern according to its second argument
3292 INIT_TYPE:
3293 if INIT_TYPE is AUTO_INIT_ZERO, use zeroes to initialize;
3294 if INIT_TYPE is AUTO_INIT_PATTERN, use 0xFE byte-repeatable pattern
3295 to initialize;
3296 The LHS variable is initialized including paddings.
3297 The reasons to choose 0xFE for pattern initialization are:
3298 1. It is a non-canonical virtual address on x86_64, and at the
3299 high end of the i386 kernel address space.
3300 2. It is a very large float value (-1.694739530317379e+38).
3301 3. It is also an unusual number for integers. */
3302 #define INIT_PATTERN_VALUE 0xFE
3303 static void
3304 expand_DEFERRED_INIT (internal_fn, gcall *stmt)
3305 {
3306 tree lhs = gimple_call_lhs (stmt);
3307 tree var_size = gimple_call_arg (stmt, 0);
3308 enum auto_init_type init_type
3309 = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
3310 bool reg_lhs = true;
3311
3312 tree var_type = TREE_TYPE (lhs);
3313 gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
3314
3315 if (TREE_CODE (lhs) == SSA_NAME)
3316 reg_lhs = true;
3317 else
3318 {
3319 tree lhs_base = lhs;
3320 while (handled_component_p (lhs_base))
3321 lhs_base = TREE_OPERAND (lhs_base, 0);
3322 reg_lhs = (mem_ref_refers_to_non_mem_p (lhs_base)
3323 || non_mem_decl_p (lhs_base));
3324 /* If this expands to a register and the underlying decl is wrapped in
3325 a MEM_REF that just serves as an access type change expose the decl
3326 if it is of correct size. This avoids a situation as in PR103271
3327 if the target does not support a direct move to the registers mode. */
3328 if (reg_lhs
3329 && TREE_CODE (lhs_base) == MEM_REF
3330 && TREE_CODE (TREE_OPERAND (lhs_base, 0)) == ADDR_EXPR
3331 && DECL_P (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))
3332 && integer_zerop (TREE_OPERAND (lhs_base, 1))
3333 && tree_fits_uhwi_p (var_size)
3334 && tree_int_cst_equal
3335 (var_size,
3336 DECL_SIZE_UNIT (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))))
3337 {
3338 lhs = TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0);
3339 var_type = TREE_TYPE (lhs);
3340 }
3341 }
3342
3343 if (!reg_lhs)
3344 {
3345 /* If the variable is not in register, expand to a memset
3346 to initialize it. */
3347 mark_addressable (lhs);
3348 tree var_addr = build_fold_addr_expr (lhs);
3349
3350 tree value = (init_type == AUTO_INIT_PATTERN)
3351 ? build_int_cst (integer_type_node,
3352 INIT_PATTERN_VALUE)
3353 : integer_zero_node;
3354 tree m_call = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMSET),
3355 3, var_addr, value, var_size);
3356 /* Expand this memset call. */
3357 expand_builtin_memset (m_call, NULL_RTX, TYPE_MODE (var_type));
3358 }
3359 else
3360 {
3361 /* If this variable is in a register use expand_assignment.
3362 For boolean scalars force zero-init. */
3363 tree init;
3364 scalar_int_mode var_mode;
3365 if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE
3366 && tree_fits_uhwi_p (var_size)
3367 && (init_type == AUTO_INIT_PATTERN
3368 || !is_gimple_reg_type (var_type))
3369 && int_mode_for_size (tree_to_uhwi (var_size) * BITS_PER_UNIT,
3370 0).exists (&var_mode)
3371 && have_insn_for (SET, var_mode))
3372 {
3373 unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
3374 unsigned char *buf = XALLOCAVEC (unsigned char, total_bytes);
3375 memset (buf, (init_type == AUTO_INIT_PATTERN
3376 ? INIT_PATTERN_VALUE : 0), total_bytes);
3377 tree itype = build_nonstandard_integer_type
3378 (total_bytes * BITS_PER_UNIT, 1);
3379 wide_int w = wi::from_buffer (buf, total_bytes);
3380 init = wide_int_to_tree (itype, w);
3381 /* Pun the LHS to make sure its type has constant size
3382 unless it is an SSA name where that's already known. */
3383 if (TREE_CODE (lhs) != SSA_NAME)
3384 lhs = build1 (VIEW_CONVERT_EXPR, itype, lhs);
3385 else
3386 init = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), init);
3387 }
3388 else
3389 /* Use zero-init also for variable-length sizes. */
3390 init = build_zero_cst (var_type);
3391
3392 expand_assignment (lhs, init, false);
3393 }
3394 }
3395
3396 /* The size of an OpenACC compute dimension. */
3397
3398 static void
3399 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
3400 {
3401 tree lhs = gimple_call_lhs (stmt);
3402
3403 if (!lhs)
3404 return;
3405
3406 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3407 if (targetm.have_oacc_dim_size ())
3408 {
3409 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3410 VOIDmode, EXPAND_NORMAL);
3411 emit_insn (targetm.gen_oacc_dim_size (target, dim));
3412 }
3413 else
3414 emit_move_insn (target, GEN_INT (1));
3415 }
3416
3417 /* The position of an OpenACC execution engine along one compute axis. */
3418
3419 static void
3420 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
3421 {
3422 tree lhs = gimple_call_lhs (stmt);
3423
3424 if (!lhs)
3425 return;
3426
3427 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3428 if (targetm.have_oacc_dim_pos ())
3429 {
3430 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3431 VOIDmode, EXPAND_NORMAL);
3432 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
3433 }
3434 else
3435 emit_move_insn (target, const0_rtx);
3436 }
3437
3438 /* This is expanded by oacc_device_lower pass. */
3439
3440 static void
3441 expand_GOACC_LOOP (internal_fn, gcall *)
3442 {
3443 gcc_unreachable ();
3444 }
3445
3446 /* This is expanded by oacc_device_lower pass. */
3447
3448 static void
3449 expand_GOACC_REDUCTION (internal_fn, gcall *)
3450 {
3451 gcc_unreachable ();
3452 }
3453
3454 /* This is expanded by oacc_device_lower pass. */
3455
3456 static void
3457 expand_GOACC_TILE (internal_fn, gcall *)
3458 {
3459 gcc_unreachable ();
3460 }
3461
3462 /* Set errno to EDOM. */
3463
3464 static void
3465 expand_SET_EDOM (internal_fn, gcall *)
3466 {
3467 #ifdef TARGET_EDOM
3468 #ifdef GEN_ERRNO_RTX
3469 rtx errno_rtx = GEN_ERRNO_RTX;
3470 #else
3471 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
3472 #endif
3473 emit_move_insn (errno_rtx,
3474 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
3475 #else
3476 gcc_unreachable ();
3477 #endif
3478 }
3479
3480 /* Expand atomic bit test and set. */
3481
3482 static void
3483 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
3484 {
3485 expand_ifn_atomic_bit_test_and (call);
3486 }
3487
3488 /* Expand atomic bit test and complement. */
3489
3490 static void
3491 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
3492 {
3493 expand_ifn_atomic_bit_test_and (call);
3494 }
3495
3496 /* Expand atomic bit test and reset. */
3497
3498 static void
3499 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
3500 {
3501 expand_ifn_atomic_bit_test_and (call);
3502 }
3503
3504 /* Expand atomic bit test and set. */
3505
3506 static void
3507 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
3508 {
3509 expand_ifn_atomic_compare_exchange (call);
3510 }
3511
3512 /* Expand atomic add fetch and cmp with 0. */
3513
3514 static void
3515 expand_ATOMIC_ADD_FETCH_CMP_0 (internal_fn, gcall *call)
3516 {
3517 expand_ifn_atomic_op_fetch_cmp_0 (call);
3518 }
3519
3520 /* Expand atomic sub fetch and cmp with 0. */
3521
3522 static void
3523 expand_ATOMIC_SUB_FETCH_CMP_0 (internal_fn, gcall *call)
3524 {
3525 expand_ifn_atomic_op_fetch_cmp_0 (call);
3526 }
3527
3528 /* Expand atomic and fetch and cmp with 0. */
3529
3530 static void
3531 expand_ATOMIC_AND_FETCH_CMP_0 (internal_fn, gcall *call)
3532 {
3533 expand_ifn_atomic_op_fetch_cmp_0 (call);
3534 }
3535
3536 /* Expand atomic or fetch and cmp with 0. */
3537
3538 static void
3539 expand_ATOMIC_OR_FETCH_CMP_0 (internal_fn, gcall *call)
3540 {
3541 expand_ifn_atomic_op_fetch_cmp_0 (call);
3542 }
3543
3544 /* Expand atomic xor fetch and cmp with 0. */
3545
3546 static void
3547 expand_ATOMIC_XOR_FETCH_CMP_0 (internal_fn, gcall *call)
3548 {
3549 expand_ifn_atomic_op_fetch_cmp_0 (call);
3550 }
3551
3552 /* Expand LAUNDER to assignment, lhs = arg0. */
3553
3554 static void
3555 expand_LAUNDER (internal_fn, gcall *call)
3556 {
3557 tree lhs = gimple_call_lhs (call);
3558
3559 if (!lhs)
3560 return;
3561
3562 expand_assignment (lhs, gimple_call_arg (call, 0), false);
3563 }
3564
3565 /* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB. */
3566
3567 static void
3568 expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3569 {
3570 internal_fn ifn = gimple_call_internal_fn (stmt);
3571 int rhs_index = internal_fn_stored_value_index (ifn);
3572 tree base = gimple_call_arg (stmt, 0);
3573 tree offset = gimple_call_arg (stmt, 1);
3574 tree scale = gimple_call_arg (stmt, 2);
3575 tree rhs = gimple_call_arg (stmt, rhs_index);
3576
3577 rtx base_rtx = expand_normal (base);
3578 rtx offset_rtx = expand_normal (offset);
3579 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3580 rtx rhs_rtx = expand_normal (rhs);
3581
3582 class expand_operand ops[8];
3583 int i = 0;
3584 create_address_operand (&ops[i++], base_rtx);
3585 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3586 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3587 create_integer_operand (&ops[i++], scale_int);
3588 create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
3589 i = add_mask_and_len_args (ops, i, stmt);
3590
3591 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
3592 TYPE_MODE (TREE_TYPE (offset)));
3593 expand_insn (icode, i, ops);
3594 }
3595
3596 /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB. */
3597
3598 static void
3599 expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3600 {
3601 tree lhs = gimple_call_lhs (stmt);
3602 tree base = gimple_call_arg (stmt, 0);
3603 tree offset = gimple_call_arg (stmt, 1);
3604 tree scale = gimple_call_arg (stmt, 2);
3605
3606 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3607 rtx base_rtx = expand_normal (base);
3608 rtx offset_rtx = expand_normal (offset);
3609 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3610
3611 int i = 0;
3612 class expand_operand ops[8];
3613 create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
3614 create_address_operand (&ops[i++], base_rtx);
3615 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3616 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3617 create_integer_operand (&ops[i++], scale_int);
3618 i = add_mask_and_len_args (ops, i, stmt);
3619 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
3620 TYPE_MODE (TREE_TYPE (offset)));
3621 expand_insn (icode, i, ops);
3622 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3623 emit_move_insn (lhs_rtx, ops[0].value);
3624 }
3625
3626 /* Helper for expand_DIVMOD. Return true if the sequence starting with
3627 INSN contains any call insns or insns with {,U}{DIV,MOD} rtxes. */
3628
3629 static bool
3630 contains_call_div_mod (rtx_insn *insn)
3631 {
3632 subrtx_iterator::array_type array;
3633 for (; insn; insn = NEXT_INSN (insn))
3634 if (CALL_P (insn))
3635 return true;
3636 else if (INSN_P (insn))
3637 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
3638 switch (GET_CODE (*iter))
3639 {
3640 case CALL:
3641 case DIV:
3642 case UDIV:
3643 case MOD:
3644 case UMOD:
3645 return true;
3646 default:
3647 break;
3648 }
3649 return false;
3650 }
3651
3652 /* Expand DIVMOD() using:
3653 a) optab handler for udivmod/sdivmod if it is available.
3654 b) If optab_handler doesn't exist, generate call to
3655 target-specific divmod libfunc. */
3656
3657 static void
3658 expand_DIVMOD (internal_fn, gcall *call_stmt)
3659 {
3660 tree lhs = gimple_call_lhs (call_stmt);
3661 tree arg0 = gimple_call_arg (call_stmt, 0);
3662 tree arg1 = gimple_call_arg (call_stmt, 1);
3663
3664 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
3665 tree type = TREE_TYPE (TREE_TYPE (lhs));
3666 machine_mode mode = TYPE_MODE (type);
3667 bool unsignedp = TYPE_UNSIGNED (type);
3668 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
3669
3670 rtx op0 = expand_normal (arg0);
3671 rtx op1 = expand_normal (arg1);
3672 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3673
3674 rtx quotient = NULL_RTX, remainder = NULL_RTX;
3675 rtx_insn *insns = NULL;
3676
3677 if (TREE_CODE (arg1) == INTEGER_CST)
3678 {
3679 /* For DIVMOD by integral constants, there could be efficient code
3680 expanded inline e.g. using shifts and plus/minus. Try to expand
3681 the division and modulo and if it emits any library calls or any
3682 {,U}{DIV,MOD} rtxes throw it away and use a divmod optab or
3683 divmod libcall. */
3684 scalar_int_mode int_mode;
3685 if (remainder == NULL_RTX
3686 && optimize
3687 && CONST_INT_P (op1)
3688 && !pow2p_hwi (INTVAL (op1))
3689 && is_int_mode (TYPE_MODE (type), &int_mode)
3690 && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
3691 && optab_handler (and_optab, word_mode) != CODE_FOR_nothing
3692 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing
3693 && optimize_insn_for_speed_p ())
3694 {
3695 rtx_insn *last = get_last_insn ();
3696 remainder = NULL_RTX;
3697 quotient = expand_doubleword_divmod (int_mode, op0, op1, &remainder,
3698 TYPE_UNSIGNED (type));
3699 if (quotient != NULL_RTX)
3700 {
3701 if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
3702 {
3703 rtx_insn *move = emit_move_insn (quotient, quotient);
3704 set_dst_reg_note (move, REG_EQUAL,
3705 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3706 ? UDIV : DIV, int_mode,
3707 copy_rtx (op0), op1),
3708 quotient);
3709 move = emit_move_insn (remainder, remainder);
3710 set_dst_reg_note (move, REG_EQUAL,
3711 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3712 ? UMOD : MOD, int_mode,
3713 copy_rtx (op0), op1),
3714 quotient);
3715 }
3716 }
3717 else
3718 delete_insns_since (last);
3719 }
3720
3721 if (remainder == NULL_RTX)
3722 {
3723 struct separate_ops ops;
3724 ops.code = TRUNC_DIV_EXPR;
3725 ops.type = type;
3726 ops.op0 = make_tree (ops.type, op0);
3727 ops.op1 = arg1;
3728 ops.op2 = NULL_TREE;
3729 ops.location = gimple_location (call_stmt);
3730 start_sequence ();
3731 quotient = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
3732 if (contains_call_div_mod (get_insns ()))
3733 quotient = NULL_RTX;
3734 else
3735 {
3736 ops.code = TRUNC_MOD_EXPR;
3737 remainder = expand_expr_real_2 (&ops, NULL_RTX, mode,
3738 EXPAND_NORMAL);
3739 if (contains_call_div_mod (get_insns ()))
3740 remainder = NULL_RTX;
3741 }
3742 if (remainder)
3743 insns = get_insns ();
3744 end_sequence ();
3745 }
3746 }
3747
3748 if (remainder)
3749 emit_insn (insns);
3750
3751 /* Check if optab_handler exists for divmod_optab for given mode. */
3752 else if (optab_handler (tab, mode) != CODE_FOR_nothing)
3753 {
3754 quotient = gen_reg_rtx (mode);
3755 remainder = gen_reg_rtx (mode);
3756 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
3757 }
3758
3759 /* Generate call to divmod libfunc if it exists. */
3760 else if (rtx libfunc = optab_libfunc (tab, mode))
3761 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
3762 &quotient, &remainder);
3763
3764 else
3765 gcc_unreachable ();
3766
3767 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
3768 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
3769 make_tree (TREE_TYPE (arg0), quotient),
3770 make_tree (TREE_TYPE (arg1), remainder)),
3771 target, VOIDmode, EXPAND_NORMAL);
3772 }
3773
3774 /* Expand a NOP. */
3775
3776 static void
3777 expand_NOP (internal_fn, gcall *)
3778 {
3779 /* Nothing. But it shouldn't really prevail. */
3780 }
3781
3782 /* Coroutines, all should have been processed at this stage. */
3783
3784 static void
3785 expand_CO_FRAME (internal_fn, gcall *)
3786 {
3787 gcc_unreachable ();
3788 }
3789
3790 static void
3791 expand_CO_YIELD (internal_fn, gcall *)
3792 {
3793 gcc_unreachable ();
3794 }
3795
3796 static void
3797 expand_CO_SUSPN (internal_fn, gcall *)
3798 {
3799 gcc_unreachable ();
3800 }
3801
3802 static void
3803 expand_CO_ACTOR (internal_fn, gcall *)
3804 {
3805 gcc_unreachable ();
3806 }
3807
3808 /* Expand a call to FN using the operands in STMT. FN has a single
3809 output operand and NARGS input operands. */
3810
3811 static void
3812 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
3813 unsigned int nargs)
3814 {
3815 tree_pair types = direct_internal_fn_types (fn, stmt);
3816 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
3817 expand_fn_using_insn (stmt, icode, 1, nargs);
3818 }
3819
3820 /* Expand WHILE_ULT call STMT using optab OPTAB. */
3821
3822 static void
3823 expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3824 {
3825 expand_operand ops[4];
3826 tree rhs_type[2];
3827
3828 tree lhs = gimple_call_lhs (stmt);
3829 tree lhs_type = TREE_TYPE (lhs);
3830 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3831 create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
3832
3833 for (unsigned int i = 0; i < 2; ++i)
3834 {
3835 tree rhs = gimple_call_arg (stmt, i);
3836 rhs_type[i] = TREE_TYPE (rhs);
3837 rtx rhs_rtx = expand_normal (rhs);
3838 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
3839 }
3840
3841 int opcnt;
3842 if (!VECTOR_MODE_P (TYPE_MODE (lhs_type)))
3843 {
3844 /* When the mask is an integer mode the exact vector length may not
3845 be clear to the backend, so we pass it in operand[3].
3846 Use the vector in arg2 for the most reliable intended size. */
3847 tree type = TREE_TYPE (gimple_call_arg (stmt, 2));
3848 create_integer_operand (&ops[3], TYPE_VECTOR_SUBPARTS (type));
3849 opcnt = 4;
3850 }
3851 else
3852 /* The mask has a vector type so the length operand is unnecessary. */
3853 opcnt = 3;
3854
3855 insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
3856 TYPE_MODE (lhs_type));
3857
3858 expand_insn (icode, opcnt, ops);
3859 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3860 emit_move_insn (lhs_rtx, ops[0].value);
3861 }
3862
3863 /* Expand a call to a convert-like optab using the operands in STMT.
3864 FN has a single output operand and NARGS input operands. */
3865
3866 static void
3867 expand_convert_optab_fn (internal_fn fn, gcall *stmt, convert_optab optab,
3868 unsigned int nargs)
3869 {
3870 tree_pair types = direct_internal_fn_types (fn, stmt);
3871 insn_code icode = convert_optab_handler (optab, TYPE_MODE (types.first),
3872 TYPE_MODE (types.second));
3873 expand_fn_using_insn (stmt, icode, 1, nargs);
3874 }
3875
3876 /* Expanders for optabs that can use expand_direct_optab_fn. */
3877
3878 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
3879 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
3880
3881 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
3882 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3883
3884 #define expand_ternary_optab_fn(FN, STMT, OPTAB) \
3885 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3886
3887 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
3888 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3889
3890 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
3891 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3892
3893 #define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
3894 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3895
3896 #define expand_cond_len_unary_optab_fn(FN, STMT, OPTAB) \
3897 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3898
3899 #define expand_cond_len_binary_optab_fn(FN, STMT, OPTAB) \
3900 expand_direct_optab_fn (FN, STMT, OPTAB, 6)
3901
3902 #define expand_cond_len_ternary_optab_fn(FN, STMT, OPTAB) \
3903 expand_direct_optab_fn (FN, STMT, OPTAB, 7)
3904
3905 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
3906 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3907
3908 #define expand_fold_len_extract_optab_fn(FN, STMT, OPTAB) \
3909 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3910
3911 #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
3912 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3913
3914 #define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
3915 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3916
3917 #define expand_mask_len_fold_left_optab_fn(FN, STMT, OPTAB) \
3918 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3919
3920 #define expand_check_ptrs_optab_fn(FN, STMT, OPTAB) \
3921 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3922
3923 /* Expanders for optabs that can use expand_convert_optab_fn. */
3924
3925 #define expand_unary_convert_optab_fn(FN, STMT, OPTAB) \
3926 expand_convert_optab_fn (FN, STMT, OPTAB, 1)
3927
3928 #define expand_vec_extract_optab_fn(FN, STMT, OPTAB) \
3929 expand_convert_optab_fn (FN, STMT, OPTAB, 2)
3930
3931 /* RETURN_TYPE and ARGS are a return type and argument list that are
3932 in principle compatible with FN (which satisfies direct_internal_fn_p).
3933 Return the types that should be used to determine whether the
3934 target supports FN. */
3935
3936 tree_pair
3937 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
3938 {
3939 const direct_internal_fn_info &info = direct_internal_fn (fn);
3940 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
3941 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
3942 return tree_pair (type0, type1);
3943 }
3944
3945 /* CALL is a call whose return type and arguments are in principle
3946 compatible with FN (which satisfies direct_internal_fn_p). Return the
3947 types that should be used to determine whether the target supports FN. */
3948
3949 tree_pair
3950 direct_internal_fn_types (internal_fn fn, gcall *call)
3951 {
3952 const direct_internal_fn_info &info = direct_internal_fn (fn);
3953 tree op0 = (info.type0 < 0
3954 ? gimple_call_lhs (call)
3955 : gimple_call_arg (call, info.type0));
3956 tree op1 = (info.type1 < 0
3957 ? gimple_call_lhs (call)
3958 : gimple_call_arg (call, info.type1));
3959 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
3960 }
3961
3962 /* Return true if OPTAB is supported for TYPES (whose modes should be
3963 the same) when the optimization type is OPT_TYPE. Used for simple
3964 direct optabs. */
3965
3966 static bool
3967 direct_optab_supported_p (direct_optab optab, tree_pair types,
3968 optimization_type opt_type)
3969 {
3970 machine_mode mode = TYPE_MODE (types.first);
3971 gcc_checking_assert (mode == TYPE_MODE (types.second));
3972 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
3973 }
3974
3975 /* Return true if OPTAB is supported for TYPES, where the first type
3976 is the destination and the second type is the source. Used for
3977 convert optabs. */
3978
3979 static bool
3980 convert_optab_supported_p (convert_optab optab, tree_pair types,
3981 optimization_type opt_type)
3982 {
3983 return (convert_optab_handler (optab, TYPE_MODE (types.first),
3984 TYPE_MODE (types.second), opt_type)
3985 != CODE_FOR_nothing);
3986 }
3987
3988 /* Return true if load/store lanes optab OPTAB is supported for
3989 array type TYPES.first when the optimization type is OPT_TYPE. */
3990
3991 static bool
3992 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
3993 optimization_type opt_type)
3994 {
3995 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
3996 machine_mode imode = TYPE_MODE (types.first);
3997 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
3998 return (convert_optab_handler (optab, imode, vmode, opt_type)
3999 != CODE_FOR_nothing);
4000 }
4001
4002 #define direct_unary_optab_supported_p direct_optab_supported_p
4003 #define direct_unary_convert_optab_supported_p convert_optab_supported_p
4004 #define direct_binary_optab_supported_p direct_optab_supported_p
4005 #define direct_ternary_optab_supported_p direct_optab_supported_p
4006 #define direct_cond_unary_optab_supported_p direct_optab_supported_p
4007 #define direct_cond_binary_optab_supported_p direct_optab_supported_p
4008 #define direct_cond_ternary_optab_supported_p direct_optab_supported_p
4009 #define direct_cond_len_unary_optab_supported_p direct_optab_supported_p
4010 #define direct_cond_len_binary_optab_supported_p direct_optab_supported_p
4011 #define direct_cond_len_ternary_optab_supported_p direct_optab_supported_p
4012 #define direct_mask_load_optab_supported_p convert_optab_supported_p
4013 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
4014 #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
4015 #define direct_gather_load_optab_supported_p convert_optab_supported_p
4016 #define direct_len_load_optab_supported_p direct_optab_supported_p
4017 #define direct_mask_len_load_optab_supported_p convert_optab_supported_p
4018 #define direct_mask_store_optab_supported_p convert_optab_supported_p
4019 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
4020 #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
4021 #define direct_vec_cond_mask_optab_supported_p convert_optab_supported_p
4022 #define direct_vec_cond_optab_supported_p convert_optab_supported_p
4023 #define direct_scatter_store_optab_supported_p convert_optab_supported_p
4024 #define direct_len_store_optab_supported_p direct_optab_supported_p
4025 #define direct_mask_len_store_optab_supported_p convert_optab_supported_p
4026 #define direct_while_optab_supported_p convert_optab_supported_p
4027 #define direct_fold_extract_optab_supported_p direct_optab_supported_p
4028 #define direct_fold_len_extract_optab_supported_p direct_optab_supported_p
4029 #define direct_fold_left_optab_supported_p direct_optab_supported_p
4030 #define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
4031 #define direct_mask_len_fold_left_optab_supported_p direct_optab_supported_p
4032 #define direct_check_ptrs_optab_supported_p direct_optab_supported_p
4033 #define direct_vec_set_optab_supported_p direct_optab_supported_p
4034 #define direct_vec_extract_optab_supported_p convert_optab_supported_p
4035
4036 /* Return the optab used by internal function FN. */
4037
4038 optab
4039 direct_internal_fn_optab (internal_fn fn, tree_pair types)
4040 {
4041 switch (fn)
4042 {
4043 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4044 case IFN_##CODE: break;
4045 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4046 case IFN_##CODE: return OPTAB##_optab;
4047 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4048 UNSIGNED_OPTAB, TYPE) \
4049 case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR) \
4050 ? UNSIGNED_OPTAB ## _optab \
4051 : SIGNED_OPTAB ## _optab);
4052 #include "internal-fn.def"
4053
4054 case IFN_LAST:
4055 break;
4056 }
4057 gcc_unreachable ();
4058 }
4059
4060 /* Return the optab used by internal function FN. */
4061
4062 static optab
4063 direct_internal_fn_optab (internal_fn fn)
4064 {
4065 switch (fn)
4066 {
4067 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4068 case IFN_##CODE: break;
4069 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4070 case IFN_##CODE: return OPTAB##_optab;
4071 #include "internal-fn.def"
4072
4073 case IFN_LAST:
4074 break;
4075 }
4076 gcc_unreachable ();
4077 }
4078
4079 /* Return true if FN is supported for the types in TYPES when the
4080 optimization type is OPT_TYPE. The types are those associated with
4081 the "type0" and "type1" fields of FN's direct_internal_fn_info
4082 structure. */
4083
4084 bool
4085 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
4086 optimization_type opt_type)
4087 {
4088 switch (fn)
4089 {
4090 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4091 case IFN_##CODE: break;
4092 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4093 case IFN_##CODE: \
4094 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
4095 opt_type);
4096 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4097 UNSIGNED_OPTAB, TYPE) \
4098 case IFN_##CODE: \
4099 { \
4100 optab which_optab = (TYPE_UNSIGNED (types.SELECTOR) \
4101 ? UNSIGNED_OPTAB ## _optab \
4102 : SIGNED_OPTAB ## _optab); \
4103 return direct_##TYPE##_optab_supported_p (which_optab, types, \
4104 opt_type); \
4105 }
4106 #include "internal-fn.def"
4107
4108 case IFN_LAST:
4109 break;
4110 }
4111 gcc_unreachable ();
4112 }
4113
4114 /* Return true if FN is supported for type TYPE when the optimization
4115 type is OPT_TYPE. The caller knows that the "type0" and "type1"
4116 fields of FN's direct_internal_fn_info structure are the same. */
4117
4118 bool
4119 direct_internal_fn_supported_p (internal_fn fn, tree type,
4120 optimization_type opt_type)
4121 {
4122 const direct_internal_fn_info &info = direct_internal_fn (fn);
4123 gcc_checking_assert (info.type0 == info.type1);
4124 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
4125 }
4126
4127 /* Return true if the STMT is supported when the optimization type is OPT_TYPE,
4128 given that STMT is a call to a direct internal function. */
4129
4130 bool
4131 direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
4132 {
4133 internal_fn fn = gimple_call_internal_fn (stmt);
4134 tree_pair types = direct_internal_fn_types (fn, stmt);
4135 return direct_internal_fn_supported_p (fn, types, opt_type);
4136 }
4137
4138 /* Return true if FN is a binary operation and if FN is commutative. */
4139
4140 bool
4141 commutative_binary_fn_p (internal_fn fn)
4142 {
4143 switch (fn)
4144 {
4145 case IFN_AVG_FLOOR:
4146 case IFN_AVG_CEIL:
4147 case IFN_MULH:
4148 case IFN_MULHS:
4149 case IFN_MULHRS:
4150 case IFN_FMIN:
4151 case IFN_FMAX:
4152 case IFN_COMPLEX_MUL:
4153 case IFN_UBSAN_CHECK_ADD:
4154 case IFN_UBSAN_CHECK_MUL:
4155 case IFN_ADD_OVERFLOW:
4156 case IFN_MUL_OVERFLOW:
4157 case IFN_VEC_WIDEN_PLUS:
4158 case IFN_VEC_WIDEN_PLUS_LO:
4159 case IFN_VEC_WIDEN_PLUS_HI:
4160 case IFN_VEC_WIDEN_PLUS_EVEN:
4161 case IFN_VEC_WIDEN_PLUS_ODD:
4162 return true;
4163
4164 default:
4165 return false;
4166 }
4167 }
4168
4169 /* Return true if FN is a ternary operation and if its first two arguments
4170 are commutative. */
4171
4172 bool
4173 commutative_ternary_fn_p (internal_fn fn)
4174 {
4175 switch (fn)
4176 {
4177 case IFN_FMA:
4178 case IFN_FMS:
4179 case IFN_FNMA:
4180 case IFN_FNMS:
4181 case IFN_UADDC:
4182 return true;
4183
4184 default:
4185 return false;
4186 }
4187 }
4188
4189 /* Return true if FN is an associative binary operation. */
4190
4191 bool
4192 associative_binary_fn_p (internal_fn fn)
4193 {
4194 switch (fn)
4195 {
4196 case IFN_FMIN:
4197 case IFN_FMAX:
4198 return true;
4199
4200 default:
4201 return false;
4202 }
4203 }
4204
4205 /* If FN is commutative in two consecutive arguments, return the
4206 index of the first, otherwise return -1. */
4207
4208 int
4209 first_commutative_argument (internal_fn fn)
4210 {
4211 switch (fn)
4212 {
4213 case IFN_COND_ADD:
4214 case IFN_COND_MUL:
4215 case IFN_COND_MIN:
4216 case IFN_COND_MAX:
4217 case IFN_COND_FMIN:
4218 case IFN_COND_FMAX:
4219 case IFN_COND_AND:
4220 case IFN_COND_IOR:
4221 case IFN_COND_XOR:
4222 case IFN_COND_FMA:
4223 case IFN_COND_FMS:
4224 case IFN_COND_FNMA:
4225 case IFN_COND_FNMS:
4226 case IFN_COND_LEN_ADD:
4227 case IFN_COND_LEN_MUL:
4228 case IFN_COND_LEN_MIN:
4229 case IFN_COND_LEN_MAX:
4230 case IFN_COND_LEN_FMIN:
4231 case IFN_COND_LEN_FMAX:
4232 case IFN_COND_LEN_AND:
4233 case IFN_COND_LEN_IOR:
4234 case IFN_COND_LEN_XOR:
4235 case IFN_COND_LEN_FMA:
4236 case IFN_COND_LEN_FMS:
4237 case IFN_COND_LEN_FNMA:
4238 case IFN_COND_LEN_FNMS:
4239 return 1;
4240
4241 default:
4242 if (commutative_binary_fn_p (fn)
4243 || commutative_ternary_fn_p (fn))
4244 return 0;
4245 return -1;
4246 }
4247 }
4248
4249 /* Return true if this CODE describes an internal_fn that returns a vector with
4250 elements twice as wide as the element size of the input vectors. */
4251
4252 bool
4253 widening_fn_p (code_helper code)
4254 {
4255 if (!code.is_fn_code ())
4256 return false;
4257
4258 if (!internal_fn_p ((combined_fn) code))
4259 return false;
4260
4261 internal_fn fn = as_internal_fn ((combined_fn) code);
4262 switch (fn)
4263 {
4264 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
4265 case IFN_##NAME: \
4266 case IFN_##NAME##_HI: \
4267 case IFN_##NAME##_LO: \
4268 case IFN_##NAME##_EVEN: \
4269 case IFN_##NAME##_ODD: \
4270 return true;
4271 #include "internal-fn.def"
4272
4273 default:
4274 return false;
4275 }
4276 }
4277
4278 /* Return true if IFN_SET_EDOM is supported. */
4279
4280 bool
4281 set_edom_supported_p (void)
4282 {
4283 #ifdef TARGET_EDOM
4284 return true;
4285 #else
4286 return false;
4287 #endif
4288 }
4289
4290 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4291 static void \
4292 expand_##CODE (internal_fn fn, gcall *stmt) \
4293 { \
4294 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
4295 }
4296 #define DEF_INTERNAL_INT_EXT_FN(CODE, FLAGS, OPTAB, TYPE)
4297 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4298 UNSIGNED_OPTAB, TYPE) \
4299 static void \
4300 expand_##CODE (internal_fn fn, gcall *stmt) \
4301 { \
4302 tree_pair types = direct_internal_fn_types (fn, stmt); \
4303 optab which_optab = direct_internal_fn_optab (fn, types); \
4304 expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
4305 }
4306 #include "internal-fn.def"
4307
4308 /* Routines to expand each internal function, indexed by function number.
4309 Each routine has the prototype:
4310
4311 expand_<NAME> (gcall *stmt)
4312
4313 where STMT is the statement that performs the call. */
4314 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
4315
4316 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
4317 #include "internal-fn.def"
4318 0
4319 };
4320
4321 /* Invoke T(CODE, SUFFIX) for each conditional function IFN_COND_##SUFFIX
4322 that maps to a tree code CODE. There is also an IFN_COND_LEN_##SUFFIX
4323 for each such IFN_COND_##SUFFIX. */
4324 #define FOR_EACH_CODE_MAPPING(T) \
4325 T (PLUS_EXPR, ADD) \
4326 T (MINUS_EXPR, SUB) \
4327 T (MULT_EXPR, MUL) \
4328 T (TRUNC_DIV_EXPR, DIV) \
4329 T (TRUNC_MOD_EXPR, MOD) \
4330 T (RDIV_EXPR, RDIV) \
4331 T (MIN_EXPR, MIN) \
4332 T (MAX_EXPR, MAX) \
4333 T (BIT_AND_EXPR, AND) \
4334 T (BIT_IOR_EXPR, IOR) \
4335 T (BIT_XOR_EXPR, XOR) \
4336 T (LSHIFT_EXPR, SHL) \
4337 T (RSHIFT_EXPR, SHR) \
4338 T (NEGATE_EXPR, NEG)
4339
4340 /* Return a function that only performs CODE when a certain condition is met
4341 and that uses a given fallback value otherwise. For example, if CODE is
4342 a binary operation associated with conditional function FN:
4343
4344 LHS = FN (COND, A, B, ELSE)
4345
4346 is equivalent to the C expression:
4347
4348 LHS = COND ? A CODE B : ELSE;
4349
4350 operating elementwise if the operands are vectors.
4351
4352 Return IFN_LAST if no such function exists. */
4353
4354 internal_fn
4355 get_conditional_internal_fn (tree_code code)
4356 {
4357 switch (code)
4358 {
4359 #define CASE(CODE, IFN) case CODE: return IFN_COND_##IFN;
4360 FOR_EACH_CODE_MAPPING(CASE)
4361 #undef CASE
4362 default:
4363 return IFN_LAST;
4364 }
4365 }
4366
4367 /* If IFN implements the conditional form of a tree code, return that
4368 tree code, otherwise return ERROR_MARK. */
4369
4370 tree_code
4371 conditional_internal_fn_code (internal_fn ifn)
4372 {
4373 switch (ifn)
4374 {
4375 #define CASE(CODE, IFN) \
4376 case IFN_COND_##IFN: \
4377 case IFN_COND_LEN_##IFN: \
4378 return CODE;
4379 FOR_EACH_CODE_MAPPING (CASE)
4380 #undef CASE
4381 default:
4382 return ERROR_MARK;
4383 }
4384 }
4385
4386 /* Like get_conditional_internal_fn, but return a function that
4387 additionally restricts the operation to the leading elements
4388 of a vector. The number of elements to process is given by a length
4389 and bias pair, as for IFN_LOAD_LEN. The values of the remaining
4390 elements are taken from the fallback ("else") argument.
4391
4392 For example, if CODE is a binary operation associated with FN:
4393
4394 LHS = FN (COND, A, B, ELSE, LEN, BIAS)
4395
4396 is equivalent to the C code:
4397
4398 for (int i = 0; i < NUNITS; i++)
4399 {
4400 if (i < LEN + BIAS && COND[i])
4401 LHS[i] = A[i] CODE B[i];
4402 else
4403 LHS[i] = ELSE[i];
4404 }
4405 */
4406
4407 internal_fn
4408 get_conditional_len_internal_fn (tree_code code)
4409 {
4410 switch (code)
4411 {
4412 #define CASE(CODE, IFN) case CODE: return IFN_COND_LEN_##IFN;
4413 FOR_EACH_CODE_MAPPING(CASE)
4414 #undef CASE
4415 default:
4416 return IFN_LAST;
4417 }
4418 }
4419
4420 /* Invoke T(IFN) for each internal function IFN that also has an
4421 IFN_COND_* form. */
4422 #define FOR_EACH_COND_FN_PAIR(T) \
4423 T (FMAX) \
4424 T (FMIN) \
4425 T (FMA) \
4426 T (FMS) \
4427 T (FNMA) \
4428 T (FNMS)
4429
4430 /* Return a function that only performs internal function FN when a
4431 certain condition is met and that uses a given fallback value otherwise.
4432 In other words, the returned function FN' is such that:
4433
4434 LHS = FN' (COND, A1, ... An, ELSE)
4435
4436 is equivalent to the C expression:
4437
4438 LHS = COND ? FN (A1, ..., An) : ELSE;
4439
4440 operating elementwise if the operands are vectors.
4441
4442 Return IFN_LAST if no such function exists. */
4443
4444 internal_fn
4445 get_conditional_internal_fn (internal_fn fn)
4446 {
4447 switch (fn)
4448 {
4449 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
4450 FOR_EACH_COND_FN_PAIR(CASE)
4451 #undef CASE
4452 default:
4453 return IFN_LAST;
4454 }
4455 }
4456
4457 /* If there exists an internal function like IFN that operates on vectors,
4458 but with additional length and bias parameters, return the internal_fn
4459 for that function, otherwise return IFN_LAST. */
4460 internal_fn
4461 get_len_internal_fn (internal_fn fn)
4462 {
4463 switch (fn)
4464 {
4465 #define DEF_INTERNAL_COND_FN(NAME, ...) \
4466 case IFN_COND_##NAME: \
4467 return IFN_COND_LEN_##NAME;
4468 #define DEF_INTERNAL_SIGNED_COND_FN(NAME, ...) \
4469 case IFN_COND_##NAME: \
4470 return IFN_COND_LEN_##NAME;
4471 #include "internal-fn.def"
4472 default:
4473 return IFN_LAST;
4474 }
4475 }
4476
4477 /* If IFN implements the conditional form of an unconditional internal
4478 function, return that unconditional function, otherwise return IFN_LAST. */
4479
4480 internal_fn
4481 get_unconditional_internal_fn (internal_fn ifn)
4482 {
4483 switch (ifn)
4484 {
4485 #define CASE(NAME) \
4486 case IFN_COND_##NAME: \
4487 case IFN_COND_LEN_##NAME: \
4488 return IFN_##NAME;
4489 FOR_EACH_COND_FN_PAIR (CASE)
4490 #undef CASE
4491 default:
4492 return IFN_LAST;
4493 }
4494 }
4495
4496 /* Return true if STMT can be interpreted as a conditional tree code
4497 operation of the form:
4498
4499 LHS = COND ? OP (RHS1, ...) : ELSE;
4500
4501 operating elementwise if the operands are vectors. This includes
4502 the case of an all-true COND, so that the operation always happens.
4503
4504 There is an alternative approach to interpret the STMT when the operands
4505 are vectors which is the operation predicated by both conditional mask
4506 and loop control length, the equivalent C code:
4507
4508 for (int i = 0; i < NUNTIS; i++)
4509 {
4510 if (i < LEN + BIAS && COND[i])
4511 LHS[i] = A[i] CODE B[i];
4512 else
4513 LHS[i] = ELSE[i];
4514 }
4515
4516 When returning true, set:
4517
4518 - *COND_OUT to the condition COND, or to NULL_TREE if the condition
4519 is known to be all-true
4520 - *CODE_OUT to the tree code
4521 - OPS[I] to operand I of *CODE_OUT
4522 - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
4523 condition is known to be all true.
4524 - *LEN to the len argument if it COND_LEN_* operations or to NULL_TREE.
4525 - *BIAS to the bias argument if it COND_LEN_* operations or to NULL_TREE. */
4526
4527 bool
4528 can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
4529 tree_code *code_out,
4530 tree (&ops)[3], tree *else_out,
4531 tree *len, tree *bias)
4532 {
4533 *len = NULL_TREE;
4534 *bias = NULL_TREE;
4535 if (gassign *assign = dyn_cast <gassign *> (stmt))
4536 {
4537 *cond_out = NULL_TREE;
4538 *code_out = gimple_assign_rhs_code (assign);
4539 ops[0] = gimple_assign_rhs1 (assign);
4540 ops[1] = gimple_assign_rhs2 (assign);
4541 ops[2] = gimple_assign_rhs3 (assign);
4542 *else_out = NULL_TREE;
4543 return true;
4544 }
4545 if (gcall *call = dyn_cast <gcall *> (stmt))
4546 if (gimple_call_internal_p (call))
4547 {
4548 internal_fn ifn = gimple_call_internal_fn (call);
4549 tree_code code = conditional_internal_fn_code (ifn);
4550 int len_index = internal_fn_len_index (ifn);
4551 int cond_nargs = len_index >= 0 ? 4 : 2;
4552 if (code != ERROR_MARK)
4553 {
4554 *cond_out = gimple_call_arg (call, 0);
4555 *code_out = code;
4556 unsigned int nops = gimple_call_num_args (call) - cond_nargs;
4557 for (unsigned int i = 0; i < 3; ++i)
4558 ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
4559 *else_out = gimple_call_arg (call, nops + 1);
4560 if (len_index < 0)
4561 {
4562 if (integer_truep (*cond_out))
4563 {
4564 *cond_out = NULL_TREE;
4565 *else_out = NULL_TREE;
4566 }
4567 }
4568 else
4569 {
4570 *len = gimple_call_arg (call, len_index);
4571 *bias = gimple_call_arg (call, len_index + 1);
4572 }
4573 return true;
4574 }
4575 }
4576 return false;
4577 }
4578
4579 /* Return true if IFN is some form of load from memory. */
4580
4581 bool
4582 internal_load_fn_p (internal_fn fn)
4583 {
4584 switch (fn)
4585 {
4586 case IFN_MASK_LOAD:
4587 case IFN_LOAD_LANES:
4588 case IFN_MASK_LOAD_LANES:
4589 case IFN_MASK_LEN_LOAD_LANES:
4590 case IFN_GATHER_LOAD:
4591 case IFN_MASK_GATHER_LOAD:
4592 case IFN_MASK_LEN_GATHER_LOAD:
4593 case IFN_LEN_LOAD:
4594 case IFN_MASK_LEN_LOAD:
4595 return true;
4596
4597 default:
4598 return false;
4599 }
4600 }
4601
4602 /* Return true if IFN is some form of store to memory. */
4603
4604 bool
4605 internal_store_fn_p (internal_fn fn)
4606 {
4607 switch (fn)
4608 {
4609 case IFN_MASK_STORE:
4610 case IFN_STORE_LANES:
4611 case IFN_MASK_STORE_LANES:
4612 case IFN_MASK_LEN_STORE_LANES:
4613 case IFN_SCATTER_STORE:
4614 case IFN_MASK_SCATTER_STORE:
4615 case IFN_MASK_LEN_SCATTER_STORE:
4616 case IFN_LEN_STORE:
4617 case IFN_MASK_LEN_STORE:
4618 return true;
4619
4620 default:
4621 return false;
4622 }
4623 }
4624
4625 /* Return true if IFN is some form of gather load or scatter store. */
4626
4627 bool
4628 internal_gather_scatter_fn_p (internal_fn fn)
4629 {
4630 switch (fn)
4631 {
4632 case IFN_GATHER_LOAD:
4633 case IFN_MASK_GATHER_LOAD:
4634 case IFN_MASK_LEN_GATHER_LOAD:
4635 case IFN_SCATTER_STORE:
4636 case IFN_MASK_SCATTER_STORE:
4637 case IFN_MASK_LEN_SCATTER_STORE:
4638 return true;
4639
4640 default:
4641 return false;
4642 }
4643 }
4644
4645 /* If FN takes a vector len argument, return the index of that argument,
4646 otherwise return -1. */
4647
4648 int
4649 internal_fn_len_index (internal_fn fn)
4650 {
4651 switch (fn)
4652 {
4653 case IFN_LEN_LOAD:
4654 case IFN_LEN_STORE:
4655 return 2;
4656
4657 case IFN_MASK_LEN_GATHER_LOAD:
4658 case IFN_MASK_LEN_SCATTER_STORE:
4659 case IFN_COND_LEN_FMA:
4660 case IFN_COND_LEN_FMS:
4661 case IFN_COND_LEN_FNMA:
4662 case IFN_COND_LEN_FNMS:
4663 return 5;
4664
4665 case IFN_COND_LEN_ADD:
4666 case IFN_COND_LEN_SUB:
4667 case IFN_COND_LEN_MUL:
4668 case IFN_COND_LEN_DIV:
4669 case IFN_COND_LEN_MOD:
4670 case IFN_COND_LEN_RDIV:
4671 case IFN_COND_LEN_MIN:
4672 case IFN_COND_LEN_MAX:
4673 case IFN_COND_LEN_FMIN:
4674 case IFN_COND_LEN_FMAX:
4675 case IFN_COND_LEN_AND:
4676 case IFN_COND_LEN_IOR:
4677 case IFN_COND_LEN_XOR:
4678 case IFN_COND_LEN_SHL:
4679 case IFN_COND_LEN_SHR:
4680 return 4;
4681
4682 case IFN_COND_LEN_NEG:
4683 case IFN_MASK_LEN_LOAD:
4684 case IFN_MASK_LEN_STORE:
4685 case IFN_MASK_LEN_LOAD_LANES:
4686 case IFN_MASK_LEN_STORE_LANES:
4687 case IFN_VCOND_MASK_LEN:
4688 return 3;
4689
4690 default:
4691 return -1;
4692 }
4693 }
4694
4695 /* If FN is an IFN_COND_* or IFN_COND_LEN_* function, return the index of the
4696 argument that is used when the condition is false. Return -1 otherwise. */
4697
4698 int
4699 internal_fn_else_index (internal_fn fn)
4700 {
4701 switch (fn)
4702 {
4703 case IFN_COND_NEG:
4704 case IFN_COND_NOT:
4705 case IFN_COND_LEN_NEG:
4706 case IFN_COND_LEN_NOT:
4707 return 2;
4708
4709 case IFN_COND_ADD:
4710 case IFN_COND_SUB:
4711 case IFN_COND_MUL:
4712 case IFN_COND_DIV:
4713 case IFN_COND_MOD:
4714 case IFN_COND_MIN:
4715 case IFN_COND_MAX:
4716 case IFN_COND_FMIN:
4717 case IFN_COND_FMAX:
4718 case IFN_COND_AND:
4719 case IFN_COND_IOR:
4720 case IFN_COND_XOR:
4721 case IFN_COND_SHL:
4722 case IFN_COND_SHR:
4723 case IFN_COND_LEN_ADD:
4724 case IFN_COND_LEN_SUB:
4725 case IFN_COND_LEN_MUL:
4726 case IFN_COND_LEN_DIV:
4727 case IFN_COND_LEN_MOD:
4728 case IFN_COND_LEN_MIN:
4729 case IFN_COND_LEN_MAX:
4730 case IFN_COND_LEN_FMIN:
4731 case IFN_COND_LEN_FMAX:
4732 case IFN_COND_LEN_AND:
4733 case IFN_COND_LEN_IOR:
4734 case IFN_COND_LEN_XOR:
4735 case IFN_COND_LEN_SHL:
4736 case IFN_COND_LEN_SHR:
4737 return 3;
4738
4739 case IFN_COND_FMA:
4740 case IFN_COND_FMS:
4741 case IFN_COND_FNMA:
4742 case IFN_COND_FNMS:
4743 case IFN_COND_LEN_FMA:
4744 case IFN_COND_LEN_FMS:
4745 case IFN_COND_LEN_FNMA:
4746 case IFN_COND_LEN_FNMS:
4747 return 4;
4748
4749 default:
4750 return -1;
4751 }
4752
4753 return -1;
4754 }
4755
4756 /* If FN takes a vector mask argument, return the index of that argument,
4757 otherwise return -1. */
4758
4759 int
4760 internal_fn_mask_index (internal_fn fn)
4761 {
4762 switch (fn)
4763 {
4764 case IFN_MASK_LOAD:
4765 case IFN_MASK_LOAD_LANES:
4766 case IFN_MASK_LEN_LOAD_LANES:
4767 case IFN_MASK_STORE:
4768 case IFN_MASK_STORE_LANES:
4769 case IFN_MASK_LEN_STORE_LANES:
4770 case IFN_MASK_LEN_LOAD:
4771 case IFN_MASK_LEN_STORE:
4772 return 2;
4773
4774 case IFN_MASK_GATHER_LOAD:
4775 case IFN_MASK_SCATTER_STORE:
4776 case IFN_MASK_LEN_GATHER_LOAD:
4777 case IFN_MASK_LEN_SCATTER_STORE:
4778 return 4;
4779
4780 case IFN_VCOND_MASK_LEN:
4781 return 0;
4782
4783 default:
4784 return (conditional_internal_fn_code (fn) != ERROR_MARK
4785 || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
4786 }
4787 }
4788
4789 /* If FN takes a value that should be stored to memory, return the index
4790 of that argument, otherwise return -1. */
4791
4792 int
4793 internal_fn_stored_value_index (internal_fn fn)
4794 {
4795 switch (fn)
4796 {
4797 case IFN_MASK_STORE:
4798 case IFN_MASK_STORE_LANES:
4799 case IFN_SCATTER_STORE:
4800 case IFN_MASK_SCATTER_STORE:
4801 case IFN_MASK_LEN_SCATTER_STORE:
4802 return 3;
4803
4804 case IFN_LEN_STORE:
4805 return 4;
4806
4807 case IFN_MASK_LEN_STORE:
4808 case IFN_MASK_LEN_STORE_LANES:
4809 return 5;
4810
4811 default:
4812 return -1;
4813 }
4814 }
4815
4816 /* Return true if the target supports gather load or scatter store function
4817 IFN. For loads, VECTOR_TYPE is the vector type of the load result,
4818 while for stores it is the vector type of the stored data argument.
4819 MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
4820 or stored. OFFSET_VECTOR_TYPE is the vector type that holds the
4821 offset from the shared base address of each loaded or stored element.
4822 SCALE is the amount by which these offsets should be multiplied
4823 *after* they have been extended to address width. */
4824
4825 bool
4826 internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
4827 tree memory_element_type,
4828 tree offset_vector_type, int scale)
4829 {
4830 if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
4831 TYPE_SIZE (memory_element_type)))
4832 return false;
4833 if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
4834 TYPE_VECTOR_SUBPARTS (offset_vector_type)))
4835 return false;
4836 optab optab = direct_internal_fn_optab (ifn);
4837 insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
4838 TYPE_MODE (offset_vector_type));
4839 int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
4840 bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
4841 return (icode != CODE_FOR_nothing
4842 && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
4843 && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
4844 }
4845
4846 /* Return true if the target supports IFN_CHECK_{RAW,WAR}_PTRS function IFN
4847 for pointers of type TYPE when the accesses have LENGTH bytes and their
4848 common byte alignment is ALIGN. */
4849
4850 bool
4851 internal_check_ptrs_fn_supported_p (internal_fn ifn, tree type,
4852 poly_uint64 length, unsigned int align)
4853 {
4854 machine_mode mode = TYPE_MODE (type);
4855 optab optab = direct_internal_fn_optab (ifn);
4856 insn_code icode = direct_optab_handler (optab, mode);
4857 if (icode == CODE_FOR_nothing)
4858 return false;
4859 rtx length_rtx = immed_wide_int_const (length, mode);
4860 return (insn_operand_matches (icode, 3, length_rtx)
4861 && insn_operand_matches (icode, 4, GEN_INT (align)));
4862 }
4863
4864 /* Return the supported bias for IFN which is either IFN_{LEN_,MASK_LEN_,}LOAD
4865 or IFN_{LEN_,MASK_LEN_,}STORE. For now we only support the biases of 0 and
4866 -1 (in case 0 is not an allowable length for {len_,mask_len_}load or
4867 {len_,mask_len_}store). If none of the biases match what the backend
4868 provides, return VECT_PARTIAL_BIAS_UNSUPPORTED. */
4869
4870 signed char
4871 internal_len_load_store_bias (internal_fn ifn, machine_mode mode)
4872 {
4873 optab optab = direct_internal_fn_optab (ifn);
4874 insn_code icode = direct_optab_handler (optab, mode);
4875 int bias_no = 3;
4876
4877 if (icode == CODE_FOR_nothing)
4878 {
4879 machine_mode mask_mode;
4880 if (!targetm.vectorize.get_mask_mode (mode).exists (&mask_mode))
4881 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4882 if (ifn == IFN_LEN_LOAD)
4883 {
4884 /* Try MASK_LEN_LOAD. */
4885 optab = direct_internal_fn_optab (IFN_MASK_LEN_LOAD);
4886 }
4887 else
4888 {
4889 /* Try MASK_LEN_STORE. */
4890 optab = direct_internal_fn_optab (IFN_MASK_LEN_STORE);
4891 }
4892 icode = convert_optab_handler (optab, mode, mask_mode);
4893 bias_no = 4;
4894 }
4895
4896 if (icode != CODE_FOR_nothing)
4897 {
4898 /* For now we only support biases of 0 or -1. Try both of them. */
4899 if (insn_operand_matches (icode, bias_no, GEN_INT (0)))
4900 return 0;
4901 if (insn_operand_matches (icode, bias_no, GEN_INT (-1)))
4902 return -1;
4903 }
4904
4905 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4906 }
4907
4908 /* Expand STMT as though it were a call to internal function FN. */
4909
4910 void
4911 expand_internal_call (internal_fn fn, gcall *stmt)
4912 {
4913 internal_fn_expanders[fn] (fn, stmt);
4914 }
4915
4916 /* Expand STMT, which is a call to internal function FN. */
4917
4918 void
4919 expand_internal_call (gcall *stmt)
4920 {
4921 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
4922 }
4923
4924 /* If TYPE is a vector type, return true if IFN is a direct internal
4925 function that is supported for that type. If TYPE is a scalar type,
4926 return true if IFN is a direct internal function that is supported for
4927 the target's preferred vector version of TYPE. */
4928
4929 bool
4930 vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
4931 {
4932 if (VECTOR_MODE_P (TYPE_MODE (type)))
4933 return direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED);
4934
4935 scalar_mode smode;
4936 if (VECTOR_TYPE_P (type)
4937 || !is_a <scalar_mode> (TYPE_MODE (type), &smode))
4938 return false;
4939
4940 machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
4941 if (VECTOR_MODE_P (vmode))
4942 {
4943 tree vectype = build_vector_type_for_mode (type, vmode);
4944 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4945 return true;
4946 }
4947
4948 auto_vector_modes vector_modes;
4949 targetm.vectorize.autovectorize_vector_modes (&vector_modes, true);
4950 for (machine_mode base_mode : vector_modes)
4951 if (related_vector_mode (base_mode, smode).exists (&vmode))
4952 {
4953 tree vectype = build_vector_type_for_mode (type, vmode);
4954 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4955 return true;
4956 }
4957
4958 return false;
4959 }
4960
4961 void
4962 expand_SHUFFLEVECTOR (internal_fn, gcall *)
4963 {
4964 gcc_unreachable ();
4965 }
4966
4967 void
4968 expand_PHI (internal_fn, gcall *)
4969 {
4970 gcc_unreachable ();
4971 }
4972
4973 void
4974 expand_SPACESHIP (internal_fn, gcall *stmt)
4975 {
4976 tree lhs = gimple_call_lhs (stmt);
4977 tree rhs1 = gimple_call_arg (stmt, 0);
4978 tree rhs2 = gimple_call_arg (stmt, 1);
4979 tree type = TREE_TYPE (rhs1);
4980
4981 do_pending_stack_adjust ();
4982
4983 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
4984 rtx op1 = expand_normal (rhs1);
4985 rtx op2 = expand_normal (rhs2);
4986
4987 class expand_operand ops[3];
4988 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (lhs)));
4989 create_input_operand (&ops[1], op1, TYPE_MODE (type));
4990 create_input_operand (&ops[2], op2, TYPE_MODE (type));
4991 insn_code icode = optab_handler (spaceship_optab, TYPE_MODE (type));
4992 expand_insn (icode, 3, ops);
4993 if (!rtx_equal_p (target, ops[0].value))
4994 emit_move_insn (target, ops[0].value);
4995 }
4996
4997 void
4998 expand_ASSUME (internal_fn, gcall *)
4999 {
5000 }
5001
5002 void
5003 expand_MASK_CALL (internal_fn, gcall *)
5004 {
5005 /* This IFN should only exist between ifcvt and vect passes. */
5006 gcc_unreachable ();
5007 }
5008
5009 void
5010 expand_MULBITINT (internal_fn, gcall *stmt)
5011 {
5012 rtx_mode_t args[6];
5013 for (int i = 0; i < 6; i++)
5014 args[i] = rtx_mode_t (expand_normal (gimple_call_arg (stmt, i)),
5015 (i & 1) ? SImode : ptr_mode);
5016 rtx fun = init_one_libfunc ("__mulbitint3");
5017 emit_library_call_value_1 (0, fun, NULL_RTX, LCT_NORMAL, VOIDmode, 6, args);
5018 }
5019
5020 void
5021 expand_DIVMODBITINT (internal_fn, gcall *stmt)
5022 {
5023 rtx_mode_t args[8];
5024 for (int i = 0; i < 8; i++)
5025 args[i] = rtx_mode_t (expand_normal (gimple_call_arg (stmt, i)),
5026 (i & 1) ? SImode : ptr_mode);
5027 rtx fun = init_one_libfunc ("__divmodbitint4");
5028 emit_library_call_value_1 (0, fun, NULL_RTX, LCT_NORMAL, VOIDmode, 8, args);
5029 }
5030
5031 void
5032 expand_FLOATTOBITINT (internal_fn, gcall *stmt)
5033 {
5034 machine_mode mode = TYPE_MODE (TREE_TYPE (gimple_call_arg (stmt, 2)));
5035 rtx arg0 = expand_normal (gimple_call_arg (stmt, 0));
5036 rtx arg1 = expand_normal (gimple_call_arg (stmt, 1));
5037 rtx arg2 = expand_normal (gimple_call_arg (stmt, 2));
5038 const char *mname = GET_MODE_NAME (mode);
5039 unsigned mname_len = strlen (mname);
5040 int len = 12 + mname_len;
5041 if (DECIMAL_FLOAT_MODE_P (mode))
5042 len += 4;
5043 char *libfunc_name = XALLOCAVEC (char, len);
5044 char *p = libfunc_name;
5045 const char *q;
5046 if (DECIMAL_FLOAT_MODE_P (mode))
5047 {
5048 #if ENABLE_DECIMAL_BID_FORMAT
5049 memcpy (p, "__bid_fix", 9);
5050 #else
5051 memcpy (p, "__dpd_fix", 9);
5052 #endif
5053 p += 9;
5054 }
5055 else
5056 {
5057 memcpy (p, "__fix", 5);
5058 p += 5;
5059 }
5060 for (q = mname; *q; q++)
5061 *p++ = TOLOWER (*q);
5062 memcpy (p, "bitint", 7);
5063 rtx fun = init_one_libfunc (libfunc_name);
5064 emit_library_call (fun, LCT_NORMAL, VOIDmode, arg0, ptr_mode, arg1,
5065 SImode, arg2, mode);
5066 }
5067
5068 void
5069 expand_BITINTTOFLOAT (internal_fn, gcall *stmt)
5070 {
5071 tree lhs = gimple_call_lhs (stmt);
5072 if (!lhs)
5073 return;
5074 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
5075 rtx arg0 = expand_normal (gimple_call_arg (stmt, 0));
5076 rtx arg1 = expand_normal (gimple_call_arg (stmt, 1));
5077 const char *mname = GET_MODE_NAME (mode);
5078 unsigned mname_len = strlen (mname);
5079 int len = 14 + mname_len;
5080 if (DECIMAL_FLOAT_MODE_P (mode))
5081 len += 4;
5082 char *libfunc_name = XALLOCAVEC (char, len);
5083 char *p = libfunc_name;
5084 const char *q;
5085 if (DECIMAL_FLOAT_MODE_P (mode))
5086 {
5087 #if ENABLE_DECIMAL_BID_FORMAT
5088 memcpy (p, "__bid_floatbitint", 17);
5089 #else
5090 memcpy (p, "__dpd_floatbitint", 17);
5091 #endif
5092 p += 17;
5093 }
5094 else
5095 {
5096 memcpy (p, "__floatbitint", 13);
5097 p += 13;
5098 }
5099 for (q = mname; *q; q++)
5100 *p++ = TOLOWER (*q);
5101 *p = '\0';
5102 rtx fun = init_one_libfunc (libfunc_name);
5103 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
5104 rtx val = emit_library_call_value (fun, target, LCT_PURE, mode,
5105 arg0, ptr_mode, arg1, SImode);
5106 if (val != target)
5107 emit_move_insn (target, val);
5108 }
5109
5110 void
5111 expand_POPCOUNT (internal_fn fn, gcall *stmt)
5112 {
5113 if (gimple_call_num_args (stmt) == 1)
5114 {
5115 expand_unary_optab_fn (fn, stmt, popcount_optab);
5116 return;
5117 }
5118 /* If .POPCOUNT call has 2 arguments, match_single_bit_test marked it
5119 because the result is only used in an equality comparison against 1.
5120 Use rtx costs in that case to determine if .POPCOUNT (arg) == 1
5121 or (arg ^ (arg - 1)) > arg - 1 is cheaper. */
5122 bool speed_p = optimize_insn_for_speed_p ();
5123 tree lhs = gimple_call_lhs (stmt);
5124 tree arg = gimple_call_arg (stmt, 0);
5125 tree type = TREE_TYPE (arg);
5126 machine_mode mode = TYPE_MODE (type);
5127 do_pending_stack_adjust ();
5128 start_sequence ();
5129 expand_unary_optab_fn (fn, stmt, popcount_optab);
5130 rtx_insn *popcount_insns = get_insns ();
5131 end_sequence ();
5132 start_sequence ();
5133 rtx plhs = expand_normal (lhs);
5134 rtx pcmp = emit_store_flag (NULL_RTX, EQ, plhs, const1_rtx, mode, 0, 0);
5135 if (pcmp == NULL_RTX)
5136 {
5137 fail:
5138 end_sequence ();
5139 emit_insn (popcount_insns);
5140 return;
5141 }
5142 rtx_insn *popcount_cmp_insns = get_insns ();
5143 end_sequence ();
5144 start_sequence ();
5145 rtx op0 = expand_normal (arg);
5146 rtx argm1 = expand_simple_binop (mode, PLUS, op0, constm1_rtx, NULL_RTX,
5147 1, OPTAB_DIRECT);
5148 if (argm1 == NULL_RTX)
5149 goto fail;
5150 rtx argxorargm1 = expand_simple_binop (mode, XOR, op0, argm1, NULL_RTX,
5151 1, OPTAB_DIRECT);
5152 if (argxorargm1 == NULL_RTX)
5153 goto fail;
5154 rtx cmp = emit_store_flag (NULL_RTX, GTU, argxorargm1, argm1, mode, 1, 1);
5155 if (cmp == NULL_RTX)
5156 goto fail;
5157 rtx_insn *cmp_insns = get_insns ();
5158 end_sequence ();
5159 unsigned popcount_cost = (seq_cost (popcount_insns, speed_p)
5160 + seq_cost (popcount_cmp_insns, speed_p));
5161 unsigned cmp_cost = seq_cost (cmp_insns, speed_p);
5162 if (popcount_cost <= cmp_cost)
5163 emit_insn (popcount_insns);
5164 else
5165 {
5166 emit_insn (cmp_insns);
5167 plhs = expand_normal (lhs);
5168 if (GET_MODE (cmp) != GET_MODE (plhs))
5169 cmp = convert_to_mode (GET_MODE (plhs), cmp, 1);
5170 emit_move_insn (plhs, cmp);
5171 }
5172 }