]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/internal-fn.c
re PR c++/85052 (Implement support for clang's __builtin_convertvector)
[thirdparty/gcc.git] / gcc / internal-fn.c
1 /* Internal functions.
2 Copyright (C) 2011-2019 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
53 /* The names of each internal function, indexed by function number. */
54 const char *const internal_fn_name_array[] = {
55 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
56 #include "internal-fn.def"
57 "<invalid-fn>"
58 };
59
60 /* The ECF_* flags of each internal function, indexed by function number. */
61 const int internal_fn_flags_array[] = {
62 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
63 #include "internal-fn.def"
64 0
65 };
66
67 /* Return the internal function called NAME, or IFN_LAST if there's
68 no such function. */
69
70 internal_fn
71 lookup_internal_fn (const char *name)
72 {
73 typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
74 static name_to_fn_map_type *name_to_fn_map;
75
76 if (!name_to_fn_map)
77 {
78 name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
79 for (unsigned int i = 0; i < IFN_LAST; ++i)
80 name_to_fn_map->put (internal_fn_name (internal_fn (i)),
81 internal_fn (i));
82 }
83 internal_fn *entry = name_to_fn_map->get (name);
84 return entry ? *entry : IFN_LAST;
85 }
86
87 /* Fnspec of each internal function, indexed by function number. */
88 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
89
90 void
91 init_internal_fns ()
92 {
93 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
94 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
95 build_string ((int) sizeof (FNSPEC), FNSPEC ? FNSPEC : "");
96 #include "internal-fn.def"
97 internal_fn_fnspec_array[IFN_LAST] = 0;
98 }
99
100 /* Create static initializers for the information returned by
101 direct_internal_fn. */
102 #define not_direct { -2, -2, false }
103 #define mask_load_direct { -1, 2, false }
104 #define load_lanes_direct { -1, -1, false }
105 #define mask_load_lanes_direct { -1, -1, false }
106 #define gather_load_direct { -1, -1, false }
107 #define mask_store_direct { 3, 2, false }
108 #define store_lanes_direct { 0, 0, false }
109 #define mask_store_lanes_direct { 0, 0, false }
110 #define scatter_store_direct { 3, 3, false }
111 #define unary_direct { 0, 0, true }
112 #define binary_direct { 0, 0, true }
113 #define ternary_direct { 0, 0, true }
114 #define cond_unary_direct { 1, 1, true }
115 #define cond_binary_direct { 1, 1, true }
116 #define cond_ternary_direct { 1, 1, true }
117 #define while_direct { 0, 2, false }
118 #define fold_extract_direct { 2, 2, false }
119 #define fold_left_direct { 1, 1, false }
120
121 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
122 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
123 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
124 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
125 UNSIGNED_OPTAB, TYPE) TYPE##_direct,
126 #include "internal-fn.def"
127 not_direct
128 };
129
130 /* ARRAY_TYPE is an array of vector modes. Return the associated insn
131 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
132
133 static enum insn_code
134 get_multi_vector_move (tree array_type, convert_optab optab)
135 {
136 machine_mode imode;
137 machine_mode vmode;
138
139 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
140 imode = TYPE_MODE (array_type);
141 vmode = TYPE_MODE (TREE_TYPE (array_type));
142
143 return convert_optab_handler (optab, imode, vmode);
144 }
145
146 /* Expand LOAD_LANES call STMT using optab OPTAB. */
147
148 static void
149 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
150 {
151 struct expand_operand ops[2];
152 tree type, lhs, rhs;
153 rtx target, mem;
154
155 lhs = gimple_call_lhs (stmt);
156 rhs = gimple_call_arg (stmt, 0);
157 type = TREE_TYPE (lhs);
158
159 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
160 mem = expand_normal (rhs);
161
162 gcc_assert (MEM_P (mem));
163 PUT_MODE (mem, TYPE_MODE (type));
164
165 create_output_operand (&ops[0], target, TYPE_MODE (type));
166 create_fixed_operand (&ops[1], mem);
167 expand_insn (get_multi_vector_move (type, optab), 2, ops);
168 }
169
170 /* Expand STORE_LANES call STMT using optab OPTAB. */
171
172 static void
173 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
174 {
175 struct expand_operand ops[2];
176 tree type, lhs, rhs;
177 rtx target, reg;
178
179 lhs = gimple_call_lhs (stmt);
180 rhs = gimple_call_arg (stmt, 0);
181 type = TREE_TYPE (rhs);
182
183 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
184 reg = expand_normal (rhs);
185
186 gcc_assert (MEM_P (target));
187 PUT_MODE (target, TYPE_MODE (type));
188
189 create_fixed_operand (&ops[0], target);
190 create_input_operand (&ops[1], reg, TYPE_MODE (type));
191 expand_insn (get_multi_vector_move (type, optab), 2, ops);
192 }
193
194 static void
195 expand_ANNOTATE (internal_fn, gcall *)
196 {
197 gcc_unreachable ();
198 }
199
200 /* This should get expanded in omp_device_lower pass. */
201
202 static void
203 expand_GOMP_USE_SIMT (internal_fn, gcall *)
204 {
205 gcc_unreachable ();
206 }
207
208 /* This should get expanded in omp_device_lower pass. */
209
210 static void
211 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
212 {
213 gcc_unreachable ();
214 }
215
216 /* Allocate per-lane storage and begin non-uniform execution region. */
217
218 static void
219 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
220 {
221 rtx target;
222 tree lhs = gimple_call_lhs (stmt);
223 if (lhs)
224 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
225 else
226 target = gen_reg_rtx (Pmode);
227 rtx size = expand_normal (gimple_call_arg (stmt, 0));
228 rtx align = expand_normal (gimple_call_arg (stmt, 1));
229 struct expand_operand ops[3];
230 create_output_operand (&ops[0], target, Pmode);
231 create_input_operand (&ops[1], size, Pmode);
232 create_input_operand (&ops[2], align, Pmode);
233 gcc_assert (targetm.have_omp_simt_enter ());
234 expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
235 }
236
237 /* Deallocate per-lane storage and leave non-uniform execution region. */
238
239 static void
240 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
241 {
242 gcc_checking_assert (!gimple_call_lhs (stmt));
243 rtx arg = expand_normal (gimple_call_arg (stmt, 0));
244 struct expand_operand ops[1];
245 create_input_operand (&ops[0], arg, Pmode);
246 gcc_assert (targetm.have_omp_simt_exit ());
247 expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
248 }
249
250 /* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
251 without SIMT execution this should be expanded in omp_device_lower pass. */
252
253 static void
254 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
255 {
256 tree lhs = gimple_call_lhs (stmt);
257 if (!lhs)
258 return;
259
260 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
261 gcc_assert (targetm.have_omp_simt_lane ());
262 emit_insn (targetm.gen_omp_simt_lane (target));
263 }
264
265 /* This should get expanded in omp_device_lower pass. */
266
267 static void
268 expand_GOMP_SIMT_VF (internal_fn, gcall *)
269 {
270 gcc_unreachable ();
271 }
272
273 /* Lane index of the first SIMT lane that supplies a non-zero argument.
274 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
275 lane that executed the last iteration for handling OpenMP lastprivate. */
276
277 static void
278 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
279 {
280 tree lhs = gimple_call_lhs (stmt);
281 if (!lhs)
282 return;
283
284 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
285 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
286 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
287 struct expand_operand ops[2];
288 create_output_operand (&ops[0], target, mode);
289 create_input_operand (&ops[1], cond, mode);
290 gcc_assert (targetm.have_omp_simt_last_lane ());
291 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
292 }
293
294 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
295
296 static void
297 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
298 {
299 tree lhs = gimple_call_lhs (stmt);
300 if (!lhs)
301 return;
302
303 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
304 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
305 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
306 struct expand_operand ops[2];
307 create_output_operand (&ops[0], target, mode);
308 create_input_operand (&ops[1], ctr, mode);
309 gcc_assert (targetm.have_omp_simt_ordered ());
310 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
311 }
312
313 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
314 any lane supplies a non-zero argument. */
315
316 static void
317 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
318 {
319 tree lhs = gimple_call_lhs (stmt);
320 if (!lhs)
321 return;
322
323 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
324 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
325 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
326 struct expand_operand ops[2];
327 create_output_operand (&ops[0], target, mode);
328 create_input_operand (&ops[1], cond, mode);
329 gcc_assert (targetm.have_omp_simt_vote_any ());
330 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
331 }
332
333 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
334 is destination lane index XOR given offset. */
335
336 static void
337 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
338 {
339 tree lhs = gimple_call_lhs (stmt);
340 if (!lhs)
341 return;
342
343 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
344 rtx src = expand_normal (gimple_call_arg (stmt, 0));
345 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
346 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
347 struct expand_operand ops[3];
348 create_output_operand (&ops[0], target, mode);
349 create_input_operand (&ops[1], src, mode);
350 create_input_operand (&ops[2], idx, SImode);
351 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
352 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
353 }
354
355 /* Exchange between SIMT lanes according to given source lane index. */
356
357 static void
358 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
359 {
360 tree lhs = gimple_call_lhs (stmt);
361 if (!lhs)
362 return;
363
364 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
365 rtx src = expand_normal (gimple_call_arg (stmt, 0));
366 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
367 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
368 struct expand_operand ops[3];
369 create_output_operand (&ops[0], target, mode);
370 create_input_operand (&ops[1], src, mode);
371 create_input_operand (&ops[2], idx, SImode);
372 gcc_assert (targetm.have_omp_simt_xchg_idx ());
373 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
374 }
375
376 /* This should get expanded in adjust_simduid_builtins. */
377
378 static void
379 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
380 {
381 gcc_unreachable ();
382 }
383
384 /* This should get expanded in adjust_simduid_builtins. */
385
386 static void
387 expand_GOMP_SIMD_VF (internal_fn, gcall *)
388 {
389 gcc_unreachable ();
390 }
391
392 /* This should get expanded in adjust_simduid_builtins. */
393
394 static void
395 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
396 {
397 gcc_unreachable ();
398 }
399
400 /* This should get expanded in adjust_simduid_builtins. */
401
402 static void
403 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
404 {
405 gcc_unreachable ();
406 }
407
408 /* This should get expanded in adjust_simduid_builtins. */
409
410 static void
411 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
412 {
413 gcc_unreachable ();
414 }
415
416 /* This should get expanded in the sanopt pass. */
417
418 static void
419 expand_UBSAN_NULL (internal_fn, gcall *)
420 {
421 gcc_unreachable ();
422 }
423
424 /* This should get expanded in the sanopt pass. */
425
426 static void
427 expand_UBSAN_BOUNDS (internal_fn, gcall *)
428 {
429 gcc_unreachable ();
430 }
431
432 /* This should get expanded in the sanopt pass. */
433
434 static void
435 expand_UBSAN_VPTR (internal_fn, gcall *)
436 {
437 gcc_unreachable ();
438 }
439
440 /* This should get expanded in the sanopt pass. */
441
442 static void
443 expand_UBSAN_PTR (internal_fn, gcall *)
444 {
445 gcc_unreachable ();
446 }
447
448 /* This should get expanded in the sanopt pass. */
449
450 static void
451 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
452 {
453 gcc_unreachable ();
454 }
455
456 /* This should get expanded in the sanopt pass. */
457
458 static void
459 expand_ASAN_CHECK (internal_fn, gcall *)
460 {
461 gcc_unreachable ();
462 }
463
464 /* This should get expanded in the sanopt pass. */
465
466 static void
467 expand_ASAN_MARK (internal_fn, gcall *)
468 {
469 gcc_unreachable ();
470 }
471
472 /* This should get expanded in the sanopt pass. */
473
474 static void
475 expand_ASAN_POISON (internal_fn, gcall *)
476 {
477 gcc_unreachable ();
478 }
479
480 /* This should get expanded in the sanopt pass. */
481
482 static void
483 expand_ASAN_POISON_USE (internal_fn, gcall *)
484 {
485 gcc_unreachable ();
486 }
487
488 /* This should get expanded in the tsan pass. */
489
490 static void
491 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
492 {
493 gcc_unreachable ();
494 }
495
496 /* This should get expanded in the lower pass. */
497
498 static void
499 expand_FALLTHROUGH (internal_fn, gcall *call)
500 {
501 error_at (gimple_location (call),
502 "invalid use of attribute %<fallthrough%>");
503 }
504
505 /* Return minimum precision needed to represent all values
506 of ARG in SIGNed integral type. */
507
508 static int
509 get_min_precision (tree arg, signop sign)
510 {
511 int prec = TYPE_PRECISION (TREE_TYPE (arg));
512 int cnt = 0;
513 signop orig_sign = sign;
514 if (TREE_CODE (arg) == INTEGER_CST)
515 {
516 int p;
517 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
518 {
519 widest_int w = wi::to_widest (arg);
520 w = wi::ext (w, prec, sign);
521 p = wi::min_precision (w, sign);
522 }
523 else
524 p = wi::min_precision (wi::to_wide (arg), sign);
525 return MIN (p, prec);
526 }
527 while (CONVERT_EXPR_P (arg)
528 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
529 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
530 {
531 arg = TREE_OPERAND (arg, 0);
532 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
533 {
534 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
535 sign = UNSIGNED;
536 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
537 return prec + (orig_sign != sign);
538 prec = TYPE_PRECISION (TREE_TYPE (arg));
539 }
540 if (++cnt > 30)
541 return prec + (orig_sign != sign);
542 }
543 if (TREE_CODE (arg) != SSA_NAME)
544 return prec + (orig_sign != sign);
545 wide_int arg_min, arg_max;
546 while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
547 {
548 gimple *g = SSA_NAME_DEF_STMT (arg);
549 if (is_gimple_assign (g)
550 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
551 {
552 tree t = gimple_assign_rhs1 (g);
553 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
554 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
555 {
556 arg = t;
557 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
558 {
559 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
560 sign = UNSIGNED;
561 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
562 return prec + (orig_sign != sign);
563 prec = TYPE_PRECISION (TREE_TYPE (arg));
564 }
565 if (++cnt > 30)
566 return prec + (orig_sign != sign);
567 continue;
568 }
569 }
570 return prec + (orig_sign != sign);
571 }
572 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
573 {
574 int p1 = wi::min_precision (arg_min, sign);
575 int p2 = wi::min_precision (arg_max, sign);
576 p1 = MAX (p1, p2);
577 prec = MIN (prec, p1);
578 }
579 else if (sign == UNSIGNED && !wi::neg_p (arg_min, SIGNED))
580 {
581 int p = wi::min_precision (arg_max, UNSIGNED);
582 prec = MIN (prec, p);
583 }
584 return prec + (orig_sign != sign);
585 }
586
587 /* Helper for expand_*_overflow. Set the __imag__ part to true
588 (1 except for signed:1 type, in which case store -1). */
589
590 static void
591 expand_arith_set_overflow (tree lhs, rtx target)
592 {
593 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
594 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
595 write_complex_part (target, constm1_rtx, true);
596 else
597 write_complex_part (target, const1_rtx, true);
598 }
599
600 /* Helper for expand_*_overflow. Store RES into the __real__ part
601 of TARGET. If RES has larger MODE than __real__ part of TARGET,
602 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
603 if LHS has smaller precision than its mode. */
604
605 static void
606 expand_arith_overflow_result_store (tree lhs, rtx target,
607 scalar_int_mode mode, rtx res)
608 {
609 scalar_int_mode tgtmode
610 = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
611 rtx lres = res;
612 if (tgtmode != mode)
613 {
614 rtx_code_label *done_label = gen_label_rtx ();
615 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
616 lres = convert_modes (tgtmode, mode, res, uns);
617 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
618 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
619 EQ, true, mode, NULL_RTX, NULL, done_label,
620 profile_probability::very_likely ());
621 expand_arith_set_overflow (lhs, target);
622 emit_label (done_label);
623 }
624 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
625 int tgtprec = GET_MODE_PRECISION (tgtmode);
626 if (prec < tgtprec)
627 {
628 rtx_code_label *done_label = gen_label_rtx ();
629 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
630 res = lres;
631 if (uns)
632 {
633 rtx mask
634 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
635 tgtmode);
636 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
637 true, OPTAB_LIB_WIDEN);
638 }
639 else
640 {
641 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
642 NULL_RTX, 1);
643 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
644 NULL_RTX, 0);
645 }
646 do_compare_rtx_and_jump (res, lres,
647 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
648 profile_probability::very_likely ());
649 expand_arith_set_overflow (lhs, target);
650 emit_label (done_label);
651 }
652 write_complex_part (target, lres, false);
653 }
654
655 /* Helper for expand_*_overflow. Store RES into TARGET. */
656
657 static void
658 expand_ubsan_result_store (rtx target, rtx res)
659 {
660 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
661 /* If this is a scalar in a register that is stored in a wider mode
662 than the declared mode, compute the result into its declared mode
663 and then convert to the wider mode. Our value is the computed
664 expression. */
665 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
666 else
667 emit_move_insn (target, res);
668 }
669
670 /* Add sub/add overflow checking to the statement STMT.
671 CODE says whether the operation is +, or -. */
672
673 static void
674 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
675 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
676 bool uns1_p, bool is_ubsan, tree *datap)
677 {
678 rtx res, target = NULL_RTX;
679 tree fn;
680 rtx_code_label *done_label = gen_label_rtx ();
681 rtx_code_label *do_error = gen_label_rtx ();
682 do_pending_stack_adjust ();
683 rtx op0 = expand_normal (arg0);
684 rtx op1 = expand_normal (arg1);
685 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
686 int prec = GET_MODE_PRECISION (mode);
687 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
688 bool do_xor = false;
689
690 if (is_ubsan)
691 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
692
693 if (lhs)
694 {
695 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
696 if (!is_ubsan)
697 write_complex_part (target, const0_rtx, true);
698 }
699
700 /* We assume both operands and result have the same precision
701 here (GET_MODE_BITSIZE (mode)), S stands for signed type
702 with that precision, U for unsigned type with that precision,
703 sgn for unsigned most significant bit in that precision.
704 s1 is signed first operand, u1 is unsigned first operand,
705 s2 is signed second operand, u2 is unsigned second operand,
706 sr is signed result, ur is unsigned result and the following
707 rules say how to compute result (which is always result of
708 the operands as if both were unsigned, cast to the right
709 signedness) and how to compute whether operation overflowed.
710
711 s1 + s2 -> sr
712 res = (S) ((U) s1 + (U) s2)
713 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
714 s1 - s2 -> sr
715 res = (S) ((U) s1 - (U) s2)
716 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
717 u1 + u2 -> ur
718 res = u1 + u2
719 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
720 u1 - u2 -> ur
721 res = u1 - u2
722 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
723 s1 + u2 -> sr
724 res = (S) ((U) s1 + u2)
725 ovf = ((U) res ^ sgn) < u2
726 s1 + u2 -> ur
727 t1 = (S) (u2 ^ sgn)
728 t2 = s1 + t1
729 res = (U) t2 ^ sgn
730 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
731 s1 - u2 -> sr
732 res = (S) ((U) s1 - u2)
733 ovf = u2 > ((U) s1 ^ sgn)
734 s1 - u2 -> ur
735 res = (U) s1 - u2
736 ovf = s1 < 0 || u2 > (U) s1
737 u1 - s2 -> sr
738 res = u1 - (U) s2
739 ovf = u1 >= ((U) s2 ^ sgn)
740 u1 - s2 -> ur
741 t1 = u1 ^ sgn
742 t2 = t1 - (U) s2
743 res = t2 ^ sgn
744 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
745 s1 + s2 -> ur
746 res = (U) s1 + (U) s2
747 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
748 u1 + u2 -> sr
749 res = (S) (u1 + u2)
750 ovf = (U) res < u2 || res < 0
751 u1 - u2 -> sr
752 res = (S) (u1 - u2)
753 ovf = u1 >= u2 ? res < 0 : res >= 0
754 s1 - s2 -> ur
755 res = (U) s1 - (U) s2
756 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
757
758 if (code == PLUS_EXPR && uns0_p && !uns1_p)
759 {
760 /* PLUS_EXPR is commutative, if operand signedness differs,
761 canonicalize to the first operand being signed and second
762 unsigned to simplify following code. */
763 std::swap (op0, op1);
764 std::swap (arg0, arg1);
765 uns0_p = false;
766 uns1_p = true;
767 }
768
769 /* u1 +- u2 -> ur */
770 if (uns0_p && uns1_p && unsr_p)
771 {
772 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
773 : usubv4_optab, mode);
774 if (icode != CODE_FOR_nothing)
775 {
776 struct expand_operand ops[4];
777 rtx_insn *last = get_last_insn ();
778
779 res = gen_reg_rtx (mode);
780 create_output_operand (&ops[0], res, mode);
781 create_input_operand (&ops[1], op0, mode);
782 create_input_operand (&ops[2], op1, mode);
783 create_fixed_operand (&ops[3], do_error);
784 if (maybe_expand_insn (icode, 4, ops))
785 {
786 last = get_last_insn ();
787 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
788 && JUMP_P (last)
789 && any_condjump_p (last)
790 && !find_reg_note (last, REG_BR_PROB, 0))
791 add_reg_br_prob_note (last,
792 profile_probability::very_unlikely ());
793 emit_jump (done_label);
794 goto do_error_label;
795 }
796
797 delete_insns_since (last);
798 }
799
800 /* Compute the operation. On RTL level, the addition is always
801 unsigned. */
802 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
803 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
804 rtx tem = op0;
805 /* For PLUS_EXPR, the operation is commutative, so we can pick
806 operand to compare against. For prec <= BITS_PER_WORD, I think
807 preferring REG operand is better over CONST_INT, because
808 the CONST_INT might enlarge the instruction or CSE would need
809 to figure out we'd already loaded it into a register before.
810 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
811 as then the multi-word comparison can be perhaps simplified. */
812 if (code == PLUS_EXPR
813 && (prec <= BITS_PER_WORD
814 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
815 : CONST_SCALAR_INT_P (op1)))
816 tem = op1;
817 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
818 true, mode, NULL_RTX, NULL, done_label,
819 profile_probability::very_likely ());
820 goto do_error_label;
821 }
822
823 /* s1 +- u2 -> sr */
824 if (!uns0_p && uns1_p && !unsr_p)
825 {
826 /* Compute the operation. On RTL level, the addition is always
827 unsigned. */
828 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
829 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
830 rtx tem = expand_binop (mode, add_optab,
831 code == PLUS_EXPR ? res : op0, sgn,
832 NULL_RTX, false, OPTAB_LIB_WIDEN);
833 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
834 done_label, profile_probability::very_likely ());
835 goto do_error_label;
836 }
837
838 /* s1 + u2 -> ur */
839 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
840 {
841 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
842 OPTAB_LIB_WIDEN);
843 /* As we've changed op1, we have to avoid using the value range
844 for the original argument. */
845 arg1 = error_mark_node;
846 do_xor = true;
847 goto do_signed;
848 }
849
850 /* u1 - s2 -> ur */
851 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
852 {
853 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
854 OPTAB_LIB_WIDEN);
855 /* As we've changed op0, we have to avoid using the value range
856 for the original argument. */
857 arg0 = error_mark_node;
858 do_xor = true;
859 goto do_signed;
860 }
861
862 /* s1 - u2 -> ur */
863 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
864 {
865 /* Compute the operation. On RTL level, the addition is always
866 unsigned. */
867 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
868 OPTAB_LIB_WIDEN);
869 int pos_neg = get_range_pos_neg (arg0);
870 if (pos_neg == 2)
871 /* If ARG0 is known to be always negative, this is always overflow. */
872 emit_jump (do_error);
873 else if (pos_neg == 3)
874 /* If ARG0 is not known to be always positive, check at runtime. */
875 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
876 NULL, do_error, profile_probability::very_unlikely ());
877 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
878 done_label, profile_probability::very_likely ());
879 goto do_error_label;
880 }
881
882 /* u1 - s2 -> sr */
883 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
884 {
885 /* Compute the operation. On RTL level, the addition is always
886 unsigned. */
887 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
888 OPTAB_LIB_WIDEN);
889 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
890 OPTAB_LIB_WIDEN);
891 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
892 done_label, profile_probability::very_likely ());
893 goto do_error_label;
894 }
895
896 /* u1 + u2 -> sr */
897 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
898 {
899 /* Compute the operation. On RTL level, the addition is always
900 unsigned. */
901 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
902 OPTAB_LIB_WIDEN);
903 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
904 NULL, do_error, profile_probability::very_unlikely ());
905 rtx tem = op1;
906 /* The operation is commutative, so we can pick operand to compare
907 against. For prec <= BITS_PER_WORD, I think preferring REG operand
908 is better over CONST_INT, because the CONST_INT might enlarge the
909 instruction or CSE would need to figure out we'd already loaded it
910 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
911 might be more beneficial, as then the multi-word comparison can be
912 perhaps simplified. */
913 if (prec <= BITS_PER_WORD
914 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
915 : CONST_SCALAR_INT_P (op0))
916 tem = op0;
917 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
918 done_label, profile_probability::very_likely ());
919 goto do_error_label;
920 }
921
922 /* s1 +- s2 -> ur */
923 if (!uns0_p && !uns1_p && unsr_p)
924 {
925 /* Compute the operation. On RTL level, the addition is always
926 unsigned. */
927 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
928 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
929 int pos_neg = get_range_pos_neg (arg1);
930 if (code == PLUS_EXPR)
931 {
932 int pos_neg0 = get_range_pos_neg (arg0);
933 if (pos_neg0 != 3 && pos_neg == 3)
934 {
935 std::swap (op0, op1);
936 pos_neg = pos_neg0;
937 }
938 }
939 rtx tem;
940 if (pos_neg != 3)
941 {
942 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
943 ? and_optab : ior_optab,
944 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
945 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
946 NULL, done_label, profile_probability::very_likely ());
947 }
948 else
949 {
950 rtx_code_label *do_ior_label = gen_label_rtx ();
951 do_compare_rtx_and_jump (op1, const0_rtx,
952 code == MINUS_EXPR ? GE : LT, false, mode,
953 NULL_RTX, NULL, do_ior_label,
954 profile_probability::even ());
955 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
956 OPTAB_LIB_WIDEN);
957 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
958 NULL, done_label, profile_probability::very_likely ());
959 emit_jump (do_error);
960 emit_label (do_ior_label);
961 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
962 OPTAB_LIB_WIDEN);
963 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
964 NULL, done_label, profile_probability::very_likely ());
965 }
966 goto do_error_label;
967 }
968
969 /* u1 - u2 -> sr */
970 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
971 {
972 /* Compute the operation. On RTL level, the addition is always
973 unsigned. */
974 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
975 OPTAB_LIB_WIDEN);
976 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
977 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
978 op0_geu_op1, profile_probability::even ());
979 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
980 NULL, done_label, profile_probability::very_likely ());
981 emit_jump (do_error);
982 emit_label (op0_geu_op1);
983 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
984 NULL, done_label, profile_probability::very_likely ());
985 goto do_error_label;
986 }
987
988 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
989
990 /* s1 +- s2 -> sr */
991 do_signed:
992 {
993 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
994 : subv4_optab, mode);
995 if (icode != CODE_FOR_nothing)
996 {
997 struct expand_operand ops[4];
998 rtx_insn *last = get_last_insn ();
999
1000 res = gen_reg_rtx (mode);
1001 create_output_operand (&ops[0], res, mode);
1002 create_input_operand (&ops[1], op0, mode);
1003 create_input_operand (&ops[2], op1, mode);
1004 create_fixed_operand (&ops[3], do_error);
1005 if (maybe_expand_insn (icode, 4, ops))
1006 {
1007 last = get_last_insn ();
1008 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1009 && JUMP_P (last)
1010 && any_condjump_p (last)
1011 && !find_reg_note (last, REG_BR_PROB, 0))
1012 add_reg_br_prob_note (last,
1013 profile_probability::very_unlikely ());
1014 emit_jump (done_label);
1015 goto do_error_label;
1016 }
1017
1018 delete_insns_since (last);
1019 }
1020
1021 /* Compute the operation. On RTL level, the addition is always
1022 unsigned. */
1023 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1024 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1025
1026 /* If we can prove that one of the arguments (for MINUS_EXPR only
1027 the second operand, as subtraction is not commutative) is always
1028 non-negative or always negative, we can do just one comparison
1029 and conditional jump. */
1030 int pos_neg = get_range_pos_neg (arg1);
1031 if (code == PLUS_EXPR)
1032 {
1033 int pos_neg0 = get_range_pos_neg (arg0);
1034 if (pos_neg0 != 3 && pos_neg == 3)
1035 {
1036 std::swap (op0, op1);
1037 pos_neg = pos_neg0;
1038 }
1039 }
1040
1041 /* Addition overflows if and only if the two operands have the same sign,
1042 and the result has the opposite sign. Subtraction overflows if and
1043 only if the two operands have opposite sign, and the subtrahend has
1044 the same sign as the result. Here 0 is counted as positive. */
1045 if (pos_neg == 3)
1046 {
1047 /* Compute op0 ^ op1 (operands have opposite sign). */
1048 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1049 OPTAB_LIB_WIDEN);
1050
1051 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1052 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1053 OPTAB_LIB_WIDEN);
1054
1055 rtx tem;
1056 if (code == PLUS_EXPR)
1057 {
1058 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1059 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1060 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1061 OPTAB_LIB_WIDEN);
1062 }
1063 else
1064 {
1065 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1066 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1067 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1068 OPTAB_LIB_WIDEN);
1069 }
1070
1071 /* No overflow if the result has bit sign cleared. */
1072 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1073 NULL, done_label, profile_probability::very_likely ());
1074 }
1075
1076 /* Compare the result of the operation with the first operand.
1077 No overflow for addition if second operand is positive and result
1078 is larger or second operand is negative and result is smaller.
1079 Likewise for subtraction with sign of second operand flipped. */
1080 else
1081 do_compare_rtx_and_jump (res, op0,
1082 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1083 false, mode, NULL_RTX, NULL, done_label,
1084 profile_probability::very_likely ());
1085 }
1086
1087 do_error_label:
1088 emit_label (do_error);
1089 if (is_ubsan)
1090 {
1091 /* Expand the ubsan builtin call. */
1092 push_temp_slots ();
1093 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1094 arg0, arg1, datap);
1095 expand_normal (fn);
1096 pop_temp_slots ();
1097 do_pending_stack_adjust ();
1098 }
1099 else if (lhs)
1100 expand_arith_set_overflow (lhs, target);
1101
1102 /* We're done. */
1103 emit_label (done_label);
1104
1105 if (lhs)
1106 {
1107 if (is_ubsan)
1108 expand_ubsan_result_store (target, res);
1109 else
1110 {
1111 if (do_xor)
1112 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1113 OPTAB_LIB_WIDEN);
1114
1115 expand_arith_overflow_result_store (lhs, target, mode, res);
1116 }
1117 }
1118 }
1119
1120 /* Add negate overflow checking to the statement STMT. */
1121
1122 static void
1123 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1124 tree *datap)
1125 {
1126 rtx res, op1;
1127 tree fn;
1128 rtx_code_label *done_label, *do_error;
1129 rtx target = NULL_RTX;
1130
1131 done_label = gen_label_rtx ();
1132 do_error = gen_label_rtx ();
1133
1134 do_pending_stack_adjust ();
1135 op1 = expand_normal (arg1);
1136
1137 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
1138 if (lhs)
1139 {
1140 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1141 if (!is_ubsan)
1142 write_complex_part (target, const0_rtx, true);
1143 }
1144
1145 enum insn_code icode = optab_handler (negv3_optab, mode);
1146 if (icode != CODE_FOR_nothing)
1147 {
1148 struct expand_operand ops[3];
1149 rtx_insn *last = get_last_insn ();
1150
1151 res = gen_reg_rtx (mode);
1152 create_output_operand (&ops[0], res, mode);
1153 create_input_operand (&ops[1], op1, mode);
1154 create_fixed_operand (&ops[2], do_error);
1155 if (maybe_expand_insn (icode, 3, ops))
1156 {
1157 last = get_last_insn ();
1158 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1159 && JUMP_P (last)
1160 && any_condjump_p (last)
1161 && !find_reg_note (last, REG_BR_PROB, 0))
1162 add_reg_br_prob_note (last,
1163 profile_probability::very_unlikely ());
1164 emit_jump (done_label);
1165 }
1166 else
1167 {
1168 delete_insns_since (last);
1169 icode = CODE_FOR_nothing;
1170 }
1171 }
1172
1173 if (icode == CODE_FOR_nothing)
1174 {
1175 /* Compute the operation. On RTL level, the addition is always
1176 unsigned. */
1177 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1178
1179 /* Compare the operand with the most negative value. */
1180 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1181 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1182 done_label, profile_probability::very_likely ());
1183 }
1184
1185 emit_label (do_error);
1186 if (is_ubsan)
1187 {
1188 /* Expand the ubsan builtin call. */
1189 push_temp_slots ();
1190 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1191 arg1, NULL_TREE, datap);
1192 expand_normal (fn);
1193 pop_temp_slots ();
1194 do_pending_stack_adjust ();
1195 }
1196 else if (lhs)
1197 expand_arith_set_overflow (lhs, target);
1198
1199 /* We're done. */
1200 emit_label (done_label);
1201
1202 if (lhs)
1203 {
1204 if (is_ubsan)
1205 expand_ubsan_result_store (target, res);
1206 else
1207 expand_arith_overflow_result_store (lhs, target, mode, res);
1208 }
1209 }
1210
1211 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1212 mode MODE can be expanded without using a libcall. */
1213
1214 static bool
1215 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1216 rtx op0, rtx op1, bool uns)
1217 {
1218 if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1219 != CODE_FOR_nothing)
1220 return true;
1221
1222 if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1223 != CODE_FOR_nothing)
1224 return true;
1225
1226 rtx_insn *last = get_last_insn ();
1227 if (CONSTANT_P (op0))
1228 op0 = convert_modes (wmode, mode, op0, uns);
1229 else
1230 op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1231 if (CONSTANT_P (op1))
1232 op1 = convert_modes (wmode, mode, op1, uns);
1233 else
1234 op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1235 rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1236 delete_insns_since (last);
1237 return ret != NULL_RTX;
1238 }
1239
1240 /* Add mul overflow checking to the statement STMT. */
1241
1242 static void
1243 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1244 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1245 tree *datap)
1246 {
1247 rtx res, op0, op1;
1248 tree fn, type;
1249 rtx_code_label *done_label, *do_error;
1250 rtx target = NULL_RTX;
1251 signop sign;
1252 enum insn_code icode;
1253
1254 done_label = gen_label_rtx ();
1255 do_error = gen_label_rtx ();
1256
1257 do_pending_stack_adjust ();
1258 op0 = expand_normal (arg0);
1259 op1 = expand_normal (arg1);
1260
1261 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1262 bool uns = unsr_p;
1263 if (lhs)
1264 {
1265 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1266 if (!is_ubsan)
1267 write_complex_part (target, const0_rtx, true);
1268 }
1269
1270 if (is_ubsan)
1271 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1272
1273 /* We assume both operands and result have the same precision
1274 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1275 with that precision, U for unsigned type with that precision,
1276 sgn for unsigned most significant bit in that precision.
1277 s1 is signed first operand, u1 is unsigned first operand,
1278 s2 is signed second operand, u2 is unsigned second operand,
1279 sr is signed result, ur is unsigned result and the following
1280 rules say how to compute result (which is always result of
1281 the operands as if both were unsigned, cast to the right
1282 signedness) and how to compute whether operation overflowed.
1283 main_ovf (false) stands for jump on signed multiplication
1284 overflow or the main algorithm with uns == false.
1285 main_ovf (true) stands for jump on unsigned multiplication
1286 overflow or the main algorithm with uns == true.
1287
1288 s1 * s2 -> sr
1289 res = (S) ((U) s1 * (U) s2)
1290 ovf = main_ovf (false)
1291 u1 * u2 -> ur
1292 res = u1 * u2
1293 ovf = main_ovf (true)
1294 s1 * u2 -> ur
1295 res = (U) s1 * u2
1296 ovf = (s1 < 0 && u2) || main_ovf (true)
1297 u1 * u2 -> sr
1298 res = (S) (u1 * u2)
1299 ovf = res < 0 || main_ovf (true)
1300 s1 * u2 -> sr
1301 res = (S) ((U) s1 * u2)
1302 ovf = (S) u2 >= 0 ? main_ovf (false)
1303 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1304 s1 * s2 -> ur
1305 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1306 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1307 res = t1 * t2
1308 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1309
1310 if (uns0_p && !uns1_p)
1311 {
1312 /* Multiplication is commutative, if operand signedness differs,
1313 canonicalize to the first operand being signed and second
1314 unsigned to simplify following code. */
1315 std::swap (op0, op1);
1316 std::swap (arg0, arg1);
1317 uns0_p = false;
1318 uns1_p = true;
1319 }
1320
1321 int pos_neg0 = get_range_pos_neg (arg0);
1322 int pos_neg1 = get_range_pos_neg (arg1);
1323
1324 /* s1 * u2 -> ur */
1325 if (!uns0_p && uns1_p && unsr_p)
1326 {
1327 switch (pos_neg0)
1328 {
1329 case 1:
1330 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1331 goto do_main;
1332 case 2:
1333 /* If s1 is negative, avoid the main code, just multiply and
1334 signal overflow if op1 is not 0. */
1335 struct separate_ops ops;
1336 ops.code = MULT_EXPR;
1337 ops.type = TREE_TYPE (arg1);
1338 ops.op0 = make_tree (ops.type, op0);
1339 ops.op1 = make_tree (ops.type, op1);
1340 ops.op2 = NULL_TREE;
1341 ops.location = loc;
1342 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1343 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1344 NULL, done_label, profile_probability::very_likely ());
1345 goto do_error_label;
1346 case 3:
1347 rtx_code_label *do_main_label;
1348 do_main_label = gen_label_rtx ();
1349 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1350 NULL, do_main_label, profile_probability::very_likely ());
1351 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1352 NULL, do_main_label, profile_probability::very_likely ());
1353 expand_arith_set_overflow (lhs, target);
1354 emit_label (do_main_label);
1355 goto do_main;
1356 default:
1357 gcc_unreachable ();
1358 }
1359 }
1360
1361 /* u1 * u2 -> sr */
1362 if (uns0_p && uns1_p && !unsr_p)
1363 {
1364 uns = true;
1365 /* Rest of handling of this case after res is computed. */
1366 goto do_main;
1367 }
1368
1369 /* s1 * u2 -> sr */
1370 if (!uns0_p && uns1_p && !unsr_p)
1371 {
1372 switch (pos_neg1)
1373 {
1374 case 1:
1375 goto do_main;
1376 case 2:
1377 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1378 avoid the main code, just multiply and signal overflow
1379 unless 0 * u2 or -1 * ((U) Smin). */
1380 struct separate_ops ops;
1381 ops.code = MULT_EXPR;
1382 ops.type = TREE_TYPE (arg1);
1383 ops.op0 = make_tree (ops.type, op0);
1384 ops.op1 = make_tree (ops.type, op1);
1385 ops.op2 = NULL_TREE;
1386 ops.location = loc;
1387 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1388 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1389 NULL, done_label, profile_probability::very_likely ());
1390 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1391 NULL, do_error, profile_probability::very_unlikely ());
1392 int prec;
1393 prec = GET_MODE_PRECISION (mode);
1394 rtx sgn;
1395 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1396 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1397 NULL, done_label, profile_probability::very_likely ());
1398 goto do_error_label;
1399 case 3:
1400 /* Rest of handling of this case after res is computed. */
1401 goto do_main;
1402 default:
1403 gcc_unreachable ();
1404 }
1405 }
1406
1407 /* s1 * s2 -> ur */
1408 if (!uns0_p && !uns1_p && unsr_p)
1409 {
1410 rtx tem, tem2;
1411 switch (pos_neg0 | pos_neg1)
1412 {
1413 case 1: /* Both operands known to be non-negative. */
1414 goto do_main;
1415 case 2: /* Both operands known to be negative. */
1416 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1417 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1418 /* Avoid looking at arg0/arg1 ranges, as we've changed
1419 the arguments. */
1420 arg0 = error_mark_node;
1421 arg1 = error_mark_node;
1422 goto do_main;
1423 case 3:
1424 if ((pos_neg0 ^ pos_neg1) == 3)
1425 {
1426 /* If one operand is known to be negative and the other
1427 non-negative, this overflows always, unless the non-negative
1428 one is 0. Just do normal multiply and set overflow
1429 unless one of the operands is 0. */
1430 struct separate_ops ops;
1431 ops.code = MULT_EXPR;
1432 ops.type
1433 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1434 1);
1435 ops.op0 = make_tree (ops.type, op0);
1436 ops.op1 = make_tree (ops.type, op1);
1437 ops.op2 = NULL_TREE;
1438 ops.location = loc;
1439 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1440 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1441 OPTAB_LIB_WIDEN);
1442 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
1443 NULL_RTX, NULL, done_label,
1444 profile_probability::very_likely ());
1445 goto do_error_label;
1446 }
1447 /* The general case, do all the needed comparisons at runtime. */
1448 rtx_code_label *do_main_label, *after_negate_label;
1449 rtx rop0, rop1;
1450 rop0 = gen_reg_rtx (mode);
1451 rop1 = gen_reg_rtx (mode);
1452 emit_move_insn (rop0, op0);
1453 emit_move_insn (rop1, op1);
1454 op0 = rop0;
1455 op1 = rop1;
1456 do_main_label = gen_label_rtx ();
1457 after_negate_label = gen_label_rtx ();
1458 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1459 OPTAB_LIB_WIDEN);
1460 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1461 NULL, after_negate_label, profile_probability::very_likely ());
1462 /* Both arguments negative here, negate them and continue with
1463 normal unsigned overflow checking multiplication. */
1464 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1465 NULL_RTX, false));
1466 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1467 NULL_RTX, false));
1468 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1469 the arguments. */
1470 arg0 = error_mark_node;
1471 arg1 = error_mark_node;
1472 emit_jump (do_main_label);
1473 emit_label (after_negate_label);
1474 tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1475 OPTAB_LIB_WIDEN);
1476 do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
1477 NULL, do_main_label, profile_probability::very_likely ());
1478 /* One argument is negative here, the other positive. This
1479 overflows always, unless one of the arguments is 0. But
1480 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1481 is, thus we can keep do_main code oring in overflow as is. */
1482 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
1483 NULL, do_main_label, profile_probability::very_likely ());
1484 expand_arith_set_overflow (lhs, target);
1485 emit_label (do_main_label);
1486 goto do_main;
1487 default:
1488 gcc_unreachable ();
1489 }
1490 }
1491
1492 do_main:
1493 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1494 sign = uns ? UNSIGNED : SIGNED;
1495 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1496 if (uns
1497 && (integer_pow2p (arg0) || integer_pow2p (arg1))
1498 && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1499 {
1500 /* Optimize unsigned multiplication by power of 2 constant
1501 using 2 shifts, one for result, one to extract the shifted
1502 out bits to see if they are all zero.
1503 Don't do this if optimizing for size and we have umulv4_optab,
1504 in that case assume multiplication will be shorter.
1505 This is heuristics based on the single target that provides
1506 umulv4 right now (i?86/x86_64), if further targets add it, this
1507 might need to be revisited.
1508 Cases where both operands are constant should be folded already
1509 during GIMPLE, and cases where one operand is constant but not
1510 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1511 below can be done without multiplication, just by shifts and adds,
1512 or we'd need to divide the result (and hope it actually doesn't
1513 really divide nor multiply) and compare the result of the division
1514 with the original operand. */
1515 rtx opn0 = op0;
1516 rtx opn1 = op1;
1517 tree argn0 = arg0;
1518 tree argn1 = arg1;
1519 if (integer_pow2p (arg0))
1520 {
1521 std::swap (opn0, opn1);
1522 std::swap (argn0, argn1);
1523 }
1524 int cnt = tree_log2 (argn1);
1525 if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1526 {
1527 rtx upper = const0_rtx;
1528 res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1529 if (cnt != 0)
1530 upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1531 GET_MODE_PRECISION (mode) - cnt,
1532 NULL_RTX, uns);
1533 do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1534 NULL_RTX, NULL, done_label,
1535 profile_probability::very_likely ());
1536 goto do_error_label;
1537 }
1538 }
1539 if (icode != CODE_FOR_nothing)
1540 {
1541 struct expand_operand ops[4];
1542 rtx_insn *last = get_last_insn ();
1543
1544 res = gen_reg_rtx (mode);
1545 create_output_operand (&ops[0], res, mode);
1546 create_input_operand (&ops[1], op0, mode);
1547 create_input_operand (&ops[2], op1, mode);
1548 create_fixed_operand (&ops[3], do_error);
1549 if (maybe_expand_insn (icode, 4, ops))
1550 {
1551 last = get_last_insn ();
1552 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1553 && JUMP_P (last)
1554 && any_condjump_p (last)
1555 && !find_reg_note (last, REG_BR_PROB, 0))
1556 add_reg_br_prob_note (last,
1557 profile_probability::very_unlikely ());
1558 emit_jump (done_label);
1559 }
1560 else
1561 {
1562 delete_insns_since (last);
1563 icode = CODE_FOR_nothing;
1564 }
1565 }
1566
1567 if (icode == CODE_FOR_nothing)
1568 {
1569 struct separate_ops ops;
1570 int prec = GET_MODE_PRECISION (mode);
1571 scalar_int_mode hmode, wmode;
1572 ops.op0 = make_tree (type, op0);
1573 ops.op1 = make_tree (type, op1);
1574 ops.op2 = NULL_TREE;
1575 ops.location = loc;
1576
1577 /* Optimize unsigned overflow check where we don't use the
1578 multiplication result, just whether overflow happened.
1579 If we can do MULT_HIGHPART_EXPR, that followed by
1580 comparison of the result against zero is cheapest.
1581 We'll still compute res, but it should be DCEd later. */
1582 use_operand_p use;
1583 gimple *use_stmt;
1584 if (!is_ubsan
1585 && lhs
1586 && uns
1587 && !(uns0_p && uns1_p && !unsr_p)
1588 && can_mult_highpart_p (mode, uns) == 1
1589 && single_imm_use (lhs, &use, &use_stmt)
1590 && is_gimple_assign (use_stmt)
1591 && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
1592 goto highpart;
1593
1594 if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1595 && targetm.scalar_mode_supported_p (wmode)
1596 && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
1597 {
1598 twoxwider:
1599 ops.code = WIDEN_MULT_EXPR;
1600 ops.type
1601 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
1602
1603 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1604 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1605 NULL_RTX, uns);
1606 hipart = convert_modes (mode, wmode, hipart, uns);
1607 res = convert_modes (mode, wmode, res, uns);
1608 if (uns)
1609 /* For the unsigned multiplication, there was overflow if
1610 HIPART is non-zero. */
1611 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1612 NULL_RTX, NULL, done_label,
1613 profile_probability::very_likely ());
1614 else
1615 {
1616 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1617 NULL_RTX, 0);
1618 /* RES is low half of the double width result, HIPART
1619 the high half. There was overflow if
1620 HIPART is different from RES < 0 ? -1 : 0. */
1621 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1622 NULL_RTX, NULL, done_label,
1623 profile_probability::very_likely ());
1624 }
1625 }
1626 else if (can_mult_highpart_p (mode, uns) == 1)
1627 {
1628 highpart:
1629 ops.code = MULT_HIGHPART_EXPR;
1630 ops.type = type;
1631
1632 rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
1633 EXPAND_NORMAL);
1634 ops.code = MULT_EXPR;
1635 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1636 if (uns)
1637 /* For the unsigned multiplication, there was overflow if
1638 HIPART is non-zero. */
1639 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1640 NULL_RTX, NULL, done_label,
1641 profile_probability::very_likely ());
1642 else
1643 {
1644 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1645 NULL_RTX, 0);
1646 /* RES is low half of the double width result, HIPART
1647 the high half. There was overflow if
1648 HIPART is different from RES < 0 ? -1 : 0. */
1649 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1650 NULL_RTX, NULL, done_label,
1651 profile_probability::very_likely ());
1652 }
1653
1654 }
1655 else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
1656 && 2 * GET_MODE_PRECISION (hmode) == prec)
1657 {
1658 rtx_code_label *large_op0 = gen_label_rtx ();
1659 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1660 rtx_code_label *one_small_one_large = gen_label_rtx ();
1661 rtx_code_label *both_ops_large = gen_label_rtx ();
1662 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1663 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
1664 rtx_code_label *do_overflow = gen_label_rtx ();
1665 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
1666
1667 unsigned int hprec = GET_MODE_PRECISION (hmode);
1668 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1669 NULL_RTX, uns);
1670 hipart0 = convert_modes (hmode, mode, hipart0, uns);
1671 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
1672 rtx signbit0 = const0_rtx;
1673 if (!uns)
1674 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1675 NULL_RTX, 0);
1676 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1677 NULL_RTX, uns);
1678 hipart1 = convert_modes (hmode, mode, hipart1, uns);
1679 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
1680 rtx signbit1 = const0_rtx;
1681 if (!uns)
1682 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1683 NULL_RTX, 0);
1684
1685 res = gen_reg_rtx (mode);
1686
1687 /* True if op0 resp. op1 are known to be in the range of
1688 halfstype. */
1689 bool op0_small_p = false;
1690 bool op1_small_p = false;
1691 /* True if op0 resp. op1 are known to have all zeros or all ones
1692 in the upper half of bits, but are not known to be
1693 op{0,1}_small_p. */
1694 bool op0_medium_p = false;
1695 bool op1_medium_p = false;
1696 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
1697 nonnegative, 1 if unknown. */
1698 int op0_sign = 1;
1699 int op1_sign = 1;
1700
1701 if (pos_neg0 == 1)
1702 op0_sign = 0;
1703 else if (pos_neg0 == 2)
1704 op0_sign = -1;
1705 if (pos_neg1 == 1)
1706 op1_sign = 0;
1707 else if (pos_neg1 == 2)
1708 op1_sign = -1;
1709
1710 unsigned int mprec0 = prec;
1711 if (arg0 != error_mark_node)
1712 mprec0 = get_min_precision (arg0, sign);
1713 if (mprec0 <= hprec)
1714 op0_small_p = true;
1715 else if (!uns && mprec0 <= hprec + 1)
1716 op0_medium_p = true;
1717 unsigned int mprec1 = prec;
1718 if (arg1 != error_mark_node)
1719 mprec1 = get_min_precision (arg1, sign);
1720 if (mprec1 <= hprec)
1721 op1_small_p = true;
1722 else if (!uns && mprec1 <= hprec + 1)
1723 op1_medium_p = true;
1724
1725 int smaller_sign = 1;
1726 int larger_sign = 1;
1727 if (op0_small_p)
1728 {
1729 smaller_sign = op0_sign;
1730 larger_sign = op1_sign;
1731 }
1732 else if (op1_small_p)
1733 {
1734 smaller_sign = op1_sign;
1735 larger_sign = op0_sign;
1736 }
1737 else if (op0_sign == op1_sign)
1738 {
1739 smaller_sign = op0_sign;
1740 larger_sign = op0_sign;
1741 }
1742
1743 if (!op0_small_p)
1744 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1745 NULL_RTX, NULL, large_op0,
1746 profile_probability::unlikely ());
1747
1748 if (!op1_small_p)
1749 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1750 NULL_RTX, NULL, small_op0_large_op1,
1751 profile_probability::unlikely ());
1752
1753 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
1754 hmode to mode, the multiplication will never overflow. We can
1755 do just one hmode x hmode => mode widening multiplication. */
1756 rtx lopart0s = lopart0, lopart1s = lopart1;
1757 if (GET_CODE (lopart0) == SUBREG)
1758 {
1759 lopart0s = shallow_copy_rtx (lopart0);
1760 SUBREG_PROMOTED_VAR_P (lopart0s) = 1;
1761 SUBREG_PROMOTED_SET (lopart0s, uns ? SRP_UNSIGNED : SRP_SIGNED);
1762 }
1763 if (GET_CODE (lopart1) == SUBREG)
1764 {
1765 lopart1s = shallow_copy_rtx (lopart1);
1766 SUBREG_PROMOTED_VAR_P (lopart1s) = 1;
1767 SUBREG_PROMOTED_SET (lopart1s, uns ? SRP_UNSIGNED : SRP_SIGNED);
1768 }
1769 tree halfstype = build_nonstandard_integer_type (hprec, uns);
1770 ops.op0 = make_tree (halfstype, lopart0s);
1771 ops.op1 = make_tree (halfstype, lopart1s);
1772 ops.code = WIDEN_MULT_EXPR;
1773 ops.type = type;
1774 rtx thisres
1775 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1776 emit_move_insn (res, thisres);
1777 emit_jump (done_label);
1778
1779 emit_label (small_op0_large_op1);
1780
1781 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
1782 but op1 is not, just swap the arguments and handle it as op1
1783 sign/zero extended, op0 not. */
1784 rtx larger = gen_reg_rtx (mode);
1785 rtx hipart = gen_reg_rtx (hmode);
1786 rtx lopart = gen_reg_rtx (hmode);
1787 emit_move_insn (larger, op1);
1788 emit_move_insn (hipart, hipart1);
1789 emit_move_insn (lopart, lopart0);
1790 emit_jump (one_small_one_large);
1791
1792 emit_label (large_op0);
1793
1794 if (!op1_small_p)
1795 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1796 NULL_RTX, NULL, both_ops_large,
1797 profile_probability::unlikely ());
1798
1799 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
1800 but op0 is not, prepare larger, hipart and lopart pseudos and
1801 handle it together with small_op0_large_op1. */
1802 emit_move_insn (larger, op0);
1803 emit_move_insn (hipart, hipart0);
1804 emit_move_insn (lopart, lopart1);
1805
1806 emit_label (one_small_one_large);
1807
1808 /* lopart is the low part of the operand that is sign extended
1809 to mode, larger is the other operand, hipart is the
1810 high part of larger and lopart0 and lopart1 are the low parts
1811 of both operands.
1812 We perform lopart0 * lopart1 and lopart * hipart widening
1813 multiplications. */
1814 tree halfutype = build_nonstandard_integer_type (hprec, 1);
1815 ops.op0 = make_tree (halfutype, lopart0);
1816 ops.op1 = make_tree (halfutype, lopart1);
1817 rtx lo0xlo1
1818 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1819
1820 ops.op0 = make_tree (halfutype, lopart);
1821 ops.op1 = make_tree (halfutype, hipart);
1822 rtx loxhi = gen_reg_rtx (mode);
1823 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1824 emit_move_insn (loxhi, tem);
1825
1826 if (!uns)
1827 {
1828 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
1829 if (larger_sign == 0)
1830 emit_jump (after_hipart_neg);
1831 else if (larger_sign != -1)
1832 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1833 NULL_RTX, NULL, after_hipart_neg,
1834 profile_probability::even ());
1835
1836 tem = convert_modes (mode, hmode, lopart, 1);
1837 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
1838 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
1839 1, OPTAB_WIDEN);
1840 emit_move_insn (loxhi, tem);
1841
1842 emit_label (after_hipart_neg);
1843
1844 /* if (lopart < 0) loxhi -= larger; */
1845 if (smaller_sign == 0)
1846 emit_jump (after_lopart_neg);
1847 else if (smaller_sign != -1)
1848 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1849 NULL_RTX, NULL, after_lopart_neg,
1850 profile_probability::even ());
1851
1852 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1853 1, OPTAB_WIDEN);
1854 emit_move_insn (loxhi, tem);
1855
1856 emit_label (after_lopart_neg);
1857 }
1858
1859 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
1860 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
1861 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
1862 1, OPTAB_WIDEN);
1863 emit_move_insn (loxhi, tem);
1864
1865 /* if (loxhi >> (bitsize / 2)
1866 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
1867 if (loxhi >> (bitsize / 2) == 0 (if uns). */
1868 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
1869 NULL_RTX, 0);
1870 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
1871 rtx signbitloxhi = const0_rtx;
1872 if (!uns)
1873 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
1874 convert_modes (hmode, mode,
1875 loxhi, 0),
1876 hprec - 1, NULL_RTX, 0);
1877
1878 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1879 NULL_RTX, NULL, do_overflow,
1880 profile_probability::very_unlikely ());
1881
1882 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
1883 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
1884 NULL_RTX, 1);
1885 tem = convert_modes (mode, hmode,
1886 convert_modes (hmode, mode, lo0xlo1, 1), 1);
1887
1888 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
1889 1, OPTAB_WIDEN);
1890 if (tem != res)
1891 emit_move_insn (res, tem);
1892 emit_jump (done_label);
1893
1894 emit_label (both_ops_large);
1895
1896 /* If both operands are large (not sign (!uns) or zero (uns)
1897 extended from hmode), then perform the full multiplication
1898 which will be the result of the operation.
1899 The only cases which don't overflow are for signed multiplication
1900 some cases where both hipart0 and highpart1 are 0 or -1.
1901 For unsigned multiplication when high parts are both non-zero
1902 this overflows always. */
1903 ops.code = MULT_EXPR;
1904 ops.op0 = make_tree (type, op0);
1905 ops.op1 = make_tree (type, op1);
1906 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1907 emit_move_insn (res, tem);
1908
1909 if (!uns)
1910 {
1911 if (!op0_medium_p)
1912 {
1913 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
1914 NULL_RTX, 1, OPTAB_WIDEN);
1915 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1916 NULL_RTX, NULL, do_error,
1917 profile_probability::very_unlikely ());
1918 }
1919
1920 if (!op1_medium_p)
1921 {
1922 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
1923 NULL_RTX, 1, OPTAB_WIDEN);
1924 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1925 NULL_RTX, NULL, do_error,
1926 profile_probability::very_unlikely ());
1927 }
1928
1929 /* At this point hipart{0,1} are both in [-1, 0]. If they are
1930 the same, overflow happened if res is non-positive, if they
1931 are different, overflow happened if res is positive. */
1932 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
1933 emit_jump (hipart_different);
1934 else if (op0_sign == 1 || op1_sign == 1)
1935 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1936 NULL_RTX, NULL, hipart_different,
1937 profile_probability::even ());
1938
1939 do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
1940 NULL_RTX, NULL, do_error,
1941 profile_probability::very_unlikely ());
1942 emit_jump (done_label);
1943
1944 emit_label (hipart_different);
1945
1946 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1947 NULL_RTX, NULL, do_error,
1948 profile_probability::very_unlikely ());
1949 emit_jump (done_label);
1950 }
1951
1952 emit_label (do_overflow);
1953
1954 /* Overflow, do full multiplication and fallthru into do_error. */
1955 ops.op0 = make_tree (type, op0);
1956 ops.op1 = make_tree (type, op1);
1957 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1958 emit_move_insn (res, tem);
1959 }
1960 else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1961 && targetm.scalar_mode_supported_p (wmode))
1962 /* Even emitting a libcall is better than not detecting overflow
1963 at all. */
1964 goto twoxwider;
1965 else
1966 {
1967 gcc_assert (!is_ubsan);
1968 ops.code = MULT_EXPR;
1969 ops.type = type;
1970 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1971 emit_jump (done_label);
1972 }
1973 }
1974
1975 do_error_label:
1976 emit_label (do_error);
1977 if (is_ubsan)
1978 {
1979 /* Expand the ubsan builtin call. */
1980 push_temp_slots ();
1981 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1982 arg0, arg1, datap);
1983 expand_normal (fn);
1984 pop_temp_slots ();
1985 do_pending_stack_adjust ();
1986 }
1987 else if (lhs)
1988 expand_arith_set_overflow (lhs, target);
1989
1990 /* We're done. */
1991 emit_label (done_label);
1992
1993 /* u1 * u2 -> sr */
1994 if (uns0_p && uns1_p && !unsr_p)
1995 {
1996 rtx_code_label *all_done_label = gen_label_rtx ();
1997 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1998 NULL, all_done_label, profile_probability::very_likely ());
1999 expand_arith_set_overflow (lhs, target);
2000 emit_label (all_done_label);
2001 }
2002
2003 /* s1 * u2 -> sr */
2004 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
2005 {
2006 rtx_code_label *all_done_label = gen_label_rtx ();
2007 rtx_code_label *set_noovf = gen_label_rtx ();
2008 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
2009 NULL, all_done_label, profile_probability::very_likely ());
2010 expand_arith_set_overflow (lhs, target);
2011 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
2012 NULL, set_noovf, profile_probability::very_likely ());
2013 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
2014 NULL, all_done_label, profile_probability::very_unlikely ());
2015 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
2016 all_done_label, profile_probability::very_unlikely ());
2017 emit_label (set_noovf);
2018 write_complex_part (target, const0_rtx, true);
2019 emit_label (all_done_label);
2020 }
2021
2022 if (lhs)
2023 {
2024 if (is_ubsan)
2025 expand_ubsan_result_store (target, res);
2026 else
2027 expand_arith_overflow_result_store (lhs, target, mode, res);
2028 }
2029 }
2030
2031 /* Expand UBSAN_CHECK_* internal function if it has vector operands. */
2032
2033 static void
2034 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2035 tree arg0, tree arg1)
2036 {
2037 poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2038 rtx_code_label *loop_lab = NULL;
2039 rtx cntvar = NULL_RTX;
2040 tree cntv = NULL_TREE;
2041 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2042 tree sz = TYPE_SIZE (eltype);
2043 tree data = NULL_TREE;
2044 tree resv = NULL_TREE;
2045 rtx lhsr = NULL_RTX;
2046 rtx resvr = NULL_RTX;
2047 unsigned HOST_WIDE_INT const_cnt = 0;
2048 bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
2049
2050 if (lhs)
2051 {
2052 optab op;
2053 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2054 if (!VECTOR_MODE_P (GET_MODE (lhsr))
2055 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2056 optab_default)) == unknown_optab
2057 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2058 == CODE_FOR_nothing))
2059 {
2060 if (MEM_P (lhsr))
2061 resv = make_tree (TREE_TYPE (lhs), lhsr);
2062 else
2063 {
2064 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2065 resv = make_tree (TREE_TYPE (lhs), resvr);
2066 }
2067 }
2068 }
2069 if (use_loop_p)
2070 {
2071 do_pending_stack_adjust ();
2072 loop_lab = gen_label_rtx ();
2073 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2074 cntv = make_tree (sizetype, cntvar);
2075 emit_move_insn (cntvar, const0_rtx);
2076 emit_label (loop_lab);
2077 }
2078 if (TREE_CODE (arg0) != VECTOR_CST)
2079 {
2080 rtx arg0r = expand_normal (arg0);
2081 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2082 }
2083 if (TREE_CODE (arg1) != VECTOR_CST)
2084 {
2085 rtx arg1r = expand_normal (arg1);
2086 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2087 }
2088 for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
2089 {
2090 tree op0, op1, res = NULL_TREE;
2091 if (use_loop_p)
2092 {
2093 tree atype = build_array_type_nelts (eltype, cnt);
2094 op0 = uniform_vector_p (arg0);
2095 if (op0 == NULL_TREE)
2096 {
2097 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2098 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2099 NULL_TREE, NULL_TREE);
2100 }
2101 op1 = uniform_vector_p (arg1);
2102 if (op1 == NULL_TREE)
2103 {
2104 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2105 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2106 NULL_TREE, NULL_TREE);
2107 }
2108 if (resv)
2109 {
2110 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2111 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2112 NULL_TREE, NULL_TREE);
2113 }
2114 }
2115 else
2116 {
2117 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2118 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2119 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2120 if (resv)
2121 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2122 bitpos);
2123 }
2124 switch (code)
2125 {
2126 case PLUS_EXPR:
2127 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2128 false, false, false, true, &data);
2129 break;
2130 case MINUS_EXPR:
2131 if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
2132 expand_neg_overflow (loc, res, op1, true, &data);
2133 else
2134 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2135 false, false, false, true, &data);
2136 break;
2137 case MULT_EXPR:
2138 expand_mul_overflow (loc, res, op0, op1, false, false, false,
2139 true, &data);
2140 break;
2141 default:
2142 gcc_unreachable ();
2143 }
2144 }
2145 if (use_loop_p)
2146 {
2147 struct separate_ops ops;
2148 ops.code = PLUS_EXPR;
2149 ops.type = TREE_TYPE (cntv);
2150 ops.op0 = cntv;
2151 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2152 ops.op2 = NULL_TREE;
2153 ops.location = loc;
2154 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2155 EXPAND_NORMAL);
2156 if (ret != cntvar)
2157 emit_move_insn (cntvar, ret);
2158 rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2159 do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
2160 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2161 profile_probability::very_likely ());
2162 }
2163 if (lhs && resv == NULL_TREE)
2164 {
2165 struct separate_ops ops;
2166 ops.code = code;
2167 ops.type = TREE_TYPE (arg0);
2168 ops.op0 = arg0;
2169 ops.op1 = arg1;
2170 ops.op2 = NULL_TREE;
2171 ops.location = loc;
2172 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2173 EXPAND_NORMAL);
2174 if (ret != lhsr)
2175 emit_move_insn (lhsr, ret);
2176 }
2177 else if (resvr)
2178 emit_move_insn (lhsr, resvr);
2179 }
2180
2181 /* Expand UBSAN_CHECK_ADD call STMT. */
2182
2183 static void
2184 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2185 {
2186 location_t loc = gimple_location (stmt);
2187 tree lhs = gimple_call_lhs (stmt);
2188 tree arg0 = gimple_call_arg (stmt, 0);
2189 tree arg1 = gimple_call_arg (stmt, 1);
2190 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2191 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2192 else
2193 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2194 false, false, false, true, NULL);
2195 }
2196
2197 /* Expand UBSAN_CHECK_SUB call STMT. */
2198
2199 static void
2200 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2201 {
2202 location_t loc = gimple_location (stmt);
2203 tree lhs = gimple_call_lhs (stmt);
2204 tree arg0 = gimple_call_arg (stmt, 0);
2205 tree arg1 = gimple_call_arg (stmt, 1);
2206 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2207 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2208 else if (integer_zerop (arg0))
2209 expand_neg_overflow (loc, lhs, arg1, true, NULL);
2210 else
2211 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2212 false, false, false, true, NULL);
2213 }
2214
2215 /* Expand UBSAN_CHECK_MUL call STMT. */
2216
2217 static void
2218 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2219 {
2220 location_t loc = gimple_location (stmt);
2221 tree lhs = gimple_call_lhs (stmt);
2222 tree arg0 = gimple_call_arg (stmt, 0);
2223 tree arg1 = gimple_call_arg (stmt, 1);
2224 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2225 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2226 else
2227 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2228 NULL);
2229 }
2230
2231 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2232
2233 static void
2234 expand_arith_overflow (enum tree_code code, gimple *stmt)
2235 {
2236 tree lhs = gimple_call_lhs (stmt);
2237 if (lhs == NULL_TREE)
2238 return;
2239 tree arg0 = gimple_call_arg (stmt, 0);
2240 tree arg1 = gimple_call_arg (stmt, 1);
2241 tree type = TREE_TYPE (TREE_TYPE (lhs));
2242 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2243 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2244 int unsr_p = TYPE_UNSIGNED (type);
2245 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2246 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2247 int precres = TYPE_PRECISION (type);
2248 location_t loc = gimple_location (stmt);
2249 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2250 uns0_p = true;
2251 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2252 uns1_p = true;
2253 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2254 prec0 = MIN (prec0, pr);
2255 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2256 prec1 = MIN (prec1, pr);
2257
2258 /* If uns0_p && uns1_p, precop is minimum needed precision
2259 of unsigned type to hold the exact result, otherwise
2260 precop is minimum needed precision of signed type to
2261 hold the exact result. */
2262 int precop;
2263 if (code == MULT_EXPR)
2264 precop = prec0 + prec1 + (uns0_p != uns1_p);
2265 else
2266 {
2267 if (uns0_p == uns1_p)
2268 precop = MAX (prec0, prec1) + 1;
2269 else if (uns0_p)
2270 precop = MAX (prec0 + 1, prec1) + 1;
2271 else
2272 precop = MAX (prec0, prec1 + 1) + 1;
2273 }
2274 int orig_precres = precres;
2275
2276 do
2277 {
2278 if ((uns0_p && uns1_p)
2279 ? ((precop + !unsr_p) <= precres
2280 /* u1 - u2 -> ur can overflow, no matter what precision
2281 the result has. */
2282 && (code != MINUS_EXPR || !unsr_p))
2283 : (!unsr_p && precop <= precres))
2284 {
2285 /* The infinity precision result will always fit into result. */
2286 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2287 write_complex_part (target, const0_rtx, true);
2288 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2289 struct separate_ops ops;
2290 ops.code = code;
2291 ops.type = type;
2292 ops.op0 = fold_convert_loc (loc, type, arg0);
2293 ops.op1 = fold_convert_loc (loc, type, arg1);
2294 ops.op2 = NULL_TREE;
2295 ops.location = loc;
2296 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2297 expand_arith_overflow_result_store (lhs, target, mode, tem);
2298 return;
2299 }
2300
2301 /* For operations with low precision, if target doesn't have them, start
2302 with precres widening right away, otherwise do it only if the most
2303 simple cases can't be used. */
2304 const int min_precision = targetm.min_arithmetic_precision ();
2305 if (orig_precres == precres && precres < min_precision)
2306 ;
2307 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2308 && prec1 <= precres)
2309 || ((!uns0_p || !uns1_p) && !unsr_p
2310 && prec0 + uns0_p <= precres
2311 && prec1 + uns1_p <= precres))
2312 {
2313 arg0 = fold_convert_loc (loc, type, arg0);
2314 arg1 = fold_convert_loc (loc, type, arg1);
2315 switch (code)
2316 {
2317 case MINUS_EXPR:
2318 if (integer_zerop (arg0) && !unsr_p)
2319 {
2320 expand_neg_overflow (loc, lhs, arg1, false, NULL);
2321 return;
2322 }
2323 /* FALLTHRU */
2324 case PLUS_EXPR:
2325 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2326 unsr_p, unsr_p, false, NULL);
2327 return;
2328 case MULT_EXPR:
2329 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2330 unsr_p, unsr_p, false, NULL);
2331 return;
2332 default:
2333 gcc_unreachable ();
2334 }
2335 }
2336
2337 /* For sub-word operations, retry with a wider type first. */
2338 if (orig_precres == precres && precop <= BITS_PER_WORD)
2339 {
2340 int p = MAX (min_precision, precop);
2341 scalar_int_mode m = smallest_int_mode_for_size (p);
2342 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2343 uns0_p && uns1_p
2344 && unsr_p);
2345 p = TYPE_PRECISION (optype);
2346 if (p > precres)
2347 {
2348 precres = p;
2349 unsr_p = TYPE_UNSIGNED (optype);
2350 type = optype;
2351 continue;
2352 }
2353 }
2354
2355 if (prec0 <= precres && prec1 <= precres)
2356 {
2357 tree types[2];
2358 if (unsr_p)
2359 {
2360 types[0] = build_nonstandard_integer_type (precres, 0);
2361 types[1] = type;
2362 }
2363 else
2364 {
2365 types[0] = type;
2366 types[1] = build_nonstandard_integer_type (precres, 1);
2367 }
2368 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2369 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2370 if (code != MULT_EXPR)
2371 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2372 uns0_p, uns1_p, false, NULL);
2373 else
2374 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2375 uns0_p, uns1_p, false, NULL);
2376 return;
2377 }
2378
2379 /* Retry with a wider type. */
2380 if (orig_precres == precres)
2381 {
2382 int p = MAX (prec0, prec1);
2383 scalar_int_mode m = smallest_int_mode_for_size (p);
2384 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2385 uns0_p && uns1_p
2386 && unsr_p);
2387 p = TYPE_PRECISION (optype);
2388 if (p > precres)
2389 {
2390 precres = p;
2391 unsr_p = TYPE_UNSIGNED (optype);
2392 type = optype;
2393 continue;
2394 }
2395 }
2396
2397 gcc_unreachable ();
2398 }
2399 while (1);
2400 }
2401
2402 /* Expand ADD_OVERFLOW STMT. */
2403
2404 static void
2405 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2406 {
2407 expand_arith_overflow (PLUS_EXPR, stmt);
2408 }
2409
2410 /* Expand SUB_OVERFLOW STMT. */
2411
2412 static void
2413 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2414 {
2415 expand_arith_overflow (MINUS_EXPR, stmt);
2416 }
2417
2418 /* Expand MUL_OVERFLOW STMT. */
2419
2420 static void
2421 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2422 {
2423 expand_arith_overflow (MULT_EXPR, stmt);
2424 }
2425
2426 /* This should get folded in tree-vectorizer.c. */
2427
2428 static void
2429 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2430 {
2431 gcc_unreachable ();
2432 }
2433
2434 /* This should get folded in tree-vectorizer.c. */
2435
2436 static void
2437 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2438 {
2439 gcc_unreachable ();
2440 }
2441
2442 /* Return a memory reference of type TYPE for argument INDEX of STMT.
2443 Use argument INDEX + 1 to derive the second (TBAA) operand. */
2444
2445 static tree
2446 expand_call_mem_ref (tree type, gcall *stmt, int index)
2447 {
2448 tree addr = gimple_call_arg (stmt, index);
2449 tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2450 unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2451 if (TYPE_ALIGN (type) != align)
2452 type = build_aligned_type (type, align);
2453
2454 tree tmp = addr;
2455 if (TREE_CODE (tmp) == SSA_NAME)
2456 {
2457 gimple *def = SSA_NAME_DEF_STMT (tmp);
2458 if (gimple_assign_single_p (def))
2459 tmp = gimple_assign_rhs1 (def);
2460 }
2461
2462 if (TREE_CODE (tmp) == ADDR_EXPR)
2463 {
2464 tree mem = TREE_OPERAND (tmp, 0);
2465 if (TREE_CODE (mem) == TARGET_MEM_REF
2466 && types_compatible_p (TREE_TYPE (mem), type))
2467 {
2468 tree offset = TMR_OFFSET (mem);
2469 if (type != TREE_TYPE (mem)
2470 || alias_ptr_type != TREE_TYPE (offset)
2471 || !integer_zerop (offset))
2472 {
2473 mem = copy_node (mem);
2474 TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2475 wi::to_poly_wide (offset));
2476 TREE_TYPE (mem) = type;
2477 }
2478 return mem;
2479 }
2480 }
2481
2482 return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2483 }
2484
2485 /* Expand MASK_LOAD{,_LANES} call STMT using optab OPTAB. */
2486
2487 static void
2488 expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2489 {
2490 struct expand_operand ops[3];
2491 tree type, lhs, rhs, maskt;
2492 rtx mem, target, mask;
2493 insn_code icode;
2494
2495 maskt = gimple_call_arg (stmt, 2);
2496 lhs = gimple_call_lhs (stmt);
2497 if (lhs == NULL_TREE)
2498 return;
2499 type = TREE_TYPE (lhs);
2500 rhs = expand_call_mem_ref (type, stmt, 0);
2501
2502 if (optab == vec_mask_load_lanes_optab)
2503 icode = get_multi_vector_move (type, optab);
2504 else
2505 icode = convert_optab_handler (optab, TYPE_MODE (type),
2506 TYPE_MODE (TREE_TYPE (maskt)));
2507
2508 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2509 gcc_assert (MEM_P (mem));
2510 mask = expand_normal (maskt);
2511 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2512 create_output_operand (&ops[0], target, TYPE_MODE (type));
2513 create_fixed_operand (&ops[1], mem);
2514 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2515 expand_insn (icode, 3, ops);
2516 }
2517
2518 #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
2519
2520 /* Expand MASK_STORE{,_LANES} call STMT using optab OPTAB. */
2521
2522 static void
2523 expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2524 {
2525 struct expand_operand ops[3];
2526 tree type, lhs, rhs, maskt;
2527 rtx mem, reg, mask;
2528 insn_code icode;
2529
2530 maskt = gimple_call_arg (stmt, 2);
2531 rhs = gimple_call_arg (stmt, 3);
2532 type = TREE_TYPE (rhs);
2533 lhs = expand_call_mem_ref (type, stmt, 0);
2534
2535 if (optab == vec_mask_store_lanes_optab)
2536 icode = get_multi_vector_move (type, optab);
2537 else
2538 icode = convert_optab_handler (optab, TYPE_MODE (type),
2539 TYPE_MODE (TREE_TYPE (maskt)));
2540
2541 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2542 gcc_assert (MEM_P (mem));
2543 mask = expand_normal (maskt);
2544 reg = expand_normal (rhs);
2545 create_fixed_operand (&ops[0], mem);
2546 create_input_operand (&ops[1], reg, TYPE_MODE (type));
2547 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2548 expand_insn (icode, 3, ops);
2549 }
2550
2551 #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
2552
2553 static void
2554 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
2555 {
2556 }
2557
2558 static void
2559 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
2560 {
2561 /* When guessing was done, the hints should be already stripped away. */
2562 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
2563
2564 rtx target;
2565 tree lhs = gimple_call_lhs (stmt);
2566 if (lhs)
2567 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2568 else
2569 target = const0_rtx;
2570 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
2571 if (lhs && val != target)
2572 emit_move_insn (target, val);
2573 }
2574
2575 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
2576 should never be called. */
2577
2578 static void
2579 expand_VA_ARG (internal_fn, gcall *)
2580 {
2581 gcc_unreachable ();
2582 }
2583
2584 /* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector. So this
2585 dummy function should never be called. */
2586
2587 static void
2588 expand_VEC_CONVERT (internal_fn, gcall *)
2589 {
2590 gcc_unreachable ();
2591 }
2592
2593 /* Expand the IFN_UNIQUE function according to its first argument. */
2594
2595 static void
2596 expand_UNIQUE (internal_fn, gcall *stmt)
2597 {
2598 rtx pattern = NULL_RTX;
2599 enum ifn_unique_kind kind
2600 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
2601
2602 switch (kind)
2603 {
2604 default:
2605 gcc_unreachable ();
2606
2607 case IFN_UNIQUE_UNSPEC:
2608 if (targetm.have_unique ())
2609 pattern = targetm.gen_unique ();
2610 break;
2611
2612 case IFN_UNIQUE_OACC_FORK:
2613 case IFN_UNIQUE_OACC_JOIN:
2614 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
2615 {
2616 tree lhs = gimple_call_lhs (stmt);
2617 rtx target = const0_rtx;
2618
2619 if (lhs)
2620 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2621
2622 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
2623 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
2624
2625 if (kind == IFN_UNIQUE_OACC_FORK)
2626 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
2627 else
2628 pattern = targetm.gen_oacc_join (target, data_dep, axis);
2629 }
2630 else
2631 gcc_unreachable ();
2632 break;
2633 }
2634
2635 if (pattern)
2636 emit_insn (pattern);
2637 }
2638
2639 /* The size of an OpenACC compute dimension. */
2640
2641 static void
2642 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
2643 {
2644 tree lhs = gimple_call_lhs (stmt);
2645
2646 if (!lhs)
2647 return;
2648
2649 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2650 if (targetm.have_oacc_dim_size ())
2651 {
2652 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2653 VOIDmode, EXPAND_NORMAL);
2654 emit_insn (targetm.gen_oacc_dim_size (target, dim));
2655 }
2656 else
2657 emit_move_insn (target, GEN_INT (1));
2658 }
2659
2660 /* The position of an OpenACC execution engine along one compute axis. */
2661
2662 static void
2663 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
2664 {
2665 tree lhs = gimple_call_lhs (stmt);
2666
2667 if (!lhs)
2668 return;
2669
2670 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2671 if (targetm.have_oacc_dim_pos ())
2672 {
2673 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2674 VOIDmode, EXPAND_NORMAL);
2675 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
2676 }
2677 else
2678 emit_move_insn (target, const0_rtx);
2679 }
2680
2681 /* This is expanded by oacc_device_lower pass. */
2682
2683 static void
2684 expand_GOACC_LOOP (internal_fn, gcall *)
2685 {
2686 gcc_unreachable ();
2687 }
2688
2689 /* This is expanded by oacc_device_lower pass. */
2690
2691 static void
2692 expand_GOACC_REDUCTION (internal_fn, gcall *)
2693 {
2694 gcc_unreachable ();
2695 }
2696
2697 /* This is expanded by oacc_device_lower pass. */
2698
2699 static void
2700 expand_GOACC_TILE (internal_fn, gcall *)
2701 {
2702 gcc_unreachable ();
2703 }
2704
2705 /* Set errno to EDOM. */
2706
2707 static void
2708 expand_SET_EDOM (internal_fn, gcall *)
2709 {
2710 #ifdef TARGET_EDOM
2711 #ifdef GEN_ERRNO_RTX
2712 rtx errno_rtx = GEN_ERRNO_RTX;
2713 #else
2714 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
2715 #endif
2716 emit_move_insn (errno_rtx,
2717 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
2718 #else
2719 gcc_unreachable ();
2720 #endif
2721 }
2722
2723 /* Expand atomic bit test and set. */
2724
2725 static void
2726 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
2727 {
2728 expand_ifn_atomic_bit_test_and (call);
2729 }
2730
2731 /* Expand atomic bit test and complement. */
2732
2733 static void
2734 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
2735 {
2736 expand_ifn_atomic_bit_test_and (call);
2737 }
2738
2739 /* Expand atomic bit test and reset. */
2740
2741 static void
2742 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
2743 {
2744 expand_ifn_atomic_bit_test_and (call);
2745 }
2746
2747 /* Expand atomic bit test and set. */
2748
2749 static void
2750 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
2751 {
2752 expand_ifn_atomic_compare_exchange (call);
2753 }
2754
2755 /* Expand LAUNDER to assignment, lhs = arg0. */
2756
2757 static void
2758 expand_LAUNDER (internal_fn, gcall *call)
2759 {
2760 tree lhs = gimple_call_lhs (call);
2761
2762 if (!lhs)
2763 return;
2764
2765 expand_assignment (lhs, gimple_call_arg (call, 0), false);
2766 }
2767
2768 /* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB. */
2769
2770 static void
2771 expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
2772 {
2773 internal_fn ifn = gimple_call_internal_fn (stmt);
2774 int rhs_index = internal_fn_stored_value_index (ifn);
2775 int mask_index = internal_fn_mask_index (ifn);
2776 tree base = gimple_call_arg (stmt, 0);
2777 tree offset = gimple_call_arg (stmt, 1);
2778 tree scale = gimple_call_arg (stmt, 2);
2779 tree rhs = gimple_call_arg (stmt, rhs_index);
2780
2781 rtx base_rtx = expand_normal (base);
2782 rtx offset_rtx = expand_normal (offset);
2783 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
2784 rtx rhs_rtx = expand_normal (rhs);
2785
2786 struct expand_operand ops[6];
2787 int i = 0;
2788 create_address_operand (&ops[i++], base_rtx);
2789 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
2790 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
2791 create_integer_operand (&ops[i++], scale_int);
2792 create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
2793 if (mask_index >= 0)
2794 {
2795 tree mask = gimple_call_arg (stmt, mask_index);
2796 rtx mask_rtx = expand_normal (mask);
2797 create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
2798 }
2799
2800 insn_code icode = direct_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)));
2801 expand_insn (icode, i, ops);
2802 }
2803
2804 /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB. */
2805
2806 static void
2807 expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
2808 {
2809 tree lhs = gimple_call_lhs (stmt);
2810 tree base = gimple_call_arg (stmt, 0);
2811 tree offset = gimple_call_arg (stmt, 1);
2812 tree scale = gimple_call_arg (stmt, 2);
2813
2814 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2815 rtx base_rtx = expand_normal (base);
2816 rtx offset_rtx = expand_normal (offset);
2817 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
2818
2819 int i = 0;
2820 struct expand_operand ops[6];
2821 create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
2822 create_address_operand (&ops[i++], base_rtx);
2823 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
2824 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
2825 create_integer_operand (&ops[i++], scale_int);
2826 if (optab == mask_gather_load_optab)
2827 {
2828 tree mask = gimple_call_arg (stmt, 3);
2829 rtx mask_rtx = expand_normal (mask);
2830 create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
2831 }
2832 insn_code icode = direct_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)));
2833 expand_insn (icode, i, ops);
2834 }
2835
2836 /* Expand DIVMOD() using:
2837 a) optab handler for udivmod/sdivmod if it is available.
2838 b) If optab_handler doesn't exist, generate call to
2839 target-specific divmod libfunc. */
2840
2841 static void
2842 expand_DIVMOD (internal_fn, gcall *call_stmt)
2843 {
2844 tree lhs = gimple_call_lhs (call_stmt);
2845 tree arg0 = gimple_call_arg (call_stmt, 0);
2846 tree arg1 = gimple_call_arg (call_stmt, 1);
2847
2848 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
2849 tree type = TREE_TYPE (TREE_TYPE (lhs));
2850 machine_mode mode = TYPE_MODE (type);
2851 bool unsignedp = TYPE_UNSIGNED (type);
2852 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
2853
2854 rtx op0 = expand_normal (arg0);
2855 rtx op1 = expand_normal (arg1);
2856 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2857
2858 rtx quotient, remainder, libfunc;
2859
2860 /* Check if optab_handler exists for divmod_optab for given mode. */
2861 if (optab_handler (tab, mode) != CODE_FOR_nothing)
2862 {
2863 quotient = gen_reg_rtx (mode);
2864 remainder = gen_reg_rtx (mode);
2865 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
2866 }
2867
2868 /* Generate call to divmod libfunc if it exists. */
2869 else if ((libfunc = optab_libfunc (tab, mode)) != NULL_RTX)
2870 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
2871 &quotient, &remainder);
2872
2873 else
2874 gcc_unreachable ();
2875
2876 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
2877 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
2878 make_tree (TREE_TYPE (arg0), quotient),
2879 make_tree (TREE_TYPE (arg1), remainder)),
2880 target, VOIDmode, EXPAND_NORMAL);
2881 }
2882
2883 /* Expand a NOP. */
2884
2885 static void
2886 expand_NOP (internal_fn, gcall *)
2887 {
2888 /* Nothing. But it shouldn't really prevail. */
2889 }
2890
2891 /* Expand a call to FN using the operands in STMT. FN has a single
2892 output operand and NARGS input operands. */
2893
2894 static void
2895 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
2896 unsigned int nargs)
2897 {
2898 expand_operand *ops = XALLOCAVEC (expand_operand, nargs + 1);
2899
2900 tree_pair types = direct_internal_fn_types (fn, stmt);
2901 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
2902 gcc_assert (icode != CODE_FOR_nothing);
2903
2904 tree lhs = gimple_call_lhs (stmt);
2905 rtx lhs_rtx = NULL_RTX;
2906 if (lhs)
2907 lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2908
2909 /* Do not assign directly to a promoted subreg, since there is no
2910 guarantee that the instruction will leave the upper bits of the
2911 register in the state required by SUBREG_PROMOTED_SIGN. */
2912 rtx dest = lhs_rtx;
2913 if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
2914 dest = NULL_RTX;
2915
2916 create_output_operand (&ops[0], dest, insn_data[icode].operand[0].mode);
2917
2918 for (unsigned int i = 0; i < nargs; ++i)
2919 {
2920 tree rhs = gimple_call_arg (stmt, i);
2921 tree rhs_type = TREE_TYPE (rhs);
2922 rtx rhs_rtx = expand_normal (rhs);
2923 if (INTEGRAL_TYPE_P (rhs_type))
2924 create_convert_operand_from (&ops[i + 1], rhs_rtx,
2925 TYPE_MODE (rhs_type),
2926 TYPE_UNSIGNED (rhs_type));
2927 else
2928 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type));
2929 }
2930
2931 expand_insn (icode, nargs + 1, ops);
2932 if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
2933 {
2934 /* If the return value has an integral type, convert the instruction
2935 result to that type. This is useful for things that return an
2936 int regardless of the size of the input. If the instruction result
2937 is smaller than required, assume that it is signed.
2938
2939 If the return value has a nonintegral type, its mode must match
2940 the instruction result. */
2941 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
2942 {
2943 /* If this is a scalar in a register that is stored in a wider
2944 mode than the declared mode, compute the result into its
2945 declared mode and then convert to the wider mode. */
2946 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
2947 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
2948 convert_move (SUBREG_REG (lhs_rtx), tmp,
2949 SUBREG_PROMOTED_SIGN (lhs_rtx));
2950 }
2951 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
2952 emit_move_insn (lhs_rtx, ops[0].value);
2953 else
2954 {
2955 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
2956 convert_move (lhs_rtx, ops[0].value, 0);
2957 }
2958 }
2959 }
2960
2961 /* Expand WHILE_ULT call STMT using optab OPTAB. */
2962
2963 static void
2964 expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2965 {
2966 expand_operand ops[3];
2967 tree rhs_type[2];
2968
2969 tree lhs = gimple_call_lhs (stmt);
2970 tree lhs_type = TREE_TYPE (lhs);
2971 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2972 create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
2973
2974 for (unsigned int i = 0; i < 2; ++i)
2975 {
2976 tree rhs = gimple_call_arg (stmt, i);
2977 rhs_type[i] = TREE_TYPE (rhs);
2978 rtx rhs_rtx = expand_normal (rhs);
2979 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
2980 }
2981
2982 insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
2983 TYPE_MODE (lhs_type));
2984
2985 expand_insn (icode, 3, ops);
2986 if (!rtx_equal_p (lhs_rtx, ops[0].value))
2987 emit_move_insn (lhs_rtx, ops[0].value);
2988 }
2989
2990 /* Expanders for optabs that can use expand_direct_optab_fn. */
2991
2992 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
2993 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
2994
2995 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
2996 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
2997
2998 #define expand_ternary_optab_fn(FN, STMT, OPTAB) \
2999 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3000
3001 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
3002 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3003
3004 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
3005 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3006
3007 #define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
3008 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3009
3010 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
3011 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3012
3013 #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
3014 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3015
3016 /* RETURN_TYPE and ARGS are a return type and argument list that are
3017 in principle compatible with FN (which satisfies direct_internal_fn_p).
3018 Return the types that should be used to determine whether the
3019 target supports FN. */
3020
3021 tree_pair
3022 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
3023 {
3024 const direct_internal_fn_info &info = direct_internal_fn (fn);
3025 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
3026 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
3027 return tree_pair (type0, type1);
3028 }
3029
3030 /* CALL is a call whose return type and arguments are in principle
3031 compatible with FN (which satisfies direct_internal_fn_p). Return the
3032 types that should be used to determine whether the target supports FN. */
3033
3034 tree_pair
3035 direct_internal_fn_types (internal_fn fn, gcall *call)
3036 {
3037 const direct_internal_fn_info &info = direct_internal_fn (fn);
3038 tree op0 = (info.type0 < 0
3039 ? gimple_call_lhs (call)
3040 : gimple_call_arg (call, info.type0));
3041 tree op1 = (info.type1 < 0
3042 ? gimple_call_lhs (call)
3043 : gimple_call_arg (call, info.type1));
3044 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
3045 }
3046
3047 /* Return true if OPTAB is supported for TYPES (whose modes should be
3048 the same) when the optimization type is OPT_TYPE. Used for simple
3049 direct optabs. */
3050
3051 static bool
3052 direct_optab_supported_p (direct_optab optab, tree_pair types,
3053 optimization_type opt_type)
3054 {
3055 machine_mode mode = TYPE_MODE (types.first);
3056 gcc_checking_assert (mode == TYPE_MODE (types.second));
3057 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
3058 }
3059
3060 /* Return true if OPTAB is supported for TYPES, where the first type
3061 is the destination and the second type is the source. Used for
3062 convert optabs. */
3063
3064 static bool
3065 convert_optab_supported_p (convert_optab optab, tree_pair types,
3066 optimization_type opt_type)
3067 {
3068 return (convert_optab_handler (optab, TYPE_MODE (types.first),
3069 TYPE_MODE (types.second), opt_type)
3070 != CODE_FOR_nothing);
3071 }
3072
3073 /* Return true if load/store lanes optab OPTAB is supported for
3074 array type TYPES.first when the optimization type is OPT_TYPE. */
3075
3076 static bool
3077 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
3078 optimization_type opt_type)
3079 {
3080 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
3081 machine_mode imode = TYPE_MODE (types.first);
3082 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
3083 return (convert_optab_handler (optab, imode, vmode, opt_type)
3084 != CODE_FOR_nothing);
3085 }
3086
3087 #define direct_unary_optab_supported_p direct_optab_supported_p
3088 #define direct_binary_optab_supported_p direct_optab_supported_p
3089 #define direct_ternary_optab_supported_p direct_optab_supported_p
3090 #define direct_cond_unary_optab_supported_p direct_optab_supported_p
3091 #define direct_cond_binary_optab_supported_p direct_optab_supported_p
3092 #define direct_cond_ternary_optab_supported_p direct_optab_supported_p
3093 #define direct_mask_load_optab_supported_p direct_optab_supported_p
3094 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
3095 #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
3096 #define direct_gather_load_optab_supported_p direct_optab_supported_p
3097 #define direct_mask_store_optab_supported_p direct_optab_supported_p
3098 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
3099 #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
3100 #define direct_scatter_store_optab_supported_p direct_optab_supported_p
3101 #define direct_while_optab_supported_p convert_optab_supported_p
3102 #define direct_fold_extract_optab_supported_p direct_optab_supported_p
3103 #define direct_fold_left_optab_supported_p direct_optab_supported_p
3104
3105 /* Return the optab used by internal function FN. */
3106
3107 static optab
3108 direct_internal_fn_optab (internal_fn fn, tree_pair types)
3109 {
3110 switch (fn)
3111 {
3112 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3113 case IFN_##CODE: break;
3114 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3115 case IFN_##CODE: return OPTAB##_optab;
3116 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3117 UNSIGNED_OPTAB, TYPE) \
3118 case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR) \
3119 ? UNSIGNED_OPTAB ## _optab \
3120 : SIGNED_OPTAB ## _optab);
3121 #include "internal-fn.def"
3122
3123 case IFN_LAST:
3124 break;
3125 }
3126 gcc_unreachable ();
3127 }
3128
3129 /* Return the optab used by internal function FN. */
3130
3131 static optab
3132 direct_internal_fn_optab (internal_fn fn)
3133 {
3134 switch (fn)
3135 {
3136 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3137 case IFN_##CODE: break;
3138 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3139 case IFN_##CODE: return OPTAB##_optab;
3140 #include "internal-fn.def"
3141
3142 case IFN_LAST:
3143 break;
3144 }
3145 gcc_unreachable ();
3146 }
3147
3148 /* Return true if FN is supported for the types in TYPES when the
3149 optimization type is OPT_TYPE. The types are those associated with
3150 the "type0" and "type1" fields of FN's direct_internal_fn_info
3151 structure. */
3152
3153 bool
3154 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
3155 optimization_type opt_type)
3156 {
3157 switch (fn)
3158 {
3159 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3160 case IFN_##CODE: break;
3161 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3162 case IFN_##CODE: \
3163 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
3164 opt_type);
3165 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3166 UNSIGNED_OPTAB, TYPE) \
3167 case IFN_##CODE: \
3168 { \
3169 optab which_optab = (TYPE_UNSIGNED (types.SELECTOR) \
3170 ? UNSIGNED_OPTAB ## _optab \
3171 : SIGNED_OPTAB ## _optab); \
3172 return direct_##TYPE##_optab_supported_p (which_optab, types, \
3173 opt_type); \
3174 }
3175 #include "internal-fn.def"
3176
3177 case IFN_LAST:
3178 break;
3179 }
3180 gcc_unreachable ();
3181 }
3182
3183 /* Return true if FN is supported for type TYPE when the optimization
3184 type is OPT_TYPE. The caller knows that the "type0" and "type1"
3185 fields of FN's direct_internal_fn_info structure are the same. */
3186
3187 bool
3188 direct_internal_fn_supported_p (internal_fn fn, tree type,
3189 optimization_type opt_type)
3190 {
3191 const direct_internal_fn_info &info = direct_internal_fn (fn);
3192 gcc_checking_assert (info.type0 == info.type1);
3193 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
3194 }
3195
3196 /* Return true if the STMT is supported when the optimization type is OPT_TYPE,
3197 given that STMT is a call to a direct internal function. */
3198
3199 bool
3200 direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
3201 {
3202 internal_fn fn = gimple_call_internal_fn (stmt);
3203 tree_pair types = direct_internal_fn_types (fn, stmt);
3204 return direct_internal_fn_supported_p (fn, types, opt_type);
3205 }
3206
3207 /* If FN is commutative in two consecutive arguments, return the
3208 index of the first, otherwise return -1. */
3209
3210 int
3211 first_commutative_argument (internal_fn fn)
3212 {
3213 switch (fn)
3214 {
3215 case IFN_FMA:
3216 case IFN_FMS:
3217 case IFN_FNMA:
3218 case IFN_FNMS:
3219 case IFN_AVG_FLOOR:
3220 case IFN_AVG_CEIL:
3221 case IFN_FMIN:
3222 case IFN_FMAX:
3223 return 0;
3224
3225 case IFN_COND_ADD:
3226 case IFN_COND_MUL:
3227 case IFN_COND_MIN:
3228 case IFN_COND_MAX:
3229 case IFN_COND_AND:
3230 case IFN_COND_IOR:
3231 case IFN_COND_XOR:
3232 case IFN_COND_FMA:
3233 case IFN_COND_FMS:
3234 case IFN_COND_FNMA:
3235 case IFN_COND_FNMS:
3236 return 1;
3237
3238 default:
3239 return -1;
3240 }
3241 }
3242
3243 /* Return true if IFN_SET_EDOM is supported. */
3244
3245 bool
3246 set_edom_supported_p (void)
3247 {
3248 #ifdef TARGET_EDOM
3249 return true;
3250 #else
3251 return false;
3252 #endif
3253 }
3254
3255 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3256 static void \
3257 expand_##CODE (internal_fn fn, gcall *stmt) \
3258 { \
3259 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
3260 }
3261 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3262 UNSIGNED_OPTAB, TYPE) \
3263 static void \
3264 expand_##CODE (internal_fn fn, gcall *stmt) \
3265 { \
3266 tree_pair types = direct_internal_fn_types (fn, stmt); \
3267 optab which_optab = direct_internal_fn_optab (fn, types); \
3268 expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
3269 }
3270 #include "internal-fn.def"
3271
3272 /* Routines to expand each internal function, indexed by function number.
3273 Each routine has the prototype:
3274
3275 expand_<NAME> (gcall *stmt)
3276
3277 where STMT is the statement that performs the call. */
3278 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
3279 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
3280 #include "internal-fn.def"
3281 0
3282 };
3283
3284 /* Invoke T(CODE, IFN) for each conditional function IFN that maps to a
3285 tree code CODE. */
3286 #define FOR_EACH_CODE_MAPPING(T) \
3287 T (PLUS_EXPR, IFN_COND_ADD) \
3288 T (MINUS_EXPR, IFN_COND_SUB) \
3289 T (MULT_EXPR, IFN_COND_MUL) \
3290 T (TRUNC_DIV_EXPR, IFN_COND_DIV) \
3291 T (TRUNC_MOD_EXPR, IFN_COND_MOD) \
3292 T (RDIV_EXPR, IFN_COND_RDIV) \
3293 T (MIN_EXPR, IFN_COND_MIN) \
3294 T (MAX_EXPR, IFN_COND_MAX) \
3295 T (BIT_AND_EXPR, IFN_COND_AND) \
3296 T (BIT_IOR_EXPR, IFN_COND_IOR) \
3297 T (BIT_XOR_EXPR, IFN_COND_XOR)
3298
3299 /* Return a function that only performs CODE when a certain condition is met
3300 and that uses a given fallback value otherwise. For example, if CODE is
3301 a binary operation associated with conditional function FN:
3302
3303 LHS = FN (COND, A, B, ELSE)
3304
3305 is equivalent to the C expression:
3306
3307 LHS = COND ? A CODE B : ELSE;
3308
3309 operating elementwise if the operands are vectors.
3310
3311 Return IFN_LAST if no such function exists. */
3312
3313 internal_fn
3314 get_conditional_internal_fn (tree_code code)
3315 {
3316 switch (code)
3317 {
3318 #define CASE(CODE, IFN) case CODE: return IFN;
3319 FOR_EACH_CODE_MAPPING(CASE)
3320 #undef CASE
3321 default:
3322 return IFN_LAST;
3323 }
3324 }
3325
3326 /* If IFN implements the conditional form of a tree code, return that
3327 tree code, otherwise return ERROR_MARK. */
3328
3329 tree_code
3330 conditional_internal_fn_code (internal_fn ifn)
3331 {
3332 switch (ifn)
3333 {
3334 #define CASE(CODE, IFN) case IFN: return CODE;
3335 FOR_EACH_CODE_MAPPING(CASE)
3336 #undef CASE
3337 default:
3338 return ERROR_MARK;
3339 }
3340 }
3341
3342 /* Invoke T(IFN) for each internal function IFN that also has an
3343 IFN_COND_* form. */
3344 #define FOR_EACH_COND_FN_PAIR(T) \
3345 T (FMA) \
3346 T (FMS) \
3347 T (FNMA) \
3348 T (FNMS)
3349
3350 /* Return a function that only performs internal function FN when a
3351 certain condition is met and that uses a given fallback value otherwise.
3352 In other words, the returned function FN' is such that:
3353
3354 LHS = FN' (COND, A1, ... An, ELSE)
3355
3356 is equivalent to the C expression:
3357
3358 LHS = COND ? FN (A1, ..., An) : ELSE;
3359
3360 operating elementwise if the operands are vectors.
3361
3362 Return IFN_LAST if no such function exists. */
3363
3364 internal_fn
3365 get_conditional_internal_fn (internal_fn fn)
3366 {
3367 switch (fn)
3368 {
3369 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
3370 FOR_EACH_COND_FN_PAIR(CASE)
3371 #undef CASE
3372 default:
3373 return IFN_LAST;
3374 }
3375 }
3376
3377 /* If IFN implements the conditional form of an unconditional internal
3378 function, return that unconditional function, otherwise return IFN_LAST. */
3379
3380 internal_fn
3381 get_unconditional_internal_fn (internal_fn ifn)
3382 {
3383 switch (ifn)
3384 {
3385 #define CASE(NAME) case IFN_COND_##NAME: return IFN_##NAME;
3386 FOR_EACH_COND_FN_PAIR(CASE)
3387 #undef CASE
3388 default:
3389 return IFN_LAST;
3390 }
3391 }
3392
3393 /* Return true if STMT can be interpreted as a conditional tree code
3394 operation of the form:
3395
3396 LHS = COND ? OP (RHS1, ...) : ELSE;
3397
3398 operating elementwise if the operands are vectors. This includes
3399 the case of an all-true COND, so that the operation always happens.
3400
3401 When returning true, set:
3402
3403 - *COND_OUT to the condition COND, or to NULL_TREE if the condition
3404 is known to be all-true
3405 - *CODE_OUT to the tree code
3406 - OPS[I] to operand I of *CODE_OUT
3407 - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
3408 condition is known to be all true. */
3409
3410 bool
3411 can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
3412 tree_code *code_out,
3413 tree (&ops)[3], tree *else_out)
3414 {
3415 if (gassign *assign = dyn_cast <gassign *> (stmt))
3416 {
3417 *cond_out = NULL_TREE;
3418 *code_out = gimple_assign_rhs_code (assign);
3419 ops[0] = gimple_assign_rhs1 (assign);
3420 ops[1] = gimple_assign_rhs2 (assign);
3421 ops[2] = gimple_assign_rhs3 (assign);
3422 *else_out = NULL_TREE;
3423 return true;
3424 }
3425 if (gcall *call = dyn_cast <gcall *> (stmt))
3426 if (gimple_call_internal_p (call))
3427 {
3428 internal_fn ifn = gimple_call_internal_fn (call);
3429 tree_code code = conditional_internal_fn_code (ifn);
3430 if (code != ERROR_MARK)
3431 {
3432 *cond_out = gimple_call_arg (call, 0);
3433 *code_out = code;
3434 unsigned int nops = gimple_call_num_args (call) - 2;
3435 for (unsigned int i = 0; i < 3; ++i)
3436 ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
3437 *else_out = gimple_call_arg (call, nops + 1);
3438 if (integer_truep (*cond_out))
3439 {
3440 *cond_out = NULL_TREE;
3441 *else_out = NULL_TREE;
3442 }
3443 return true;
3444 }
3445 }
3446 return false;
3447 }
3448
3449 /* Return true if IFN is some form of load from memory. */
3450
3451 bool
3452 internal_load_fn_p (internal_fn fn)
3453 {
3454 switch (fn)
3455 {
3456 case IFN_MASK_LOAD:
3457 case IFN_LOAD_LANES:
3458 case IFN_MASK_LOAD_LANES:
3459 case IFN_GATHER_LOAD:
3460 case IFN_MASK_GATHER_LOAD:
3461 return true;
3462
3463 default:
3464 return false;
3465 }
3466 }
3467
3468 /* Return true if IFN is some form of store to memory. */
3469
3470 bool
3471 internal_store_fn_p (internal_fn fn)
3472 {
3473 switch (fn)
3474 {
3475 case IFN_MASK_STORE:
3476 case IFN_STORE_LANES:
3477 case IFN_MASK_STORE_LANES:
3478 case IFN_SCATTER_STORE:
3479 case IFN_MASK_SCATTER_STORE:
3480 return true;
3481
3482 default:
3483 return false;
3484 }
3485 }
3486
3487 /* Return true if IFN is some form of gather load or scatter store. */
3488
3489 bool
3490 internal_gather_scatter_fn_p (internal_fn fn)
3491 {
3492 switch (fn)
3493 {
3494 case IFN_GATHER_LOAD:
3495 case IFN_MASK_GATHER_LOAD:
3496 case IFN_SCATTER_STORE:
3497 case IFN_MASK_SCATTER_STORE:
3498 return true;
3499
3500 default:
3501 return false;
3502 }
3503 }
3504
3505 /* If FN takes a vector mask argument, return the index of that argument,
3506 otherwise return -1. */
3507
3508 int
3509 internal_fn_mask_index (internal_fn fn)
3510 {
3511 switch (fn)
3512 {
3513 case IFN_MASK_LOAD:
3514 case IFN_MASK_LOAD_LANES:
3515 case IFN_MASK_STORE:
3516 case IFN_MASK_STORE_LANES:
3517 return 2;
3518
3519 case IFN_MASK_GATHER_LOAD:
3520 return 3;
3521
3522 case IFN_MASK_SCATTER_STORE:
3523 return 4;
3524
3525 default:
3526 return (conditional_internal_fn_code (fn) != ERROR_MARK
3527 || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
3528 }
3529 }
3530
3531 /* If FN takes a value that should be stored to memory, return the index
3532 of that argument, otherwise return -1. */
3533
3534 int
3535 internal_fn_stored_value_index (internal_fn fn)
3536 {
3537 switch (fn)
3538 {
3539 case IFN_MASK_STORE:
3540 case IFN_SCATTER_STORE:
3541 case IFN_MASK_SCATTER_STORE:
3542 return 3;
3543
3544 default:
3545 return -1;
3546 }
3547 }
3548
3549 /* Return true if the target supports gather load or scatter store function
3550 IFN. For loads, VECTOR_TYPE is the vector type of the load result,
3551 while for stores it is the vector type of the stored data argument.
3552 MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
3553 or stored. OFFSET_SIGN is the sign of the offset argument, which is
3554 only relevant when the offset is narrower than an address. SCALE is
3555 the amount by which the offset should be multiplied *after* it has
3556 been extended to address width. */
3557
3558 bool
3559 internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
3560 tree memory_element_type,
3561 signop offset_sign, int scale)
3562 {
3563 if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
3564 TYPE_SIZE (memory_element_type)))
3565 return false;
3566 optab optab = direct_internal_fn_optab (ifn);
3567 insn_code icode = direct_optab_handler (optab, TYPE_MODE (vector_type));
3568 int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
3569 return (icode != CODE_FOR_nothing
3570 && insn_operand_matches (icode, 2 + output_ops,
3571 GEN_INT (offset_sign == UNSIGNED))
3572 && insn_operand_matches (icode, 3 + output_ops,
3573 GEN_INT (scale)));
3574 }
3575
3576 /* Expand STMT as though it were a call to internal function FN. */
3577
3578 void
3579 expand_internal_call (internal_fn fn, gcall *stmt)
3580 {
3581 internal_fn_expanders[fn] (fn, stmt);
3582 }
3583
3584 /* Expand STMT, which is a call to internal function FN. */
3585
3586 void
3587 expand_internal_call (gcall *stmt)
3588 {
3589 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
3590 }
3591
3592 /* If TYPE is a vector type, return true if IFN is a direct internal
3593 function that is supported for that type. If TYPE is a scalar type,
3594 return true if IFN is a direct internal function that is supported for
3595 the target's preferred vector version of TYPE. */
3596
3597 bool
3598 vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
3599 {
3600 scalar_mode smode;
3601 if (!VECTOR_TYPE_P (type) && is_a <scalar_mode> (TYPE_MODE (type), &smode))
3602 {
3603 machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
3604 if (VECTOR_MODE_P (vmode))
3605 type = build_vector_type_for_mode (type, vmode);
3606 }
3607
3608 return (VECTOR_MODE_P (TYPE_MODE (type))
3609 && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED));
3610 }
3611
3612 void
3613 expand_PHI (internal_fn, gcall *)
3614 {
3615 gcc_unreachable ();
3616 }