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