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