]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/internal-fn.c
fix PR68343: disable fuse-*.c tests for isl 0.14 or earlier
[thirdparty/gcc.git] / gcc / internal-fn.c
CommitLineData
25583c4f 1/* Internal functions.
818ab71a 2 Copyright (C) 2011-2016 Free Software Foundation, Inc.
25583c4f
RS
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
c7131fb2 23#include "backend.h"
957060b5
AM
24#include "target.h"
25#include "rtl.h"
25583c4f 26#include "tree.h"
c7131fb2 27#include "gimple.h"
957060b5
AM
28#include "predict.h"
29#include "stringpool.h"
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 {
cde9d596
RH
549 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
550 : usubv4_optab, mode);
551 if (icode != CODE_FOR_nothing)
552 {
553 struct expand_operand ops[4];
554 rtx_insn *last = get_last_insn ();
555
556 res = gen_reg_rtx (mode);
557 create_output_operand (&ops[0], res, mode);
558 create_input_operand (&ops[1], op0, mode);
559 create_input_operand (&ops[2], op1, mode);
560 create_fixed_operand (&ops[3], do_error);
561 if (maybe_expand_insn (icode, 4, ops))
562 {
563 last = get_last_insn ();
564 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
565 && JUMP_P (last)
566 && any_condjump_p (last)
567 && !find_reg_note (last, REG_BR_PROB, 0))
568 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
569 emit_jump (done_label);
570 goto do_error_label;
571 }
572
573 delete_insns_since (last);
574 }
575
1304953e
JJ
576 /* Compute the operation. On RTL level, the addition is always
577 unsigned. */
578 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
579 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
580 rtx tem = op0;
581 /* For PLUS_EXPR, the operation is commutative, so we can pick
582 operand to compare against. For prec <= BITS_PER_WORD, I think
583 preferring REG operand is better over CONST_INT, because
584 the CONST_INT might enlarge the instruction or CSE would need
585 to figure out we'd already loaded it into a register before.
586 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
587 as then the multi-word comparison can be perhaps simplified. */
588 if (code == PLUS_EXPR
589 && (prec <= BITS_PER_WORD
590 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
591 : CONST_SCALAR_INT_P (op1)))
592 tem = op1;
92344ed0 593 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
1476d1bd 594 true, mode, NULL_RTX, NULL, done_label,
1304953e
JJ
595 PROB_VERY_LIKELY);
596 goto do_error_label;
597 }
598
599 /* s1 +- u2 -> sr */
600 if (!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, code == PLUS_EXPR ? add_optab : sub_optab,
605 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
606 rtx tem = expand_binop (mode, add_optab,
607 code == PLUS_EXPR ? res : op0, sgn,
608 NULL_RTX, false, OPTAB_LIB_WIDEN);
1476d1bd 609 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
610 done_label, PROB_VERY_LIKELY);
611 goto do_error_label;
612 }
613
614 /* s1 + u2 -> ur */
615 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
616 {
617 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
618 OPTAB_LIB_WIDEN);
619 /* As we've changed op1, we have to avoid using the value range
620 for the original argument. */
621 arg1 = error_mark_node;
622 do_xor = true;
623 goto do_signed;
624 }
625
626 /* u1 - s2 -> ur */
627 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
628 {
629 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
630 OPTAB_LIB_WIDEN);
631 /* As we've changed op0, we have to avoid using the value range
632 for the original argument. */
633 arg0 = error_mark_node;
634 do_xor = true;
635 goto do_signed;
636 }
637
638 /* s1 - u2 -> ur */
639 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
640 {
641 /* Compute the operation. On RTL level, the addition is always
642 unsigned. */
643 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
644 OPTAB_LIB_WIDEN);
645 int pos_neg = get_range_pos_neg (arg0);
646 if (pos_neg == 2)
647 /* If ARG0 is known to be always negative, this is always overflow. */
648 emit_jump (do_error);
649 else if (pos_neg == 3)
650 /* If ARG0 is not known to be always positive, check at runtime. */
92344ed0 651 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd
MM
652 NULL, do_error, PROB_VERY_UNLIKELY);
653 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
654 done_label, PROB_VERY_LIKELY);
655 goto do_error_label;
656 }
657
658 /* u1 - s2 -> sr */
659 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
660 {
661 /* Compute the operation. On RTL level, the addition is always
662 unsigned. */
663 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
664 OPTAB_LIB_WIDEN);
665 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
666 OPTAB_LIB_WIDEN);
1476d1bd 667 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
1304953e
JJ
668 done_label, PROB_VERY_LIKELY);
669 goto do_error_label;
670 }
671
672 /* u1 + u2 -> sr */
673 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
674 {
675 /* Compute the operation. On RTL level, the addition is always
676 unsigned. */
677 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
678 OPTAB_LIB_WIDEN);
92344ed0 679 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd 680 NULL, do_error, PROB_VERY_UNLIKELY);
1304953e
JJ
681 rtx tem = op1;
682 /* The operation is commutative, so we can pick operand to compare
683 against. For prec <= BITS_PER_WORD, I think preferring REG operand
684 is better over CONST_INT, because the CONST_INT might enlarge the
685 instruction or CSE would need to figure out we'd already loaded it
686 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
687 might be more beneficial, as then the multi-word comparison can be
688 perhaps simplified. */
689 if (prec <= BITS_PER_WORD
690 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
691 : CONST_SCALAR_INT_P (op0))
692 tem = op0;
1476d1bd 693 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
694 done_label, PROB_VERY_LIKELY);
695 goto do_error_label;
696 }
697
698 /* s1 +- s2 -> ur */
699 if (!uns0_p && !uns1_p && unsr_p)
700 {
701 /* Compute the operation. On RTL level, the addition is always
702 unsigned. */
703 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
704 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
705 int pos_neg = get_range_pos_neg (arg1);
706 if (code == PLUS_EXPR)
707 {
708 int pos_neg0 = get_range_pos_neg (arg0);
709 if (pos_neg0 != 3 && pos_neg == 3)
710 {
6b4db501 711 std::swap (op0, op1);
1304953e
JJ
712 pos_neg = pos_neg0;
713 }
714 }
715 rtx tem;
716 if (pos_neg != 3)
717 {
718 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
719 ? and_optab : ior_optab,
720 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
1476d1bd
MM
721 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
722 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
723 }
724 else
725 {
726 rtx_code_label *do_ior_label = gen_label_rtx ();
92344ed0
JJ
727 do_compare_rtx_and_jump (op1, const0_rtx,
728 code == MINUS_EXPR ? GE : LT, false, mode,
1476d1bd 729 NULL_RTX, NULL, do_ior_label,
92344ed0 730 PROB_EVEN);
1304953e
JJ
731 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
732 OPTAB_LIB_WIDEN);
92344ed0 733 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 734 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
735 emit_jump (do_error);
736 emit_label (do_ior_label);
737 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
738 OPTAB_LIB_WIDEN);
92344ed0 739 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 740 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
741 }
742 goto do_error_label;
743 }
744
745 /* u1 - u2 -> sr */
746 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
747 {
748 /* Compute the operation. On RTL level, the addition is always
749 unsigned. */
750 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
751 OPTAB_LIB_WIDEN);
752 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
1476d1bd 753 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
1304953e 754 op0_geu_op1, PROB_EVEN);
92344ed0 755 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd 756 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
757 emit_jump (do_error);
758 emit_label (op0_geu_op1);
92344ed0 759 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 760 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
761 goto do_error_label;
762 }
31e071ae 763
1304953e
JJ
764 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
765
766 /* s1 +- s2 -> sr */
cde9d596
RH
767 do_signed:
768 {
769 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
770 : subv4_optab, mode);
771 if (icode != CODE_FOR_nothing)
772 {
773 struct expand_operand ops[4];
774 rtx_insn *last = get_last_insn ();
775
776 res = gen_reg_rtx (mode);
777 create_output_operand (&ops[0], res, mode);
778 create_input_operand (&ops[1], op0, mode);
779 create_input_operand (&ops[2], op1, mode);
780 create_fixed_operand (&ops[3], do_error);
781 if (maybe_expand_insn (icode, 4, ops))
782 {
783 last = get_last_insn ();
784 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
785 && JUMP_P (last)
786 && any_condjump_p (last)
787 && !find_reg_note (last, REG_BR_PROB, 0))
788 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
789 emit_jump (done_label);
790 goto do_error_label;
791 }
792
793 delete_insns_since (last);
794 }
795
796 rtx_code_label *sub_check = gen_label_rtx ();
797 int pos_neg = 3;
798
799 /* Compute the operation. On RTL level, the addition is always
800 unsigned. */
801 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
802 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
803
804 /* If we can prove one of the arguments (for MINUS_EXPR only
805 the second operand, as subtraction is not commutative) is always
806 non-negative or always negative, we can do just one comparison
807 and conditional jump instead of 2 at runtime, 3 present in the
808 emitted code. If one of the arguments is CONST_INT, all we
809 need is to make sure it is op1, then the first
810 do_compare_rtx_and_jump will be just folded. Otherwise try
811 to use range info if available. */
812 if (code == PLUS_EXPR && CONST_INT_P (op0))
813 std::swap (op0, op1);
814 else if (CONST_INT_P (op1))
815 ;
816 else if (code == PLUS_EXPR && TREE_CODE (arg0) == SSA_NAME)
817 {
818 pos_neg = get_range_pos_neg (arg0);
819 if (pos_neg != 3)
820 std::swap (op0, op1);
821 }
822 if (pos_neg == 3 && !CONST_INT_P (op1) && TREE_CODE (arg1) == SSA_NAME)
823 pos_neg = get_range_pos_neg (arg1);
824
825 /* If the op1 is negative, we have to use a different check. */
826 if (pos_neg == 3)
827 do_compare_rtx_and_jump (op1, const0_rtx, LT, false, mode, NULL_RTX,
828 NULL, sub_check, PROB_EVEN);
829
830 /* Compare the result of the operation with one of the operands. */
831 if (pos_neg & 1)
832 do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? GE : LE,
833 false, mode, NULL_RTX, NULL, done_label,
834 PROB_VERY_LIKELY);
97286431 835
cde9d596
RH
836 /* If we get here, we have to print the error. */
837 if (pos_neg == 3)
838 {
839 emit_jump (do_error);
840 emit_label (sub_check);
841 }
31e071ae 842
cde9d596
RH
843 /* We have k = a + b for b < 0 here. k <= a must hold. */
844 if (pos_neg & 2)
845 do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? LE : GE,
846 false, mode, NULL_RTX, NULL, done_label,
847 PROB_VERY_LIKELY);
848 }
31e071ae 849
1304953e 850 do_error_label:
1769415d 851 emit_label (do_error);
1304953e
JJ
852 if (is_ubsan)
853 {
854 /* Expand the ubsan builtin call. */
855 push_temp_slots ();
856 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
857 arg0, arg1);
858 expand_normal (fn);
859 pop_temp_slots ();
860 do_pending_stack_adjust ();
861 }
862 else if (lhs)
863 write_complex_part (target, const1_rtx, true);
31e071ae 864
1769415d
MP
865 /* We're done. */
866 emit_label (done_label);
31e071ae
MP
867
868 if (lhs)
1304953e
JJ
869 {
870 if (is_ubsan)
5620052d 871 expand_ubsan_result_store (target, res);
1304953e
JJ
872 else
873 {
874 if (do_xor)
875 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
876 OPTAB_LIB_WIDEN);
877
878 expand_arith_overflow_result_store (lhs, target, mode, res);
879 }
880 }
31e071ae
MP
881}
882
883/* Add negate overflow checking to the statement STMT. */
884
1304953e
JJ
885static void
886expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan)
31e071ae
MP
887{
888 rtx res, op1;
1304953e 889 tree fn;
da664544
DM
890 rtx_code_label *done_label, *do_error;
891 rtx target = NULL_RTX;
31e071ae 892
31e071ae
MP
893 done_label = gen_label_rtx ();
894 do_error = gen_label_rtx ();
31e071ae
MP
895
896 do_pending_stack_adjust ();
897 op1 = expand_normal (arg1);
898
ef4bddc2 899 machine_mode mode = TYPE_MODE (TREE_TYPE (arg1));
31e071ae 900 if (lhs)
1304953e
JJ
901 {
902 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
903 if (!is_ubsan)
904 write_complex_part (target, const0_rtx, true);
905 }
31e071ae
MP
906
907 enum insn_code icode = optab_handler (negv3_optab, mode);
908 if (icode != CODE_FOR_nothing)
909 {
910 struct expand_operand ops[3];
da664544 911 rtx_insn *last = get_last_insn ();
31e071ae
MP
912
913 res = gen_reg_rtx (mode);
914 create_output_operand (&ops[0], res, mode);
915 create_input_operand (&ops[1], op1, mode);
916 create_fixed_operand (&ops[2], do_error);
917 if (maybe_expand_insn (icode, 3, ops))
918 {
919 last = get_last_insn ();
0a6a6ac9 920 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
31e071ae
MP
921 && JUMP_P (last)
922 && any_condjump_p (last)
923 && !find_reg_note (last, REG_BR_PROB, 0))
924 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
925 emit_jump (done_label);
926 }
927 else
928 {
929 delete_insns_since (last);
930 icode = CODE_FOR_nothing;
931 }
932 }
933
934 if (icode == CODE_FOR_nothing)
935 {
936 /* Compute the operation. On RTL level, the addition is always
937 unsigned. */
938 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
939
940 /* Compare the operand with the most negative value. */
941 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1476d1bd 942 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
31e071ae
MP
943 done_label, PROB_VERY_LIKELY);
944 }
945
946 emit_label (do_error);
1304953e
JJ
947 if (is_ubsan)
948 {
949 /* Expand the ubsan builtin call. */
950 push_temp_slots ();
951 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
952 arg1, NULL_TREE);
953 expand_normal (fn);
954 pop_temp_slots ();
955 do_pending_stack_adjust ();
956 }
957 else if (lhs)
958 write_complex_part (target, const1_rtx, true);
31e071ae
MP
959
960 /* We're done. */
961 emit_label (done_label);
962
963 if (lhs)
1304953e
JJ
964 {
965 if (is_ubsan)
5620052d 966 expand_ubsan_result_store (target, res);
1304953e
JJ
967 else
968 expand_arith_overflow_result_store (lhs, target, mode, res);
969 }
31e071ae
MP
970}
971
972/* Add mul overflow checking to the statement STMT. */
973
1304953e
JJ
974static void
975expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
976 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan)
31e071ae
MP
977{
978 rtx res, op0, op1;
1304953e 979 tree fn, type;
da664544
DM
980 rtx_code_label *done_label, *do_error;
981 rtx target = NULL_RTX;
1304953e
JJ
982 signop sign;
983 enum insn_code icode;
31e071ae 984
31e071ae
MP
985 done_label = gen_label_rtx ();
986 do_error = gen_label_rtx ();
31e071ae
MP
987
988 do_pending_stack_adjust ();
989 op0 = expand_normal (arg0);
990 op1 = expand_normal (arg1);
991
ef4bddc2 992 machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
1304953e 993 bool uns = unsr_p;
31e071ae 994 if (lhs)
1304953e
JJ
995 {
996 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
997 if (!is_ubsan)
998 write_complex_part (target, const0_rtx, true);
999 }
1000
1001 if (is_ubsan)
1002 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1003
1004 /* We assume both operands and result have the same precision
1005 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1006 with that precision, U for unsigned type with that precision,
1007 sgn for unsigned most significant bit in that precision.
1008 s1 is signed first operand, u1 is unsigned first operand,
1009 s2 is signed second operand, u2 is unsigned second operand,
1010 sr is signed result, ur is unsigned result and the following
1011 rules say how to compute result (which is always result of
1012 the operands as if both were unsigned, cast to the right
1013 signedness) and how to compute whether operation overflowed.
1014 main_ovf (false) stands for jump on signed multiplication
1015 overflow or the main algorithm with uns == false.
1016 main_ovf (true) stands for jump on unsigned multiplication
1017 overflow or the main algorithm with uns == true.
1018
1019 s1 * s2 -> sr
1020 res = (S) ((U) s1 * (U) s2)
1021 ovf = main_ovf (false)
1022 u1 * u2 -> ur
1023 res = u1 * u2
1024 ovf = main_ovf (true)
1025 s1 * u2 -> ur
1026 res = (U) s1 * u2
1027 ovf = (s1 < 0 && u2) || main_ovf (true)
1028 u1 * u2 -> sr
1029 res = (S) (u1 * u2)
1030 ovf = res < 0 || main_ovf (true)
1031 s1 * u2 -> sr
1032 res = (S) ((U) s1 * u2)
1033 ovf = (S) u2 >= 0 ? main_ovf (false)
1034 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1035 s1 * s2 -> ur
1036 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1037 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1038 res = t1 * t2
1039 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1040
1041 if (uns0_p && !uns1_p)
1042 {
1043 /* Multiplication is commutative, if operand signedness differs,
1044 canonicalize to the first operand being signed and second
1045 unsigned to simplify following code. */
6b4db501
MM
1046 std::swap (op0, op1);
1047 std::swap (arg0, arg1);
1048 uns0_p = false;
1049 uns1_p = true;
1304953e
JJ
1050 }
1051
1052 int pos_neg0 = get_range_pos_neg (arg0);
1053 int pos_neg1 = get_range_pos_neg (arg1);
1054
1055 /* s1 * u2 -> ur */
1056 if (!uns0_p && uns1_p && unsr_p)
1057 {
1058 switch (pos_neg0)
1059 {
1060 case 1:
1061 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1062 goto do_main;
1063 case 2:
1064 /* If s1 is negative, avoid the main code, just multiply and
1065 signal overflow if op1 is not 0. */
1066 struct separate_ops ops;
1067 ops.code = MULT_EXPR;
1068 ops.type = TREE_TYPE (arg1);
1069 ops.op0 = make_tree (ops.type, op0);
1070 ops.op1 = make_tree (ops.type, op1);
1071 ops.op2 = NULL_TREE;
1072 ops.location = loc;
1073 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
92344ed0 1074 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1075 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
1076 goto do_error_label;
1077 case 3:
1078 rtx_code_label *do_main_label;
1079 do_main_label = gen_label_rtx ();
92344ed0 1080 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1081 NULL, do_main_label, PROB_VERY_LIKELY);
92344ed0 1082 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1083 NULL, do_main_label, PROB_VERY_LIKELY);
1304953e
JJ
1084 write_complex_part (target, const1_rtx, true);
1085 emit_label (do_main_label);
1086 goto do_main;
1087 default:
1088 gcc_unreachable ();
1089 }
1090 }
1091
1092 /* u1 * u2 -> sr */
1093 if (uns0_p && uns1_p && !unsr_p)
1094 {
1095 uns = true;
1096 /* Rest of handling of this case after res is computed. */
1097 goto do_main;
1098 }
1099
1100 /* s1 * u2 -> sr */
1101 if (!uns0_p && uns1_p && !unsr_p)
1102 {
1103 switch (pos_neg1)
1104 {
1105 case 1:
1106 goto do_main;
1107 case 2:
1108 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1109 avoid the main code, just multiply and signal overflow
1110 unless 0 * u2 or -1 * ((U) Smin). */
1111 struct separate_ops ops;
1112 ops.code = MULT_EXPR;
1113 ops.type = TREE_TYPE (arg1);
1114 ops.op0 = make_tree (ops.type, op0);
1115 ops.op1 = make_tree (ops.type, op1);
1116 ops.op2 = NULL_TREE;
1117 ops.location = loc;
1118 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
92344ed0 1119 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1120 NULL, done_label, PROB_VERY_LIKELY);
92344ed0 1121 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1476d1bd 1122 NULL, do_error, PROB_VERY_UNLIKELY);
1304953e
JJ
1123 int prec;
1124 prec = GET_MODE_PRECISION (mode);
1125 rtx sgn;
1126 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
92344ed0 1127 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1476d1bd 1128 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
1129 goto do_error_label;
1130 case 3:
1131 /* Rest of handling of this case after res is computed. */
1132 goto do_main;
1133 default:
1134 gcc_unreachable ();
1135 }
1136 }
31e071ae 1137
1304953e
JJ
1138 /* s1 * s2 -> ur */
1139 if (!uns0_p && !uns1_p && unsr_p)
1140 {
1141 rtx tem, tem2;
1142 switch (pos_neg0 | pos_neg1)
1143 {
1144 case 1: /* Both operands known to be non-negative. */
1145 goto do_main;
1146 case 2: /* Both operands known to be negative. */
1147 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1148 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1149 /* Avoid looking at arg0/arg1 ranges, as we've changed
1150 the arguments. */
1151 arg0 = error_mark_node;
1152 arg1 = error_mark_node;
1153 goto do_main;
1154 case 3:
1155 if ((pos_neg0 ^ pos_neg1) == 3)
1156 {
1157 /* If one operand is known to be negative and the other
1158 non-negative, this overflows always, unless the non-negative
1159 one is 0. Just do normal multiply and set overflow
1160 unless one of the operands is 0. */
1161 struct separate_ops ops;
1162 ops.code = MULT_EXPR;
1163 ops.type
1164 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1165 1);
1166 ops.op0 = make_tree (ops.type, op0);
1167 ops.op1 = make_tree (ops.type, op1);
1168 ops.op2 = NULL_TREE;
1169 ops.location = loc;
1170 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1171 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1172 OPTAB_LIB_WIDEN);
92344ed0 1173 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
1476d1bd 1174 NULL_RTX, NULL, done_label,
92344ed0 1175 PROB_VERY_LIKELY);
1304953e
JJ
1176 goto do_error_label;
1177 }
1178 /* The general case, do all the needed comparisons at runtime. */
1179 rtx_code_label *do_main_label, *after_negate_label;
1180 rtx rop0, rop1;
1181 rop0 = gen_reg_rtx (mode);
1182 rop1 = gen_reg_rtx (mode);
1183 emit_move_insn (rop0, op0);
1184 emit_move_insn (rop1, op1);
1185 op0 = rop0;
1186 op1 = rop1;
1187 do_main_label = gen_label_rtx ();
1188 after_negate_label = gen_label_rtx ();
1189 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1190 OPTAB_LIB_WIDEN);
92344ed0 1191 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1192 NULL, after_negate_label, PROB_VERY_LIKELY);
1304953e
JJ
1193 /* Both arguments negative here, negate them and continue with
1194 normal unsigned overflow checking multiplication. */
1195 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1196 NULL_RTX, false));
1197 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1198 NULL_RTX, false));
1199 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1200 the arguments. */
1201 arg0 = error_mark_node;
1202 arg1 = error_mark_node;
1203 emit_jump (do_main_label);
1204 emit_label (after_negate_label);
1205 tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1206 OPTAB_LIB_WIDEN);
92344ed0 1207 do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1208 NULL, do_main_label, PROB_VERY_LIKELY);
1304953e
JJ
1209 /* One argument is negative here, the other positive. This
1210 overflows always, unless one of the arguments is 0. But
1211 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1212 is, thus we can keep do_main code oring in overflow as is. */
92344ed0 1213 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1214 NULL, do_main_label, PROB_VERY_LIKELY);
1304953e
JJ
1215 write_complex_part (target, const1_rtx, true);
1216 emit_label (do_main_label);
1217 goto do_main;
1218 default:
1219 gcc_unreachable ();
1220 }
1221 }
1222
1223 do_main:
1224 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1225 sign = uns ? UNSIGNED : SIGNED;
1226 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
31e071ae
MP
1227 if (icode != CODE_FOR_nothing)
1228 {
1229 struct expand_operand ops[4];
da664544 1230 rtx_insn *last = get_last_insn ();
31e071ae
MP
1231
1232 res = gen_reg_rtx (mode);
1233 create_output_operand (&ops[0], res, mode);
1234 create_input_operand (&ops[1], op0, mode);
1235 create_input_operand (&ops[2], op1, mode);
1236 create_fixed_operand (&ops[3], do_error);
1237 if (maybe_expand_insn (icode, 4, ops))
1238 {
1239 last = get_last_insn ();
0a6a6ac9 1240 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
31e071ae
MP
1241 && JUMP_P (last)
1242 && any_condjump_p (last)
1243 && !find_reg_note (last, REG_BR_PROB, 0))
1244 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
1245 emit_jump (done_label);
1246 }
1247 else
1248 {
1249 delete_insns_since (last);
1250 icode = CODE_FOR_nothing;
1251 }
1252 }
1253
1254 if (icode == CODE_FOR_nothing)
1255 {
1256 struct separate_ops ops;
1304953e
JJ
1257 int prec = GET_MODE_PRECISION (mode);
1258 machine_mode hmode = mode_for_size (prec / 2, MODE_INT, 1);
1259 ops.op0 = make_tree (type, op0);
1260 ops.op1 = make_tree (type, op1);
31e071ae 1261 ops.op2 = NULL_TREE;
1304953e 1262 ops.location = loc;
31e071ae
MP
1263 if (GET_MODE_2XWIDER_MODE (mode) != VOIDmode
1264 && targetm.scalar_mode_supported_p (GET_MODE_2XWIDER_MODE (mode)))
1265 {
ef4bddc2 1266 machine_mode wmode = GET_MODE_2XWIDER_MODE (mode);
31e071ae
MP
1267 ops.code = WIDEN_MULT_EXPR;
1268 ops.type
1304953e 1269 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
31e071ae
MP
1270
1271 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1304953e
JJ
1272 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1273 NULL_RTX, uns);
31e071ae
MP
1274 hipart = gen_lowpart (mode, hipart);
1275 res = gen_lowpart (mode, res);
1304953e
JJ
1276 if (uns)
1277 /* For the unsigned multiplication, there was overflow if
1278 HIPART is non-zero. */
92344ed0 1279 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1476d1bd 1280 NULL_RTX, NULL, done_label,
92344ed0 1281 PROB_VERY_LIKELY);
1304953e
JJ
1282 else
1283 {
1284 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1285 NULL_RTX, 0);
1286 /* RES is low half of the double width result, HIPART
1287 the high half. There was overflow if
1288 HIPART is different from RES < 0 ? -1 : 0. */
92344ed0 1289 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1476d1bd 1290 NULL_RTX, NULL, done_label,
92344ed0 1291 PROB_VERY_LIKELY);
1304953e 1292 }
31e071ae 1293 }
1304953e 1294 else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
d5fa9cc9 1295 {
da664544
DM
1296 rtx_code_label *large_op0 = gen_label_rtx ();
1297 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1298 rtx_code_label *one_small_one_large = gen_label_rtx ();
1299 rtx_code_label *both_ops_large = gen_label_rtx ();
1304953e
JJ
1300 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1301 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
da664544 1302 rtx_code_label *do_overflow = gen_label_rtx ();
1304953e 1303 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
d5fa9cc9 1304
807e902e 1305 unsigned int hprec = GET_MODE_PRECISION (hmode);
d5fa9cc9 1306 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1304953e 1307 NULL_RTX, uns);
d5fa9cc9
JJ
1308 hipart0 = gen_lowpart (hmode, hipart0);
1309 rtx lopart0 = gen_lowpart (hmode, op0);
1304953e
JJ
1310 rtx signbit0 = const0_rtx;
1311 if (!uns)
1312 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1313 NULL_RTX, 0);
d5fa9cc9 1314 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1304953e 1315 NULL_RTX, uns);
d5fa9cc9
JJ
1316 hipart1 = gen_lowpart (hmode, hipart1);
1317 rtx lopart1 = gen_lowpart (hmode, op1);
1304953e
JJ
1318 rtx signbit1 = const0_rtx;
1319 if (!uns)
1320 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1321 NULL_RTX, 0);
d5fa9cc9
JJ
1322
1323 res = gen_reg_rtx (mode);
1324
1325 /* True if op0 resp. op1 are known to be in the range of
1326 halfstype. */
1327 bool op0_small_p = false;
1328 bool op1_small_p = false;
1329 /* True if op0 resp. op1 are known to have all zeros or all ones
1330 in the upper half of bits, but are not known to be
1331 op{0,1}_small_p. */
1332 bool op0_medium_p = false;
1333 bool op1_medium_p = false;
1334 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
1335 nonnegative, 1 if unknown. */
1336 int op0_sign = 1;
1337 int op1_sign = 1;
1338
1304953e
JJ
1339 if (pos_neg0 == 1)
1340 op0_sign = 0;
1341 else if (pos_neg0 == 2)
1342 op0_sign = -1;
1343 if (pos_neg1 == 1)
1344 op1_sign = 0;
1345 else if (pos_neg1 == 2)
1346 op1_sign = -1;
1347
1348 unsigned int mprec0 = prec;
1349 if (arg0 != error_mark_node)
1350 mprec0 = get_min_precision (arg0, sign);
1351 if (mprec0 <= hprec)
1352 op0_small_p = true;
1353 else if (!uns && mprec0 <= hprec + 1)
1354 op0_medium_p = true;
1355 unsigned int mprec1 = prec;
1356 if (arg1 != error_mark_node)
1357 mprec1 = get_min_precision (arg1, sign);
1358 if (mprec1 <= hprec)
1359 op1_small_p = true;
1360 else if (!uns && mprec1 <= hprec + 1)
1361 op1_medium_p = true;
d5fa9cc9
JJ
1362
1363 int smaller_sign = 1;
1364 int larger_sign = 1;
1365 if (op0_small_p)
1366 {
1367 smaller_sign = op0_sign;
1368 larger_sign = op1_sign;
1369 }
1370 else if (op1_small_p)
1371 {
1372 smaller_sign = op1_sign;
1373 larger_sign = op0_sign;
1374 }
1375 else if (op0_sign == op1_sign)
1376 {
1377 smaller_sign = op0_sign;
1378 larger_sign = op0_sign;
1379 }
1380
1381 if (!op0_small_p)
92344ed0 1382 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1476d1bd 1383 NULL_RTX, NULL, large_op0,
92344ed0 1384 PROB_UNLIKELY);
d5fa9cc9
JJ
1385
1386 if (!op1_small_p)
92344ed0 1387 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1476d1bd 1388 NULL_RTX, NULL, small_op0_large_op1,
d5fa9cc9
JJ
1389 PROB_UNLIKELY);
1390
1304953e
JJ
1391 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
1392 hmode to mode, the multiplication will never overflow. We can
1393 do just one hmode x hmode => mode widening multiplication. */
1394 rtx lopart0s = lopart0, lopart1s = lopart1;
d5fa9cc9
JJ
1395 if (GET_CODE (lopart0) == SUBREG)
1396 {
1304953e
JJ
1397 lopart0s = shallow_copy_rtx (lopart0);
1398 SUBREG_PROMOTED_VAR_P (lopart0s) = 1;
1399 SUBREG_PROMOTED_SET (lopart0s, uns ? SRP_UNSIGNED : SRP_SIGNED);
d5fa9cc9
JJ
1400 }
1401 if (GET_CODE (lopart1) == SUBREG)
1402 {
1304953e
JJ
1403 lopart1s = shallow_copy_rtx (lopart1);
1404 SUBREG_PROMOTED_VAR_P (lopart1s) = 1;
1405 SUBREG_PROMOTED_SET (lopart1s, uns ? SRP_UNSIGNED : SRP_SIGNED);
d5fa9cc9 1406 }
1304953e
JJ
1407 tree halfstype = build_nonstandard_integer_type (hprec, uns);
1408 ops.op0 = make_tree (halfstype, lopart0s);
1409 ops.op1 = make_tree (halfstype, lopart1s);
d5fa9cc9 1410 ops.code = WIDEN_MULT_EXPR;
1304953e 1411 ops.type = type;
d5fa9cc9
JJ
1412 rtx thisres
1413 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1414 emit_move_insn (res, thisres);
1415 emit_jump (done_label);
1416
1417 emit_label (small_op0_large_op1);
1418
1304953e
JJ
1419 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
1420 but op1 is not, just swap the arguments and handle it as op1
1421 sign/zero extended, op0 not. */
d5fa9cc9
JJ
1422 rtx larger = gen_reg_rtx (mode);
1423 rtx hipart = gen_reg_rtx (hmode);
1424 rtx lopart = gen_reg_rtx (hmode);
1425 emit_move_insn (larger, op1);
1426 emit_move_insn (hipart, hipart1);
1427 emit_move_insn (lopart, lopart0);
1428 emit_jump (one_small_one_large);
1429
1430 emit_label (large_op0);
1431
1432 if (!op1_small_p)
92344ed0 1433 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1476d1bd 1434 NULL_RTX, NULL, both_ops_large,
92344ed0 1435 PROB_UNLIKELY);
d5fa9cc9 1436
1304953e
JJ
1437 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
1438 but op0 is not, prepare larger, hipart and lopart pseudos and
1439 handle it together with small_op0_large_op1. */
d5fa9cc9
JJ
1440 emit_move_insn (larger, op0);
1441 emit_move_insn (hipart, hipart0);
1442 emit_move_insn (lopart, lopart1);
1443
1444 emit_label (one_small_one_large);
1445
1446 /* lopart is the low part of the operand that is sign extended
026c3cfd 1447 to mode, larger is the other operand, hipart is the
d5fa9cc9
JJ
1448 high part of larger and lopart0 and lopart1 are the low parts
1449 of both operands.
1450 We perform lopart0 * lopart1 and lopart * hipart widening
1451 multiplications. */
1452 tree halfutype = build_nonstandard_integer_type (hprec, 1);
1453 ops.op0 = make_tree (halfutype, lopart0);
1454 ops.op1 = make_tree (halfutype, lopart1);
1455 rtx lo0xlo1
1456 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1457
1458 ops.op0 = make_tree (halfutype, lopart);
1459 ops.op1 = make_tree (halfutype, hipart);
1460 rtx loxhi = gen_reg_rtx (mode);
1461 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1462 emit_move_insn (loxhi, tem);
1463
1304953e
JJ
1464 if (!uns)
1465 {
1466 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
1467 if (larger_sign == 0)
1468 emit_jump (after_hipart_neg);
1469 else if (larger_sign != -1)
92344ed0 1470 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1476d1bd 1471 NULL_RTX, NULL, after_hipart_neg,
1304953e
JJ
1472 PROB_EVEN);
1473
1474 tem = convert_modes (mode, hmode, lopart, 1);
1475 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
1476 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
1477 1, OPTAB_DIRECT);
1478 emit_move_insn (loxhi, tem);
1479
1480 emit_label (after_hipart_neg);
1481
1482 /* if (lopart < 0) loxhi -= larger; */
1483 if (smaller_sign == 0)
1484 emit_jump (after_lopart_neg);
1485 else if (smaller_sign != -1)
92344ed0 1486 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1476d1bd 1487 NULL_RTX, NULL, after_lopart_neg,
1304953e
JJ
1488 PROB_EVEN);
1489
1490 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1491 1, OPTAB_DIRECT);
1492 emit_move_insn (loxhi, tem);
1493
1494 emit_label (after_lopart_neg);
1495 }
d5fa9cc9
JJ
1496
1497 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
1498 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
1499 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
1500 1, OPTAB_DIRECT);
1501 emit_move_insn (loxhi, tem);
1502
1503 /* if (loxhi >> (bitsize / 2)
1304953e
JJ
1504 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
1505 if (loxhi >> (bitsize / 2) == 0 (if uns). */
d5fa9cc9
JJ
1506 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
1507 NULL_RTX, 0);
1508 hipartloxhi = gen_lowpart (hmode, hipartloxhi);
1304953e
JJ
1509 rtx signbitloxhi = const0_rtx;
1510 if (!uns)
1511 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
1512 gen_lowpart (hmode, loxhi),
1513 hprec - 1, NULL_RTX, 0);
d5fa9cc9 1514
92344ed0 1515 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1476d1bd 1516 NULL_RTX, NULL, do_overflow,
d5fa9cc9
JJ
1517 PROB_VERY_UNLIKELY);
1518
1519 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
1520 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
1521 NULL_RTX, 1);
1522 tem = convert_modes (mode, hmode, gen_lowpart (hmode, lo0xlo1), 1);
1523
1524 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
1525 1, OPTAB_DIRECT);
1526 if (tem != res)
1527 emit_move_insn (res, tem);
1528 emit_jump (done_label);
1529
1530 emit_label (both_ops_large);
1531
1304953e
JJ
1532 /* If both operands are large (not sign (!uns) or zero (uns)
1533 extended from hmode), then perform the full multiplication
1534 which will be the result of the operation.
1535 The only cases which don't overflow are for signed multiplication
1536 some cases where both hipart0 and highpart1 are 0 or -1.
1537 For unsigned multiplication when high parts are both non-zero
1538 this overflows always. */
d5fa9cc9 1539 ops.code = MULT_EXPR;
1304953e
JJ
1540 ops.op0 = make_tree (type, op0);
1541 ops.op1 = make_tree (type, op1);
d5fa9cc9
JJ
1542 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1543 emit_move_insn (res, tem);
1544
1304953e 1545 if (!uns)
d5fa9cc9 1546 {
1304953e
JJ
1547 if (!op0_medium_p)
1548 {
1549 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
1550 NULL_RTX, 1, OPTAB_DIRECT);
92344ed0 1551 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1476d1bd 1552 NULL_RTX, NULL, do_error,
1304953e
JJ
1553 PROB_VERY_UNLIKELY);
1554 }
d5fa9cc9 1555
1304953e
JJ
1556 if (!op1_medium_p)
1557 {
1558 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
1559 NULL_RTX, 1, OPTAB_DIRECT);
92344ed0 1560 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1476d1bd 1561 NULL_RTX, NULL, do_error,
1304953e
JJ
1562 PROB_VERY_UNLIKELY);
1563 }
d5fa9cc9 1564
1304953e
JJ
1565 /* At this point hipart{0,1} are both in [-1, 0]. If they are
1566 the same, overflow happened if res is negative, if they are
1567 different, overflow happened if res is positive. */
1568 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
1569 emit_jump (hipart_different);
1570 else if (op0_sign == 1 || op1_sign == 1)
92344ed0 1571 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1476d1bd 1572 NULL_RTX, NULL, hipart_different,
92344ed0 1573 PROB_EVEN);
d5fa9cc9 1574
92344ed0 1575 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
1476d1bd 1576 NULL_RTX, NULL, do_error,
92344ed0 1577 PROB_VERY_UNLIKELY);
1304953e 1578 emit_jump (done_label);
d5fa9cc9 1579
1304953e
JJ
1580 emit_label (hipart_different);
1581
92344ed0 1582 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1476d1bd 1583 NULL_RTX, NULL, do_error,
92344ed0 1584 PROB_VERY_UNLIKELY);
1304953e
JJ
1585 emit_jump (done_label);
1586 }
d5fa9cc9
JJ
1587
1588 emit_label (do_overflow);
1589
1590 /* Overflow, do full multiplication and fallthru into do_error. */
1304953e
JJ
1591 ops.op0 = make_tree (type, op0);
1592 ops.op1 = make_tree (type, op1);
d5fa9cc9
JJ
1593 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1594 emit_move_insn (res, tem);
1595 }
31e071ae
MP
1596 else
1597 {
1304953e 1598 gcc_assert (!is_ubsan);
31e071ae 1599 ops.code = MULT_EXPR;
1304953e 1600 ops.type = type;
31e071ae
MP
1601 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1602 emit_jump (done_label);
1603 }
1604 }
1605
1304953e 1606 do_error_label:
31e071ae 1607 emit_label (do_error);
1304953e
JJ
1608 if (is_ubsan)
1609 {
1610 /* Expand the ubsan builtin call. */
1611 push_temp_slots ();
1612 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1613 arg0, arg1);
1614 expand_normal (fn);
1615 pop_temp_slots ();
1616 do_pending_stack_adjust ();
1617 }
1618 else if (lhs)
1619 write_complex_part (target, const1_rtx, true);
31e071ae
MP
1620
1621 /* We're done. */
1622 emit_label (done_label);
1623
1304953e
JJ
1624 /* u1 * u2 -> sr */
1625 if (uns0_p && uns1_p && !unsr_p)
1626 {
1627 rtx_code_label *all_done_label = gen_label_rtx ();
92344ed0 1628 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1629 NULL, all_done_label, PROB_VERY_LIKELY);
1304953e
JJ
1630 write_complex_part (target, const1_rtx, true);
1631 emit_label (all_done_label);
1632 }
1633
1634 /* s1 * u2 -> sr */
1635 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
1636 {
1637 rtx_code_label *all_done_label = gen_label_rtx ();
1638 rtx_code_label *set_noovf = gen_label_rtx ();
92344ed0 1639 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1640 NULL, all_done_label, PROB_VERY_LIKELY);
1304953e 1641 write_complex_part (target, const1_rtx, true);
92344ed0 1642 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1643 NULL, set_noovf, PROB_VERY_LIKELY);
92344ed0 1644 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1476d1bd
MM
1645 NULL, all_done_label, PROB_VERY_UNLIKELY);
1646 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
92344ed0 1647 all_done_label, PROB_VERY_UNLIKELY);
1304953e
JJ
1648 emit_label (set_noovf);
1649 write_complex_part (target, const0_rtx, true);
1650 emit_label (all_done_label);
1651 }
1652
31e071ae 1653 if (lhs)
1304953e
JJ
1654 {
1655 if (is_ubsan)
5620052d 1656 expand_ubsan_result_store (target, res);
1304953e
JJ
1657 else
1658 expand_arith_overflow_result_store (lhs, target, mode, res);
1659 }
31e071ae
MP
1660}
1661
1662/* Expand UBSAN_CHECK_ADD call STMT. */
1663
1664static void
4cfe7a6c 1665expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
31e071ae 1666{
1304953e
JJ
1667 location_t loc = gimple_location (stmt);
1668 tree lhs = gimple_call_lhs (stmt);
1669 tree arg0 = gimple_call_arg (stmt, 0);
1670 tree arg1 = gimple_call_arg (stmt, 1);
1671 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
1672 false, false, false, true);
31e071ae
MP
1673}
1674
1675/* Expand UBSAN_CHECK_SUB call STMT. */
1676
1677static void
4cfe7a6c 1678expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
31e071ae 1679{
1304953e
JJ
1680 location_t loc = gimple_location (stmt);
1681 tree lhs = gimple_call_lhs (stmt);
1682 tree arg0 = gimple_call_arg (stmt, 0);
1683 tree arg1 = gimple_call_arg (stmt, 1);
1684 if (integer_zerop (arg0))
1685 expand_neg_overflow (loc, lhs, arg1, true);
31e071ae 1686 else
1304953e
JJ
1687 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
1688 false, false, false, true);
31e071ae
MP
1689}
1690
1691/* Expand UBSAN_CHECK_MUL call STMT. */
1692
1693static void
4cfe7a6c 1694expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
31e071ae 1695{
1304953e
JJ
1696 location_t loc = gimple_location (stmt);
1697 tree lhs = gimple_call_lhs (stmt);
1698 tree arg0 = gimple_call_arg (stmt, 0);
1699 tree arg1 = gimple_call_arg (stmt, 1);
1700 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true);
1701}
1702
1703/* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
1704
1705static void
355fe088 1706expand_arith_overflow (enum tree_code code, gimple *stmt)
1304953e
JJ
1707{
1708 tree lhs = gimple_call_lhs (stmt);
1709 if (lhs == NULL_TREE)
1710 return;
1711 tree arg0 = gimple_call_arg (stmt, 0);
1712 tree arg1 = gimple_call_arg (stmt, 1);
1713 tree type = TREE_TYPE (TREE_TYPE (lhs));
1714 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
1715 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
1716 int unsr_p = TYPE_UNSIGNED (type);
1717 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
1718 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
1719 int precres = TYPE_PRECISION (type);
1720 location_t loc = gimple_location (stmt);
1721 if (!uns0_p && get_range_pos_neg (arg0) == 1)
1722 uns0_p = true;
1723 if (!uns1_p && get_range_pos_neg (arg1) == 1)
1724 uns1_p = true;
1725 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
1726 prec0 = MIN (prec0, pr);
1727 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
1728 prec1 = MIN (prec1, pr);
1729
1730 /* If uns0_p && uns1_p, precop is minimum needed precision
1731 of unsigned type to hold the exact result, otherwise
1732 precop is minimum needed precision of signed type to
1733 hold the exact result. */
1734 int precop;
1735 if (code == MULT_EXPR)
1736 precop = prec0 + prec1 + (uns0_p != uns1_p);
1737 else
1738 {
1739 if (uns0_p == uns1_p)
1740 precop = MAX (prec0, prec1) + 1;
1741 else if (uns0_p)
1742 precop = MAX (prec0 + 1, prec1) + 1;
1743 else
1744 precop = MAX (prec0, prec1 + 1) + 1;
1745 }
1746 int orig_precres = precres;
1747
1748 do
1749 {
1750 if ((uns0_p && uns1_p)
1751 ? ((precop + !unsr_p) <= precres
1752 /* u1 - u2 -> ur can overflow, no matter what precision
1753 the result has. */
1754 && (code != MINUS_EXPR || !unsr_p))
1755 : (!unsr_p && precop <= precres))
1756 {
1757 /* The infinity precision result will always fit into result. */
1758 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1759 write_complex_part (target, const0_rtx, true);
1760 enum machine_mode mode = TYPE_MODE (type);
1761 struct separate_ops ops;
1762 ops.code = code;
1763 ops.type = type;
1764 ops.op0 = fold_convert_loc (loc, type, arg0);
1765 ops.op1 = fold_convert_loc (loc, type, arg1);
1766 ops.op2 = NULL_TREE;
1767 ops.location = loc;
1768 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1769 expand_arith_overflow_result_store (lhs, target, mode, tem);
1770 return;
1771 }
1772
1304953e
JJ
1773 /* For sub-word operations, if target doesn't have them, start
1774 with precres widening right away, otherwise do it only
1775 if the most simple cases can't be used. */
9e11bfef
TS
1776 if (WORD_REGISTER_OPERATIONS
1777 && orig_precres == precres
1778 && precres < BITS_PER_WORD)
1304953e 1779 ;
9e11bfef
TS
1780 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
1781 && prec1 <= precres)
1304953e
JJ
1782 || ((!uns0_p || !uns1_p) && !unsr_p
1783 && prec0 + uns0_p <= precres
1784 && prec1 + uns1_p <= precres))
1785 {
1786 arg0 = fold_convert_loc (loc, type, arg0);
1787 arg1 = fold_convert_loc (loc, type, arg1);
1788 switch (code)
1789 {
1790 case MINUS_EXPR:
1791 if (integer_zerop (arg0) && !unsr_p)
1792 expand_neg_overflow (loc, lhs, arg1, false);
1793 /* FALLTHRU */
1794 case PLUS_EXPR:
1795 expand_addsub_overflow (loc, code, lhs, arg0, arg1,
1796 unsr_p, unsr_p, unsr_p, false);
1797 return;
1798 case MULT_EXPR:
1799 expand_mul_overflow (loc, lhs, arg0, arg1,
1800 unsr_p, unsr_p, unsr_p, false);
1801 return;
1802 default:
1803 gcc_unreachable ();
1804 }
1805 }
1806
1807 /* For sub-word operations, retry with a wider type first. */
1808 if (orig_precres == precres && precop <= BITS_PER_WORD)
1809 {
9e11bfef 1810#if WORD_REGISTER_OPERATIONS
1304953e
JJ
1811 int p = BITS_PER_WORD;
1812#else
1813 int p = precop;
1814#endif
1815 enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
1816 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
1817 uns0_p && uns1_p
1818 && unsr_p);
1819 p = TYPE_PRECISION (optype);
1820 if (p > precres)
1821 {
1822 precres = p;
1823 unsr_p = TYPE_UNSIGNED (optype);
1824 type = optype;
1825 continue;
1826 }
1827 }
1828
1829 if (prec0 <= precres && prec1 <= precres)
1830 {
1831 tree types[2];
1832 if (unsr_p)
1833 {
1834 types[0] = build_nonstandard_integer_type (precres, 0);
1835 types[1] = type;
1836 }
1837 else
1838 {
1839 types[0] = type;
1840 types[1] = build_nonstandard_integer_type (precres, 1);
1841 }
1842 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
1843 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
1844 if (code != MULT_EXPR)
1845 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
1846 uns0_p, uns1_p, false);
1847 else
1848 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
1849 uns0_p, uns1_p, false);
1850 return;
1851 }
1852
1853 /* Retry with a wider type. */
1854 if (orig_precres == precres)
1855 {
1856 int p = MAX (prec0, prec1);
1857 enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
1858 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
1859 uns0_p && uns1_p
1860 && unsr_p);
1861 p = TYPE_PRECISION (optype);
1862 if (p > precres)
1863 {
1864 precres = p;
1865 unsr_p = TYPE_UNSIGNED (optype);
1866 type = optype;
1867 continue;
1868 }
1869 }
1870
1871 gcc_unreachable ();
1872 }
1873 while (1);
1874}
1875
1876/* Expand ADD_OVERFLOW STMT. */
1877
1878static void
4cfe7a6c 1879expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
1880{
1881 expand_arith_overflow (PLUS_EXPR, stmt);
1882}
1883
1884/* Expand SUB_OVERFLOW STMT. */
1885
1886static void
4cfe7a6c 1887expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
1888{
1889 expand_arith_overflow (MINUS_EXPR, stmt);
1890}
1891
1892/* Expand MUL_OVERFLOW STMT. */
1893
1894static void
4cfe7a6c 1895expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
1896{
1897 expand_arith_overflow (MULT_EXPR, stmt);
31e071ae
MP
1898}
1899
5ce9450f
JJ
1900/* This should get folded in tree-vectorizer.c. */
1901
1902static void
4cfe7a6c 1903expand_LOOP_VECTORIZED (internal_fn, gcall *)
5ce9450f
JJ
1904{
1905 gcc_unreachable ();
1906}
1907
ab23f5d9
RS
1908/* Expand MASK_LOAD call STMT using optab OPTAB. */
1909
5ce9450f 1910static void
4cfe7a6c 1911expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
5ce9450f
JJ
1912{
1913 struct expand_operand ops[3];
08554c26 1914 tree type, lhs, rhs, maskt, ptr;
5ce9450f 1915 rtx mem, target, mask;
08554c26 1916 unsigned align;
5ce9450f
JJ
1917
1918 maskt = gimple_call_arg (stmt, 2);
1919 lhs = gimple_call_lhs (stmt);
8e91d222
JJ
1920 if (lhs == NULL_TREE)
1921 return;
5ce9450f 1922 type = TREE_TYPE (lhs);
08554c26
JJ
1923 ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
1924 align = tree_to_shwi (gimple_call_arg (stmt, 1));
1925 if (TYPE_ALIGN (type) != align)
1926 type = build_aligned_type (type, align);
1927 rhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
5ce9450f
JJ
1928
1929 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1930 gcc_assert (MEM_P (mem));
1931 mask = expand_normal (maskt);
1932 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1933 create_output_operand (&ops[0], target, TYPE_MODE (type));
1934 create_fixed_operand (&ops[1], mem);
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
ab23f5d9
RS
1941/* Expand MASK_STORE call STMT using optab OPTAB. */
1942
5ce9450f 1943static void
4cfe7a6c 1944expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
5ce9450f
JJ
1945{
1946 struct expand_operand ops[3];
08554c26 1947 tree type, lhs, rhs, maskt, ptr;
5ce9450f 1948 rtx mem, reg, mask;
08554c26 1949 unsigned align;
5ce9450f
JJ
1950
1951 maskt = gimple_call_arg (stmt, 2);
1952 rhs = gimple_call_arg (stmt, 3);
1953 type = TREE_TYPE (rhs);
08554c26
JJ
1954 ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
1955 align = tree_to_shwi (gimple_call_arg (stmt, 1));
1956 if (TYPE_ALIGN (type) != align)
1957 type = build_aligned_type (type, align);
1958 lhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
5ce9450f
JJ
1959
1960 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1961 gcc_assert (MEM_P (mem));
1962 mask = expand_normal (maskt);
1963 reg = expand_normal (rhs);
1964 create_fixed_operand (&ops[0], mem);
1965 create_input_operand (&ops[1], reg, TYPE_MODE (type));
1966 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
ab23f5d9 1967 expand_insn (convert_optab_handler (optab, TYPE_MODE (type),
045c1278
IE
1968 TYPE_MODE (TREE_TYPE (maskt))),
1969 3, ops);
5ce9450f
JJ
1970}
1971
09b22f48 1972static void
4cfe7a6c 1973expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
09b22f48
JJ
1974{
1975}
1976
ed9c79e1 1977static void
4cfe7a6c 1978expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
ed9c79e1
JJ
1979{
1980 /* When guessing was done, the hints should be already stripped away. */
1981 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
1982
1983 rtx target;
1984 tree lhs = gimple_call_lhs (stmt);
1985 if (lhs)
1986 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1987 else
1988 target = const0_rtx;
1989 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
1990 if (lhs && val != target)
1991 emit_move_insn (target, val);
1992}
1993
f8e89441
TV
1994/* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
1995 should never be called. */
1996
1997static void
4cfe7a6c 1998expand_VA_ARG (internal_fn, gcall *)
f8e89441
TV
1999{
2000 gcc_unreachable ();
2001}
2002
8ab78162
NS
2003/* Expand the IFN_UNIQUE function according to its first argument. */
2004
2005static void
4cfe7a6c 2006expand_UNIQUE (internal_fn, gcall *stmt)
8ab78162
NS
2007{
2008 rtx pattern = NULL_RTX;
2009 enum ifn_unique_kind kind
2010 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
2011
2012 switch (kind)
2013 {
2014 default:
2015 gcc_unreachable ();
2016
2017 case IFN_UNIQUE_UNSPEC:
2018 if (targetm.have_unique ())
2019 pattern = targetm.gen_unique ();
2020 break;
9bd46bc9
NS
2021
2022 case IFN_UNIQUE_OACC_FORK:
2023 case IFN_UNIQUE_OACC_JOIN:
2024 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
2025 {
2026 tree lhs = gimple_call_lhs (stmt);
2027 rtx target = const0_rtx;
2028
2029 if (lhs)
2030 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2031
2032 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
2033 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
2034
2035 if (kind == IFN_UNIQUE_OACC_FORK)
2036 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
2037 else
2038 pattern = targetm.gen_oacc_join (target, data_dep, axis);
2039 }
2040 else
2041 gcc_unreachable ();
2042 break;
8ab78162
NS
2043 }
2044
2045 if (pattern)
2046 emit_insn (pattern);
2047}
2048
9bd46bc9
NS
2049/* The size of an OpenACC compute dimension. */
2050
2051static void
4cfe7a6c 2052expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
9bd46bc9
NS
2053{
2054 tree lhs = gimple_call_lhs (stmt);
2055
2056 if (!lhs)
2057 return;
2058
2059 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2060 if (targetm.have_oacc_dim_size ())
2061 {
2062 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2063 VOIDmode, EXPAND_NORMAL);
2064 emit_insn (targetm.gen_oacc_dim_size (target, dim));
2065 }
2066 else
2067 emit_move_insn (target, GEN_INT (1));
2068}
2069
2070/* The position of an OpenACC execution engine along one compute axis. */
2071
2072static void
4cfe7a6c 2073expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
9bd46bc9
NS
2074{
2075 tree lhs = gimple_call_lhs (stmt);
2076
2077 if (!lhs)
2078 return;
2079
2080 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2081 if (targetm.have_oacc_dim_pos ())
2082 {
2083 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2084 VOIDmode, EXPAND_NORMAL);
2085 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
2086 }
2087 else
2088 emit_move_insn (target, const0_rtx);
2089}
2090
2091/* This is expanded by oacc_device_lower pass. */
2092
2093static void
4cfe7a6c 2094expand_GOACC_LOOP (internal_fn, gcall *)
9bd46bc9
NS
2095{
2096 gcc_unreachable ();
2097}
2098
e5014671
NS
2099/* This is expanded by oacc_device_lower pass. */
2100
2101static void
4cfe7a6c 2102expand_GOACC_REDUCTION (internal_fn, gcall *)
e5014671
NS
2103{
2104 gcc_unreachable ();
2105}
2106
883cabde
RS
2107/* Set errno to EDOM. */
2108
2109static void
2110expand_SET_EDOM (internal_fn, gcall *)
2111{
2112#ifdef TARGET_EDOM
2113#ifdef GEN_ERRNO_RTX
2114 rtx errno_rtx = GEN_ERRNO_RTX;
2115#else
2116 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
2117#endif
2118 emit_move_insn (errno_rtx,
2119 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
2120#else
2121 gcc_unreachable ();
2122#endif
2123}
2124
4cfe7a6c
RS
2125/* Expand a call to FN using the operands in STMT. FN has a single
2126 output operand and NARGS input operands. */
686ee971
RS
2127
2128static void
4cfe7a6c
RS
2129expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
2130 unsigned int nargs)
686ee971
RS
2131{
2132 expand_operand *ops = XALLOCAVEC (expand_operand, nargs + 1);
2133
686ee971
RS
2134 tree_pair types = direct_internal_fn_types (fn, stmt);
2135 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
2136
2137 tree lhs = gimple_call_lhs (stmt);
2138 tree lhs_type = TREE_TYPE (lhs);
2139 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2140 create_output_operand (&ops[0], lhs_rtx, insn_data[icode].operand[0].mode);
2141
2142 for (unsigned int i = 0; i < nargs; ++i)
2143 {
2144 tree rhs = gimple_call_arg (stmt, i);
2145 tree rhs_type = TREE_TYPE (rhs);
2146 rtx rhs_rtx = expand_normal (rhs);
2147 if (INTEGRAL_TYPE_P (rhs_type))
2148 create_convert_operand_from (&ops[i + 1], rhs_rtx,
2149 TYPE_MODE (rhs_type),
2150 TYPE_UNSIGNED (rhs_type));
2151 else
2152 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type));
2153 }
2154
2155 expand_insn (icode, nargs + 1, ops);
2156 if (!rtx_equal_p (lhs_rtx, ops[0].value))
2157 {
ee132692
RS
2158 /* If the return value has an integral type, convert the instruction
2159 result to that type. This is useful for things that return an
2160 int regardless of the size of the input. If the instruction result
2161 is smaller than required, assume that it is signed.
2162
2163 If the return value has a nonintegral type, its mode must match
2164 the instruction result. */
2165 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
2166 {
2167 /* If this is a scalar in a register that is stored in a wider
2168 mode than the declared mode, compute the result into its
2169 declared mode and then convert to the wider mode. */
2170 gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2171 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
2172 convert_move (SUBREG_REG (lhs_rtx), tmp,
2173 SUBREG_PROMOTED_SIGN (lhs_rtx));
2174 }
2175 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
686ee971 2176 emit_move_insn (lhs_rtx, ops[0].value);
ee132692
RS
2177 else
2178 {
2179 gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2180 convert_move (lhs_rtx, ops[0].value, 0);
2181 }
686ee971
RS
2182 }
2183}
2184
2185/* Expanders for optabs that can use expand_direct_optab_fn. */
2186
4cfe7a6c
RS
2187#define expand_unary_optab_fn(FN, STMT, OPTAB) \
2188 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
686ee971 2189
4cfe7a6c
RS
2190#define expand_binary_optab_fn(FN, STMT, OPTAB) \
2191 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
686ee971 2192
ab23f5d9
RS
2193/* RETURN_TYPE and ARGS are a return type and argument list that are
2194 in principle compatible with FN (which satisfies direct_internal_fn_p).
2195 Return the types that should be used to determine whether the
2196 target supports FN. */
2197
2198tree_pair
2199direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
2200{
2201 const direct_internal_fn_info &info = direct_internal_fn (fn);
2202 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
2203 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
2204 return tree_pair (type0, type1);
2205}
2206
2207/* CALL is a call whose return type and arguments are in principle
2208 compatible with FN (which satisfies direct_internal_fn_p). Return the
2209 types that should be used to determine whether the target supports FN. */
2210
2211tree_pair
2212direct_internal_fn_types (internal_fn fn, gcall *call)
2213{
2214 const direct_internal_fn_info &info = direct_internal_fn (fn);
2215 tree op0 = (info.type0 < 0
2216 ? gimple_call_lhs (call)
2217 : gimple_call_arg (call, info.type0));
2218 tree op1 = (info.type1 < 0
2219 ? gimple_call_lhs (call)
2220 : gimple_call_arg (call, info.type1));
2221 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
2222}
2223
2224/* Return true if OPTAB is supported for TYPES (whose modes should be
d95ab70a
RS
2225 the same) when the optimization type is OPT_TYPE. Used for simple
2226 direct optabs. */
ab23f5d9
RS
2227
2228static bool
d95ab70a
RS
2229direct_optab_supported_p (direct_optab optab, tree_pair types,
2230 optimization_type opt_type)
ab23f5d9
RS
2231{
2232 machine_mode mode = TYPE_MODE (types.first);
2233 gcc_checking_assert (mode == TYPE_MODE (types.second));
d95ab70a 2234 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
ab23f5d9
RS
2235}
2236
2237/* Return true if load/store lanes optab OPTAB is supported for
d95ab70a 2238 array type TYPES.first when the optimization type is OPT_TYPE. */
ab23f5d9
RS
2239
2240static bool
d95ab70a
RS
2241multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
2242 optimization_type opt_type)
ab23f5d9 2243{
d95ab70a
RS
2244 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
2245 machine_mode imode = TYPE_MODE (types.first);
2246 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
2247 return (convert_optab_handler (optab, imode, vmode, opt_type)
2248 != CODE_FOR_nothing);
ab23f5d9
RS
2249}
2250
686ee971
RS
2251#define direct_unary_optab_supported_p direct_optab_supported_p
2252#define direct_binary_optab_supported_p direct_optab_supported_p
ab23f5d9
RS
2253#define direct_mask_load_optab_supported_p direct_optab_supported_p
2254#define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
2255#define direct_mask_store_optab_supported_p direct_optab_supported_p
2256#define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
2257
d95ab70a
RS
2258/* Return true if FN is supported for the types in TYPES when the
2259 optimization type is OPT_TYPE. The types are those associated with
2260 the "type0" and "type1" fields of FN's direct_internal_fn_info
2261 structure. */
ab23f5d9
RS
2262
2263bool
d95ab70a
RS
2264direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
2265 optimization_type opt_type)
ab23f5d9
RS
2266{
2267 switch (fn)
2268 {
2269#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
2270 case IFN_##CODE: break;
2271#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
2272 case IFN_##CODE: \
d95ab70a
RS
2273 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
2274 opt_type);
ab23f5d9
RS
2275#include "internal-fn.def"
2276
2277 case IFN_LAST:
2278 break;
2279 }
2280 gcc_unreachable ();
2281}
2282
d95ab70a
RS
2283/* Return true if FN is supported for type TYPE when the optimization
2284 type is OPT_TYPE. The caller knows that the "type0" and "type1"
2285 fields of FN's direct_internal_fn_info structure are the same. */
ab23f5d9
RS
2286
2287bool
d95ab70a
RS
2288direct_internal_fn_supported_p (internal_fn fn, tree type,
2289 optimization_type opt_type)
ab23f5d9
RS
2290{
2291 const direct_internal_fn_info &info = direct_internal_fn (fn);
2292 gcc_checking_assert (info.type0 == info.type1);
d95ab70a 2293 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
ab23f5d9
RS
2294}
2295
883cabde
RS
2296/* Return true if IFN_SET_EDOM is supported. */
2297
2298bool
2299set_edom_supported_p (void)
2300{
2301#ifdef TARGET_EDOM
2302 return true;
2303#else
2304 return false;
2305#endif
2306}
2307
ab23f5d9
RS
2308#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
2309 static void \
4cfe7a6c 2310 expand_##CODE (internal_fn fn, gcall *stmt) \
ab23f5d9 2311 { \
4cfe7a6c 2312 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
ab23f5d9
RS
2313 }
2314#include "internal-fn.def"
2315
25583c4f
RS
2316/* Routines to expand each internal function, indexed by function number.
2317 Each routine has the prototype:
2318
538dd0b7 2319 expand_<NAME> (gcall *stmt)
25583c4f
RS
2320
2321 where STMT is the statement that performs the call. */
4cfe7a6c 2322static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
b78475cf 2323#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
25583c4f 2324#include "internal-fn.def"
25583c4f
RS
2325 0
2326};
2327
4cfe7a6c
RS
2328/* Expand STMT as though it were a call to internal function FN. */
2329
2330void
2331expand_internal_call (internal_fn fn, gcall *stmt)
2332{
2333 internal_fn_expanders[fn] (fn, stmt);
2334}
2335
25583c4f
RS
2336/* Expand STMT, which is a call to internal function FN. */
2337
2338void
538dd0b7 2339expand_internal_call (gcall *stmt)
25583c4f 2340{
4cfe7a6c 2341 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
25583c4f 2342}