]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/internal-fn.c
* es.po, fr.po: Update.
[thirdparty/gcc.git] / gcc / internal-fn.c
CommitLineData
25583c4f 1/* Internal functions.
818ab71a 2 Copyright (C) 2011-2016 Free Software Foundation, Inc.
25583c4f
RS
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along 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"
c7131fb2 23#include "backend.h"
957060b5
AM
24#include "target.h"
25#include "rtl.h"
25583c4f 26#include "tree.h"
c7131fb2 27#include "gimple.h"
957060b5
AM
28#include "predict.h"
29#include "stringpool.h"
f90aa46c 30#include "tree-vrp.h"
957060b5
AM
31#include "tree-ssanames.h"
32#include "expmed.h"
4d0cdd0c 33#include "memmodel.h"
957060b5
AM
34#include "optabs.h"
35#include "emit-rtl.h"
36#include "diagnostic-core.h"
40e23961 37#include "fold-const.h"
0e37a2f3 38#include "internal-fn.h"
d8a2d370 39#include "stor-layout.h"
36566b39 40#include "dojump.h"
25583c4f 41#include "expr.h"
31e071ae 42#include "ubsan.h"
686ee971 43#include "recog.h"
adedd5c1 44#include "builtins.h"
1705cebd 45#include "optabs-tree.h"
25583c4f
RS
46
47/* The names of each internal function, indexed by function number. */
48const char *const internal_fn_name_array[] = {
b78475cf 49#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
25583c4f 50#include "internal-fn.def"
25583c4f
RS
51 "<invalid-fn>"
52};
53
54/* The ECF_* flags of each internal function, indexed by function number. */
55const int internal_fn_flags_array[] = {
b78475cf 56#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
25583c4f 57#include "internal-fn.def"
25583c4f
RS
58 0
59};
60
b78475cf
YG
61/* Fnspec of each internal function, indexed by function number. */
62const_tree internal_fn_fnspec_array[IFN_LAST + 1];
63
64void
65init_internal_fns ()
66{
67#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
68 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
63a4184f 69 build_string ((int) sizeof (FNSPEC), FNSPEC ? FNSPEC : "");
b78475cf 70#include "internal-fn.def"
b78475cf
YG
71 internal_fn_fnspec_array[IFN_LAST] = 0;
72}
73
ab23f5d9
RS
74/* Create static initializers for the information returned by
75 direct_internal_fn. */
70439f0d
RS
76#define not_direct { -2, -2, false }
77#define mask_load_direct { -1, 2, false }
78#define load_lanes_direct { -1, -1, false }
79#define mask_store_direct { 3, 2, false }
80#define store_lanes_direct { 0, 0, false }
81#define unary_direct { 0, 0, true }
82#define binary_direct { 0, 0, true }
ab23f5d9
RS
83
84const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
85#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
86#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
87#include "internal-fn.def"
88 not_direct
89};
90
272c6793 91/* ARRAY_TYPE is an array of vector modes. Return the associated insn
ab23f5d9 92 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
272c6793
RS
93
94static enum insn_code
95get_multi_vector_move (tree array_type, convert_optab optab)
96{
ef4bddc2
RS
97 machine_mode imode;
98 machine_mode vmode;
272c6793
RS
99
100 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
101 imode = TYPE_MODE (array_type);
102 vmode = TYPE_MODE (TREE_TYPE (array_type));
103
ab23f5d9 104 return convert_optab_handler (optab, imode, vmode);
272c6793
RS
105}
106
ab23f5d9 107/* Expand LOAD_LANES call STMT using optab OPTAB. */
272c6793
RS
108
109static void
4cfe7a6c 110expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
272c6793
RS
111{
112 struct expand_operand ops[2];
113 tree type, lhs, rhs;
114 rtx target, mem;
115
116 lhs = gimple_call_lhs (stmt);
117 rhs = gimple_call_arg (stmt, 0);
118 type = TREE_TYPE (lhs);
119
120 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
121 mem = expand_normal (rhs);
122
123 gcc_assert (MEM_P (mem));
124 PUT_MODE (mem, TYPE_MODE (type));
125
126 create_output_operand (&ops[0], target, TYPE_MODE (type));
127 create_fixed_operand (&ops[1], mem);
ab23f5d9 128 expand_insn (get_multi_vector_move (type, optab), 2, ops);
272c6793
RS
129}
130
ab23f5d9 131/* Expand STORE_LANES call STMT using optab OPTAB. */
272c6793
RS
132
133static void
4cfe7a6c 134expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
272c6793
RS
135{
136 struct expand_operand ops[2];
137 tree type, lhs, rhs;
138 rtx target, reg;
139
140 lhs = gimple_call_lhs (stmt);
141 rhs = gimple_call_arg (stmt, 0);
142 type = TREE_TYPE (rhs);
143
144 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
145 reg = expand_normal (rhs);
146
147 gcc_assert (MEM_P (target));
148 PUT_MODE (target, TYPE_MODE (type));
149
150 create_fixed_operand (&ops[0], target);
151 create_input_operand (&ops[1], reg, TYPE_MODE (type));
ab23f5d9 152 expand_insn (get_multi_vector_move (type, optab), 2, ops);
272c6793
RS
153}
154
8170608b 155static void
4cfe7a6c 156expand_ANNOTATE (internal_fn, gcall *)
8170608b
TB
157{
158 gcc_unreachable ();
159}
160
9669b00b
AM
161/* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
162 without SIMT execution this should be expanded in omp_device_lower pass. */
163
164static void
165expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
166{
167 tree lhs = gimple_call_lhs (stmt);
168 if (!lhs)
169 return;
170
171 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
172 gcc_assert (targetm.have_omp_simt_lane ());
173 emit_insn (targetm.gen_omp_simt_lane (target));
174}
175
176/* This should get expanded in omp_device_lower pass. */
177
178static void
179expand_GOMP_SIMT_VF (internal_fn, gcall *)
180{
181 gcc_unreachable ();
182}
183
184/* Lane index of the first SIMT lane that supplies a non-zero argument.
185 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
186 lane that executed the last iteration for handling OpenMP lastprivate. */
187
188static void
189expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
190{
191 tree lhs = gimple_call_lhs (stmt);
192 if (!lhs)
193 return;
194
195 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
196 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
197 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
198 struct expand_operand ops[2];
199 create_output_operand (&ops[0], target, mode);
200 create_input_operand (&ops[1], cond, mode);
201 gcc_assert (targetm.have_omp_simt_last_lane ());
202 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
203}
204
205/* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
206
207static void
208expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
209{
210 tree lhs = gimple_call_lhs (stmt);
211 if (!lhs)
212 return;
213
214 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
215 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
216 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
217 struct expand_operand ops[2];
218 create_output_operand (&ops[0], target, mode);
219 create_input_operand (&ops[1], ctr, mode);
220 gcc_assert (targetm.have_omp_simt_ordered ());
221 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
222}
223
224/* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
225 any lane supplies a non-zero argument. */
226
227static void
228expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
229{
230 tree lhs = gimple_call_lhs (stmt);
231 if (!lhs)
232 return;
233
234 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
235 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
236 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
237 struct expand_operand ops[2];
238 create_output_operand (&ops[0], target, mode);
239 create_input_operand (&ops[1], cond, mode);
240 gcc_assert (targetm.have_omp_simt_vote_any ());
241 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
242}
243
244/* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
245 is destination lane index XOR given offset. */
246
247static void
248expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
249{
250 tree lhs = gimple_call_lhs (stmt);
251 if (!lhs)
252 return;
253
254 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
255 rtx src = expand_normal (gimple_call_arg (stmt, 0));
256 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
257 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
258 struct expand_operand ops[3];
259 create_output_operand (&ops[0], target, mode);
260 create_input_operand (&ops[1], src, mode);
261 create_input_operand (&ops[2], idx, SImode);
262 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
263 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
264}
265
266/* Exchange between SIMT lanes according to given source lane index. */
267
268static void
269expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
270{
271 tree lhs = gimple_call_lhs (stmt);
272 if (!lhs)
273 return;
274
275 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
276 rtx src = expand_normal (gimple_call_arg (stmt, 0));
277 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
278 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
279 struct expand_operand ops[3];
280 create_output_operand (&ops[0], target, mode);
281 create_input_operand (&ops[1], src, mode);
282 create_input_operand (&ops[2], idx, SImode);
283 gcc_assert (targetm.have_omp_simt_xchg_idx ());
284 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
285}
286
74bf76ed
JJ
287/* This should get expanded in adjust_simduid_builtins. */
288
289static void
4cfe7a6c 290expand_GOMP_SIMD_LANE (internal_fn, gcall *)
74bf76ed
JJ
291{
292 gcc_unreachable ();
293}
294
295/* This should get expanded in adjust_simduid_builtins. */
296
297static void
4cfe7a6c 298expand_GOMP_SIMD_VF (internal_fn, gcall *)
74bf76ed
JJ
299{
300 gcc_unreachable ();
301}
302
303/* This should get expanded in adjust_simduid_builtins. */
304
305static void
4cfe7a6c 306expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
74bf76ed
JJ
307{
308 gcc_unreachable ();
309}
310
d9a6bd32
JJ
311/* This should get expanded in adjust_simduid_builtins. */
312
313static void
4cfe7a6c 314expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
d9a6bd32
JJ
315{
316 gcc_unreachable ();
317}
318
319/* This should get expanded in adjust_simduid_builtins. */
320
321static void
4cfe7a6c 322expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
d9a6bd32
JJ
323{
324 gcc_unreachable ();
325}
326
b9a55b13
MP
327/* This should get expanded in the sanopt pass. */
328
329static void
4cfe7a6c 330expand_UBSAN_NULL (internal_fn, gcall *)
b9a55b13
MP
331{
332 gcc_unreachable ();
333}
334
0e37a2f3
MP
335/* This should get expanded in the sanopt pass. */
336
337static void
4cfe7a6c 338expand_UBSAN_BOUNDS (internal_fn, gcall *)
0e82f089
MP
339{
340 gcc_unreachable ();
341}
342
343/* This should get expanded in the sanopt pass. */
344
345static void
4cfe7a6c 346expand_UBSAN_VPTR (internal_fn, gcall *)
0e37a2f3
MP
347{
348 gcc_unreachable ();
349}
350
c62ccb9a
YG
351/* This should get expanded in the sanopt pass. */
352
353static void
4cfe7a6c 354expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
35228ac7
JJ
355{
356 gcc_unreachable ();
357}
358
359/* This should get expanded in the sanopt pass. */
360
361static void
4cfe7a6c 362expand_ASAN_CHECK (internal_fn, gcall *)
c62ccb9a
YG
363{
364 gcc_unreachable ();
365}
366
6dc4a604
ML
367/* This should get expanded in the sanopt pass. */
368
369static void
370expand_ASAN_MARK (internal_fn, gcall *)
371{
372 gcc_unreachable ();
373}
374
375
fca4adf2
JJ
376/* This should get expanded in the tsan pass. */
377
378static void
4cfe7a6c 379expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
fca4adf2
JJ
380{
381 gcc_unreachable ();
382}
383
81fea426
MP
384/* This should get expanded in the lower pass. */
385
386static void
387expand_FALLTHROUGH (internal_fn, gcall *call)
388{
389 error_at (gimple_location (call),
390 "invalid use of attribute %<fallthrough%>");
391}
392
1304953e
JJ
393/* Helper function for expand_addsub_overflow. Return 1
394 if ARG interpreted as signed in its precision is known to be always
395 positive or 2 if ARG is known to be always negative, or 3 if ARG may
396 be positive or negative. */
397
398static int
399get_range_pos_neg (tree arg)
400{
401 if (arg == error_mark_node)
402 return 3;
403
404 int prec = TYPE_PRECISION (TREE_TYPE (arg));
405 int cnt = 0;
406 if (TREE_CODE (arg) == INTEGER_CST)
407 {
408 wide_int w = wi::sext (arg, prec);
409 if (wi::neg_p (w))
410 return 2;
411 else
412 return 1;
413 }
414 while (CONVERT_EXPR_P (arg)
415 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
416 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
417 {
418 arg = TREE_OPERAND (arg, 0);
419 /* Narrower value zero extended into wider type
420 will always result in positive values. */
421 if (TYPE_UNSIGNED (TREE_TYPE (arg))
422 && TYPE_PRECISION (TREE_TYPE (arg)) < prec)
423 return 1;
424 prec = TYPE_PRECISION (TREE_TYPE (arg));
425 if (++cnt > 30)
426 return 3;
427 }
428
429 if (TREE_CODE (arg) != SSA_NAME)
430 return 3;
431 wide_int arg_min, arg_max;
432 while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
433 {
355fe088 434 gimple *g = SSA_NAME_DEF_STMT (arg);
1304953e
JJ
435 if (is_gimple_assign (g)
436 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
437 {
438 tree t = gimple_assign_rhs1 (g);
439 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
440 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
441 {
442 if (TYPE_UNSIGNED (TREE_TYPE (t))
443 && TYPE_PRECISION (TREE_TYPE (t)) < prec)
444 return 1;
445 prec = TYPE_PRECISION (TREE_TYPE (t));
446 arg = t;
447 if (++cnt > 30)
448 return 3;
449 continue;
450 }
451 }
452 return 3;
453 }
454 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
455 {
456 /* For unsigned values, the "positive" range comes
457 below the "negative" range. */
458 if (!wi::neg_p (wi::sext (arg_max, prec), SIGNED))
459 return 1;
460 if (wi::neg_p (wi::sext (arg_min, prec), SIGNED))
461 return 2;
462 }
463 else
464 {
465 if (!wi::neg_p (wi::sext (arg_min, prec), SIGNED))
466 return 1;
467 if (wi::neg_p (wi::sext (arg_max, prec), SIGNED))
468 return 2;
469 }
470 return 3;
471}
472
473/* Return minimum precision needed to represent all values
474 of ARG in SIGNed integral type. */
475
476static int
477get_min_precision (tree arg, signop sign)
478{
479 int prec = TYPE_PRECISION (TREE_TYPE (arg));
480 int cnt = 0;
481 signop orig_sign = sign;
482 if (TREE_CODE (arg) == INTEGER_CST)
483 {
484 int p;
485 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
486 {
487 widest_int w = wi::to_widest (arg);
488 w = wi::ext (w, prec, sign);
489 p = wi::min_precision (w, sign);
490 }
491 else
492 p = wi::min_precision (arg, sign);
493 return MIN (p, prec);
494 }
495 while (CONVERT_EXPR_P (arg)
496 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
497 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
498 {
499 arg = TREE_OPERAND (arg, 0);
500 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
501 {
502 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
503 sign = UNSIGNED;
504 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
505 return prec + (orig_sign != sign);
506 prec = TYPE_PRECISION (TREE_TYPE (arg));
507 }
508 if (++cnt > 30)
509 return prec + (orig_sign != sign);
510 }
511 if (TREE_CODE (arg) != SSA_NAME)
512 return prec + (orig_sign != sign);
513 wide_int arg_min, arg_max;
514 while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
515 {
355fe088 516 gimple *g = SSA_NAME_DEF_STMT (arg);
1304953e
JJ
517 if (is_gimple_assign (g)
518 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
519 {
520 tree t = gimple_assign_rhs1 (g);
521 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
522 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
523 {
524 arg = t;
525 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
526 {
527 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
528 sign = UNSIGNED;
529 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
530 return prec + (orig_sign != sign);
531 prec = TYPE_PRECISION (TREE_TYPE (arg));
532 }
533 if (++cnt > 30)
534 return prec + (orig_sign != sign);
535 continue;
536 }
537 }
538 return prec + (orig_sign != sign);
539 }
540 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
541 {
542 int p1 = wi::min_precision (arg_min, sign);
543 int p2 = wi::min_precision (arg_max, sign);
544 p1 = MAX (p1, p2);
545 prec = MIN (prec, p1);
546 }
547 else if (sign == UNSIGNED && !wi::neg_p (arg_min, SIGNED))
548 {
c1ee2e62 549 int p = wi::min_precision (arg_max, UNSIGNED);
1304953e
JJ
550 prec = MIN (prec, p);
551 }
552 return prec + (orig_sign != sign);
553}
554
a86451b9
JJ
555/* Helper for expand_*_overflow. Set the __imag__ part to true
556 (1 except for signed:1 type, in which case store -1). */
557
558static void
559expand_arith_set_overflow (tree lhs, rtx target)
560{
561 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
562 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
563 write_complex_part (target, constm1_rtx, true);
564 else
565 write_complex_part (target, const1_rtx, true);
566}
567
1304953e
JJ
568/* Helper for expand_*_overflow. Store RES into the __real__ part
569 of TARGET. If RES has larger MODE than __real__ part of TARGET,
a86451b9
JJ
570 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
571 if LHS has smaller precision than its mode. */
1304953e
JJ
572
573static void
574expand_arith_overflow_result_store (tree lhs, rtx target,
575 machine_mode mode, rtx res)
576{
577 machine_mode tgtmode = GET_MODE_INNER (GET_MODE (target));
578 rtx lres = res;
579 if (tgtmode != mode)
580 {
581 rtx_code_label *done_label = gen_label_rtx ();
582 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
583 lres = convert_modes (tgtmode, mode, res, uns);
584 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
92344ed0 585 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
1476d1bd 586 EQ, true, mode, NULL_RTX, NULL, done_label,
1304953e 587 PROB_VERY_LIKELY);
a86451b9
JJ
588 expand_arith_set_overflow (lhs, target);
589 emit_label (done_label);
590 }
591 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
592 int tgtprec = GET_MODE_PRECISION (tgtmode);
593 if (prec < tgtprec)
594 {
595 rtx_code_label *done_label = gen_label_rtx ();
596 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
597 res = lres;
598 if (uns)
599 {
600 rtx mask
601 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
602 tgtmode);
603 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
95ef39f4 604 true, OPTAB_LIB_WIDEN);
a86451b9
JJ
605 }
606 else
607 {
608 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
609 NULL_RTX, 1);
610 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
611 NULL_RTX, 0);
612 }
613 do_compare_rtx_and_jump (res, lres,
614 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
615 PROB_VERY_LIKELY);
616 expand_arith_set_overflow (lhs, target);
1304953e
JJ
617 emit_label (done_label);
618 }
619 write_complex_part (target, lres, false);
620}
621
5620052d
JJ
622/* Helper for expand_*_overflow. Store RES into TARGET. */
623
624static void
625expand_ubsan_result_store (rtx target, rtx res)
626{
627 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
628 /* If this is a scalar in a register that is stored in a wider mode
629 than the declared mode, compute the result into its declared mode
630 and then convert to the wider mode. Our value is the computed
631 expression. */
632 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
633 else
634 emit_move_insn (target, res);
635}
636
31e071ae
MP
637/* Add sub/add overflow checking to the statement STMT.
638 CODE says whether the operation is +, or -. */
639
1304953e
JJ
640static void
641expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
642 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
1705cebd 643 bool uns1_p, bool is_ubsan, tree *datap)
31e071ae 644{
1304953e
JJ
645 rtx res, target = NULL_RTX;
646 tree fn;
647 rtx_code_label *done_label = gen_label_rtx ();
648 rtx_code_label *do_error = gen_label_rtx ();
31e071ae 649 do_pending_stack_adjust ();
1304953e
JJ
650 rtx op0 = expand_normal (arg0);
651 rtx op1 = expand_normal (arg1);
ef4bddc2 652 machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
1304953e
JJ
653 int prec = GET_MODE_PRECISION (mode);
654 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
655 bool do_xor = false;
656
657 if (is_ubsan)
658 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
659
31e071ae 660 if (lhs)
1304953e
JJ
661 {
662 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
663 if (!is_ubsan)
664 write_complex_part (target, const0_rtx, true);
665 }
666
667 /* We assume both operands and result have the same precision
668 here (GET_MODE_BITSIZE (mode)), S stands for signed type
669 with that precision, U for unsigned type with that precision,
670 sgn for unsigned most significant bit in that precision.
671 s1 is signed first operand, u1 is unsigned first operand,
672 s2 is signed second operand, u2 is unsigned second operand,
673 sr is signed result, ur is unsigned result and the following
674 rules say how to compute result (which is always result of
675 the operands as if both were unsigned, cast to the right
676 signedness) and how to compute whether operation overflowed.
677
678 s1 + s2 -> sr
679 res = (S) ((U) s1 + (U) s2)
680 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
681 s1 - s2 -> sr
682 res = (S) ((U) s1 - (U) s2)
683 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
684 u1 + u2 -> ur
685 res = u1 + u2
686 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
687 u1 - u2 -> ur
688 res = u1 - u2
689 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
690 s1 + u2 -> sr
691 res = (S) ((U) s1 + u2)
692 ovf = ((U) res ^ sgn) < u2
693 s1 + u2 -> ur
694 t1 = (S) (u2 ^ sgn)
695 t2 = s1 + t1
696 res = (U) t2 ^ sgn
697 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
698 s1 - u2 -> sr
699 res = (S) ((U) s1 - u2)
700 ovf = u2 > ((U) s1 ^ sgn)
701 s1 - u2 -> ur
702 res = (U) s1 - u2
703 ovf = s1 < 0 || u2 > (U) s1
704 u1 - s2 -> sr
705 res = u1 - (U) s2
706 ovf = u1 >= ((U) s2 ^ sgn)
707 u1 - s2 -> ur
708 t1 = u1 ^ sgn
709 t2 = t1 - (U) s2
710 res = t2 ^ sgn
711 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
712 s1 + s2 -> ur
713 res = (U) s1 + (U) s2
714 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
715 u1 + u2 -> sr
716 res = (S) (u1 + u2)
717 ovf = (U) res < u2 || res < 0
718 u1 - u2 -> sr
719 res = (S) (u1 - u2)
720 ovf = u1 >= u2 ? res < 0 : res >= 0
721 s1 - s2 -> ur
722 res = (U) s1 - (U) s2
723 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
724
725 if (code == PLUS_EXPR && uns0_p && !uns1_p)
726 {
727 /* PLUS_EXPR is commutative, if operand signedness differs,
728 canonicalize to the first operand being signed and second
729 unsigned to simplify following code. */
6b4db501
MM
730 std::swap (op0, op1);
731 std::swap (arg0, arg1);
732 uns0_p = false;
733 uns1_p = true;
1304953e
JJ
734 }
735
736 /* u1 +- u2 -> ur */
737 if (uns0_p && uns1_p && unsr_p)
738 {
cde9d596
RH
739 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
740 : usubv4_optab, mode);
741 if (icode != CODE_FOR_nothing)
742 {
743 struct expand_operand ops[4];
744 rtx_insn *last = get_last_insn ();
745
746 res = gen_reg_rtx (mode);
747 create_output_operand (&ops[0], res, mode);
748 create_input_operand (&ops[1], op0, mode);
749 create_input_operand (&ops[2], op1, mode);
750 create_fixed_operand (&ops[3], do_error);
751 if (maybe_expand_insn (icode, 4, ops))
752 {
753 last = get_last_insn ();
754 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
755 && JUMP_P (last)
756 && any_condjump_p (last)
757 && !find_reg_note (last, REG_BR_PROB, 0))
758 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
759 emit_jump (done_label);
760 goto do_error_label;
761 }
762
763 delete_insns_since (last);
764 }
765
1304953e
JJ
766 /* Compute the operation. On RTL level, the addition is always
767 unsigned. */
768 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
769 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
770 rtx tem = op0;
771 /* For PLUS_EXPR, the operation is commutative, so we can pick
772 operand to compare against. For prec <= BITS_PER_WORD, I think
773 preferring REG operand is better over CONST_INT, because
774 the CONST_INT might enlarge the instruction or CSE would need
775 to figure out we'd already loaded it into a register before.
776 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
777 as then the multi-word comparison can be perhaps simplified. */
778 if (code == PLUS_EXPR
779 && (prec <= BITS_PER_WORD
780 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
781 : CONST_SCALAR_INT_P (op1)))
782 tem = op1;
92344ed0 783 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
1476d1bd 784 true, mode, NULL_RTX, NULL, done_label,
1304953e
JJ
785 PROB_VERY_LIKELY);
786 goto do_error_label;
787 }
788
789 /* s1 +- u2 -> sr */
790 if (!uns0_p && uns1_p && !unsr_p)
791 {
792 /* Compute the operation. On RTL level, the addition is always
793 unsigned. */
794 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
795 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
796 rtx tem = expand_binop (mode, add_optab,
797 code == PLUS_EXPR ? res : op0, sgn,
798 NULL_RTX, false, OPTAB_LIB_WIDEN);
1476d1bd 799 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
800 done_label, PROB_VERY_LIKELY);
801 goto do_error_label;
802 }
803
804 /* s1 + u2 -> ur */
805 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
806 {
807 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
808 OPTAB_LIB_WIDEN);
809 /* As we've changed op1, we have to avoid using the value range
810 for the original argument. */
811 arg1 = error_mark_node;
812 do_xor = true;
813 goto do_signed;
814 }
815
816 /* u1 - s2 -> ur */
817 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
818 {
819 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
820 OPTAB_LIB_WIDEN);
821 /* As we've changed op0, we have to avoid using the value range
822 for the original argument. */
823 arg0 = error_mark_node;
824 do_xor = true;
825 goto do_signed;
826 }
827
828 /* s1 - u2 -> ur */
829 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
830 {
831 /* Compute the operation. On RTL level, the addition is always
832 unsigned. */
833 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
834 OPTAB_LIB_WIDEN);
835 int pos_neg = get_range_pos_neg (arg0);
836 if (pos_neg == 2)
837 /* If ARG0 is known to be always negative, this is always overflow. */
838 emit_jump (do_error);
839 else if (pos_neg == 3)
840 /* If ARG0 is not known to be always positive, check at runtime. */
92344ed0 841 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd
MM
842 NULL, do_error, PROB_VERY_UNLIKELY);
843 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
844 done_label, PROB_VERY_LIKELY);
845 goto do_error_label;
846 }
847
848 /* u1 - s2 -> sr */
849 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
850 {
851 /* Compute the operation. On RTL level, the addition is always
852 unsigned. */
853 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
854 OPTAB_LIB_WIDEN);
855 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
856 OPTAB_LIB_WIDEN);
1476d1bd 857 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
1304953e
JJ
858 done_label, PROB_VERY_LIKELY);
859 goto do_error_label;
860 }
861
862 /* u1 + u2 -> sr */
863 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
864 {
865 /* Compute the operation. On RTL level, the addition is always
866 unsigned. */
867 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
868 OPTAB_LIB_WIDEN);
92344ed0 869 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd 870 NULL, do_error, PROB_VERY_UNLIKELY);
1304953e
JJ
871 rtx tem = op1;
872 /* The operation is commutative, so we can pick operand to compare
873 against. For prec <= BITS_PER_WORD, I think preferring REG operand
874 is better over CONST_INT, because the CONST_INT might enlarge the
875 instruction or CSE would need to figure out we'd already loaded it
876 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
877 might be more beneficial, as then the multi-word comparison can be
878 perhaps simplified. */
879 if (prec <= BITS_PER_WORD
880 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
881 : CONST_SCALAR_INT_P (op0))
882 tem = op0;
1476d1bd 883 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
884 done_label, PROB_VERY_LIKELY);
885 goto do_error_label;
886 }
887
888 /* s1 +- s2 -> ur */
889 if (!uns0_p && !uns1_p && unsr_p)
890 {
891 /* Compute the operation. On RTL level, the addition is always
892 unsigned. */
893 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
894 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
895 int pos_neg = get_range_pos_neg (arg1);
896 if (code == PLUS_EXPR)
897 {
898 int pos_neg0 = get_range_pos_neg (arg0);
899 if (pos_neg0 != 3 && pos_neg == 3)
900 {
6b4db501 901 std::swap (op0, op1);
1304953e
JJ
902 pos_neg = pos_neg0;
903 }
904 }
905 rtx tem;
906 if (pos_neg != 3)
907 {
908 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
909 ? and_optab : ior_optab,
910 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
1476d1bd
MM
911 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
912 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
913 }
914 else
915 {
916 rtx_code_label *do_ior_label = gen_label_rtx ();
92344ed0
JJ
917 do_compare_rtx_and_jump (op1, const0_rtx,
918 code == MINUS_EXPR ? GE : LT, false, mode,
1476d1bd 919 NULL_RTX, NULL, do_ior_label,
92344ed0 920 PROB_EVEN);
1304953e
JJ
921 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
922 OPTAB_LIB_WIDEN);
92344ed0 923 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 924 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
925 emit_jump (do_error);
926 emit_label (do_ior_label);
927 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
928 OPTAB_LIB_WIDEN);
92344ed0 929 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 930 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
931 }
932 goto do_error_label;
933 }
934
935 /* u1 - u2 -> sr */
936 if (code == MINUS_EXPR && 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, sub_optab, op0, op1, NULL_RTX, false,
941 OPTAB_LIB_WIDEN);
942 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
1476d1bd 943 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
1304953e 944 op0_geu_op1, PROB_EVEN);
92344ed0 945 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd 946 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
947 emit_jump (do_error);
948 emit_label (op0_geu_op1);
92344ed0 949 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 950 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
951 goto do_error_label;
952 }
31e071ae 953
1304953e
JJ
954 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
955
956 /* s1 +- s2 -> sr */
cde9d596
RH
957 do_signed:
958 {
959 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
960 : subv4_optab, mode);
961 if (icode != CODE_FOR_nothing)
962 {
963 struct expand_operand ops[4];
964 rtx_insn *last = get_last_insn ();
965
966 res = gen_reg_rtx (mode);
967 create_output_operand (&ops[0], res, mode);
968 create_input_operand (&ops[1], op0, mode);
969 create_input_operand (&ops[2], op1, mode);
970 create_fixed_operand (&ops[3], do_error);
971 if (maybe_expand_insn (icode, 4, ops))
972 {
973 last = get_last_insn ();
974 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
975 && JUMP_P (last)
976 && any_condjump_p (last)
977 && !find_reg_note (last, REG_BR_PROB, 0))
978 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
979 emit_jump (done_label);
980 goto do_error_label;
981 }
982
983 delete_insns_since (last);
984 }
985
cde9d596
RH
986 /* Compute the operation. On RTL level, the addition is always
987 unsigned. */
988 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
989 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
990
47135167 991 /* If we can prove that one of the arguments (for MINUS_EXPR only
cde9d596
RH
992 the second operand, as subtraction is not commutative) is always
993 non-negative or always negative, we can do just one comparison
47135167
EB
994 and conditional jump. */
995 int pos_neg = get_range_pos_neg (arg1);
996 if (code == PLUS_EXPR)
cde9d596 997 {
47135167
EB
998 int pos_neg0 = get_range_pos_neg (arg0);
999 if (pos_neg0 != 3 && pos_neg == 3)
1000 {
1001 std::swap (op0, op1);
1002 pos_neg = pos_neg0;
1003 }
cde9d596 1004 }
cde9d596 1005
47135167
EB
1006 /* Addition overflows if and only if the two operands have the same sign,
1007 and the result has the opposite sign. Subtraction overflows if and
1008 only if the two operands have opposite sign, and the subtrahend has
1009 the same sign as the result. Here 0 is counted as positive. */
cde9d596 1010 if (pos_neg == 3)
47135167
EB
1011 {
1012 /* Compute op0 ^ op1 (operands have opposite sign). */
1013 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1014 OPTAB_LIB_WIDEN);
cde9d596 1015
47135167
EB
1016 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1017 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1018 OPTAB_LIB_WIDEN);
97286431 1019
47135167
EB
1020 rtx tem;
1021 if (code == PLUS_EXPR)
1022 {
1023 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1024 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1025 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1026 OPTAB_LIB_WIDEN);
1027 }
1028 else
1029 {
1030 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1031 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1032 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1033 OPTAB_LIB_WIDEN);
1034 }
1035
1036 /* No overflow if the result has bit sign cleared. */
1037 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1038 NULL, done_label, PROB_VERY_LIKELY);
cde9d596 1039 }
31e071ae 1040
47135167
EB
1041 /* Compare the result of the operation with the first operand.
1042 No overflow for addition if second operand is positive and result
1043 is larger or second operand is negative and result is smaller.
1044 Likewise for subtraction with sign of second operand flipped. */
1045 else
1046 do_compare_rtx_and_jump (res, op0,
1047 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
cde9d596
RH
1048 false, mode, NULL_RTX, NULL, done_label,
1049 PROB_VERY_LIKELY);
1050 }
31e071ae 1051
1304953e 1052 do_error_label:
1769415d 1053 emit_label (do_error);
1304953e
JJ
1054 if (is_ubsan)
1055 {
1056 /* Expand the ubsan builtin call. */
1057 push_temp_slots ();
1058 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1705cebd 1059 arg0, arg1, datap);
1304953e
JJ
1060 expand_normal (fn);
1061 pop_temp_slots ();
1062 do_pending_stack_adjust ();
1063 }
1064 else if (lhs)
a86451b9 1065 expand_arith_set_overflow (lhs, target);
31e071ae 1066
1769415d
MP
1067 /* We're done. */
1068 emit_label (done_label);
31e071ae
MP
1069
1070 if (lhs)
1304953e
JJ
1071 {
1072 if (is_ubsan)
5620052d 1073 expand_ubsan_result_store (target, res);
1304953e
JJ
1074 else
1075 {
1076 if (do_xor)
1077 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1078 OPTAB_LIB_WIDEN);
1079
1080 expand_arith_overflow_result_store (lhs, target, mode, res);
1081 }
1082 }
31e071ae
MP
1083}
1084
1085/* Add negate overflow checking to the statement STMT. */
1086
1304953e 1087static void
1705cebd
JJ
1088expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1089 tree *datap)
31e071ae
MP
1090{
1091 rtx res, op1;
1304953e 1092 tree fn;
da664544
DM
1093 rtx_code_label *done_label, *do_error;
1094 rtx target = NULL_RTX;
31e071ae 1095
31e071ae
MP
1096 done_label = gen_label_rtx ();
1097 do_error = gen_label_rtx ();
31e071ae
MP
1098
1099 do_pending_stack_adjust ();
1100 op1 = expand_normal (arg1);
1101
ef4bddc2 1102 machine_mode mode = TYPE_MODE (TREE_TYPE (arg1));
31e071ae 1103 if (lhs)
1304953e
JJ
1104 {
1105 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1106 if (!is_ubsan)
1107 write_complex_part (target, const0_rtx, true);
1108 }
31e071ae
MP
1109
1110 enum insn_code icode = optab_handler (negv3_optab, mode);
1111 if (icode != CODE_FOR_nothing)
1112 {
1113 struct expand_operand ops[3];
da664544 1114 rtx_insn *last = get_last_insn ();
31e071ae
MP
1115
1116 res = gen_reg_rtx (mode);
1117 create_output_operand (&ops[0], res, mode);
1118 create_input_operand (&ops[1], op1, mode);
1119 create_fixed_operand (&ops[2], do_error);
1120 if (maybe_expand_insn (icode, 3, ops))
1121 {
1122 last = get_last_insn ();
0a6a6ac9 1123 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
31e071ae
MP
1124 && JUMP_P (last)
1125 && any_condjump_p (last)
1126 && !find_reg_note (last, REG_BR_PROB, 0))
1127 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
1128 emit_jump (done_label);
1129 }
1130 else
1131 {
1132 delete_insns_since (last);
1133 icode = CODE_FOR_nothing;
1134 }
1135 }
1136
1137 if (icode == CODE_FOR_nothing)
1138 {
1139 /* Compute the operation. On RTL level, the addition is always
1140 unsigned. */
1141 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1142
1143 /* Compare the operand with the most negative value. */
1144 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1476d1bd 1145 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
31e071ae
MP
1146 done_label, PROB_VERY_LIKELY);
1147 }
1148
1149 emit_label (do_error);
1304953e
JJ
1150 if (is_ubsan)
1151 {
1152 /* Expand the ubsan builtin call. */
1153 push_temp_slots ();
1154 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1705cebd 1155 arg1, NULL_TREE, datap);
1304953e
JJ
1156 expand_normal (fn);
1157 pop_temp_slots ();
1158 do_pending_stack_adjust ();
1159 }
1160 else if (lhs)
a86451b9 1161 expand_arith_set_overflow (lhs, target);
31e071ae
MP
1162
1163 /* We're done. */
1164 emit_label (done_label);
1165
1166 if (lhs)
1304953e
JJ
1167 {
1168 if (is_ubsan)
5620052d 1169 expand_ubsan_result_store (target, res);
1304953e
JJ
1170 else
1171 expand_arith_overflow_result_store (lhs, target, mode, res);
1172 }
31e071ae
MP
1173}
1174
1175/* Add mul overflow checking to the statement STMT. */
1176
1304953e
JJ
1177static void
1178expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1705cebd
JJ
1179 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1180 tree *datap)
31e071ae
MP
1181{
1182 rtx res, op0, op1;
1304953e 1183 tree fn, type;
da664544
DM
1184 rtx_code_label *done_label, *do_error;
1185 rtx target = NULL_RTX;
1304953e
JJ
1186 signop sign;
1187 enum insn_code icode;
31e071ae 1188
31e071ae
MP
1189 done_label = gen_label_rtx ();
1190 do_error = gen_label_rtx ();
31e071ae
MP
1191
1192 do_pending_stack_adjust ();
1193 op0 = expand_normal (arg0);
1194 op1 = expand_normal (arg1);
1195
ef4bddc2 1196 machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
1304953e 1197 bool uns = unsr_p;
31e071ae 1198 if (lhs)
1304953e
JJ
1199 {
1200 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1201 if (!is_ubsan)
1202 write_complex_part (target, const0_rtx, true);
1203 }
1204
1205 if (is_ubsan)
1206 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1207
1208 /* We assume both operands and result have the same precision
1209 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1210 with that precision, U for unsigned type with that precision,
1211 sgn for unsigned most significant bit in that precision.
1212 s1 is signed first operand, u1 is unsigned first operand,
1213 s2 is signed second operand, u2 is unsigned second operand,
1214 sr is signed result, ur is unsigned result and the following
1215 rules say how to compute result (which is always result of
1216 the operands as if both were unsigned, cast to the right
1217 signedness) and how to compute whether operation overflowed.
1218 main_ovf (false) stands for jump on signed multiplication
1219 overflow or the main algorithm with uns == false.
1220 main_ovf (true) stands for jump on unsigned multiplication
1221 overflow or the main algorithm with uns == true.
1222
1223 s1 * s2 -> sr
1224 res = (S) ((U) s1 * (U) s2)
1225 ovf = main_ovf (false)
1226 u1 * u2 -> ur
1227 res = u1 * u2
1228 ovf = main_ovf (true)
1229 s1 * u2 -> ur
1230 res = (U) s1 * u2
1231 ovf = (s1 < 0 && u2) || main_ovf (true)
1232 u1 * u2 -> sr
1233 res = (S) (u1 * u2)
1234 ovf = res < 0 || main_ovf (true)
1235 s1 * u2 -> sr
1236 res = (S) ((U) s1 * u2)
1237 ovf = (S) u2 >= 0 ? main_ovf (false)
1238 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1239 s1 * s2 -> ur
1240 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1241 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1242 res = t1 * t2
1243 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1244
1245 if (uns0_p && !uns1_p)
1246 {
1247 /* Multiplication is commutative, if operand signedness differs,
1248 canonicalize to the first operand being signed and second
1249 unsigned to simplify following code. */
6b4db501
MM
1250 std::swap (op0, op1);
1251 std::swap (arg0, arg1);
1252 uns0_p = false;
1253 uns1_p = true;
1304953e
JJ
1254 }
1255
1256 int pos_neg0 = get_range_pos_neg (arg0);
1257 int pos_neg1 = get_range_pos_neg (arg1);
1258
1259 /* s1 * u2 -> ur */
1260 if (!uns0_p && uns1_p && unsr_p)
1261 {
1262 switch (pos_neg0)
1263 {
1264 case 1:
1265 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1266 goto do_main;
1267 case 2:
1268 /* If s1 is negative, avoid the main code, just multiply and
1269 signal overflow if op1 is not 0. */
1270 struct separate_ops ops;
1271 ops.code = MULT_EXPR;
1272 ops.type = TREE_TYPE (arg1);
1273 ops.op0 = make_tree (ops.type, op0);
1274 ops.op1 = make_tree (ops.type, op1);
1275 ops.op2 = NULL_TREE;
1276 ops.location = loc;
1277 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
92344ed0 1278 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1279 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
1280 goto do_error_label;
1281 case 3:
1282 rtx_code_label *do_main_label;
1283 do_main_label = gen_label_rtx ();
92344ed0 1284 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1285 NULL, do_main_label, PROB_VERY_LIKELY);
92344ed0 1286 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1287 NULL, do_main_label, PROB_VERY_LIKELY);
a86451b9 1288 expand_arith_set_overflow (lhs, target);
1304953e
JJ
1289 emit_label (do_main_label);
1290 goto do_main;
1291 default:
1292 gcc_unreachable ();
1293 }
1294 }
1295
1296 /* u1 * u2 -> sr */
1297 if (uns0_p && uns1_p && !unsr_p)
1298 {
1299 uns = true;
1300 /* Rest of handling of this case after res is computed. */
1301 goto do_main;
1302 }
1303
1304 /* s1 * u2 -> sr */
1305 if (!uns0_p && uns1_p && !unsr_p)
1306 {
1307 switch (pos_neg1)
1308 {
1309 case 1:
1310 goto do_main;
1311 case 2:
1312 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1313 avoid the main code, just multiply and signal overflow
1314 unless 0 * u2 or -1 * ((U) Smin). */
1315 struct separate_ops ops;
1316 ops.code = MULT_EXPR;
1317 ops.type = TREE_TYPE (arg1);
1318 ops.op0 = make_tree (ops.type, op0);
1319 ops.op1 = make_tree (ops.type, op1);
1320 ops.op2 = NULL_TREE;
1321 ops.location = loc;
1322 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
92344ed0 1323 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1324 NULL, done_label, PROB_VERY_LIKELY);
92344ed0 1325 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1476d1bd 1326 NULL, do_error, PROB_VERY_UNLIKELY);
1304953e
JJ
1327 int prec;
1328 prec = GET_MODE_PRECISION (mode);
1329 rtx sgn;
1330 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
92344ed0 1331 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1476d1bd 1332 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
1333 goto do_error_label;
1334 case 3:
1335 /* Rest of handling of this case after res is computed. */
1336 goto do_main;
1337 default:
1338 gcc_unreachable ();
1339 }
1340 }
31e071ae 1341
1304953e
JJ
1342 /* s1 * s2 -> ur */
1343 if (!uns0_p && !uns1_p && unsr_p)
1344 {
1345 rtx tem, tem2;
1346 switch (pos_neg0 | pos_neg1)
1347 {
1348 case 1: /* Both operands known to be non-negative. */
1349 goto do_main;
1350 case 2: /* Both operands known to be negative. */
1351 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1352 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1353 /* Avoid looking at arg0/arg1 ranges, as we've changed
1354 the arguments. */
1355 arg0 = error_mark_node;
1356 arg1 = error_mark_node;
1357 goto do_main;
1358 case 3:
1359 if ((pos_neg0 ^ pos_neg1) == 3)
1360 {
1361 /* If one operand is known to be negative and the other
1362 non-negative, this overflows always, unless the non-negative
1363 one is 0. Just do normal multiply and set overflow
1364 unless one of the operands is 0. */
1365 struct separate_ops ops;
1366 ops.code = MULT_EXPR;
1367 ops.type
1368 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1369 1);
1370 ops.op0 = make_tree (ops.type, op0);
1371 ops.op1 = make_tree (ops.type, op1);
1372 ops.op2 = NULL_TREE;
1373 ops.location = loc;
1374 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1375 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1376 OPTAB_LIB_WIDEN);
92344ed0 1377 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
1476d1bd 1378 NULL_RTX, NULL, done_label,
92344ed0 1379 PROB_VERY_LIKELY);
1304953e
JJ
1380 goto do_error_label;
1381 }
1382 /* The general case, do all the needed comparisons at runtime. */
1383 rtx_code_label *do_main_label, *after_negate_label;
1384 rtx rop0, rop1;
1385 rop0 = gen_reg_rtx (mode);
1386 rop1 = gen_reg_rtx (mode);
1387 emit_move_insn (rop0, op0);
1388 emit_move_insn (rop1, op1);
1389 op0 = rop0;
1390 op1 = rop1;
1391 do_main_label = gen_label_rtx ();
1392 after_negate_label = gen_label_rtx ();
1393 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1394 OPTAB_LIB_WIDEN);
92344ed0 1395 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1396 NULL, after_negate_label, PROB_VERY_LIKELY);
1304953e
JJ
1397 /* Both arguments negative here, negate them and continue with
1398 normal unsigned overflow checking multiplication. */
1399 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1400 NULL_RTX, false));
1401 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1402 NULL_RTX, false));
1403 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1404 the arguments. */
1405 arg0 = error_mark_node;
1406 arg1 = error_mark_node;
1407 emit_jump (do_main_label);
1408 emit_label (after_negate_label);
1409 tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1410 OPTAB_LIB_WIDEN);
92344ed0 1411 do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1412 NULL, do_main_label, PROB_VERY_LIKELY);
1304953e
JJ
1413 /* One argument is negative here, the other positive. This
1414 overflows always, unless one of the arguments is 0. But
1415 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1416 is, thus we can keep do_main code oring in overflow as is. */
92344ed0 1417 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1418 NULL, do_main_label, PROB_VERY_LIKELY);
a86451b9 1419 expand_arith_set_overflow (lhs, target);
1304953e
JJ
1420 emit_label (do_main_label);
1421 goto do_main;
1422 default:
1423 gcc_unreachable ();
1424 }
1425 }
1426
1427 do_main:
1428 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1429 sign = uns ? UNSIGNED : SIGNED;
1430 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
31e071ae
MP
1431 if (icode != CODE_FOR_nothing)
1432 {
1433 struct expand_operand ops[4];
da664544 1434 rtx_insn *last = get_last_insn ();
31e071ae
MP
1435
1436 res = gen_reg_rtx (mode);
1437 create_output_operand (&ops[0], res, mode);
1438 create_input_operand (&ops[1], op0, mode);
1439 create_input_operand (&ops[2], op1, mode);
1440 create_fixed_operand (&ops[3], do_error);
1441 if (maybe_expand_insn (icode, 4, ops))
1442 {
1443 last = get_last_insn ();
0a6a6ac9 1444 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
31e071ae
MP
1445 && JUMP_P (last)
1446 && any_condjump_p (last)
1447 && !find_reg_note (last, REG_BR_PROB, 0))
1448 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
1449 emit_jump (done_label);
1450 }
1451 else
1452 {
1453 delete_insns_since (last);
1454 icode = CODE_FOR_nothing;
1455 }
1456 }
1457
1458 if (icode == CODE_FOR_nothing)
1459 {
1460 struct separate_ops ops;
1304953e
JJ
1461 int prec = GET_MODE_PRECISION (mode);
1462 machine_mode hmode = mode_for_size (prec / 2, MODE_INT, 1);
1463 ops.op0 = make_tree (type, op0);
1464 ops.op1 = make_tree (type, op1);
31e071ae 1465 ops.op2 = NULL_TREE;
1304953e 1466 ops.location = loc;
31e071ae
MP
1467 if (GET_MODE_2XWIDER_MODE (mode) != VOIDmode
1468 && targetm.scalar_mode_supported_p (GET_MODE_2XWIDER_MODE (mode)))
1469 {
ef4bddc2 1470 machine_mode wmode = GET_MODE_2XWIDER_MODE (mode);
31e071ae
MP
1471 ops.code = WIDEN_MULT_EXPR;
1472 ops.type
1304953e 1473 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
31e071ae
MP
1474
1475 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1304953e
JJ
1476 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1477 NULL_RTX, uns);
31e071ae
MP
1478 hipart = gen_lowpart (mode, hipart);
1479 res = gen_lowpart (mode, res);
1304953e
JJ
1480 if (uns)
1481 /* For the unsigned multiplication, there was overflow if
1482 HIPART is non-zero. */
92344ed0 1483 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1476d1bd 1484 NULL_RTX, NULL, done_label,
92344ed0 1485 PROB_VERY_LIKELY);
1304953e
JJ
1486 else
1487 {
1488 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1489 NULL_RTX, 0);
1490 /* RES is low half of the double width result, HIPART
1491 the high half. There was overflow if
1492 HIPART is different from RES < 0 ? -1 : 0. */
92344ed0 1493 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1476d1bd 1494 NULL_RTX, NULL, done_label,
92344ed0 1495 PROB_VERY_LIKELY);
1304953e 1496 }
31e071ae 1497 }
1304953e 1498 else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
d5fa9cc9 1499 {
da664544
DM
1500 rtx_code_label *large_op0 = gen_label_rtx ();
1501 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1502 rtx_code_label *one_small_one_large = gen_label_rtx ();
1503 rtx_code_label *both_ops_large = gen_label_rtx ();
1304953e
JJ
1504 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1505 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
da664544 1506 rtx_code_label *do_overflow = gen_label_rtx ();
1304953e 1507 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
d5fa9cc9 1508
807e902e 1509 unsigned int hprec = GET_MODE_PRECISION (hmode);
d5fa9cc9 1510 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1304953e 1511 NULL_RTX, uns);
d5fa9cc9
JJ
1512 hipart0 = gen_lowpart (hmode, hipart0);
1513 rtx lopart0 = gen_lowpart (hmode, op0);
1304953e
JJ
1514 rtx signbit0 = const0_rtx;
1515 if (!uns)
1516 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1517 NULL_RTX, 0);
d5fa9cc9 1518 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1304953e 1519 NULL_RTX, uns);
d5fa9cc9
JJ
1520 hipart1 = gen_lowpart (hmode, hipart1);
1521 rtx lopart1 = gen_lowpart (hmode, op1);
1304953e
JJ
1522 rtx signbit1 = const0_rtx;
1523 if (!uns)
1524 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1525 NULL_RTX, 0);
d5fa9cc9
JJ
1526
1527 res = gen_reg_rtx (mode);
1528
1529 /* True if op0 resp. op1 are known to be in the range of
1530 halfstype. */
1531 bool op0_small_p = false;
1532 bool op1_small_p = false;
1533 /* True if op0 resp. op1 are known to have all zeros or all ones
1534 in the upper half of bits, but are not known to be
1535 op{0,1}_small_p. */
1536 bool op0_medium_p = false;
1537 bool op1_medium_p = false;
1538 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
1539 nonnegative, 1 if unknown. */
1540 int op0_sign = 1;
1541 int op1_sign = 1;
1542
1304953e
JJ
1543 if (pos_neg0 == 1)
1544 op0_sign = 0;
1545 else if (pos_neg0 == 2)
1546 op0_sign = -1;
1547 if (pos_neg1 == 1)
1548 op1_sign = 0;
1549 else if (pos_neg1 == 2)
1550 op1_sign = -1;
1551
1552 unsigned int mprec0 = prec;
1553 if (arg0 != error_mark_node)
1554 mprec0 = get_min_precision (arg0, sign);
1555 if (mprec0 <= hprec)
1556 op0_small_p = true;
1557 else if (!uns && mprec0 <= hprec + 1)
1558 op0_medium_p = true;
1559 unsigned int mprec1 = prec;
1560 if (arg1 != error_mark_node)
1561 mprec1 = get_min_precision (arg1, sign);
1562 if (mprec1 <= hprec)
1563 op1_small_p = true;
1564 else if (!uns && mprec1 <= hprec + 1)
1565 op1_medium_p = true;
d5fa9cc9
JJ
1566
1567 int smaller_sign = 1;
1568 int larger_sign = 1;
1569 if (op0_small_p)
1570 {
1571 smaller_sign = op0_sign;
1572 larger_sign = op1_sign;
1573 }
1574 else if (op1_small_p)
1575 {
1576 smaller_sign = op1_sign;
1577 larger_sign = op0_sign;
1578 }
1579 else if (op0_sign == op1_sign)
1580 {
1581 smaller_sign = op0_sign;
1582 larger_sign = op0_sign;
1583 }
1584
1585 if (!op0_small_p)
92344ed0 1586 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1476d1bd 1587 NULL_RTX, NULL, large_op0,
92344ed0 1588 PROB_UNLIKELY);
d5fa9cc9
JJ
1589
1590 if (!op1_small_p)
92344ed0 1591 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1476d1bd 1592 NULL_RTX, NULL, small_op0_large_op1,
d5fa9cc9
JJ
1593 PROB_UNLIKELY);
1594
1304953e
JJ
1595 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
1596 hmode to mode, the multiplication will never overflow. We can
1597 do just one hmode x hmode => mode widening multiplication. */
1598 rtx lopart0s = lopart0, lopart1s = lopart1;
d5fa9cc9
JJ
1599 if (GET_CODE (lopart0) == SUBREG)
1600 {
1304953e
JJ
1601 lopart0s = shallow_copy_rtx (lopart0);
1602 SUBREG_PROMOTED_VAR_P (lopart0s) = 1;
1603 SUBREG_PROMOTED_SET (lopart0s, uns ? SRP_UNSIGNED : SRP_SIGNED);
d5fa9cc9
JJ
1604 }
1605 if (GET_CODE (lopart1) == SUBREG)
1606 {
1304953e
JJ
1607 lopart1s = shallow_copy_rtx (lopart1);
1608 SUBREG_PROMOTED_VAR_P (lopart1s) = 1;
1609 SUBREG_PROMOTED_SET (lopart1s, uns ? SRP_UNSIGNED : SRP_SIGNED);
d5fa9cc9 1610 }
1304953e
JJ
1611 tree halfstype = build_nonstandard_integer_type (hprec, uns);
1612 ops.op0 = make_tree (halfstype, lopart0s);
1613 ops.op1 = make_tree (halfstype, lopart1s);
d5fa9cc9 1614 ops.code = WIDEN_MULT_EXPR;
1304953e 1615 ops.type = type;
d5fa9cc9
JJ
1616 rtx thisres
1617 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1618 emit_move_insn (res, thisres);
1619 emit_jump (done_label);
1620
1621 emit_label (small_op0_large_op1);
1622
1304953e
JJ
1623 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
1624 but op1 is not, just swap the arguments and handle it as op1
1625 sign/zero extended, op0 not. */
d5fa9cc9
JJ
1626 rtx larger = gen_reg_rtx (mode);
1627 rtx hipart = gen_reg_rtx (hmode);
1628 rtx lopart = gen_reg_rtx (hmode);
1629 emit_move_insn (larger, op1);
1630 emit_move_insn (hipart, hipart1);
1631 emit_move_insn (lopart, lopart0);
1632 emit_jump (one_small_one_large);
1633
1634 emit_label (large_op0);
1635
1636 if (!op1_small_p)
92344ed0 1637 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1476d1bd 1638 NULL_RTX, NULL, both_ops_large,
92344ed0 1639 PROB_UNLIKELY);
d5fa9cc9 1640
1304953e
JJ
1641 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
1642 but op0 is not, prepare larger, hipart and lopart pseudos and
1643 handle it together with small_op0_large_op1. */
d5fa9cc9
JJ
1644 emit_move_insn (larger, op0);
1645 emit_move_insn (hipart, hipart0);
1646 emit_move_insn (lopart, lopart1);
1647
1648 emit_label (one_small_one_large);
1649
1650 /* lopart is the low part of the operand that is sign extended
026c3cfd 1651 to mode, larger is the other operand, hipart is the
d5fa9cc9
JJ
1652 high part of larger and lopart0 and lopart1 are the low parts
1653 of both operands.
1654 We perform lopart0 * lopart1 and lopart * hipart widening
1655 multiplications. */
1656 tree halfutype = build_nonstandard_integer_type (hprec, 1);
1657 ops.op0 = make_tree (halfutype, lopart0);
1658 ops.op1 = make_tree (halfutype, lopart1);
1659 rtx lo0xlo1
1660 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1661
1662 ops.op0 = make_tree (halfutype, lopart);
1663 ops.op1 = make_tree (halfutype, hipart);
1664 rtx loxhi = gen_reg_rtx (mode);
1665 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1666 emit_move_insn (loxhi, tem);
1667
1304953e
JJ
1668 if (!uns)
1669 {
1670 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
1671 if (larger_sign == 0)
1672 emit_jump (after_hipart_neg);
1673 else if (larger_sign != -1)
92344ed0 1674 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1476d1bd 1675 NULL_RTX, NULL, after_hipart_neg,
1304953e
JJ
1676 PROB_EVEN);
1677
1678 tem = convert_modes (mode, hmode, lopart, 1);
1679 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
1680 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
1681 1, OPTAB_DIRECT);
1682 emit_move_insn (loxhi, tem);
1683
1684 emit_label (after_hipart_neg);
1685
1686 /* if (lopart < 0) loxhi -= larger; */
1687 if (smaller_sign == 0)
1688 emit_jump (after_lopart_neg);
1689 else if (smaller_sign != -1)
92344ed0 1690 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1476d1bd 1691 NULL_RTX, NULL, after_lopart_neg,
1304953e
JJ
1692 PROB_EVEN);
1693
1694 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1695 1, OPTAB_DIRECT);
1696 emit_move_insn (loxhi, tem);
1697
1698 emit_label (after_lopart_neg);
1699 }
d5fa9cc9
JJ
1700
1701 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
1702 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
1703 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
1704 1, OPTAB_DIRECT);
1705 emit_move_insn (loxhi, tem);
1706
1707 /* if (loxhi >> (bitsize / 2)
1304953e
JJ
1708 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
1709 if (loxhi >> (bitsize / 2) == 0 (if uns). */
d5fa9cc9
JJ
1710 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
1711 NULL_RTX, 0);
1712 hipartloxhi = gen_lowpart (hmode, hipartloxhi);
1304953e
JJ
1713 rtx signbitloxhi = const0_rtx;
1714 if (!uns)
1715 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
1716 gen_lowpart (hmode, loxhi),
1717 hprec - 1, NULL_RTX, 0);
d5fa9cc9 1718
92344ed0 1719 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1476d1bd 1720 NULL_RTX, NULL, do_overflow,
d5fa9cc9
JJ
1721 PROB_VERY_UNLIKELY);
1722
1723 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
1724 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
1725 NULL_RTX, 1);
1726 tem = convert_modes (mode, hmode, gen_lowpart (hmode, lo0xlo1), 1);
1727
1728 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
1729 1, OPTAB_DIRECT);
1730 if (tem != res)
1731 emit_move_insn (res, tem);
1732 emit_jump (done_label);
1733
1734 emit_label (both_ops_large);
1735
1304953e
JJ
1736 /* If both operands are large (not sign (!uns) or zero (uns)
1737 extended from hmode), then perform the full multiplication
1738 which will be the result of the operation.
1739 The only cases which don't overflow are for signed multiplication
1740 some cases where both hipart0 and highpart1 are 0 or -1.
1741 For unsigned multiplication when high parts are both non-zero
1742 this overflows always. */
d5fa9cc9 1743 ops.code = MULT_EXPR;
1304953e
JJ
1744 ops.op0 = make_tree (type, op0);
1745 ops.op1 = make_tree (type, op1);
d5fa9cc9
JJ
1746 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1747 emit_move_insn (res, tem);
1748
1304953e 1749 if (!uns)
d5fa9cc9 1750 {
1304953e
JJ
1751 if (!op0_medium_p)
1752 {
1753 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
1754 NULL_RTX, 1, OPTAB_DIRECT);
92344ed0 1755 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1476d1bd 1756 NULL_RTX, NULL, do_error,
1304953e
JJ
1757 PROB_VERY_UNLIKELY);
1758 }
d5fa9cc9 1759
1304953e
JJ
1760 if (!op1_medium_p)
1761 {
1762 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
1763 NULL_RTX, 1, OPTAB_DIRECT);
92344ed0 1764 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1476d1bd 1765 NULL_RTX, NULL, do_error,
1304953e
JJ
1766 PROB_VERY_UNLIKELY);
1767 }
d5fa9cc9 1768
1304953e
JJ
1769 /* At this point hipart{0,1} are both in [-1, 0]. If they are
1770 the same, overflow happened if res is negative, if they are
1771 different, overflow happened if res is positive. */
1772 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
1773 emit_jump (hipart_different);
1774 else if (op0_sign == 1 || op1_sign == 1)
92344ed0 1775 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1476d1bd 1776 NULL_RTX, NULL, hipart_different,
92344ed0 1777 PROB_EVEN);
d5fa9cc9 1778
92344ed0 1779 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
1476d1bd 1780 NULL_RTX, NULL, do_error,
92344ed0 1781 PROB_VERY_UNLIKELY);
1304953e 1782 emit_jump (done_label);
d5fa9cc9 1783
1304953e
JJ
1784 emit_label (hipart_different);
1785
92344ed0 1786 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1476d1bd 1787 NULL_RTX, NULL, do_error,
92344ed0 1788 PROB_VERY_UNLIKELY);
1304953e
JJ
1789 emit_jump (done_label);
1790 }
d5fa9cc9
JJ
1791
1792 emit_label (do_overflow);
1793
1794 /* Overflow, do full multiplication and fallthru into do_error. */
1304953e
JJ
1795 ops.op0 = make_tree (type, op0);
1796 ops.op1 = make_tree (type, op1);
d5fa9cc9
JJ
1797 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1798 emit_move_insn (res, tem);
1799 }
31e071ae
MP
1800 else
1801 {
1304953e 1802 gcc_assert (!is_ubsan);
31e071ae 1803 ops.code = MULT_EXPR;
1304953e 1804 ops.type = type;
31e071ae
MP
1805 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1806 emit_jump (done_label);
1807 }
1808 }
1809
1304953e 1810 do_error_label:
31e071ae 1811 emit_label (do_error);
1304953e
JJ
1812 if (is_ubsan)
1813 {
1814 /* Expand the ubsan builtin call. */
1815 push_temp_slots ();
1816 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1705cebd 1817 arg0, arg1, datap);
1304953e
JJ
1818 expand_normal (fn);
1819 pop_temp_slots ();
1820 do_pending_stack_adjust ();
1821 }
1822 else if (lhs)
a86451b9 1823 expand_arith_set_overflow (lhs, target);
31e071ae
MP
1824
1825 /* We're done. */
1826 emit_label (done_label);
1827
1304953e
JJ
1828 /* u1 * u2 -> sr */
1829 if (uns0_p && uns1_p && !unsr_p)
1830 {
1831 rtx_code_label *all_done_label = gen_label_rtx ();
92344ed0 1832 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1833 NULL, all_done_label, PROB_VERY_LIKELY);
a86451b9 1834 expand_arith_set_overflow (lhs, target);
1304953e
JJ
1835 emit_label (all_done_label);
1836 }
1837
1838 /* s1 * u2 -> sr */
1839 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
1840 {
1841 rtx_code_label *all_done_label = gen_label_rtx ();
1842 rtx_code_label *set_noovf = gen_label_rtx ();
92344ed0 1843 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1844 NULL, all_done_label, PROB_VERY_LIKELY);
a86451b9 1845 expand_arith_set_overflow (lhs, target);
92344ed0 1846 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1847 NULL, set_noovf, PROB_VERY_LIKELY);
92344ed0 1848 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1476d1bd
MM
1849 NULL, all_done_label, PROB_VERY_UNLIKELY);
1850 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
92344ed0 1851 all_done_label, PROB_VERY_UNLIKELY);
1304953e
JJ
1852 emit_label (set_noovf);
1853 write_complex_part (target, const0_rtx, true);
1854 emit_label (all_done_label);
1855 }
1856
31e071ae 1857 if (lhs)
1304953e
JJ
1858 {
1859 if (is_ubsan)
5620052d 1860 expand_ubsan_result_store (target, res);
1304953e
JJ
1861 else
1862 expand_arith_overflow_result_store (lhs, target, mode, res);
1863 }
31e071ae
MP
1864}
1865
1705cebd
JJ
1866/* Expand UBSAN_CHECK_* internal function if it has vector operands. */
1867
1868static void
1869expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
1870 tree arg0, tree arg1)
1871{
1872 int cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
1873 rtx_code_label *loop_lab = NULL;
1874 rtx cntvar = NULL_RTX;
1875 tree cntv = NULL_TREE;
1876 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
1877 tree sz = TYPE_SIZE (eltype);
1878 tree data = NULL_TREE;
1879 tree resv = NULL_TREE;
1880 rtx lhsr = NULL_RTX;
1881 rtx resvr = NULL_RTX;
1882
1883 if (lhs)
1884 {
1885 optab op;
1886 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1887 if (GET_MODE (lhsr) == BLKmode
1888 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
1889 optab_default)) == unknown_optab
1890 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
1891 == CODE_FOR_nothing))
1892 {
1893 if (MEM_P (lhsr))
1894 resv = make_tree (TREE_TYPE (lhs), lhsr);
1895 else
1896 {
1897 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
1898 resv = make_tree (TREE_TYPE (lhs), resvr);
1899 }
1900 }
1901 }
1902 if (cnt > 4)
1903 {
1904 do_pending_stack_adjust ();
1905 loop_lab = gen_label_rtx ();
1906 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
1907 cntv = make_tree (sizetype, cntvar);
1908 emit_move_insn (cntvar, const0_rtx);
1909 emit_label (loop_lab);
1910 }
1911 if (TREE_CODE (arg0) != VECTOR_CST)
1912 {
1913 rtx arg0r = expand_normal (arg0);
1914 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
1915 }
1916 if (TREE_CODE (arg1) != VECTOR_CST)
1917 {
1918 rtx arg1r = expand_normal (arg1);
1919 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
1920 }
1921 for (int i = 0; i < (cnt > 4 ? 1 : cnt); i++)
1922 {
1923 tree op0, op1, res = NULL_TREE;
1924 if (cnt > 4)
1925 {
1926 tree atype = build_array_type_nelts (eltype, cnt);
1927 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
1928 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
1929 NULL_TREE, NULL_TREE);
1930 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
1931 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
1932 NULL_TREE, NULL_TREE);
1933 if (resv)
1934 {
1935 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
1936 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
1937 NULL_TREE, NULL_TREE);
1938 }
1939 }
1940 else
1941 {
1942 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
1943 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
1944 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
1945 if (resv)
1946 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
1947 bitpos);
1948 }
1949 switch (code)
1950 {
1951 case PLUS_EXPR:
1952 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
1953 false, false, false, true, &data);
1954 break;
1955 case MINUS_EXPR:
1956 if (cnt > 4 ? integer_zerop (arg0) : integer_zerop (op0))
1957 expand_neg_overflow (loc, res, op1, true, &data);
1958 else
1959 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
1960 false, false, false, true, &data);
1961 break;
1962 case MULT_EXPR:
1963 expand_mul_overflow (loc, res, op0, op1, false, false, false,
1964 true, &data);
1965 break;
1966 default:
1967 gcc_unreachable ();
1968 }
1969 }
1970 if (cnt > 4)
1971 {
1972 struct separate_ops ops;
1973 ops.code = PLUS_EXPR;
1974 ops.type = TREE_TYPE (cntv);
1975 ops.op0 = cntv;
1976 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
1977 ops.op2 = NULL_TREE;
1978 ops.location = loc;
1979 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
1980 EXPAND_NORMAL);
1981 if (ret != cntvar)
1982 emit_move_insn (cntvar, ret);
1983 do_compare_rtx_and_jump (cntvar, GEN_INT (cnt), NE, false,
1984 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
1985 PROB_VERY_LIKELY);
1986 }
1987 if (lhs && resv == NULL_TREE)
1988 {
1989 struct separate_ops ops;
1990 ops.code = code;
1991 ops.type = TREE_TYPE (arg0);
1992 ops.op0 = arg0;
1993 ops.op1 = arg1;
1994 ops.op2 = NULL_TREE;
1995 ops.location = loc;
1996 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
1997 EXPAND_NORMAL);
1998 if (ret != lhsr)
1999 emit_move_insn (lhsr, ret);
2000 }
2001 else if (resvr)
2002 emit_move_insn (lhsr, resvr);
2003}
2004
31e071ae
MP
2005/* Expand UBSAN_CHECK_ADD call STMT. */
2006
2007static void
4cfe7a6c 2008expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
31e071ae 2009{
1304953e
JJ
2010 location_t loc = gimple_location (stmt);
2011 tree lhs = gimple_call_lhs (stmt);
2012 tree arg0 = gimple_call_arg (stmt, 0);
2013 tree arg1 = gimple_call_arg (stmt, 1);
1705cebd
JJ
2014 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2015 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2016 else
2017 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2018 false, false, false, true, NULL);
31e071ae
MP
2019}
2020
2021/* Expand UBSAN_CHECK_SUB call STMT. */
2022
2023static void
4cfe7a6c 2024expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
31e071ae 2025{
1304953e
JJ
2026 location_t loc = gimple_location (stmt);
2027 tree lhs = gimple_call_lhs (stmt);
2028 tree arg0 = gimple_call_arg (stmt, 0);
2029 tree arg1 = gimple_call_arg (stmt, 1);
1705cebd
JJ
2030 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2031 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2032 else if (integer_zerop (arg0))
2033 expand_neg_overflow (loc, lhs, arg1, true, NULL);
31e071ae 2034 else
1304953e 2035 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
1705cebd 2036 false, false, false, true, NULL);
31e071ae
MP
2037}
2038
2039/* Expand UBSAN_CHECK_MUL call STMT. */
2040
2041static void
4cfe7a6c 2042expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
31e071ae 2043{
1304953e
JJ
2044 location_t loc = gimple_location (stmt);
2045 tree lhs = gimple_call_lhs (stmt);
2046 tree arg0 = gimple_call_arg (stmt, 0);
2047 tree arg1 = gimple_call_arg (stmt, 1);
1705cebd
JJ
2048 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2049 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2050 else
2051 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2052 NULL);
1304953e
JJ
2053}
2054
2055/* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2056
2057static void
355fe088 2058expand_arith_overflow (enum tree_code code, gimple *stmt)
1304953e
JJ
2059{
2060 tree lhs = gimple_call_lhs (stmt);
2061 if (lhs == NULL_TREE)
2062 return;
2063 tree arg0 = gimple_call_arg (stmt, 0);
2064 tree arg1 = gimple_call_arg (stmt, 1);
2065 tree type = TREE_TYPE (TREE_TYPE (lhs));
2066 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2067 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2068 int unsr_p = TYPE_UNSIGNED (type);
2069 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2070 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2071 int precres = TYPE_PRECISION (type);
2072 location_t loc = gimple_location (stmt);
2073 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2074 uns0_p = true;
2075 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2076 uns1_p = true;
2077 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2078 prec0 = MIN (prec0, pr);
2079 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2080 prec1 = MIN (prec1, pr);
2081
2082 /* If uns0_p && uns1_p, precop is minimum needed precision
2083 of unsigned type to hold the exact result, otherwise
2084 precop is minimum needed precision of signed type to
2085 hold the exact result. */
2086 int precop;
2087 if (code == MULT_EXPR)
2088 precop = prec0 + prec1 + (uns0_p != uns1_p);
2089 else
2090 {
2091 if (uns0_p == uns1_p)
2092 precop = MAX (prec0, prec1) + 1;
2093 else if (uns0_p)
2094 precop = MAX (prec0 + 1, prec1) + 1;
2095 else
2096 precop = MAX (prec0, prec1 + 1) + 1;
2097 }
2098 int orig_precres = precres;
2099
2100 do
2101 {
2102 if ((uns0_p && uns1_p)
2103 ? ((precop + !unsr_p) <= precres
2104 /* u1 - u2 -> ur can overflow, no matter what precision
2105 the result has. */
2106 && (code != MINUS_EXPR || !unsr_p))
2107 : (!unsr_p && precop <= precres))
2108 {
2109 /* The infinity precision result will always fit into result. */
2110 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2111 write_complex_part (target, const0_rtx, true);
2112 enum machine_mode mode = TYPE_MODE (type);
2113 struct separate_ops ops;
2114 ops.code = code;
2115 ops.type = type;
2116 ops.op0 = fold_convert_loc (loc, type, arg0);
2117 ops.op1 = fold_convert_loc (loc, type, arg1);
2118 ops.op2 = NULL_TREE;
2119 ops.location = loc;
2120 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2121 expand_arith_overflow_result_store (lhs, target, mode, tem);
2122 return;
2123 }
2124
894d8b41
EB
2125 /* For operations with low precision, if target doesn't have them, start
2126 with precres widening right away, otherwise do it only if the most
2127 simple cases can't be used. */
2128 const int min_precision = targetm.min_arithmetic_precision ();
2129 if (orig_precres == precres && precres < min_precision)
1304953e 2130 ;
9e11bfef
TS
2131 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2132 && prec1 <= precres)
1304953e
JJ
2133 || ((!uns0_p || !uns1_p) && !unsr_p
2134 && prec0 + uns0_p <= precres
2135 && prec1 + uns1_p <= precres))
2136 {
2137 arg0 = fold_convert_loc (loc, type, arg0);
2138 arg1 = fold_convert_loc (loc, type, arg1);
2139 switch (code)
2140 {
2141 case MINUS_EXPR:
2142 if (integer_zerop (arg0) && !unsr_p)
7d704548 2143 {
1705cebd 2144 expand_neg_overflow (loc, lhs, arg1, false, NULL);
7d704548
JJ
2145 return;
2146 }
1304953e
JJ
2147 /* FALLTHRU */
2148 case PLUS_EXPR:
1705cebd
JJ
2149 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2150 unsr_p, unsr_p, false, NULL);
1304953e
JJ
2151 return;
2152 case MULT_EXPR:
1705cebd
JJ
2153 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2154 unsr_p, unsr_p, false, NULL);
1304953e
JJ
2155 return;
2156 default:
2157 gcc_unreachable ();
2158 }
2159 }
2160
2161 /* For sub-word operations, retry with a wider type first. */
2162 if (orig_precres == precres && precop <= BITS_PER_WORD)
2163 {
894d8b41 2164 int p = MAX (min_precision, precop);
1304953e
JJ
2165 enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
2166 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2167 uns0_p && uns1_p
2168 && unsr_p);
2169 p = TYPE_PRECISION (optype);
2170 if (p > precres)
2171 {
2172 precres = p;
2173 unsr_p = TYPE_UNSIGNED (optype);
2174 type = optype;
2175 continue;
2176 }
2177 }
2178
2179 if (prec0 <= precres && prec1 <= precres)
2180 {
2181 tree types[2];
2182 if (unsr_p)
2183 {
2184 types[0] = build_nonstandard_integer_type (precres, 0);
2185 types[1] = type;
2186 }
2187 else
2188 {
2189 types[0] = type;
2190 types[1] = build_nonstandard_integer_type (precres, 1);
2191 }
2192 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2193 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2194 if (code != MULT_EXPR)
2195 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
1705cebd 2196 uns0_p, uns1_p, false, NULL);
1304953e
JJ
2197 else
2198 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
1705cebd 2199 uns0_p, uns1_p, false, NULL);
1304953e
JJ
2200 return;
2201 }
2202
2203 /* Retry with a wider type. */
2204 if (orig_precres == precres)
2205 {
2206 int p = MAX (prec0, prec1);
2207 enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
2208 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2209 uns0_p && uns1_p
2210 && unsr_p);
2211 p = TYPE_PRECISION (optype);
2212 if (p > precres)
2213 {
2214 precres = p;
2215 unsr_p = TYPE_UNSIGNED (optype);
2216 type = optype;
2217 continue;
2218 }
2219 }
2220
2221 gcc_unreachable ();
2222 }
2223 while (1);
2224}
2225
2226/* Expand ADD_OVERFLOW STMT. */
2227
2228static void
4cfe7a6c 2229expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
2230{
2231 expand_arith_overflow (PLUS_EXPR, stmt);
2232}
2233
2234/* Expand SUB_OVERFLOW STMT. */
2235
2236static void
4cfe7a6c 2237expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
2238{
2239 expand_arith_overflow (MINUS_EXPR, stmt);
2240}
2241
2242/* Expand MUL_OVERFLOW STMT. */
2243
2244static void
4cfe7a6c 2245expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
2246{
2247 expand_arith_overflow (MULT_EXPR, stmt);
31e071ae
MP
2248}
2249
5ce9450f
JJ
2250/* This should get folded in tree-vectorizer.c. */
2251
2252static void
4cfe7a6c 2253expand_LOOP_VECTORIZED (internal_fn, gcall *)
5ce9450f
JJ
2254{
2255 gcc_unreachable ();
2256}
2257
ab23f5d9
RS
2258/* Expand MASK_LOAD call STMT using optab OPTAB. */
2259
5ce9450f 2260static void
4cfe7a6c 2261expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
5ce9450f
JJ
2262{
2263 struct expand_operand ops[3];
08554c26 2264 tree type, lhs, rhs, maskt, ptr;
5ce9450f 2265 rtx mem, target, mask;
08554c26 2266 unsigned align;
5ce9450f
JJ
2267
2268 maskt = gimple_call_arg (stmt, 2);
2269 lhs = gimple_call_lhs (stmt);
8e91d222
JJ
2270 if (lhs == NULL_TREE)
2271 return;
5ce9450f 2272 type = TREE_TYPE (lhs);
08554c26
JJ
2273 ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
2274 align = tree_to_shwi (gimple_call_arg (stmt, 1));
2275 if (TYPE_ALIGN (type) != align)
2276 type = build_aligned_type (type, align);
2277 rhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
5ce9450f
JJ
2278
2279 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2280 gcc_assert (MEM_P (mem));
2281 mask = expand_normal (maskt);
2282 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2283 create_output_operand (&ops[0], target, TYPE_MODE (type));
2284 create_fixed_operand (&ops[1], mem);
2285 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
ab23f5d9 2286 expand_insn (convert_optab_handler (optab, TYPE_MODE (type),
045c1278
IE
2287 TYPE_MODE (TREE_TYPE (maskt))),
2288 3, ops);
5ce9450f
JJ
2289}
2290
ab23f5d9
RS
2291/* Expand MASK_STORE call STMT using optab OPTAB. */
2292
5ce9450f 2293static void
4cfe7a6c 2294expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
5ce9450f
JJ
2295{
2296 struct expand_operand ops[3];
08554c26 2297 tree type, lhs, rhs, maskt, ptr;
5ce9450f 2298 rtx mem, reg, mask;
08554c26 2299 unsigned align;
5ce9450f
JJ
2300
2301 maskt = gimple_call_arg (stmt, 2);
2302 rhs = gimple_call_arg (stmt, 3);
2303 type = TREE_TYPE (rhs);
08554c26
JJ
2304 ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
2305 align = tree_to_shwi (gimple_call_arg (stmt, 1));
2306 if (TYPE_ALIGN (type) != align)
2307 type = build_aligned_type (type, align);
2308 lhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
5ce9450f
JJ
2309
2310 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2311 gcc_assert (MEM_P (mem));
2312 mask = expand_normal (maskt);
2313 reg = expand_normal (rhs);
2314 create_fixed_operand (&ops[0], mem);
2315 create_input_operand (&ops[1], reg, TYPE_MODE (type));
2316 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
ab23f5d9 2317 expand_insn (convert_optab_handler (optab, TYPE_MODE (type),
045c1278
IE
2318 TYPE_MODE (TREE_TYPE (maskt))),
2319 3, ops);
5ce9450f
JJ
2320}
2321
09b22f48 2322static void
4cfe7a6c 2323expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
09b22f48
JJ
2324{
2325}
2326
ed9c79e1 2327static void
4cfe7a6c 2328expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
ed9c79e1
JJ
2329{
2330 /* When guessing was done, the hints should be already stripped away. */
2331 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
2332
2333 rtx target;
2334 tree lhs = gimple_call_lhs (stmt);
2335 if (lhs)
2336 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2337 else
2338 target = const0_rtx;
2339 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
2340 if (lhs && val != target)
2341 emit_move_insn (target, val);
2342}
2343
f8e89441
TV
2344/* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
2345 should never be called. */
2346
2347static void
4cfe7a6c 2348expand_VA_ARG (internal_fn, gcall *)
f8e89441
TV
2349{
2350 gcc_unreachable ();
2351}
2352
8ab78162
NS
2353/* Expand the IFN_UNIQUE function according to its first argument. */
2354
2355static void
4cfe7a6c 2356expand_UNIQUE (internal_fn, gcall *stmt)
8ab78162
NS
2357{
2358 rtx pattern = NULL_RTX;
2359 enum ifn_unique_kind kind
2360 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
2361
2362 switch (kind)
2363 {
2364 default:
2365 gcc_unreachable ();
2366
2367 case IFN_UNIQUE_UNSPEC:
2368 if (targetm.have_unique ())
2369 pattern = targetm.gen_unique ();
2370 break;
9bd46bc9
NS
2371
2372 case IFN_UNIQUE_OACC_FORK:
2373 case IFN_UNIQUE_OACC_JOIN:
2374 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
2375 {
2376 tree lhs = gimple_call_lhs (stmt);
2377 rtx target = const0_rtx;
2378
2379 if (lhs)
2380 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2381
2382 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
2383 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
2384
2385 if (kind == IFN_UNIQUE_OACC_FORK)
2386 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
2387 else
2388 pattern = targetm.gen_oacc_join (target, data_dep, axis);
2389 }
2390 else
2391 gcc_unreachable ();
2392 break;
8ab78162
NS
2393 }
2394
2395 if (pattern)
2396 emit_insn (pattern);
2397}
2398
9bd46bc9
NS
2399/* The size of an OpenACC compute dimension. */
2400
2401static void
4cfe7a6c 2402expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
9bd46bc9
NS
2403{
2404 tree lhs = gimple_call_lhs (stmt);
2405
2406 if (!lhs)
2407 return;
2408
2409 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2410 if (targetm.have_oacc_dim_size ())
2411 {
2412 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2413 VOIDmode, EXPAND_NORMAL);
2414 emit_insn (targetm.gen_oacc_dim_size (target, dim));
2415 }
2416 else
2417 emit_move_insn (target, GEN_INT (1));
2418}
2419
2420/* The position of an OpenACC execution engine along one compute axis. */
2421
2422static void
4cfe7a6c 2423expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
9bd46bc9
NS
2424{
2425 tree lhs = gimple_call_lhs (stmt);
2426
2427 if (!lhs)
2428 return;
2429
2430 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2431 if (targetm.have_oacc_dim_pos ())
2432 {
2433 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2434 VOIDmode, EXPAND_NORMAL);
2435 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
2436 }
2437 else
2438 emit_move_insn (target, const0_rtx);
2439}
2440
2441/* This is expanded by oacc_device_lower pass. */
2442
2443static void
4cfe7a6c 2444expand_GOACC_LOOP (internal_fn, gcall *)
9bd46bc9
NS
2445{
2446 gcc_unreachable ();
2447}
2448
e5014671
NS
2449/* This is expanded by oacc_device_lower pass. */
2450
2451static void
4cfe7a6c 2452expand_GOACC_REDUCTION (internal_fn, gcall *)
e5014671
NS
2453{
2454 gcc_unreachable ();
2455}
2456
883cabde
RS
2457/* Set errno to EDOM. */
2458
2459static void
2460expand_SET_EDOM (internal_fn, gcall *)
2461{
2462#ifdef TARGET_EDOM
2463#ifdef GEN_ERRNO_RTX
2464 rtx errno_rtx = GEN_ERRNO_RTX;
2465#else
2466 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
2467#endif
2468 emit_move_insn (errno_rtx,
2469 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
2470#else
2471 gcc_unreachable ();
2472#endif
2473}
2474
adedd5c1
JJ
2475/* Expand atomic bit test and set. */
2476
2477static void
2478expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
2479{
2480 expand_ifn_atomic_bit_test_and (call);
2481}
2482
2483/* Expand atomic bit test and complement. */
2484
2485static void
2486expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
2487{
2488 expand_ifn_atomic_bit_test_and (call);
2489}
2490
2491/* Expand atomic bit test and reset. */
2492
2493static void
2494expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
2495{
2496 expand_ifn_atomic_bit_test_and (call);
2497}
2498
849a76a5
JJ
2499/* Expand atomic bit test and set. */
2500
2501static void
2502expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
2503{
2504 expand_ifn_atomic_compare_exchange (call);
2505}
2506
e16f1cc7
JJ
2507/* Expand LAUNDER to assignment, lhs = arg0. */
2508
2509static void
2510expand_LAUNDER (internal_fn, gcall *call)
2511{
2512 tree lhs = gimple_call_lhs (call);
2513
2514 if (!lhs)
2515 return;
2516
2517 expand_assignment (lhs, gimple_call_arg (call, 0), false);
2518}
2519
e72531b9
PK
2520/* Expand DIVMOD() using:
2521 a) optab handler for udivmod/sdivmod if it is available.
2522 b) If optab_handler doesn't exist, generate call to
2523 target-specific divmod libfunc. */
2524
2525static void
2526expand_DIVMOD (internal_fn, gcall *call_stmt)
2527{
2528 tree lhs = gimple_call_lhs (call_stmt);
2529 tree arg0 = gimple_call_arg (call_stmt, 0);
2530 tree arg1 = gimple_call_arg (call_stmt, 1);
2531
2532 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
2533 tree type = TREE_TYPE (TREE_TYPE (lhs));
2534 machine_mode mode = TYPE_MODE (type);
2535 bool unsignedp = TYPE_UNSIGNED (type);
2536 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
2537
2538 rtx op0 = expand_normal (arg0);
2539 rtx op1 = expand_normal (arg1);
2540 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2541
2542 rtx quotient, remainder, libfunc;
2543
2544 /* Check if optab_handler exists for divmod_optab for given mode. */
2545 if (optab_handler (tab, mode) != CODE_FOR_nothing)
2546 {
2547 quotient = gen_reg_rtx (mode);
2548 remainder = gen_reg_rtx (mode);
2549 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
2550 }
2551
2552 /* Generate call to divmod libfunc if it exists. */
2553 else if ((libfunc = optab_libfunc (tab, mode)) != NULL_RTX)
2554 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
2555 &quotient, &remainder);
2556
2557 else
2558 gcc_unreachable ();
2559
2560 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
2561 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
2562 make_tree (TREE_TYPE (arg0), quotient),
2563 make_tree (TREE_TYPE (arg1), remainder)),
2564 target, VOIDmode, EXPAND_NORMAL);
2565}
2566
4cfe7a6c
RS
2567/* Expand a call to FN using the operands in STMT. FN has a single
2568 output operand and NARGS input operands. */
686ee971
RS
2569
2570static void
4cfe7a6c
RS
2571expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
2572 unsigned int nargs)
686ee971
RS
2573{
2574 expand_operand *ops = XALLOCAVEC (expand_operand, nargs + 1);
2575
686ee971
RS
2576 tree_pair types = direct_internal_fn_types (fn, stmt);
2577 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
2578
2579 tree lhs = gimple_call_lhs (stmt);
2580 tree lhs_type = TREE_TYPE (lhs);
2581 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2582 create_output_operand (&ops[0], lhs_rtx, insn_data[icode].operand[0].mode);
2583
2584 for (unsigned int i = 0; i < nargs; ++i)
2585 {
2586 tree rhs = gimple_call_arg (stmt, i);
2587 tree rhs_type = TREE_TYPE (rhs);
2588 rtx rhs_rtx = expand_normal (rhs);
2589 if (INTEGRAL_TYPE_P (rhs_type))
2590 create_convert_operand_from (&ops[i + 1], rhs_rtx,
2591 TYPE_MODE (rhs_type),
2592 TYPE_UNSIGNED (rhs_type));
2593 else
2594 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type));
2595 }
2596
2597 expand_insn (icode, nargs + 1, ops);
2598 if (!rtx_equal_p (lhs_rtx, ops[0].value))
2599 {
ee132692
RS
2600 /* If the return value has an integral type, convert the instruction
2601 result to that type. This is useful for things that return an
2602 int regardless of the size of the input. If the instruction result
2603 is smaller than required, assume that it is signed.
2604
2605 If the return value has a nonintegral type, its mode must match
2606 the instruction result. */
2607 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
2608 {
2609 /* If this is a scalar in a register that is stored in a wider
2610 mode than the declared mode, compute the result into its
2611 declared mode and then convert to the wider mode. */
2612 gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2613 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
2614 convert_move (SUBREG_REG (lhs_rtx), tmp,
2615 SUBREG_PROMOTED_SIGN (lhs_rtx));
2616 }
2617 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
686ee971 2618 emit_move_insn (lhs_rtx, ops[0].value);
ee132692
RS
2619 else
2620 {
2621 gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2622 convert_move (lhs_rtx, ops[0].value, 0);
2623 }
686ee971
RS
2624 }
2625}
2626
2627/* Expanders for optabs that can use expand_direct_optab_fn. */
2628
4cfe7a6c
RS
2629#define expand_unary_optab_fn(FN, STMT, OPTAB) \
2630 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
686ee971 2631
4cfe7a6c
RS
2632#define expand_binary_optab_fn(FN, STMT, OPTAB) \
2633 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
686ee971 2634
ab23f5d9
RS
2635/* RETURN_TYPE and ARGS are a return type and argument list that are
2636 in principle compatible with FN (which satisfies direct_internal_fn_p).
2637 Return the types that should be used to determine whether the
2638 target supports FN. */
2639
2640tree_pair
2641direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
2642{
2643 const direct_internal_fn_info &info = direct_internal_fn (fn);
2644 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
2645 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
2646 return tree_pair (type0, type1);
2647}
2648
2649/* CALL is a call whose return type and arguments are in principle
2650 compatible with FN (which satisfies direct_internal_fn_p). Return the
2651 types that should be used to determine whether the target supports FN. */
2652
2653tree_pair
2654direct_internal_fn_types (internal_fn fn, gcall *call)
2655{
2656 const direct_internal_fn_info &info = direct_internal_fn (fn);
2657 tree op0 = (info.type0 < 0
2658 ? gimple_call_lhs (call)
2659 : gimple_call_arg (call, info.type0));
2660 tree op1 = (info.type1 < 0
2661 ? gimple_call_lhs (call)
2662 : gimple_call_arg (call, info.type1));
2663 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
2664}
2665
2666/* Return true if OPTAB is supported for TYPES (whose modes should be
d95ab70a
RS
2667 the same) when the optimization type is OPT_TYPE. Used for simple
2668 direct optabs. */
ab23f5d9
RS
2669
2670static bool
d95ab70a
RS
2671direct_optab_supported_p (direct_optab optab, tree_pair types,
2672 optimization_type opt_type)
ab23f5d9
RS
2673{
2674 machine_mode mode = TYPE_MODE (types.first);
2675 gcc_checking_assert (mode == TYPE_MODE (types.second));
d95ab70a 2676 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
ab23f5d9
RS
2677}
2678
2679/* Return true if load/store lanes optab OPTAB is supported for
d95ab70a 2680 array type TYPES.first when the optimization type is OPT_TYPE. */
ab23f5d9
RS
2681
2682static bool
d95ab70a
RS
2683multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
2684 optimization_type opt_type)
ab23f5d9 2685{
d95ab70a
RS
2686 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
2687 machine_mode imode = TYPE_MODE (types.first);
2688 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
2689 return (convert_optab_handler (optab, imode, vmode, opt_type)
2690 != CODE_FOR_nothing);
ab23f5d9
RS
2691}
2692
686ee971
RS
2693#define direct_unary_optab_supported_p direct_optab_supported_p
2694#define direct_binary_optab_supported_p direct_optab_supported_p
ab23f5d9
RS
2695#define direct_mask_load_optab_supported_p direct_optab_supported_p
2696#define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
2697#define direct_mask_store_optab_supported_p direct_optab_supported_p
2698#define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
2699
d95ab70a
RS
2700/* Return true if FN is supported for the types in TYPES when the
2701 optimization type is OPT_TYPE. The types are those associated with
2702 the "type0" and "type1" fields of FN's direct_internal_fn_info
2703 structure. */
ab23f5d9
RS
2704
2705bool
d95ab70a
RS
2706direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
2707 optimization_type opt_type)
ab23f5d9
RS
2708{
2709 switch (fn)
2710 {
2711#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
2712 case IFN_##CODE: break;
2713#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
2714 case IFN_##CODE: \
d95ab70a
RS
2715 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
2716 opt_type);
ab23f5d9
RS
2717#include "internal-fn.def"
2718
2719 case IFN_LAST:
2720 break;
2721 }
2722 gcc_unreachable ();
2723}
2724
d95ab70a
RS
2725/* Return true if FN is supported for type TYPE when the optimization
2726 type is OPT_TYPE. The caller knows that the "type0" and "type1"
2727 fields of FN's direct_internal_fn_info structure are the same. */
ab23f5d9
RS
2728
2729bool
d95ab70a
RS
2730direct_internal_fn_supported_p (internal_fn fn, tree type,
2731 optimization_type opt_type)
ab23f5d9
RS
2732{
2733 const direct_internal_fn_info &info = direct_internal_fn (fn);
2734 gcc_checking_assert (info.type0 == info.type1);
d95ab70a 2735 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
ab23f5d9
RS
2736}
2737
883cabde
RS
2738/* Return true if IFN_SET_EDOM is supported. */
2739
2740bool
2741set_edom_supported_p (void)
2742{
2743#ifdef TARGET_EDOM
2744 return true;
2745#else
2746 return false;
2747#endif
2748}
2749
ab23f5d9
RS
2750#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
2751 static void \
4cfe7a6c 2752 expand_##CODE (internal_fn fn, gcall *stmt) \
ab23f5d9 2753 { \
4cfe7a6c 2754 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
ab23f5d9
RS
2755 }
2756#include "internal-fn.def"
2757
25583c4f
RS
2758/* Routines to expand each internal function, indexed by function number.
2759 Each routine has the prototype:
2760
538dd0b7 2761 expand_<NAME> (gcall *stmt)
25583c4f
RS
2762
2763 where STMT is the statement that performs the call. */
4cfe7a6c 2764static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
b78475cf 2765#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
25583c4f 2766#include "internal-fn.def"
25583c4f
RS
2767 0
2768};
2769
4cfe7a6c
RS
2770/* Expand STMT as though it were a call to internal function FN. */
2771
2772void
2773expand_internal_call (internal_fn fn, gcall *stmt)
2774{
2775 internal_fn_expanders[fn] (fn, stmt);
2776}
2777
25583c4f
RS
2778/* Expand STMT, which is a call to internal function FN. */
2779
2780void
538dd0b7 2781expand_internal_call (gcall *stmt)
25583c4f 2782{
4cfe7a6c 2783 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
25583c4f 2784}
1ee62b92
PG
2785
2786void
2787expand_PHI (internal_fn, gcall *)
2788{
2789 gcc_unreachable ();
2790}