]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/internal-fn.c
Pass manager: add support for termination of pass list
[thirdparty/gcc.git] / gcc / internal-fn.c
CommitLineData
25583c4f 1/* Internal functions.
5624e564 2 Copyright (C) 2011-2015 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"
30#include "tree-ssanames.h"
31#include "expmed.h"
32#include "optabs.h"
33#include "emit-rtl.h"
34#include "diagnostic-core.h"
40e23961 35#include "fold-const.h"
0e37a2f3 36#include "internal-fn.h"
d8a2d370 37#include "stor-layout.h"
36566b39 38#include "dojump.h"
25583c4f 39#include "expr.h"
31e071ae 40#include "ubsan.h"
25583c4f
RS
41
42/* The names of each internal function, indexed by function number. */
43const char *const internal_fn_name_array[] = {
b78475cf 44#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
25583c4f
RS
45#include "internal-fn.def"
46#undef DEF_INTERNAL_FN
47 "<invalid-fn>"
48};
49
50/* The ECF_* flags of each internal function, indexed by function number. */
51const int internal_fn_flags_array[] = {
b78475cf 52#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
25583c4f
RS
53#include "internal-fn.def"
54#undef DEF_INTERNAL_FN
55 0
56};
57
b78475cf
YG
58/* Fnspec of each internal function, indexed by function number. */
59const_tree internal_fn_fnspec_array[IFN_LAST + 1];
60
61void
62init_internal_fns ()
63{
64#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
65 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
63a4184f 66 build_string ((int) sizeof (FNSPEC), FNSPEC ? FNSPEC : "");
b78475cf
YG
67#include "internal-fn.def"
68#undef DEF_INTERNAL_FN
69 internal_fn_fnspec_array[IFN_LAST] = 0;
70}
71
272c6793
RS
72/* ARRAY_TYPE is an array of vector modes. Return the associated insn
73 for load-lanes-style optab OPTAB. The insn must exist. */
74
75static enum insn_code
76get_multi_vector_move (tree array_type, convert_optab optab)
77{
78 enum insn_code icode;
ef4bddc2
RS
79 machine_mode imode;
80 machine_mode vmode;
272c6793
RS
81
82 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
83 imode = TYPE_MODE (array_type);
84 vmode = TYPE_MODE (TREE_TYPE (array_type));
85
86 icode = convert_optab_handler (optab, imode, vmode);
87 gcc_assert (icode != CODE_FOR_nothing);
88 return icode;
89}
90
91/* Expand LOAD_LANES call STMT. */
92
93static void
538dd0b7 94expand_LOAD_LANES (gcall *stmt)
272c6793
RS
95{
96 struct expand_operand ops[2];
97 tree type, lhs, rhs;
98 rtx target, mem;
99
100 lhs = gimple_call_lhs (stmt);
101 rhs = gimple_call_arg (stmt, 0);
102 type = TREE_TYPE (lhs);
103
104 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
105 mem = expand_normal (rhs);
106
107 gcc_assert (MEM_P (mem));
108 PUT_MODE (mem, TYPE_MODE (type));
109
110 create_output_operand (&ops[0], target, TYPE_MODE (type));
111 create_fixed_operand (&ops[1], mem);
112 expand_insn (get_multi_vector_move (type, vec_load_lanes_optab), 2, ops);
113}
114
115/* Expand STORE_LANES call STMT. */
116
117static void
538dd0b7 118expand_STORE_LANES (gcall *stmt)
272c6793
RS
119{
120 struct expand_operand ops[2];
121 tree type, lhs, rhs;
122 rtx target, reg;
123
124 lhs = gimple_call_lhs (stmt);
125 rhs = gimple_call_arg (stmt, 0);
126 type = TREE_TYPE (rhs);
127
128 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
129 reg = expand_normal (rhs);
130
131 gcc_assert (MEM_P (target));
132 PUT_MODE (target, TYPE_MODE (type));
133
134 create_fixed_operand (&ops[0], target);
135 create_input_operand (&ops[1], reg, TYPE_MODE (type));
136 expand_insn (get_multi_vector_move (type, vec_store_lanes_optab), 2, ops);
137}
138
8170608b 139static void
35228ac7 140expand_ANNOTATE (gcall *)
8170608b
TB
141{
142 gcc_unreachable ();
143}
144
74bf76ed
JJ
145/* This should get expanded in adjust_simduid_builtins. */
146
147static void
35228ac7 148expand_GOMP_SIMD_LANE (gcall *)
74bf76ed
JJ
149{
150 gcc_unreachable ();
151}
152
153/* This should get expanded in adjust_simduid_builtins. */
154
155static void
35228ac7 156expand_GOMP_SIMD_VF (gcall *)
74bf76ed
JJ
157{
158 gcc_unreachable ();
159}
160
161/* This should get expanded in adjust_simduid_builtins. */
162
163static void
35228ac7 164expand_GOMP_SIMD_LAST_LANE (gcall *)
74bf76ed
JJ
165{
166 gcc_unreachable ();
167}
168
d9a6bd32
JJ
169/* This should get expanded in adjust_simduid_builtins. */
170
171static void
172expand_GOMP_SIMD_ORDERED_START (gcall *)
173{
174 gcc_unreachable ();
175}
176
177/* This should get expanded in adjust_simduid_builtins. */
178
179static void
180expand_GOMP_SIMD_ORDERED_END (gcall *)
181{
182 gcc_unreachable ();
183}
184
b9a55b13
MP
185/* This should get expanded in the sanopt pass. */
186
187static void
35228ac7 188expand_UBSAN_NULL (gcall *)
b9a55b13
MP
189{
190 gcc_unreachable ();
191}
192
0e37a2f3
MP
193/* This should get expanded in the sanopt pass. */
194
195static void
35228ac7 196expand_UBSAN_BOUNDS (gcall *)
0e82f089
MP
197{
198 gcc_unreachable ();
199}
200
201/* This should get expanded in the sanopt pass. */
202
203static void
35228ac7 204expand_UBSAN_VPTR (gcall *)
0e37a2f3
MP
205{
206 gcc_unreachable ();
207}
208
c62ccb9a
YG
209/* This should get expanded in the sanopt pass. */
210
211static void
35228ac7
JJ
212expand_UBSAN_OBJECT_SIZE (gcall *)
213{
214 gcc_unreachable ();
215}
216
217/* This should get expanded in the sanopt pass. */
218
219static void
220expand_ASAN_CHECK (gcall *)
c62ccb9a
YG
221{
222 gcc_unreachable ();
223}
224
fca4adf2
JJ
225/* This should get expanded in the tsan pass. */
226
227static void
228expand_TSAN_FUNC_EXIT (gcall *)
229{
230 gcc_unreachable ();
231}
232
1304953e
JJ
233/* Helper function for expand_addsub_overflow. Return 1
234 if ARG interpreted as signed in its precision is known to be always
235 positive or 2 if ARG is known to be always negative, or 3 if ARG may
236 be positive or negative. */
237
238static int
239get_range_pos_neg (tree arg)
240{
241 if (arg == error_mark_node)
242 return 3;
243
244 int prec = TYPE_PRECISION (TREE_TYPE (arg));
245 int cnt = 0;
246 if (TREE_CODE (arg) == INTEGER_CST)
247 {
248 wide_int w = wi::sext (arg, prec);
249 if (wi::neg_p (w))
250 return 2;
251 else
252 return 1;
253 }
254 while (CONVERT_EXPR_P (arg)
255 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
256 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
257 {
258 arg = TREE_OPERAND (arg, 0);
259 /* Narrower value zero extended into wider type
260 will always result in positive values. */
261 if (TYPE_UNSIGNED (TREE_TYPE (arg))
262 && TYPE_PRECISION (TREE_TYPE (arg)) < prec)
263 return 1;
264 prec = TYPE_PRECISION (TREE_TYPE (arg));
265 if (++cnt > 30)
266 return 3;
267 }
268
269 if (TREE_CODE (arg) != SSA_NAME)
270 return 3;
271 wide_int arg_min, arg_max;
272 while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
273 {
355fe088 274 gimple *g = SSA_NAME_DEF_STMT (arg);
1304953e
JJ
275 if (is_gimple_assign (g)
276 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
277 {
278 tree t = gimple_assign_rhs1 (g);
279 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
280 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
281 {
282 if (TYPE_UNSIGNED (TREE_TYPE (t))
283 && TYPE_PRECISION (TREE_TYPE (t)) < prec)
284 return 1;
285 prec = TYPE_PRECISION (TREE_TYPE (t));
286 arg = t;
287 if (++cnt > 30)
288 return 3;
289 continue;
290 }
291 }
292 return 3;
293 }
294 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
295 {
296 /* For unsigned values, the "positive" range comes
297 below the "negative" range. */
298 if (!wi::neg_p (wi::sext (arg_max, prec), SIGNED))
299 return 1;
300 if (wi::neg_p (wi::sext (arg_min, prec), SIGNED))
301 return 2;
302 }
303 else
304 {
305 if (!wi::neg_p (wi::sext (arg_min, prec), SIGNED))
306 return 1;
307 if (wi::neg_p (wi::sext (arg_max, prec), SIGNED))
308 return 2;
309 }
310 return 3;
311}
312
313/* Return minimum precision needed to represent all values
314 of ARG in SIGNed integral type. */
315
316static int
317get_min_precision (tree arg, signop sign)
318{
319 int prec = TYPE_PRECISION (TREE_TYPE (arg));
320 int cnt = 0;
321 signop orig_sign = sign;
322 if (TREE_CODE (arg) == INTEGER_CST)
323 {
324 int p;
325 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
326 {
327 widest_int w = wi::to_widest (arg);
328 w = wi::ext (w, prec, sign);
329 p = wi::min_precision (w, sign);
330 }
331 else
332 p = wi::min_precision (arg, sign);
333 return MIN (p, prec);
334 }
335 while (CONVERT_EXPR_P (arg)
336 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
337 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
338 {
339 arg = TREE_OPERAND (arg, 0);
340 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
341 {
342 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
343 sign = UNSIGNED;
344 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
345 return prec + (orig_sign != sign);
346 prec = TYPE_PRECISION (TREE_TYPE (arg));
347 }
348 if (++cnt > 30)
349 return prec + (orig_sign != sign);
350 }
351 if (TREE_CODE (arg) != SSA_NAME)
352 return prec + (orig_sign != sign);
353 wide_int arg_min, arg_max;
354 while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
355 {
355fe088 356 gimple *g = SSA_NAME_DEF_STMT (arg);
1304953e
JJ
357 if (is_gimple_assign (g)
358 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
359 {
360 tree t = gimple_assign_rhs1 (g);
361 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
362 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
363 {
364 arg = t;
365 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
366 {
367 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
368 sign = UNSIGNED;
369 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
370 return prec + (orig_sign != sign);
371 prec = TYPE_PRECISION (TREE_TYPE (arg));
372 }
373 if (++cnt > 30)
374 return prec + (orig_sign != sign);
375 continue;
376 }
377 }
378 return prec + (orig_sign != sign);
379 }
380 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
381 {
382 int p1 = wi::min_precision (arg_min, sign);
383 int p2 = wi::min_precision (arg_max, sign);
384 p1 = MAX (p1, p2);
385 prec = MIN (prec, p1);
386 }
387 else if (sign == UNSIGNED && !wi::neg_p (arg_min, SIGNED))
388 {
c1ee2e62 389 int p = wi::min_precision (arg_max, UNSIGNED);
1304953e
JJ
390 prec = MIN (prec, p);
391 }
392 return prec + (orig_sign != sign);
393}
394
395/* Helper for expand_*_overflow. Store RES into the __real__ part
396 of TARGET. If RES has larger MODE than __real__ part of TARGET,
397 set the __imag__ part to 1 if RES doesn't fit into it. */
398
399static void
400expand_arith_overflow_result_store (tree lhs, rtx target,
401 machine_mode mode, rtx res)
402{
403 machine_mode tgtmode = GET_MODE_INNER (GET_MODE (target));
404 rtx lres = res;
405 if (tgtmode != mode)
406 {
407 rtx_code_label *done_label = gen_label_rtx ();
408 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
409 lres = convert_modes (tgtmode, mode, res, uns);
410 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
92344ed0 411 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
1476d1bd 412 EQ, true, mode, NULL_RTX, NULL, done_label,
1304953e
JJ
413 PROB_VERY_LIKELY);
414 write_complex_part (target, const1_rtx, true);
415 emit_label (done_label);
416 }
417 write_complex_part (target, lres, false);
418}
419
5620052d
JJ
420/* Helper for expand_*_overflow. Store RES into TARGET. */
421
422static void
423expand_ubsan_result_store (rtx target, rtx res)
424{
425 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
426 /* If this is a scalar in a register that is stored in a wider mode
427 than the declared mode, compute the result into its declared mode
428 and then convert to the wider mode. Our value is the computed
429 expression. */
430 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
431 else
432 emit_move_insn (target, res);
433}
434
31e071ae
MP
435/* Add sub/add overflow checking to the statement STMT.
436 CODE says whether the operation is +, or -. */
437
1304953e
JJ
438static void
439expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
440 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
441 bool uns1_p, bool is_ubsan)
31e071ae 442{
1304953e
JJ
443 rtx res, target = NULL_RTX;
444 tree fn;
445 rtx_code_label *done_label = gen_label_rtx ();
446 rtx_code_label *do_error = gen_label_rtx ();
31e071ae 447 do_pending_stack_adjust ();
1304953e
JJ
448 rtx op0 = expand_normal (arg0);
449 rtx op1 = expand_normal (arg1);
ef4bddc2 450 machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
1304953e
JJ
451 int prec = GET_MODE_PRECISION (mode);
452 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
453 bool do_xor = false;
454
455 if (is_ubsan)
456 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
457
31e071ae 458 if (lhs)
1304953e
JJ
459 {
460 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
461 if (!is_ubsan)
462 write_complex_part (target, const0_rtx, true);
463 }
464
465 /* We assume both operands and result have the same precision
466 here (GET_MODE_BITSIZE (mode)), S stands for signed type
467 with that precision, U for unsigned type with that precision,
468 sgn for unsigned most significant bit in that precision.
469 s1 is signed first operand, u1 is unsigned first operand,
470 s2 is signed second operand, u2 is unsigned second operand,
471 sr is signed result, ur is unsigned result and the following
472 rules say how to compute result (which is always result of
473 the operands as if both were unsigned, cast to the right
474 signedness) and how to compute whether operation overflowed.
475
476 s1 + s2 -> sr
477 res = (S) ((U) s1 + (U) s2)
478 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
479 s1 - s2 -> sr
480 res = (S) ((U) s1 - (U) s2)
481 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
482 u1 + u2 -> ur
483 res = u1 + u2
484 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
485 u1 - u2 -> ur
486 res = u1 - u2
487 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
488 s1 + u2 -> sr
489 res = (S) ((U) s1 + u2)
490 ovf = ((U) res ^ sgn) < u2
491 s1 + u2 -> ur
492 t1 = (S) (u2 ^ sgn)
493 t2 = s1 + t1
494 res = (U) t2 ^ sgn
495 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
496 s1 - u2 -> sr
497 res = (S) ((U) s1 - u2)
498 ovf = u2 > ((U) s1 ^ sgn)
499 s1 - u2 -> ur
500 res = (U) s1 - u2
501 ovf = s1 < 0 || u2 > (U) s1
502 u1 - s2 -> sr
503 res = u1 - (U) s2
504 ovf = u1 >= ((U) s2 ^ sgn)
505 u1 - s2 -> ur
506 t1 = u1 ^ sgn
507 t2 = t1 - (U) s2
508 res = t2 ^ sgn
509 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
510 s1 + s2 -> ur
511 res = (U) s1 + (U) s2
512 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
513 u1 + u2 -> sr
514 res = (S) (u1 + u2)
515 ovf = (U) res < u2 || res < 0
516 u1 - u2 -> sr
517 res = (S) (u1 - u2)
518 ovf = u1 >= u2 ? res < 0 : res >= 0
519 s1 - s2 -> ur
520 res = (U) s1 - (U) s2
521 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
522
523 if (code == PLUS_EXPR && uns0_p && !uns1_p)
524 {
525 /* PLUS_EXPR is commutative, if operand signedness differs,
526 canonicalize to the first operand being signed and second
527 unsigned to simplify following code. */
6b4db501
MM
528 std::swap (op0, op1);
529 std::swap (arg0, arg1);
530 uns0_p = false;
531 uns1_p = true;
1304953e
JJ
532 }
533
534 /* u1 +- u2 -> ur */
535 if (uns0_p && uns1_p && unsr_p)
536 {
537 /* Compute the operation. On RTL level, the addition is always
538 unsigned. */
539 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
540 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
541 rtx tem = op0;
542 /* For PLUS_EXPR, the operation is commutative, so we can pick
543 operand to compare against. For prec <= BITS_PER_WORD, I think
544 preferring REG operand is better over CONST_INT, because
545 the CONST_INT might enlarge the instruction or CSE would need
546 to figure out we'd already loaded it into a register before.
547 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
548 as then the multi-word comparison can be perhaps simplified. */
549 if (code == PLUS_EXPR
550 && (prec <= BITS_PER_WORD
551 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
552 : CONST_SCALAR_INT_P (op1)))
553 tem = op1;
92344ed0 554 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
1476d1bd 555 true, mode, NULL_RTX, NULL, done_label,
1304953e
JJ
556 PROB_VERY_LIKELY);
557 goto do_error_label;
558 }
559
560 /* s1 +- u2 -> sr */
561 if (!uns0_p && uns1_p && !unsr_p)
562 {
563 /* Compute the operation. On RTL level, the addition is always
564 unsigned. */
565 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
566 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
567 rtx tem = expand_binop (mode, add_optab,
568 code == PLUS_EXPR ? res : op0, sgn,
569 NULL_RTX, false, OPTAB_LIB_WIDEN);
1476d1bd 570 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
571 done_label, PROB_VERY_LIKELY);
572 goto do_error_label;
573 }
574
575 /* s1 + u2 -> ur */
576 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
577 {
578 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
579 OPTAB_LIB_WIDEN);
580 /* As we've changed op1, we have to avoid using the value range
581 for the original argument. */
582 arg1 = error_mark_node;
583 do_xor = true;
584 goto do_signed;
585 }
586
587 /* u1 - s2 -> ur */
588 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
589 {
590 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
591 OPTAB_LIB_WIDEN);
592 /* As we've changed op0, we have to avoid using the value range
593 for the original argument. */
594 arg0 = error_mark_node;
595 do_xor = true;
596 goto do_signed;
597 }
598
599 /* s1 - u2 -> ur */
600 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
601 {
602 /* Compute the operation. On RTL level, the addition is always
603 unsigned. */
604 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
605 OPTAB_LIB_WIDEN);
606 int pos_neg = get_range_pos_neg (arg0);
607 if (pos_neg == 2)
608 /* If ARG0 is known to be always negative, this is always overflow. */
609 emit_jump (do_error);
610 else if (pos_neg == 3)
611 /* If ARG0 is not known to be always positive, check at runtime. */
92344ed0 612 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd
MM
613 NULL, do_error, PROB_VERY_UNLIKELY);
614 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
615 done_label, PROB_VERY_LIKELY);
616 goto do_error_label;
617 }
618
619 /* u1 - s2 -> sr */
620 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
621 {
622 /* Compute the operation. On RTL level, the addition is always
623 unsigned. */
624 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
625 OPTAB_LIB_WIDEN);
626 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
627 OPTAB_LIB_WIDEN);
1476d1bd 628 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
1304953e
JJ
629 done_label, PROB_VERY_LIKELY);
630 goto do_error_label;
631 }
632
633 /* u1 + u2 -> sr */
634 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
635 {
636 /* Compute the operation. On RTL level, the addition is always
637 unsigned. */
638 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
639 OPTAB_LIB_WIDEN);
92344ed0 640 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd 641 NULL, do_error, PROB_VERY_UNLIKELY);
1304953e
JJ
642 rtx tem = op1;
643 /* The operation is commutative, so we can pick operand to compare
644 against. For prec <= BITS_PER_WORD, I think preferring REG operand
645 is better over CONST_INT, because the CONST_INT might enlarge the
646 instruction or CSE would need to figure out we'd already loaded it
647 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
648 might be more beneficial, as then the multi-word comparison can be
649 perhaps simplified. */
650 if (prec <= BITS_PER_WORD
651 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
652 : CONST_SCALAR_INT_P (op0))
653 tem = op0;
1476d1bd 654 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
655 done_label, PROB_VERY_LIKELY);
656 goto do_error_label;
657 }
658
659 /* s1 +- s2 -> ur */
660 if (!uns0_p && !uns1_p && unsr_p)
661 {
662 /* Compute the operation. On RTL level, the addition is always
663 unsigned. */
664 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
665 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
666 int pos_neg = get_range_pos_neg (arg1);
667 if (code == PLUS_EXPR)
668 {
669 int pos_neg0 = get_range_pos_neg (arg0);
670 if (pos_neg0 != 3 && pos_neg == 3)
671 {
6b4db501 672 std::swap (op0, op1);
1304953e
JJ
673 pos_neg = pos_neg0;
674 }
675 }
676 rtx tem;
677 if (pos_neg != 3)
678 {
679 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
680 ? and_optab : ior_optab,
681 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
1476d1bd
MM
682 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
683 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
684 }
685 else
686 {
687 rtx_code_label *do_ior_label = gen_label_rtx ();
92344ed0
JJ
688 do_compare_rtx_and_jump (op1, const0_rtx,
689 code == MINUS_EXPR ? GE : LT, false, mode,
1476d1bd 690 NULL_RTX, NULL, do_ior_label,
92344ed0 691 PROB_EVEN);
1304953e
JJ
692 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
693 OPTAB_LIB_WIDEN);
92344ed0 694 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 695 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
696 emit_jump (do_error);
697 emit_label (do_ior_label);
698 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
699 OPTAB_LIB_WIDEN);
92344ed0 700 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 701 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
702 }
703 goto do_error_label;
704 }
705
706 /* u1 - u2 -> sr */
707 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
708 {
709 /* Compute the operation. On RTL level, the addition is always
710 unsigned. */
711 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
712 OPTAB_LIB_WIDEN);
713 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
1476d1bd 714 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
1304953e 715 op0_geu_op1, PROB_EVEN);
92344ed0 716 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd 717 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
718 emit_jump (do_error);
719 emit_label (op0_geu_op1);
92344ed0 720 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 721 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
722 goto do_error_label;
723 }
31e071ae 724
1304953e
JJ
725 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
726
727 /* s1 +- s2 -> sr */
728 do_signed: ;
729 enum insn_code icode;
730 icode = optab_handler (code == PLUS_EXPR ? addv4_optab : subv4_optab, mode);
31e071ae
MP
731 if (icode != CODE_FOR_nothing)
732 {
733 struct expand_operand ops[4];
da664544 734 rtx_insn *last = get_last_insn ();
31e071ae
MP
735
736 res = gen_reg_rtx (mode);
737 create_output_operand (&ops[0], res, mode);
738 create_input_operand (&ops[1], op0, mode);
739 create_input_operand (&ops[2], op1, mode);
740 create_fixed_operand (&ops[3], do_error);
741 if (maybe_expand_insn (icode, 4, ops))
742 {
743 last = get_last_insn ();
0a6a6ac9 744 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
31e071ae
MP
745 && JUMP_P (last)
746 && any_condjump_p (last)
747 && !find_reg_note (last, REG_BR_PROB, 0))
748 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
749 emit_jump (done_label);
750 }
751 else
752 {
753 delete_insns_since (last);
754 icode = CODE_FOR_nothing;
755 }
756 }
757
758 if (icode == CODE_FOR_nothing)
759 {
da664544 760 rtx_code_label *sub_check = gen_label_rtx ();
97286431 761 int pos_neg = 3;
31e071ae
MP
762
763 /* Compute the operation. On RTL level, the addition is always
764 unsigned. */
7ddf4d5a
MP
765 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
766 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
31e071ae 767
f451d3a8
JJ
768 /* If we can prove one of the arguments (for MINUS_EXPR only
769 the second operand, as subtraction is not commutative) is always
770 non-negative or always negative, we can do just one comparison
771 and conditional jump instead of 2 at runtime, 3 present in the
97286431
JJ
772 emitted code. If one of the arguments is CONST_INT, all we
773 need is to make sure it is op1, then the first
92344ed0 774 do_compare_rtx_and_jump will be just folded. Otherwise try
97286431 775 to use range info if available. */
f451d3a8 776 if (code == PLUS_EXPR && CONST_INT_P (op0))
6b4db501 777 std::swap (op0, op1);
97286431
JJ
778 else if (CONST_INT_P (op1))
779 ;
f451d3a8 780 else if (code == PLUS_EXPR && TREE_CODE (arg0) == SSA_NAME)
97286431 781 {
1304953e 782 pos_neg = get_range_pos_neg (arg0);
97286431 783 if (pos_neg != 3)
6b4db501 784 std::swap (op0, op1);
97286431
JJ
785 }
786 if (pos_neg == 3 && !CONST_INT_P (op1) && TREE_CODE (arg1) == SSA_NAME)
1304953e 787 pos_neg = get_range_pos_neg (arg1);
97286431 788
31e071ae 789 /* If the op1 is negative, we have to use a different check. */
97286431 790 if (pos_neg == 3)
92344ed0 791 do_compare_rtx_and_jump (op1, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd 792 NULL, sub_check, PROB_EVEN);
31e071ae 793
7ddf4d5a 794 /* Compare the result of the operation with one of the operands. */
97286431 795 if (pos_neg & 1)
92344ed0 796 do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? GE : LE,
1476d1bd 797 false, mode, NULL_RTX, NULL, done_label,
97286431
JJ
798 PROB_VERY_LIKELY);
799
31e071ae 800 /* If we get here, we have to print the error. */
97286431
JJ
801 if (pos_neg == 3)
802 {
803 emit_jump (do_error);
804
805 emit_label (sub_check);
806 }
31e071ae 807
31e071ae 808 /* We have k = a + b for b < 0 here. k <= a must hold. */
97286431 809 if (pos_neg & 2)
92344ed0 810 do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? LE : GE,
1476d1bd 811 false, mode, NULL_RTX, NULL, done_label,
97286431 812 PROB_VERY_LIKELY);
31e071ae
MP
813 }
814
1304953e 815 do_error_label:
1769415d 816 emit_label (do_error);
1304953e
JJ
817 if (is_ubsan)
818 {
819 /* Expand the ubsan builtin call. */
820 push_temp_slots ();
821 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
822 arg0, arg1);
823 expand_normal (fn);
824 pop_temp_slots ();
825 do_pending_stack_adjust ();
826 }
827 else if (lhs)
828 write_complex_part (target, const1_rtx, true);
31e071ae 829
1769415d
MP
830 /* We're done. */
831 emit_label (done_label);
31e071ae
MP
832
833 if (lhs)
1304953e
JJ
834 {
835 if (is_ubsan)
5620052d 836 expand_ubsan_result_store (target, res);
1304953e
JJ
837 else
838 {
839 if (do_xor)
840 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
841 OPTAB_LIB_WIDEN);
842
843 expand_arith_overflow_result_store (lhs, target, mode, res);
844 }
845 }
31e071ae
MP
846}
847
848/* Add negate overflow checking to the statement STMT. */
849
1304953e
JJ
850static void
851expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan)
31e071ae
MP
852{
853 rtx res, op1;
1304953e 854 tree fn;
da664544
DM
855 rtx_code_label *done_label, *do_error;
856 rtx target = NULL_RTX;
31e071ae 857
31e071ae
MP
858 done_label = gen_label_rtx ();
859 do_error = gen_label_rtx ();
31e071ae
MP
860
861 do_pending_stack_adjust ();
862 op1 = expand_normal (arg1);
863
ef4bddc2 864 machine_mode mode = TYPE_MODE (TREE_TYPE (arg1));
31e071ae 865 if (lhs)
1304953e
JJ
866 {
867 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
868 if (!is_ubsan)
869 write_complex_part (target, const0_rtx, true);
870 }
31e071ae
MP
871
872 enum insn_code icode = optab_handler (negv3_optab, mode);
873 if (icode != CODE_FOR_nothing)
874 {
875 struct expand_operand ops[3];
da664544 876 rtx_insn *last = get_last_insn ();
31e071ae
MP
877
878 res = gen_reg_rtx (mode);
879 create_output_operand (&ops[0], res, mode);
880 create_input_operand (&ops[1], op1, mode);
881 create_fixed_operand (&ops[2], do_error);
882 if (maybe_expand_insn (icode, 3, ops))
883 {
884 last = get_last_insn ();
0a6a6ac9 885 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
31e071ae
MP
886 && JUMP_P (last)
887 && any_condjump_p (last)
888 && !find_reg_note (last, REG_BR_PROB, 0))
889 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
890 emit_jump (done_label);
891 }
892 else
893 {
894 delete_insns_since (last);
895 icode = CODE_FOR_nothing;
896 }
897 }
898
899 if (icode == CODE_FOR_nothing)
900 {
901 /* Compute the operation. On RTL level, the addition is always
902 unsigned. */
903 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
904
905 /* Compare the operand with the most negative value. */
906 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1476d1bd 907 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
31e071ae
MP
908 done_label, PROB_VERY_LIKELY);
909 }
910
911 emit_label (do_error);
1304953e
JJ
912 if (is_ubsan)
913 {
914 /* Expand the ubsan builtin call. */
915 push_temp_slots ();
916 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
917 arg1, NULL_TREE);
918 expand_normal (fn);
919 pop_temp_slots ();
920 do_pending_stack_adjust ();
921 }
922 else if (lhs)
923 write_complex_part (target, const1_rtx, true);
31e071ae
MP
924
925 /* We're done. */
926 emit_label (done_label);
927
928 if (lhs)
1304953e
JJ
929 {
930 if (is_ubsan)
5620052d 931 expand_ubsan_result_store (target, res);
1304953e
JJ
932 else
933 expand_arith_overflow_result_store (lhs, target, mode, res);
934 }
31e071ae
MP
935}
936
937/* Add mul overflow checking to the statement STMT. */
938
1304953e
JJ
939static void
940expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
941 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan)
31e071ae
MP
942{
943 rtx res, op0, op1;
1304953e 944 tree fn, type;
da664544
DM
945 rtx_code_label *done_label, *do_error;
946 rtx target = NULL_RTX;
1304953e
JJ
947 signop sign;
948 enum insn_code icode;
31e071ae 949
31e071ae
MP
950 done_label = gen_label_rtx ();
951 do_error = gen_label_rtx ();
31e071ae
MP
952
953 do_pending_stack_adjust ();
954 op0 = expand_normal (arg0);
955 op1 = expand_normal (arg1);
956
ef4bddc2 957 machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
1304953e 958 bool uns = unsr_p;
31e071ae 959 if (lhs)
1304953e
JJ
960 {
961 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
962 if (!is_ubsan)
963 write_complex_part (target, const0_rtx, true);
964 }
965
966 if (is_ubsan)
967 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
968
969 /* We assume both operands and result have the same precision
970 here (GET_MODE_BITSIZE (mode)), S stands for signed type
971 with that precision, U for unsigned type with that precision,
972 sgn for unsigned most significant bit in that precision.
973 s1 is signed first operand, u1 is unsigned first operand,
974 s2 is signed second operand, u2 is unsigned second operand,
975 sr is signed result, ur is unsigned result and the following
976 rules say how to compute result (which is always result of
977 the operands as if both were unsigned, cast to the right
978 signedness) and how to compute whether operation overflowed.
979 main_ovf (false) stands for jump on signed multiplication
980 overflow or the main algorithm with uns == false.
981 main_ovf (true) stands for jump on unsigned multiplication
982 overflow or the main algorithm with uns == true.
983
984 s1 * s2 -> sr
985 res = (S) ((U) s1 * (U) s2)
986 ovf = main_ovf (false)
987 u1 * u2 -> ur
988 res = u1 * u2
989 ovf = main_ovf (true)
990 s1 * u2 -> ur
991 res = (U) s1 * u2
992 ovf = (s1 < 0 && u2) || main_ovf (true)
993 u1 * u2 -> sr
994 res = (S) (u1 * u2)
995 ovf = res < 0 || main_ovf (true)
996 s1 * u2 -> sr
997 res = (S) ((U) s1 * u2)
998 ovf = (S) u2 >= 0 ? main_ovf (false)
999 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1000 s1 * s2 -> ur
1001 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1002 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1003 res = t1 * t2
1004 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1005
1006 if (uns0_p && !uns1_p)
1007 {
1008 /* Multiplication is commutative, if operand signedness differs,
1009 canonicalize to the first operand being signed and second
1010 unsigned to simplify following code. */
6b4db501
MM
1011 std::swap (op0, op1);
1012 std::swap (arg0, arg1);
1013 uns0_p = false;
1014 uns1_p = true;
1304953e
JJ
1015 }
1016
1017 int pos_neg0 = get_range_pos_neg (arg0);
1018 int pos_neg1 = get_range_pos_neg (arg1);
1019
1020 /* s1 * u2 -> ur */
1021 if (!uns0_p && uns1_p && unsr_p)
1022 {
1023 switch (pos_neg0)
1024 {
1025 case 1:
1026 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1027 goto do_main;
1028 case 2:
1029 /* If s1 is negative, avoid the main code, just multiply and
1030 signal overflow if op1 is not 0. */
1031 struct separate_ops ops;
1032 ops.code = MULT_EXPR;
1033 ops.type = TREE_TYPE (arg1);
1034 ops.op0 = make_tree (ops.type, op0);
1035 ops.op1 = make_tree (ops.type, op1);
1036 ops.op2 = NULL_TREE;
1037 ops.location = loc;
1038 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
92344ed0 1039 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1040 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
1041 goto do_error_label;
1042 case 3:
1043 rtx_code_label *do_main_label;
1044 do_main_label = gen_label_rtx ();
92344ed0 1045 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1046 NULL, do_main_label, PROB_VERY_LIKELY);
92344ed0 1047 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1048 NULL, do_main_label, PROB_VERY_LIKELY);
1304953e
JJ
1049 write_complex_part (target, const1_rtx, true);
1050 emit_label (do_main_label);
1051 goto do_main;
1052 default:
1053 gcc_unreachable ();
1054 }
1055 }
1056
1057 /* u1 * u2 -> sr */
1058 if (uns0_p && uns1_p && !unsr_p)
1059 {
1060 uns = true;
1061 /* Rest of handling of this case after res is computed. */
1062 goto do_main;
1063 }
1064
1065 /* s1 * u2 -> sr */
1066 if (!uns0_p && uns1_p && !unsr_p)
1067 {
1068 switch (pos_neg1)
1069 {
1070 case 1:
1071 goto do_main;
1072 case 2:
1073 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1074 avoid the main code, just multiply and signal overflow
1075 unless 0 * u2 or -1 * ((U) Smin). */
1076 struct separate_ops ops;
1077 ops.code = MULT_EXPR;
1078 ops.type = TREE_TYPE (arg1);
1079 ops.op0 = make_tree (ops.type, op0);
1080 ops.op1 = make_tree (ops.type, op1);
1081 ops.op2 = NULL_TREE;
1082 ops.location = loc;
1083 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
92344ed0 1084 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1085 NULL, done_label, PROB_VERY_LIKELY);
92344ed0 1086 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1476d1bd 1087 NULL, do_error, PROB_VERY_UNLIKELY);
1304953e
JJ
1088 int prec;
1089 prec = GET_MODE_PRECISION (mode);
1090 rtx sgn;
1091 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
92344ed0 1092 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1476d1bd 1093 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
1094 goto do_error_label;
1095 case 3:
1096 /* Rest of handling of this case after res is computed. */
1097 goto do_main;
1098 default:
1099 gcc_unreachable ();
1100 }
1101 }
31e071ae 1102
1304953e
JJ
1103 /* s1 * s2 -> ur */
1104 if (!uns0_p && !uns1_p && unsr_p)
1105 {
1106 rtx tem, tem2;
1107 switch (pos_neg0 | pos_neg1)
1108 {
1109 case 1: /* Both operands known to be non-negative. */
1110 goto do_main;
1111 case 2: /* Both operands known to be negative. */
1112 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1113 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1114 /* Avoid looking at arg0/arg1 ranges, as we've changed
1115 the arguments. */
1116 arg0 = error_mark_node;
1117 arg1 = error_mark_node;
1118 goto do_main;
1119 case 3:
1120 if ((pos_neg0 ^ pos_neg1) == 3)
1121 {
1122 /* If one operand is known to be negative and the other
1123 non-negative, this overflows always, unless the non-negative
1124 one is 0. Just do normal multiply and set overflow
1125 unless one of the operands is 0. */
1126 struct separate_ops ops;
1127 ops.code = MULT_EXPR;
1128 ops.type
1129 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1130 1);
1131 ops.op0 = make_tree (ops.type, op0);
1132 ops.op1 = make_tree (ops.type, op1);
1133 ops.op2 = NULL_TREE;
1134 ops.location = loc;
1135 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1136 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1137 OPTAB_LIB_WIDEN);
92344ed0 1138 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
1476d1bd 1139 NULL_RTX, NULL, done_label,
92344ed0 1140 PROB_VERY_LIKELY);
1304953e
JJ
1141 goto do_error_label;
1142 }
1143 /* The general case, do all the needed comparisons at runtime. */
1144 rtx_code_label *do_main_label, *after_negate_label;
1145 rtx rop0, rop1;
1146 rop0 = gen_reg_rtx (mode);
1147 rop1 = gen_reg_rtx (mode);
1148 emit_move_insn (rop0, op0);
1149 emit_move_insn (rop1, op1);
1150 op0 = rop0;
1151 op1 = rop1;
1152 do_main_label = gen_label_rtx ();
1153 after_negate_label = gen_label_rtx ();
1154 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1155 OPTAB_LIB_WIDEN);
92344ed0 1156 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1157 NULL, after_negate_label, PROB_VERY_LIKELY);
1304953e
JJ
1158 /* Both arguments negative here, negate them and continue with
1159 normal unsigned overflow checking multiplication. */
1160 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1161 NULL_RTX, false));
1162 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1163 NULL_RTX, false));
1164 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1165 the arguments. */
1166 arg0 = error_mark_node;
1167 arg1 = error_mark_node;
1168 emit_jump (do_main_label);
1169 emit_label (after_negate_label);
1170 tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1171 OPTAB_LIB_WIDEN);
92344ed0 1172 do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1173 NULL, do_main_label, PROB_VERY_LIKELY);
1304953e
JJ
1174 /* One argument is negative here, the other positive. This
1175 overflows always, unless one of the arguments is 0. But
1176 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1177 is, thus we can keep do_main code oring in overflow as is. */
92344ed0 1178 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1179 NULL, do_main_label, PROB_VERY_LIKELY);
1304953e
JJ
1180 write_complex_part (target, const1_rtx, true);
1181 emit_label (do_main_label);
1182 goto do_main;
1183 default:
1184 gcc_unreachable ();
1185 }
1186 }
1187
1188 do_main:
1189 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1190 sign = uns ? UNSIGNED : SIGNED;
1191 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
31e071ae
MP
1192 if (icode != CODE_FOR_nothing)
1193 {
1194 struct expand_operand ops[4];
da664544 1195 rtx_insn *last = get_last_insn ();
31e071ae
MP
1196
1197 res = gen_reg_rtx (mode);
1198 create_output_operand (&ops[0], res, mode);
1199 create_input_operand (&ops[1], op0, mode);
1200 create_input_operand (&ops[2], op1, mode);
1201 create_fixed_operand (&ops[3], do_error);
1202 if (maybe_expand_insn (icode, 4, ops))
1203 {
1204 last = get_last_insn ();
0a6a6ac9 1205 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
31e071ae
MP
1206 && JUMP_P (last)
1207 && any_condjump_p (last)
1208 && !find_reg_note (last, REG_BR_PROB, 0))
1209 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
1210 emit_jump (done_label);
1211 }
1212 else
1213 {
1214 delete_insns_since (last);
1215 icode = CODE_FOR_nothing;
1216 }
1217 }
1218
1219 if (icode == CODE_FOR_nothing)
1220 {
1221 struct separate_ops ops;
1304953e
JJ
1222 int prec = GET_MODE_PRECISION (mode);
1223 machine_mode hmode = mode_for_size (prec / 2, MODE_INT, 1);
1224 ops.op0 = make_tree (type, op0);
1225 ops.op1 = make_tree (type, op1);
31e071ae 1226 ops.op2 = NULL_TREE;
1304953e 1227 ops.location = loc;
31e071ae
MP
1228 if (GET_MODE_2XWIDER_MODE (mode) != VOIDmode
1229 && targetm.scalar_mode_supported_p (GET_MODE_2XWIDER_MODE (mode)))
1230 {
ef4bddc2 1231 machine_mode wmode = GET_MODE_2XWIDER_MODE (mode);
31e071ae
MP
1232 ops.code = WIDEN_MULT_EXPR;
1233 ops.type
1304953e 1234 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
31e071ae
MP
1235
1236 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1304953e
JJ
1237 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1238 NULL_RTX, uns);
31e071ae
MP
1239 hipart = gen_lowpart (mode, hipart);
1240 res = gen_lowpart (mode, res);
1304953e
JJ
1241 if (uns)
1242 /* For the unsigned multiplication, there was overflow if
1243 HIPART is non-zero. */
92344ed0 1244 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1476d1bd 1245 NULL_RTX, NULL, done_label,
92344ed0 1246 PROB_VERY_LIKELY);
1304953e
JJ
1247 else
1248 {
1249 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1250 NULL_RTX, 0);
1251 /* RES is low half of the double width result, HIPART
1252 the high half. There was overflow if
1253 HIPART is different from RES < 0 ? -1 : 0. */
92344ed0 1254 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1476d1bd 1255 NULL_RTX, NULL, done_label,
92344ed0 1256 PROB_VERY_LIKELY);
1304953e 1257 }
31e071ae 1258 }
1304953e 1259 else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
d5fa9cc9 1260 {
da664544
DM
1261 rtx_code_label *large_op0 = gen_label_rtx ();
1262 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1263 rtx_code_label *one_small_one_large = gen_label_rtx ();
1264 rtx_code_label *both_ops_large = gen_label_rtx ();
1304953e
JJ
1265 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1266 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
da664544 1267 rtx_code_label *do_overflow = gen_label_rtx ();
1304953e 1268 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
d5fa9cc9 1269
807e902e 1270 unsigned int hprec = GET_MODE_PRECISION (hmode);
d5fa9cc9 1271 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1304953e 1272 NULL_RTX, uns);
d5fa9cc9
JJ
1273 hipart0 = gen_lowpart (hmode, hipart0);
1274 rtx lopart0 = gen_lowpart (hmode, op0);
1304953e
JJ
1275 rtx signbit0 = const0_rtx;
1276 if (!uns)
1277 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1278 NULL_RTX, 0);
d5fa9cc9 1279 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1304953e 1280 NULL_RTX, uns);
d5fa9cc9
JJ
1281 hipart1 = gen_lowpart (hmode, hipart1);
1282 rtx lopart1 = gen_lowpart (hmode, op1);
1304953e
JJ
1283 rtx signbit1 = const0_rtx;
1284 if (!uns)
1285 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1286 NULL_RTX, 0);
d5fa9cc9
JJ
1287
1288 res = gen_reg_rtx (mode);
1289
1290 /* True if op0 resp. op1 are known to be in the range of
1291 halfstype. */
1292 bool op0_small_p = false;
1293 bool op1_small_p = false;
1294 /* True if op0 resp. op1 are known to have all zeros or all ones
1295 in the upper half of bits, but are not known to be
1296 op{0,1}_small_p. */
1297 bool op0_medium_p = false;
1298 bool op1_medium_p = false;
1299 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
1300 nonnegative, 1 if unknown. */
1301 int op0_sign = 1;
1302 int op1_sign = 1;
1303
1304953e
JJ
1304 if (pos_neg0 == 1)
1305 op0_sign = 0;
1306 else if (pos_neg0 == 2)
1307 op0_sign = -1;
1308 if (pos_neg1 == 1)
1309 op1_sign = 0;
1310 else if (pos_neg1 == 2)
1311 op1_sign = -1;
1312
1313 unsigned int mprec0 = prec;
1314 if (arg0 != error_mark_node)
1315 mprec0 = get_min_precision (arg0, sign);
1316 if (mprec0 <= hprec)
1317 op0_small_p = true;
1318 else if (!uns && mprec0 <= hprec + 1)
1319 op0_medium_p = true;
1320 unsigned int mprec1 = prec;
1321 if (arg1 != error_mark_node)
1322 mprec1 = get_min_precision (arg1, sign);
1323 if (mprec1 <= hprec)
1324 op1_small_p = true;
1325 else if (!uns && mprec1 <= hprec + 1)
1326 op1_medium_p = true;
d5fa9cc9
JJ
1327
1328 int smaller_sign = 1;
1329 int larger_sign = 1;
1330 if (op0_small_p)
1331 {
1332 smaller_sign = op0_sign;
1333 larger_sign = op1_sign;
1334 }
1335 else if (op1_small_p)
1336 {
1337 smaller_sign = op1_sign;
1338 larger_sign = op0_sign;
1339 }
1340 else if (op0_sign == op1_sign)
1341 {
1342 smaller_sign = op0_sign;
1343 larger_sign = op0_sign;
1344 }
1345
1346 if (!op0_small_p)
92344ed0 1347 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1476d1bd 1348 NULL_RTX, NULL, large_op0,
92344ed0 1349 PROB_UNLIKELY);
d5fa9cc9
JJ
1350
1351 if (!op1_small_p)
92344ed0 1352 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1476d1bd 1353 NULL_RTX, NULL, small_op0_large_op1,
d5fa9cc9
JJ
1354 PROB_UNLIKELY);
1355
1304953e
JJ
1356 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
1357 hmode to mode, the multiplication will never overflow. We can
1358 do just one hmode x hmode => mode widening multiplication. */
1359 rtx lopart0s = lopart0, lopart1s = lopart1;
d5fa9cc9
JJ
1360 if (GET_CODE (lopart0) == SUBREG)
1361 {
1304953e
JJ
1362 lopart0s = shallow_copy_rtx (lopart0);
1363 SUBREG_PROMOTED_VAR_P (lopart0s) = 1;
1364 SUBREG_PROMOTED_SET (lopart0s, uns ? SRP_UNSIGNED : SRP_SIGNED);
d5fa9cc9
JJ
1365 }
1366 if (GET_CODE (lopart1) == SUBREG)
1367 {
1304953e
JJ
1368 lopart1s = shallow_copy_rtx (lopart1);
1369 SUBREG_PROMOTED_VAR_P (lopart1s) = 1;
1370 SUBREG_PROMOTED_SET (lopart1s, uns ? SRP_UNSIGNED : SRP_SIGNED);
d5fa9cc9 1371 }
1304953e
JJ
1372 tree halfstype = build_nonstandard_integer_type (hprec, uns);
1373 ops.op0 = make_tree (halfstype, lopart0s);
1374 ops.op1 = make_tree (halfstype, lopart1s);
d5fa9cc9 1375 ops.code = WIDEN_MULT_EXPR;
1304953e 1376 ops.type = type;
d5fa9cc9
JJ
1377 rtx thisres
1378 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1379 emit_move_insn (res, thisres);
1380 emit_jump (done_label);
1381
1382 emit_label (small_op0_large_op1);
1383
1304953e
JJ
1384 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
1385 but op1 is not, just swap the arguments and handle it as op1
1386 sign/zero extended, op0 not. */
d5fa9cc9
JJ
1387 rtx larger = gen_reg_rtx (mode);
1388 rtx hipart = gen_reg_rtx (hmode);
1389 rtx lopart = gen_reg_rtx (hmode);
1390 emit_move_insn (larger, op1);
1391 emit_move_insn (hipart, hipart1);
1392 emit_move_insn (lopart, lopart0);
1393 emit_jump (one_small_one_large);
1394
1395 emit_label (large_op0);
1396
1397 if (!op1_small_p)
92344ed0 1398 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1476d1bd 1399 NULL_RTX, NULL, both_ops_large,
92344ed0 1400 PROB_UNLIKELY);
d5fa9cc9 1401
1304953e
JJ
1402 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
1403 but op0 is not, prepare larger, hipart and lopart pseudos and
1404 handle it together with small_op0_large_op1. */
d5fa9cc9
JJ
1405 emit_move_insn (larger, op0);
1406 emit_move_insn (hipart, hipart0);
1407 emit_move_insn (lopart, lopart1);
1408
1409 emit_label (one_small_one_large);
1410
1411 /* lopart is the low part of the operand that is sign extended
026c3cfd 1412 to mode, larger is the other operand, hipart is the
d5fa9cc9
JJ
1413 high part of larger and lopart0 and lopart1 are the low parts
1414 of both operands.
1415 We perform lopart0 * lopart1 and lopart * hipart widening
1416 multiplications. */
1417 tree halfutype = build_nonstandard_integer_type (hprec, 1);
1418 ops.op0 = make_tree (halfutype, lopart0);
1419 ops.op1 = make_tree (halfutype, lopart1);
1420 rtx lo0xlo1
1421 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1422
1423 ops.op0 = make_tree (halfutype, lopart);
1424 ops.op1 = make_tree (halfutype, hipart);
1425 rtx loxhi = gen_reg_rtx (mode);
1426 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1427 emit_move_insn (loxhi, tem);
1428
1304953e
JJ
1429 if (!uns)
1430 {
1431 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
1432 if (larger_sign == 0)
1433 emit_jump (after_hipart_neg);
1434 else if (larger_sign != -1)
92344ed0 1435 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1476d1bd 1436 NULL_RTX, NULL, after_hipart_neg,
1304953e
JJ
1437 PROB_EVEN);
1438
1439 tem = convert_modes (mode, hmode, lopart, 1);
1440 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
1441 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
1442 1, OPTAB_DIRECT);
1443 emit_move_insn (loxhi, tem);
1444
1445 emit_label (after_hipart_neg);
1446
1447 /* if (lopart < 0) loxhi -= larger; */
1448 if (smaller_sign == 0)
1449 emit_jump (after_lopart_neg);
1450 else if (smaller_sign != -1)
92344ed0 1451 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1476d1bd 1452 NULL_RTX, NULL, after_lopart_neg,
1304953e
JJ
1453 PROB_EVEN);
1454
1455 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1456 1, OPTAB_DIRECT);
1457 emit_move_insn (loxhi, tem);
1458
1459 emit_label (after_lopart_neg);
1460 }
d5fa9cc9
JJ
1461
1462 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
1463 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
1464 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
1465 1, OPTAB_DIRECT);
1466 emit_move_insn (loxhi, tem);
1467
1468 /* if (loxhi >> (bitsize / 2)
1304953e
JJ
1469 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
1470 if (loxhi >> (bitsize / 2) == 0 (if uns). */
d5fa9cc9
JJ
1471 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
1472 NULL_RTX, 0);
1473 hipartloxhi = gen_lowpart (hmode, hipartloxhi);
1304953e
JJ
1474 rtx signbitloxhi = const0_rtx;
1475 if (!uns)
1476 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
1477 gen_lowpart (hmode, loxhi),
1478 hprec - 1, NULL_RTX, 0);
d5fa9cc9 1479
92344ed0 1480 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1476d1bd 1481 NULL_RTX, NULL, do_overflow,
d5fa9cc9
JJ
1482 PROB_VERY_UNLIKELY);
1483
1484 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
1485 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
1486 NULL_RTX, 1);
1487 tem = convert_modes (mode, hmode, gen_lowpart (hmode, lo0xlo1), 1);
1488
1489 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
1490 1, OPTAB_DIRECT);
1491 if (tem != res)
1492 emit_move_insn (res, tem);
1493 emit_jump (done_label);
1494
1495 emit_label (both_ops_large);
1496
1304953e
JJ
1497 /* If both operands are large (not sign (!uns) or zero (uns)
1498 extended from hmode), then perform the full multiplication
1499 which will be the result of the operation.
1500 The only cases which don't overflow are for signed multiplication
1501 some cases where both hipart0 and highpart1 are 0 or -1.
1502 For unsigned multiplication when high parts are both non-zero
1503 this overflows always. */
d5fa9cc9 1504 ops.code = MULT_EXPR;
1304953e
JJ
1505 ops.op0 = make_tree (type, op0);
1506 ops.op1 = make_tree (type, op1);
d5fa9cc9
JJ
1507 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1508 emit_move_insn (res, tem);
1509
1304953e 1510 if (!uns)
d5fa9cc9 1511 {
1304953e
JJ
1512 if (!op0_medium_p)
1513 {
1514 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
1515 NULL_RTX, 1, OPTAB_DIRECT);
92344ed0 1516 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1476d1bd 1517 NULL_RTX, NULL, do_error,
1304953e
JJ
1518 PROB_VERY_UNLIKELY);
1519 }
d5fa9cc9 1520
1304953e
JJ
1521 if (!op1_medium_p)
1522 {
1523 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
1524 NULL_RTX, 1, OPTAB_DIRECT);
92344ed0 1525 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1476d1bd 1526 NULL_RTX, NULL, do_error,
1304953e
JJ
1527 PROB_VERY_UNLIKELY);
1528 }
d5fa9cc9 1529
1304953e
JJ
1530 /* At this point hipart{0,1} are both in [-1, 0]. If they are
1531 the same, overflow happened if res is negative, if they are
1532 different, overflow happened if res is positive. */
1533 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
1534 emit_jump (hipart_different);
1535 else if (op0_sign == 1 || op1_sign == 1)
92344ed0 1536 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1476d1bd 1537 NULL_RTX, NULL, hipart_different,
92344ed0 1538 PROB_EVEN);
d5fa9cc9 1539
92344ed0 1540 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
1476d1bd 1541 NULL_RTX, NULL, do_error,
92344ed0 1542 PROB_VERY_UNLIKELY);
1304953e 1543 emit_jump (done_label);
d5fa9cc9 1544
1304953e
JJ
1545 emit_label (hipart_different);
1546
92344ed0 1547 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1476d1bd 1548 NULL_RTX, NULL, do_error,
92344ed0 1549 PROB_VERY_UNLIKELY);
1304953e
JJ
1550 emit_jump (done_label);
1551 }
d5fa9cc9
JJ
1552
1553 emit_label (do_overflow);
1554
1555 /* Overflow, do full multiplication and fallthru into do_error. */
1304953e
JJ
1556 ops.op0 = make_tree (type, op0);
1557 ops.op1 = make_tree (type, op1);
d5fa9cc9
JJ
1558 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1559 emit_move_insn (res, tem);
1560 }
31e071ae
MP
1561 else
1562 {
1304953e 1563 gcc_assert (!is_ubsan);
31e071ae 1564 ops.code = MULT_EXPR;
1304953e 1565 ops.type = type;
31e071ae
MP
1566 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1567 emit_jump (done_label);
1568 }
1569 }
1570
1304953e 1571 do_error_label:
31e071ae 1572 emit_label (do_error);
1304953e
JJ
1573 if (is_ubsan)
1574 {
1575 /* Expand the ubsan builtin call. */
1576 push_temp_slots ();
1577 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1578 arg0, arg1);
1579 expand_normal (fn);
1580 pop_temp_slots ();
1581 do_pending_stack_adjust ();
1582 }
1583 else if (lhs)
1584 write_complex_part (target, const1_rtx, true);
31e071ae
MP
1585
1586 /* We're done. */
1587 emit_label (done_label);
1588
1304953e
JJ
1589 /* u1 * u2 -> sr */
1590 if (uns0_p && uns1_p && !unsr_p)
1591 {
1592 rtx_code_label *all_done_label = gen_label_rtx ();
92344ed0 1593 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1594 NULL, all_done_label, PROB_VERY_LIKELY);
1304953e
JJ
1595 write_complex_part (target, const1_rtx, true);
1596 emit_label (all_done_label);
1597 }
1598
1599 /* s1 * u2 -> sr */
1600 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
1601 {
1602 rtx_code_label *all_done_label = gen_label_rtx ();
1603 rtx_code_label *set_noovf = gen_label_rtx ();
92344ed0 1604 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1605 NULL, all_done_label, PROB_VERY_LIKELY);
1304953e 1606 write_complex_part (target, const1_rtx, true);
92344ed0 1607 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1608 NULL, set_noovf, PROB_VERY_LIKELY);
92344ed0 1609 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1476d1bd
MM
1610 NULL, all_done_label, PROB_VERY_UNLIKELY);
1611 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
92344ed0 1612 all_done_label, PROB_VERY_UNLIKELY);
1304953e
JJ
1613 emit_label (set_noovf);
1614 write_complex_part (target, const0_rtx, true);
1615 emit_label (all_done_label);
1616 }
1617
31e071ae 1618 if (lhs)
1304953e
JJ
1619 {
1620 if (is_ubsan)
5620052d 1621 expand_ubsan_result_store (target, res);
1304953e
JJ
1622 else
1623 expand_arith_overflow_result_store (lhs, target, mode, res);
1624 }
31e071ae
MP
1625}
1626
1627/* Expand UBSAN_CHECK_ADD call STMT. */
1628
1629static void
538dd0b7 1630expand_UBSAN_CHECK_ADD (gcall *stmt)
31e071ae 1631{
1304953e
JJ
1632 location_t loc = gimple_location (stmt);
1633 tree lhs = gimple_call_lhs (stmt);
1634 tree arg0 = gimple_call_arg (stmt, 0);
1635 tree arg1 = gimple_call_arg (stmt, 1);
1636 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
1637 false, false, false, true);
31e071ae
MP
1638}
1639
1640/* Expand UBSAN_CHECK_SUB call STMT. */
1641
1642static void
538dd0b7 1643expand_UBSAN_CHECK_SUB (gcall *stmt)
31e071ae 1644{
1304953e
JJ
1645 location_t loc = gimple_location (stmt);
1646 tree lhs = gimple_call_lhs (stmt);
1647 tree arg0 = gimple_call_arg (stmt, 0);
1648 tree arg1 = gimple_call_arg (stmt, 1);
1649 if (integer_zerop (arg0))
1650 expand_neg_overflow (loc, lhs, arg1, true);
31e071ae 1651 else
1304953e
JJ
1652 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
1653 false, false, false, true);
31e071ae
MP
1654}
1655
1656/* Expand UBSAN_CHECK_MUL call STMT. */
1657
1658static void
538dd0b7 1659expand_UBSAN_CHECK_MUL (gcall *stmt)
31e071ae 1660{
1304953e
JJ
1661 location_t loc = gimple_location (stmt);
1662 tree lhs = gimple_call_lhs (stmt);
1663 tree arg0 = gimple_call_arg (stmt, 0);
1664 tree arg1 = gimple_call_arg (stmt, 1);
1665 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true);
1666}
1667
1668/* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
1669
1670static void
355fe088 1671expand_arith_overflow (enum tree_code code, gimple *stmt)
1304953e
JJ
1672{
1673 tree lhs = gimple_call_lhs (stmt);
1674 if (lhs == NULL_TREE)
1675 return;
1676 tree arg0 = gimple_call_arg (stmt, 0);
1677 tree arg1 = gimple_call_arg (stmt, 1);
1678 tree type = TREE_TYPE (TREE_TYPE (lhs));
1679 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
1680 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
1681 int unsr_p = TYPE_UNSIGNED (type);
1682 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
1683 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
1684 int precres = TYPE_PRECISION (type);
1685 location_t loc = gimple_location (stmt);
1686 if (!uns0_p && get_range_pos_neg (arg0) == 1)
1687 uns0_p = true;
1688 if (!uns1_p && get_range_pos_neg (arg1) == 1)
1689 uns1_p = true;
1690 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
1691 prec0 = MIN (prec0, pr);
1692 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
1693 prec1 = MIN (prec1, pr);
1694
1695 /* If uns0_p && uns1_p, precop is minimum needed precision
1696 of unsigned type to hold the exact result, otherwise
1697 precop is minimum needed precision of signed type to
1698 hold the exact result. */
1699 int precop;
1700 if (code == MULT_EXPR)
1701 precop = prec0 + prec1 + (uns0_p != uns1_p);
1702 else
1703 {
1704 if (uns0_p == uns1_p)
1705 precop = MAX (prec0, prec1) + 1;
1706 else if (uns0_p)
1707 precop = MAX (prec0 + 1, prec1) + 1;
1708 else
1709 precop = MAX (prec0, prec1 + 1) + 1;
1710 }
1711 int orig_precres = precres;
1712
1713 do
1714 {
1715 if ((uns0_p && uns1_p)
1716 ? ((precop + !unsr_p) <= precres
1717 /* u1 - u2 -> ur can overflow, no matter what precision
1718 the result has. */
1719 && (code != MINUS_EXPR || !unsr_p))
1720 : (!unsr_p && precop <= precres))
1721 {
1722 /* The infinity precision result will always fit into result. */
1723 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1724 write_complex_part (target, const0_rtx, true);
1725 enum machine_mode mode = TYPE_MODE (type);
1726 struct separate_ops ops;
1727 ops.code = code;
1728 ops.type = type;
1729 ops.op0 = fold_convert_loc (loc, type, arg0);
1730 ops.op1 = fold_convert_loc (loc, type, arg1);
1731 ops.op2 = NULL_TREE;
1732 ops.location = loc;
1733 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1734 expand_arith_overflow_result_store (lhs, target, mode, tem);
1735 return;
1736 }
1737
1304953e
JJ
1738 /* For sub-word operations, if target doesn't have them, start
1739 with precres widening right away, otherwise do it only
1740 if the most simple cases can't be used. */
9e11bfef
TS
1741 if (WORD_REGISTER_OPERATIONS
1742 && orig_precres == precres
1743 && precres < BITS_PER_WORD)
1304953e 1744 ;
9e11bfef
TS
1745 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
1746 && prec1 <= precres)
1304953e
JJ
1747 || ((!uns0_p || !uns1_p) && !unsr_p
1748 && prec0 + uns0_p <= precres
1749 && prec1 + uns1_p <= precres))
1750 {
1751 arg0 = fold_convert_loc (loc, type, arg0);
1752 arg1 = fold_convert_loc (loc, type, arg1);
1753 switch (code)
1754 {
1755 case MINUS_EXPR:
1756 if (integer_zerop (arg0) && !unsr_p)
1757 expand_neg_overflow (loc, lhs, arg1, false);
1758 /* FALLTHRU */
1759 case PLUS_EXPR:
1760 expand_addsub_overflow (loc, code, lhs, arg0, arg1,
1761 unsr_p, unsr_p, unsr_p, false);
1762 return;
1763 case MULT_EXPR:
1764 expand_mul_overflow (loc, lhs, arg0, arg1,
1765 unsr_p, unsr_p, unsr_p, false);
1766 return;
1767 default:
1768 gcc_unreachable ();
1769 }
1770 }
1771
1772 /* For sub-word operations, retry with a wider type first. */
1773 if (orig_precres == precres && precop <= BITS_PER_WORD)
1774 {
9e11bfef 1775#if WORD_REGISTER_OPERATIONS
1304953e
JJ
1776 int p = BITS_PER_WORD;
1777#else
1778 int p = precop;
1779#endif
1780 enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
1781 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
1782 uns0_p && uns1_p
1783 && unsr_p);
1784 p = TYPE_PRECISION (optype);
1785 if (p > precres)
1786 {
1787 precres = p;
1788 unsr_p = TYPE_UNSIGNED (optype);
1789 type = optype;
1790 continue;
1791 }
1792 }
1793
1794 if (prec0 <= precres && prec1 <= precres)
1795 {
1796 tree types[2];
1797 if (unsr_p)
1798 {
1799 types[0] = build_nonstandard_integer_type (precres, 0);
1800 types[1] = type;
1801 }
1802 else
1803 {
1804 types[0] = type;
1805 types[1] = build_nonstandard_integer_type (precres, 1);
1806 }
1807 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
1808 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
1809 if (code != MULT_EXPR)
1810 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
1811 uns0_p, uns1_p, false);
1812 else
1813 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
1814 uns0_p, uns1_p, false);
1815 return;
1816 }
1817
1818 /* Retry with a wider type. */
1819 if (orig_precres == precres)
1820 {
1821 int p = MAX (prec0, prec1);
1822 enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
1823 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
1824 uns0_p && uns1_p
1825 && unsr_p);
1826 p = TYPE_PRECISION (optype);
1827 if (p > precres)
1828 {
1829 precres = p;
1830 unsr_p = TYPE_UNSIGNED (optype);
1831 type = optype;
1832 continue;
1833 }
1834 }
1835
1836 gcc_unreachable ();
1837 }
1838 while (1);
1839}
1840
1841/* Expand ADD_OVERFLOW STMT. */
1842
1843static void
538dd0b7 1844expand_ADD_OVERFLOW (gcall *stmt)
1304953e
JJ
1845{
1846 expand_arith_overflow (PLUS_EXPR, stmt);
1847}
1848
1849/* Expand SUB_OVERFLOW STMT. */
1850
1851static void
538dd0b7 1852expand_SUB_OVERFLOW (gcall *stmt)
1304953e
JJ
1853{
1854 expand_arith_overflow (MINUS_EXPR, stmt);
1855}
1856
1857/* Expand MUL_OVERFLOW STMT. */
1858
1859static void
538dd0b7 1860expand_MUL_OVERFLOW (gcall *stmt)
1304953e
JJ
1861{
1862 expand_arith_overflow (MULT_EXPR, stmt);
31e071ae
MP
1863}
1864
5ce9450f
JJ
1865/* This should get folded in tree-vectorizer.c. */
1866
1867static void
35228ac7 1868expand_LOOP_VECTORIZED (gcall *)
5ce9450f
JJ
1869{
1870 gcc_unreachable ();
1871}
1872
1873static void
538dd0b7 1874expand_MASK_LOAD (gcall *stmt)
5ce9450f
JJ
1875{
1876 struct expand_operand ops[3];
1877 tree type, lhs, rhs, maskt;
1878 rtx mem, target, mask;
1879
1880 maskt = gimple_call_arg (stmt, 2);
1881 lhs = gimple_call_lhs (stmt);
8e91d222
JJ
1882 if (lhs == NULL_TREE)
1883 return;
5ce9450f
JJ
1884 type = TREE_TYPE (lhs);
1885 rhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0),
1886 gimple_call_arg (stmt, 1));
1887
1888 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1889 gcc_assert (MEM_P (mem));
1890 mask = expand_normal (maskt);
1891 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1892 create_output_operand (&ops[0], target, TYPE_MODE (type));
1893 create_fixed_operand (&ops[1], mem);
1894 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
1895 expand_insn (optab_handler (maskload_optab, TYPE_MODE (type)), 3, ops);
1896}
1897
1898static void
538dd0b7 1899expand_MASK_STORE (gcall *stmt)
5ce9450f
JJ
1900{
1901 struct expand_operand ops[3];
1902 tree type, lhs, rhs, maskt;
1903 rtx mem, reg, mask;
1904
1905 maskt = gimple_call_arg (stmt, 2);
1906 rhs = gimple_call_arg (stmt, 3);
1907 type = TREE_TYPE (rhs);
1908 lhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0),
1909 gimple_call_arg (stmt, 1));
1910
1911 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1912 gcc_assert (MEM_P (mem));
1913 mask = expand_normal (maskt);
1914 reg = expand_normal (rhs);
1915 create_fixed_operand (&ops[0], mem);
1916 create_input_operand (&ops[1], reg, TYPE_MODE (type));
1917 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
1918 expand_insn (optab_handler (maskstore_optab, TYPE_MODE (type)), 3, ops);
1919}
1920
09b22f48 1921static void
538dd0b7 1922expand_ABNORMAL_DISPATCHER (gcall *)
09b22f48
JJ
1923{
1924}
1925
ed9c79e1 1926static void
538dd0b7 1927expand_BUILTIN_EXPECT (gcall *stmt)
ed9c79e1
JJ
1928{
1929 /* When guessing was done, the hints should be already stripped away. */
1930 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
1931
1932 rtx target;
1933 tree lhs = gimple_call_lhs (stmt);
1934 if (lhs)
1935 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1936 else
1937 target = const0_rtx;
1938 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
1939 if (lhs && val != target)
1940 emit_move_insn (target, val);
1941}
1942
f8e89441
TV
1943/* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
1944 should never be called. */
1945
1946static void
1947expand_VA_ARG (gcall *stmt ATTRIBUTE_UNUSED)
1948{
1949 gcc_unreachable ();
1950}
1951
8ab78162
NS
1952/* Expand the IFN_UNIQUE function according to its first argument. */
1953
1954static void
1955expand_UNIQUE (gcall *stmt)
1956{
1957 rtx pattern = NULL_RTX;
1958 enum ifn_unique_kind kind
1959 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
1960
1961 switch (kind)
1962 {
1963 default:
1964 gcc_unreachable ();
1965
1966 case IFN_UNIQUE_UNSPEC:
1967 if (targetm.have_unique ())
1968 pattern = targetm.gen_unique ();
1969 break;
9bd46bc9
NS
1970
1971 case IFN_UNIQUE_OACC_FORK:
1972 case IFN_UNIQUE_OACC_JOIN:
1973 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
1974 {
1975 tree lhs = gimple_call_lhs (stmt);
1976 rtx target = const0_rtx;
1977
1978 if (lhs)
1979 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1980
1981 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
1982 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
1983
1984 if (kind == IFN_UNIQUE_OACC_FORK)
1985 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
1986 else
1987 pattern = targetm.gen_oacc_join (target, data_dep, axis);
1988 }
1989 else
1990 gcc_unreachable ();
1991 break;
8ab78162
NS
1992 }
1993
1994 if (pattern)
1995 emit_insn (pattern);
1996}
1997
9bd46bc9
NS
1998/* The size of an OpenACC compute dimension. */
1999
2000static void
2001expand_GOACC_DIM_SIZE (gcall *stmt)
2002{
2003 tree lhs = gimple_call_lhs (stmt);
2004
2005 if (!lhs)
2006 return;
2007
2008 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2009 if (targetm.have_oacc_dim_size ())
2010 {
2011 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2012 VOIDmode, EXPAND_NORMAL);
2013 emit_insn (targetm.gen_oacc_dim_size (target, dim));
2014 }
2015 else
2016 emit_move_insn (target, GEN_INT (1));
2017}
2018
2019/* The position of an OpenACC execution engine along one compute axis. */
2020
2021static void
2022expand_GOACC_DIM_POS (gcall *stmt)
2023{
2024 tree lhs = gimple_call_lhs (stmt);
2025
2026 if (!lhs)
2027 return;
2028
2029 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2030 if (targetm.have_oacc_dim_pos ())
2031 {
2032 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2033 VOIDmode, EXPAND_NORMAL);
2034 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
2035 }
2036 else
2037 emit_move_insn (target, const0_rtx);
2038}
2039
2040/* This is expanded by oacc_device_lower pass. */
2041
2042static void
2043expand_GOACC_LOOP (gcall *stmt ATTRIBUTE_UNUSED)
2044{
2045 gcc_unreachable ();
2046}
2047
25583c4f
RS
2048/* Routines to expand each internal function, indexed by function number.
2049 Each routine has the prototype:
2050
538dd0b7 2051 expand_<NAME> (gcall *stmt)
25583c4f
RS
2052
2053 where STMT is the statement that performs the call. */
538dd0b7 2054static void (*const internal_fn_expanders[]) (gcall *) = {
b78475cf 2055#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
25583c4f
RS
2056#include "internal-fn.def"
2057#undef DEF_INTERNAL_FN
2058 0
2059};
2060
2061/* Expand STMT, which is a call to internal function FN. */
2062
2063void
538dd0b7 2064expand_internal_call (gcall *stmt)
25583c4f
RS
2065{
2066 internal_fn_expanders[(int) gimple_call_internal_fn (stmt)] (stmt);
2067}