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