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