IA MCU psABI support: changes to libraries
[gcc.git] / gcc / builtins.c
index 29ddde8742a3fc677a0e3583842c5ca9793d3066..4dc8a15338462a0c0dee9b16ea13caa677c5e918 100644 (file)
@@ -1,5 +1,5 @@
 /* Expand builtin functions.
-   Copyright (C) 1988-2014 Free Software Foundation, Inc.
+   Copyright (C) 1988-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,34 +21,42 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "machmode.h"
 #include "rtl.h"
+#include "alias.h"
+#include "symtab.h"
 #include "tree.h"
+#include "fold-const.h"
 #include "stringpool.h"
 #include "stor-layout.h"
 #include "calls.h"
 #include "varasm.h"
 #include "tree-object-size.h"
 #include "realmpfr.h"
+#include "predict.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "cfgrtl.h"
 #include "basic-block.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
 #include "gimple-expr.h"
-#include "is-a.h"
 #include "gimple.h"
 #include "flags.h"
 #include "regs.h"
-#include "hard-reg-set.h"
 #include "except.h"
-#include "function.h"
 #include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "emit-rtl.h"
+#include "stmt.h"
 #include "expr.h"
+#include "insn-codes.h"
 #include "optabs.h"
 #include "libfuncs.h"
 #include "recog.h"
 #include "output.h"
 #include "typeclass.h"
-#include "predict.h"
 #include "tm_p.h"
 #include "target.h"
 #include "langhooks.h"
@@ -57,8 +65,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "value-prof.h"
 #include "diagnostic-core.h"
 #include "builtins.h"
-#include "ubsan.h"
+#include "asan.h"
 #include "cilk.h"
+#include "lto-streamer.h"
+#include "cgraph.h"
+#include "tree-chkp.h"
+#include "rtl-chkp.h"
+#include "gomp-constants.h"
 
 
 static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
@@ -79,14 +92,14 @@ const char * built_in_names[(int) END_BUILTINS] =
 };
 #undef DEF_BUILTIN
 
-/* Setup an array of _DECL trees, make sure each element is
+/* Setup an array of builtin_info_type, make sure each element decl is
    initialized to NULL_TREE.  */
-builtin_info_type builtin_info;
+builtin_info_type builtin_info[(int)END_BUILTINS];
 
 /* Non-zero if __builtin_constant_p should be folded right away.  */
 bool force_folding_builtin_constant_p;
 
-static rtx c_readstr (const char *, enum machine_mode);
+static rtx c_readstr (const char *, machine_mode);
 static int target_char_cast (tree, char *);
 static rtx get_memory_rtx (tree, tree);
 static int apply_args_size (void);
@@ -94,7 +107,6 @@ static int apply_result_size (void);
 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
 static rtx result_vector (int, rtx);
 #endif
-static void expand_builtin_update_setjmp_buf (rtx);
 static void expand_builtin_prefetch (tree);
 static rtx expand_builtin_apply_args (void);
 static rtx expand_builtin_apply_args_1 (void);
@@ -116,25 +128,29 @@ static rtx expand_builtin_next_arg (void);
 static rtx expand_builtin_va_start (tree);
 static rtx expand_builtin_va_end (tree);
 static rtx expand_builtin_va_copy (tree);
-static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
+static rtx expand_builtin_memcmp (tree, rtx, machine_mode);
 static rtx expand_builtin_strcmp (tree, rtx);
-static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
-static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
+static rtx expand_builtin_strncmp (tree, rtx, machine_mode);
+static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, machine_mode);
 static rtx expand_builtin_memcpy (tree, rtx);
-static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
+static rtx expand_builtin_memcpy_with_bounds (tree, rtx);
+static rtx expand_builtin_memcpy_args (tree, tree, tree, rtx, tree);
+static rtx expand_builtin_mempcpy (tree, rtx, machine_mode);
+static rtx expand_builtin_mempcpy_with_bounds (tree, rtx, machine_mode);
 static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
-                                       enum machine_mode, int);
+                                       machine_mode, int, tree);
 static rtx expand_builtin_strcpy (tree, rtx);
 static rtx expand_builtin_strcpy_args (tree, tree, rtx);
-static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
+static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
 static rtx expand_builtin_strncpy (tree, rtx);
-static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
-static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
-static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
+static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, machine_mode);
+static rtx expand_builtin_memset (tree, rtx, machine_mode);
+static rtx expand_builtin_memset_with_bounds (tree, rtx, machine_mode);
+static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree);
 static rtx expand_builtin_bzero (tree);
-static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
+static rtx expand_builtin_strlen (tree, rtx, machine_mode);
 static rtx expand_builtin_alloca (tree, bool);
-static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
+static rtx expand_builtin_unop (machine_mode, tree, rtx, rtx, optab);
 static rtx expand_builtin_frame_address (tree, tree);
 static tree stabilize_va_list_loc (location_t, tree, int);
 static rtx expand_builtin_expect (tree, rtx);
@@ -176,41 +192,33 @@ static tree fold_builtin_fabs (location_t, tree, tree);
 static tree fold_builtin_abs (location_t, tree, tree);
 static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code,
                                        enum tree_code);
-static tree fold_builtin_n (location_t, tree, tree *, int, bool);
-static tree fold_builtin_0 (location_t, tree, bool);
-static tree fold_builtin_1 (location_t, tree, tree, bool);
-static tree fold_builtin_2 (location_t, tree, tree, tree, bool);
-static tree fold_builtin_3 (location_t, tree, tree, tree, tree, bool);
-static tree fold_builtin_4 (location_t, tree, tree, tree, tree, tree, bool);
-static tree fold_builtin_varargs (location_t, tree, tree, bool);
+static tree fold_builtin_0 (location_t, tree);
+static tree fold_builtin_1 (location_t, tree, tree);
+static tree fold_builtin_2 (location_t, tree, tree, tree);
+static tree fold_builtin_3 (location_t, tree, tree, tree, tree);
+static tree fold_builtin_varargs (location_t, tree, tree*, int);
 
 static tree fold_builtin_strpbrk (location_t, tree, tree, tree);
 static tree fold_builtin_strstr (location_t, tree, tree, tree);
 static tree fold_builtin_strrchr (location_t, tree, tree, tree);
-static tree fold_builtin_strncat (location_t, tree, tree, tree);
 static tree fold_builtin_strspn (location_t, tree, tree);
 static tree fold_builtin_strcspn (location_t, tree, tree);
 
 static rtx expand_builtin_object_size (tree);
-static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
+static rtx expand_builtin_memory_chk (tree, rtx, machine_mode,
                                      enum built_in_function);
 static void maybe_emit_chk_warning (tree, enum built_in_function);
 static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
 static void maybe_emit_free_warning (tree);
 static tree fold_builtin_object_size (tree, tree);
-static tree fold_builtin_strcat_chk (location_t, tree, tree, tree, tree);
-static tree fold_builtin_strncat_chk (location_t, tree, tree, tree, tree, tree);
-static tree fold_builtin_printf (location_t, tree, tree, tree, bool, enum built_in_function);
-static tree fold_builtin_fprintf (location_t, tree, tree, tree, tree, bool,
-                                 enum built_in_function);
 
-static unsigned HOST_WIDE_INT target_newline;
+unsigned HOST_WIDE_INT target_newline;
 unsigned HOST_WIDE_INT target_percent;
 static unsigned HOST_WIDE_INT target_c;
 static unsigned HOST_WIDE_INT target_s;
-static char target_percent_c[3];
+char target_percent_c[3];
 char target_percent_s[3];
-static char target_percent_s_newline[4];
+char target_percent_s_newline[4];
 static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t),
                          const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool);
 static tree do_mpfr_arg2 (tree, tree, tree,
@@ -287,7 +295,7 @@ get_object_alignment_2 (tree exp, unsigned int *alignp,
 {
   HOST_WIDE_INT bitsize, bitpos;
   tree offset;
-  enum machine_mode mode;
+  machine_mode mode;
   int unsignedp, volatilep;
   unsigned int align = BITS_PER_UNIT;
   bool known_alignment = false;
@@ -337,13 +345,15 @@ get_object_alignment_2 (tree exp, unsigned int *alignp,
       tree addr = TREE_OPERAND (exp, 0);
       unsigned ptr_align;
       unsigned HOST_WIDE_INT ptr_bitpos;
+      unsigned HOST_WIDE_INT ptr_bitmask = ~0;
 
+      /* If the address is explicitely aligned, handle that.  */
       if (TREE_CODE (addr) == BIT_AND_EXPR
          && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
        {
-         align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
-                   & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
-         align *= BITS_PER_UNIT;
+         ptr_bitmask = TREE_INT_CST_LOW (TREE_OPERAND (addr, 1));
+         ptr_bitmask *= BITS_PER_UNIT;
+         align = ptr_bitmask & -ptr_bitmask;
          addr = TREE_OPERAND (addr, 0);
        }
 
@@ -351,6 +361,9 @@ get_object_alignment_2 (tree exp, unsigned int *alignp,
        = get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
       align = MAX (ptr_align, align);
 
+      /* Re-apply explicit alignment to the bitpos.  */
+      ptr_bitpos &= ptr_bitmask;
+
       /* The alignment of the pointer operand in a TARGET_MEM_REF
         has to take the variable offset parts into account.  */
       if (TREE_CODE (exp) == TARGET_MEM_REF)
@@ -649,7 +662,7 @@ c_getstr (tree src)
    GET_MODE_BITSIZE (MODE) bits from string constant STR.  */
 
 static rtx
-c_readstr (const char *str, enum machine_mode mode)
+c_readstr (const char *str, machine_mode mode)
 {
   HOST_WIDE_INT ch;
   unsigned int i, j;
@@ -775,10 +788,8 @@ expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
      register.  There is no way to access it off of the current frame
      pointer, but it can be accessed off the previous frame pointer by
      reading the value from the register window save area.  */
-#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
-  if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
+  if (RETURN_ADDR_IN_PREVIOUS_FRAME && fndecl_code == BUILT_IN_RETURN_ADDRESS)
     count--;
-#endif
 
   /* Scan back COUNT frames to the specified frame.  */
   for (i = 0; i < count; i++)
@@ -823,7 +834,7 @@ static alias_set_type setjmp_alias_set = -1;
 void
 expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
 {
-  enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
+  machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
   rtx stack_save;
   rtx mem;
 
@@ -965,8 +976,9 @@ expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
 static void
 expand_builtin_longjmp (rtx buf_addr, rtx value)
 {
-  rtx fp, lab, stack, insn, last;
-  enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
+  rtx fp, lab, stack;
+  rtx_insn *insn, *last;
+  machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
 
   /* DRAP is needed for stack realign if longjmp is expanded to current
      function  */
@@ -1109,7 +1121,8 @@ static rtx
 expand_builtin_nonlocal_goto (tree exp)
 {
   tree t_label, t_save_area;
-  rtx r_label, r_save_area, r_fp, r_sp, insn;
+  rtx r_label, r_save_area, r_fp, r_sp;
+  rtx_insn *insn;
 
   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
     return NULL_RTX;
@@ -1186,13 +1199,13 @@ expand_builtin_nonlocal_goto (tree exp)
 
 /* __builtin_update_setjmp_buf is passed a pointer to an array of five words
    (not all will be used on all machines) that was passed to __builtin_setjmp.
-   It updates the stack pointer in that block to correspond to the current
-   stack pointer.  */
+   It updates the stack pointer in that block to the current value.  This is
+   also called directly by the SJLJ exception handling code.  */
 
-static void
+void
 expand_builtin_update_setjmp_buf (rtx buf_addr)
 {
-  enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
+  machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
   rtx stack_save
     = gen_rtx_MEM (sa_mode,
                   memory_address
@@ -1354,7 +1367,7 @@ apply_args_size (void)
   static int size = -1;
   int align;
   unsigned int regno;
-  enum machine_mode mode;
+  machine_mode mode;
 
   /* The values computed by this function never change.  */
   if (size < 0)
@@ -1396,7 +1409,7 @@ apply_result_size (void)
 {
   static int size = -1;
   int align, regno;
-  enum machine_mode mode;
+  machine_mode mode;
 
   /* The values computed by this function never change.  */
   if (size < 0)
@@ -1437,7 +1450,7 @@ static rtx
 result_vector (int savep, rtx result)
 {
   int regno, size, align, nelts;
-  enum machine_mode mode;
+  machine_mode mode;
   rtx reg, mem;
   rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
 
@@ -1451,8 +1464,8 @@ result_vector (int savep, rtx result)
        reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
        mem = adjust_address (result, mode, size);
        savevec[nelts++] = (savep
-                           ? gen_rtx_SET (VOIDmode, mem, reg)
-                           : gen_rtx_SET (VOIDmode, reg, mem));
+                           ? gen_rtx_SET (mem, reg)
+                           : gen_rtx_SET (reg, mem));
        size += GET_MODE_SIZE (mode);
       }
   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
@@ -1467,7 +1480,7 @@ expand_builtin_apply_args_1 (void)
 {
   rtx registers, tem;
   int size, align, regno;
-  enum machine_mode mode;
+  machine_mode mode;
   rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
 
   /* Create a block where the arg-pointer, structure value address,
@@ -1495,14 +1508,14 @@ expand_builtin_apply_args_1 (void)
 
   /* Save the arg pointer to the block.  */
   tem = copy_to_reg (crtl->args.internal_arg_pointer);
-#ifdef STACK_GROWS_DOWNWARD
   /* We need the pointer as the caller actually passed them to us, not
      as we might have pretended they were passed.  Make sure it's a valid
      operand, as emit_move_insn isn't expected to handle a PLUS.  */
-  tem
-    = force_operand (plus_constant (Pmode, tem, crtl->args.pretend_args_size),
-                    NULL_RTX);
-#endif
+  if (STACK_GROWS_DOWNWARD)
+    tem
+      = force_operand (plus_constant (Pmode, tem,
+                                     crtl->args.pretend_args_size),
+                      NULL_RTX);
   emit_move_insn (adjust_address (registers, Pmode, 0), tem);
 
   size = GET_MODE_SIZE (Pmode);
@@ -1539,11 +1552,10 @@ expand_builtin_apply_args (void)
        saved on entry to this function.  So we migrate the
        call to the first insn of this function.  */
     rtx temp;
-    rtx seq;
 
     start_sequence ();
     temp = expand_builtin_apply_args_1 ();
-    seq = get_insns ();
+    rtx_insn *seq = get_insns ();
     end_sequence ();
 
     apply_args_value = temp;
@@ -1572,8 +1584,9 @@ static rtx
 expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
 {
   int size, align, regno;
-  enum machine_mode mode;
-  rtx incoming_args, result, reg, dest, src, call_insn;
+  machine_mode mode;
+  rtx incoming_args, result, reg, dest, src;
+  rtx_call_insn *call_insn;
   rtx old_stack_level = 0;
   rtx call_fusage = 0;
   rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
@@ -1586,10 +1599,9 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
   /* Fetch the arg pointer from the ARGUMENTS block.  */
   incoming_args = gen_reg_rtx (Pmode);
   emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
-#ifndef STACK_GROWS_DOWNWARD
-  incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
-                                      incoming_args, 0, OPTAB_LIB_WIDEN);
-#endif
+  if (!STACK_GROWS_DOWNWARD)
+    incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
+                                        incoming_args, 0, OPTAB_LIB_WIDEN);
 
   /* Push a new argument block and copy the arguments.  Do not allow
      the (potential) memcpy call below to interfere with our stack
@@ -1619,12 +1631,13 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
     crtl->need_drap = true;
 
   dest = virtual_outgoing_args_rtx;
-#ifndef STACK_GROWS_DOWNWARD
-  if (CONST_INT_P (argsize))
-    dest = plus_constant (Pmode, dest, -INTVAL (argsize));
-  else
-    dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
-#endif
+  if (!STACK_GROWS_DOWNWARD)
+    {
+      if (CONST_INT_P (argsize))
+       dest = plus_constant (Pmode, dest, -INTVAL (argsize));
+      else
+       dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
+    }
   dest = gen_rtx_MEM (BLKmode, dest);
   set_mem_align (dest, PARM_BOUNDARY);
   src = gen_rtx_MEM (BLKmode, incoming_args);
@@ -1738,9 +1751,9 @@ static void
 expand_builtin_return (rtx result)
 {
   int size, align, regno;
-  enum machine_mode mode;
+  machine_mode mode;
   rtx reg;
-  rtx call_fusage = 0;
+  rtx_insn *call_fusage = 0;
 
   result = convert_memory_address (Pmode, result);
 
@@ -1968,12 +1981,12 @@ mathfn_built_in (tree type, enum built_in_function fn)
 static void
 expand_errno_check (tree exp, rtx target)
 {
-  rtx lab = gen_label_rtx ();
+  rtx_code_label *lab = gen_label_rtx ();
 
   /* Test the result; if it is NaN, set errno=EDOM because
      the argument was not in the domain.  */
   do_compare_rtx_and_jump (target, target, EQ, 0, GET_MODE (target),
-                          NULL_RTX, NULL_RTX, lab,
+                          NULL_RTX, NULL, lab,
                           /* The jump is very likely.  */
                           REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1));
 
@@ -2015,9 +2028,10 @@ static rtx
 expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
 {
   optab builtin_optab;
-  rtx op0, insns;
+  rtx op0;
+  rtx_insn *insns;
   tree fndecl = get_callee_fndecl (exp);
-  enum machine_mode mode;
+  machine_mode mode;
   bool errno_set = false;
   bool try_widening = false;
   tree arg;
@@ -2141,11 +2155,12 @@ static rtx
 expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
 {
   optab builtin_optab;
-  rtx op0, op1, insns, result;
+  rtx op0, op1, result;
+  rtx_insn *insns;
   int op1_type = REAL_TYPE;
   tree fndecl = get_callee_fndecl (exp);
   tree arg0, arg1;
-  enum machine_mode mode;
+  machine_mode mode;
   bool errno_set = true;
 
   switch (DECL_FUNCTION_CODE (fndecl))
@@ -2250,10 +2265,11 @@ static rtx
 expand_builtin_mathfn_ternary (tree exp, rtx target, rtx subtarget)
 {
   optab builtin_optab;
-  rtx op0, op1, op2, insns, result;
+  rtx op0, op1, op2, result;
+  rtx_insn *insns;
   tree fndecl = get_callee_fndecl (exp);
   tree arg0, arg1, arg2;
-  enum machine_mode mode;
+  machine_mode mode;
 
   if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, REAL_TYPE, VOID_TYPE))
     return NULL_RTX;
@@ -2323,9 +2339,10 @@ static rtx
 expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
 {
   optab builtin_optab;
-  rtx op0, insns;
+  rtx op0;
+  rtx_insn *insns;
   tree fndecl = get_callee_fndecl (exp);
-  enum machine_mode mode;
+  machine_mode mode;
   tree arg;
 
   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
@@ -2421,7 +2438,7 @@ interclass_mathfn_icode (tree arg, tree fndecl)
 {
   bool errno_set = false;
   optab builtin_optab = unknown_optab;
-  enum machine_mode mode;
+  machine_mode mode;
 
   switch (DECL_FUNCTION_CODE (fndecl))
     {
@@ -2469,7 +2486,7 @@ expand_builtin_interclass_mathfn (tree exp, rtx target)
   enum insn_code icode = CODE_FOR_nothing;
   rtx op0;
   tree fndecl = get_callee_fndecl (exp);
-  enum machine_mode mode;
+  machine_mode mode;
   tree arg;
 
   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
@@ -2482,7 +2499,7 @@ expand_builtin_interclass_mathfn (tree exp, rtx target)
   if (icode != CODE_FOR_nothing)
     {
       struct expand_operand ops[1];
-      rtx last = get_last_insn ();
+      rtx_insn *last = get_last_insn ();
       tree orig_arg = arg;
 
       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
@@ -2516,7 +2533,7 @@ static rtx
 expand_builtin_sincos (tree exp)
 {
   rtx op0, op1, op2, target1, target2;
-  enum machine_mode mode;
+  machine_mode mode;
   tree arg, sinp, cosp;
   int result;
   location_t loc = EXPR_LOCATION (exp);
@@ -2570,7 +2587,7 @@ expand_builtin_cexpi (tree exp, rtx target)
 {
   tree fndecl = get_callee_fndecl (exp);
   tree arg, type;
-  enum machine_mode mode;
+  machine_mode mode;
   rtx op0, op1, op2;
   location_t loc = EXPR_LOCATION (exp);
 
@@ -2700,11 +2717,12 @@ static rtx
 expand_builtin_int_roundingfn (tree exp, rtx target)
 {
   convert_optab builtin_optab;
-  rtx op0, insns, tmp;
+  rtx op0, tmp;
+  rtx_insn *insns;
   tree fndecl = get_callee_fndecl (exp);
   enum built_in_function fallback_fn;
   tree fallback_fndecl;
-  enum machine_mode mode;
+  machine_mode mode;
   tree arg;
 
   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
@@ -2836,10 +2854,11 @@ static rtx
 expand_builtin_int_roundingfn_2 (tree exp, rtx target)
 {
   convert_optab builtin_optab;
-  rtx op0, insns;
+  rtx op0;
+  rtx_insn *insns;
   tree fndecl = get_callee_fndecl (exp);
   tree arg;
-  enum machine_mode mode;
+  machine_mode mode;
   enum built_in_function fallback_fn = BUILT_IN_NONE;
 
   if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
@@ -2937,8 +2956,8 @@ expand_builtin_powi (tree exp, rtx target)
 {
   tree arg0, arg1;
   rtx op0, op1;
-  enum machine_mode mode;
-  enum machine_mode mode2;
+  machine_mode mode;
+  machine_mode mode2;
 
   if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
     return NULL_RTX;
@@ -2975,7 +2994,7 @@ expand_builtin_powi (tree exp, rtx target)
 
 static rtx
 expand_builtin_strlen (tree exp, rtx target,
-                      enum machine_mode target_mode)
+                      machine_mode target_mode)
 {
   if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
     return NULL_RTX;
@@ -2985,8 +3004,9 @@ expand_builtin_strlen (tree exp, rtx target,
       rtx pat;
       tree len;
       tree src = CALL_EXPR_ARG (exp, 0);
-      rtx src_reg, before_strlen;
-      enum machine_mode insn_mode = target_mode;
+      rtx src_reg;
+      rtx_insn *before_strlen;
+      machine_mode insn_mode = target_mode;
       enum insn_code icode = CODE_FOR_nothing;
       unsigned int align;
 
@@ -3079,7 +3099,7 @@ expand_builtin_strlen (tree exp, rtx target,
 
 static rtx
 builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
-                        enum machine_mode mode)
+                        machine_mode mode)
 {
   const char *str = (const char *) data;
 
@@ -3157,6 +3177,81 @@ determine_block_size (tree len, rtx len_rtx,
                          GET_MODE_MASK (GET_MODE (len_rtx)));
 }
 
+/* Helper function to do the actual work for expand_builtin_memcpy.  */
+
+static rtx
+expand_builtin_memcpy_args (tree dest, tree src, tree len, rtx target, tree exp)
+{
+  const char *src_str;
+  unsigned int src_align = get_pointer_alignment (src);
+  unsigned int dest_align = get_pointer_alignment (dest);
+  rtx dest_mem, src_mem, dest_addr, len_rtx;
+  HOST_WIDE_INT expected_size = -1;
+  unsigned int expected_align = 0;
+  unsigned HOST_WIDE_INT min_size;
+  unsigned HOST_WIDE_INT max_size;
+  unsigned HOST_WIDE_INT probable_max_size;
+
+  /* If DEST is not a pointer type, call the normal function.  */
+  if (dest_align == 0)
+    return NULL_RTX;
+
+  /* If either SRC is not a pointer type, don't do this
+     operation in-line.  */
+  if (src_align == 0)
+    return NULL_RTX;
+
+  if (currently_expanding_gimple_stmt)
+    stringop_block_profile (currently_expanding_gimple_stmt,
+                           &expected_align, &expected_size);
+
+  if (expected_align < dest_align)
+    expected_align = dest_align;
+  dest_mem = get_memory_rtx (dest, len);
+  set_mem_align (dest_mem, dest_align);
+  len_rtx = expand_normal (len);
+  determine_block_size (len, len_rtx, &min_size, &max_size,
+                       &probable_max_size);
+  src_str = c_getstr (src);
+
+  /* If SRC is a string constant and block move would be done
+     by pieces, we can avoid loading the string from memory
+     and only stored the computed constants.  */
+  if (src_str
+      && CONST_INT_P (len_rtx)
+      && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
+      && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
+                             CONST_CAST (char *, src_str),
+                             dest_align, false))
+    {
+      dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
+                                 builtin_memcpy_read_str,
+                                 CONST_CAST (char *, src_str),
+                                 dest_align, false, 0);
+      dest_mem = force_operand (XEXP (dest_mem, 0), target);
+      dest_mem = convert_memory_address (ptr_mode, dest_mem);
+      return dest_mem;
+    }
+
+  src_mem = get_memory_rtx (src, len);
+  set_mem_align (src_mem, src_align);
+
+  /* Copy word part most expediently.  */
+  dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
+                                    CALL_EXPR_TAILCALL (exp)
+                                    ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
+                                    expected_align, expected_size,
+                                    min_size, max_size, probable_max_size);
+
+  if (dest_addr == 0)
+    {
+      dest_addr = force_operand (XEXP (dest_mem, 0), target);
+      dest_addr = convert_memory_address (ptr_mode, dest_addr);
+    }
+
+  return dest_addr;
+}
+
 /* Expand a call EXP to the memcpy builtin.
    Return NULL_RTX if we failed, the caller should emit a normal call,
    otherwise try to get the result in TARGET, if convenient (and in
@@ -3173,73 +3268,38 @@ expand_builtin_memcpy (tree exp, rtx target)
       tree dest = CALL_EXPR_ARG (exp, 0);
       tree src = CALL_EXPR_ARG (exp, 1);
       tree len = CALL_EXPR_ARG (exp, 2);
-      const char *src_str;
-      unsigned int src_align = get_pointer_alignment (src);
-      unsigned int dest_align = get_pointer_alignment (dest);
-      rtx dest_mem, src_mem, dest_addr, len_rtx;
-      HOST_WIDE_INT expected_size = -1;
-      unsigned int expected_align = 0;
-      unsigned HOST_WIDE_INT min_size;
-      unsigned HOST_WIDE_INT max_size;
-      unsigned HOST_WIDE_INT probable_max_size;
-
-      /* If DEST is not a pointer type, call the normal function.  */
-      if (dest_align == 0)
-       return NULL_RTX;
-
-      /* If either SRC is not a pointer type, don't do this
-        operation in-line.  */
-      if (src_align == 0)
-       return NULL_RTX;
-
-      if (currently_expanding_gimple_stmt)
-        stringop_block_profile (currently_expanding_gimple_stmt,
-                               &expected_align, &expected_size);
-
-      if (expected_align < dest_align)
-       expected_align = dest_align;
-      dest_mem = get_memory_rtx (dest, len);
-      set_mem_align (dest_mem, dest_align);
-      len_rtx = expand_normal (len);
-      determine_block_size (len, len_rtx, &min_size, &max_size,
-                           &probable_max_size);
-      src_str = c_getstr (src);
-
-      /* If SRC is a string constant and block move would be done
-        by pieces, we can avoid loading the string from memory
-        and only stored the computed constants.  */
-      if (src_str
-         && CONST_INT_P (len_rtx)
-         && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
-         && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
-                                 CONST_CAST (char *, src_str),
-                                 dest_align, false))
-       {
-         dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
-                                     builtin_memcpy_read_str,
-                                     CONST_CAST (char *, src_str),
-                                     dest_align, false, 0);
-         dest_mem = force_operand (XEXP (dest_mem, 0), target);
-         dest_mem = convert_memory_address (ptr_mode, dest_mem);
-         return dest_mem;
-       }
+      return expand_builtin_memcpy_args (dest, src, len, target, exp);
+    }
+}
 
-      src_mem = get_memory_rtx (src, len);
-      set_mem_align (src_mem, src_align);
+/* Expand an instrumented call EXP to the memcpy builtin.
+   Return NULL_RTX if we failed, the caller should emit a normal call,
+   otherwise try to get the result in TARGET, if convenient (and in
+   mode MODE if that's convenient).  */
 
-      /* Copy word part most expediently.  */
-      dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
-                                        CALL_EXPR_TAILCALL (exp)
-                                        ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
-                                        expected_align, expected_size,
-                                        min_size, max_size, probable_max_size);
+static rtx
+expand_builtin_memcpy_with_bounds (tree exp, rtx target)
+{
+  if (!validate_arglist (exp,
+                        POINTER_TYPE, POINTER_BOUNDS_TYPE,
+                        POINTER_TYPE, POINTER_BOUNDS_TYPE,
+                        INTEGER_TYPE, VOID_TYPE))
+    return NULL_RTX;
+  else
+    {
+      tree dest = CALL_EXPR_ARG (exp, 0);
+      tree src = CALL_EXPR_ARG (exp, 2);
+      tree len = CALL_EXPR_ARG (exp, 4);
+      rtx res = expand_builtin_memcpy_args (dest, src, len, target, exp);
 
-      if (dest_addr == 0)
+      /* Return src bounds with the result.  */
+      if (res)
        {
-         dest_addr = force_operand (XEXP (dest_mem, 0), target);
-         dest_addr = convert_memory_address (ptr_mode, dest_addr);
+         rtx bnd = force_reg (targetm.chkp_bound_mode (),
+                              expand_normal (CALL_EXPR_ARG (exp, 1)));
+         res = chkp_join_splitted_slot (res, bnd);
        }
-      return dest_addr;
+      return res;
     }
 }
 
@@ -3252,7 +3312,7 @@ expand_builtin_memcpy (tree exp, rtx target)
    stpcpy.  */
 
 static rtx
-expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
+expand_builtin_mempcpy (tree exp, rtx target, machine_mode mode)
 {
   if (!validate_arglist (exp,
                         POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -3263,7 +3323,40 @@ expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
       tree src = CALL_EXPR_ARG (exp, 1);
       tree len = CALL_EXPR_ARG (exp, 2);
       return expand_builtin_mempcpy_args (dest, src, len,
-                                         target, mode, /*endp=*/ 1);
+                                         target, mode, /*endp=*/ 1,
+                                         exp);
+    }
+}
+
+/* Expand an instrumented call EXP to the mempcpy builtin.
+   Return NULL_RTX if we failed, the caller should emit a normal call,
+   otherwise try to get the result in TARGET, if convenient (and in
+   mode MODE if that's convenient).  */
+
+static rtx
+expand_builtin_mempcpy_with_bounds (tree exp, rtx target, machine_mode mode)
+{
+  if (!validate_arglist (exp,
+                        POINTER_TYPE, POINTER_BOUNDS_TYPE,
+                        POINTER_TYPE, POINTER_BOUNDS_TYPE,
+                        INTEGER_TYPE, VOID_TYPE))
+    return NULL_RTX;
+  else
+    {
+      tree dest = CALL_EXPR_ARG (exp, 0);
+      tree src = CALL_EXPR_ARG (exp, 2);
+      tree len = CALL_EXPR_ARG (exp, 4);
+      rtx res = expand_builtin_mempcpy_args (dest, src, len, target,
+                                            mode, 1, exp);
+
+      /* Return src bounds with the result.  */
+      if (res)
+       {
+         rtx bnd = force_reg (targetm.chkp_bound_mode (),
+                              expand_normal (CALL_EXPR_ARG (exp, 1)));
+         res = chkp_join_splitted_slot (res, bnd);
+       }
+      return res;
     }
 }
 
@@ -3275,10 +3368,23 @@ expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
 
 static rtx
 expand_builtin_mempcpy_args (tree dest, tree src, tree len,
-                            rtx target, enum machine_mode mode, int endp)
+                            rtx target, machine_mode mode, int endp,
+                            tree orig_exp)
 {
+  tree fndecl = get_callee_fndecl (orig_exp);
+
     /* If return value is ignored, transform mempcpy into memcpy.  */
-  if (target == const0_rtx && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
+  if (target == const0_rtx
+      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK_CHKP
+      && builtin_decl_implicit_p (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP))
+    {
+      tree fn = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP);
+      tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
+                                          dest, src, len);
+      return expand_expr (result, target, mode, EXPAND_NORMAL);
+    }
+  else if (target == const0_rtx
+          && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
     {
       tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
       tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
@@ -3431,7 +3537,7 @@ expand_builtin_strcpy_args (tree dest, tree src, rtx target)
    mode MODE if that's convenient).  */
 
 static rtx
-expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
+expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
 {
   tree dst, src;
   location_t loc = EXPR_LOCATION (exp);
@@ -3463,7 +3569,8 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
 
       lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
       ret = expand_builtin_mempcpy_args (dst, src, lenp1,
-                                        target, mode, /*endp=*/2);
+                                        target, mode, /*endp=*/2,
+                                        exp);
 
       if (ret)
        return ret;
@@ -3507,7 +3614,7 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
 
 rtx
 builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
-                         enum machine_mode mode)
+                         machine_mode mode)
 {
   const char *str = (const char *) data;
 
@@ -3573,7 +3680,7 @@ expand_builtin_strncpy (tree exp, rtx target)
 
 rtx
 builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
-                        enum machine_mode mode)
+                        machine_mode mode)
 {
   const char *c = (const char *) data;
   char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
@@ -3590,7 +3697,7 @@ builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
 
 static rtx
 builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
-                       enum machine_mode mode)
+                       machine_mode mode)
 {
   rtx target, coeff;
   size_t size;
@@ -3615,7 +3722,7 @@ builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
    convenient).  */
 
 static rtx
-expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
+expand_builtin_memset (tree exp, rtx target, machine_mode mode)
 {
   if (!validate_arglist (exp,
                         POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -3629,6 +3736,36 @@ expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
     }
 }
 
+/* Expand expression EXP, which is an instrumented call to the memset builtin.
+   Return NULL_RTX if we failed the caller should emit a normal call, otherwise
+   try to get the result in TARGET, if convenient (and in mode MODE if that's
+   convenient).  */
+
+static rtx
+expand_builtin_memset_with_bounds (tree exp, rtx target, machine_mode mode)
+{
+  if (!validate_arglist (exp,
+                        POINTER_TYPE, POINTER_BOUNDS_TYPE,
+                        INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
+    return NULL_RTX;
+  else
+    {
+      tree dest = CALL_EXPR_ARG (exp, 0);
+      tree val = CALL_EXPR_ARG (exp, 2);
+      tree len = CALL_EXPR_ARG (exp, 3);
+      rtx res = expand_builtin_memset_args (dest, val, len, target, mode, exp);
+
+      /* Return src bounds with the result.  */
+      if (res)
+       {
+         rtx bnd = force_reg (targetm.chkp_bound_mode (),
+                              expand_normal (CALL_EXPR_ARG (exp, 1)));
+         res = chkp_join_splitted_slot (res, bnd);
+       }
+      return res;
+    }
+}
+
 /* Helper function to do the actual work for expand_builtin_memset.  The
    arguments to the builtin_memset call DEST, VAL, and LEN are broken out
    so that this can also be called without constructing an actual CALL_EXPR.
@@ -3637,11 +3774,11 @@ expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
 
 static rtx
 expand_builtin_memset_args (tree dest, tree val, tree len,
-                           rtx target, enum machine_mode mode, tree orig_exp)
+                           rtx target, machine_mode mode, tree orig_exp)
 {
   tree fndecl, fn;
   enum built_in_function fcode;
-  enum machine_mode val_mode;
+  machine_mode val_mode;
   char c;
   unsigned int dest_align;
   rtx dest_mem, dest_addr, len_rtx;
@@ -3757,7 +3894,8 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
  do_libcall:
   fndecl = get_callee_fndecl (orig_exp);
   fcode = DECL_FUNCTION_CODE (fndecl);
-  if (fcode == BUILT_IN_MEMSET)
+  if (fcode == BUILT_IN_MEMSET
+      || fcode == BUILT_IN_CHKP_MEMSET_NOBND_NOCHK_CHKP)
     fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
                                dest, val, len);
   else if (fcode == BUILT_IN_BZERO)
@@ -3803,7 +3941,7 @@ expand_builtin_bzero (tree exp)
 
 static rtx
 expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
-                      ATTRIBUTE_UNUSED enum machine_mode mode)
+                      ATTRIBUTE_UNUSED machine_mode mode)
 {
   location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
 
@@ -3825,7 +3963,7 @@ expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
 
     unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
     unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
-    enum machine_mode insn_mode;
+    machine_mode insn_mode;
 
     if (HAVE_cmpmemsi)
       insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
@@ -3926,7 +4064,7 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
       /* Try to call cmpstrsi.  */
       if (HAVE_cmpstrsi)
        {
-         enum machine_mode insn_mode
+         machine_mode insn_mode
            = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
 
          /* Make a place to write the result of the instruction.  */
@@ -3947,7 +4085,7 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
          tree len;
          rtx arg3_rtx;
 
-         enum machine_mode insn_mode
+         machine_mode insn_mode
            = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
          tree len1 = c_strlen (arg1, 1);
          tree len2 = c_strlen (arg2, 1);
@@ -4001,7 +4139,7 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
 
       if (insn)
        {
-         enum machine_mode mode;
+         machine_mode mode;
          emit_insn (insn);
 
          /* Return the value in the proper mode for this function.  */
@@ -4035,7 +4173,7 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
 
 static rtx
 expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
-                       ATTRIBUTE_UNUSED enum machine_mode mode)
+                       ATTRIBUTE_UNUSED machine_mode mode)
 {
   location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp);
 
@@ -4059,7 +4197,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
 
     unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
     unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
-    enum machine_mode insn_mode
+    machine_mode insn_mode
       = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
 
     len1 = c_strlen (arg1, 1);
@@ -4156,7 +4294,8 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
 rtx
 expand_builtin_saveregs (void)
 {
-  rtx val, seq;
+  rtx val;
+  rtx_insn *seq;
 
   /* Don't do __builtin_saveregs more than once in a function.
      Save the result of the first call and reuse it.  */
@@ -4309,6 +4448,13 @@ std_expand_builtin_va_start (tree valist, rtx nextarg)
 {
   rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
   convert_move (va_r, nextarg, 0);
+
+  /* We do not have any valid bounds for the pointer, so
+     just store zero bounds for it.  */
+  if (chkp_function_instrumented_p (current_function_decl))
+    chkp_expand_bounds_reset_for_mem (valist,
+                                     make_tree (TREE_TYPE (valist),
+                                                nextarg));
 }
 
 /* Expand EXP, a call to __builtin_va_start.  */
@@ -4497,7 +4643,7 @@ expand_builtin_alloca (tree exp, bool cannot_accumulate)
    SUBTARGET may be used as the target for computing one of EXP's operands.  */
 
 static rtx
-expand_builtin_bswap (enum machine_mode target_mode, tree exp, rtx target,
+expand_builtin_bswap (machine_mode target_mode, tree exp, rtx target,
                      rtx subtarget)
 {
   tree arg;
@@ -4527,7 +4673,7 @@ expand_builtin_bswap (enum machine_mode target_mode, tree exp, rtx target,
    SUBTARGET may be used as the target for computing one of EXP's operands.  */
 
 static rtx
-expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
+expand_builtin_unop (machine_mode target_mode, tree exp, rtx target,
                     rtx subtarget, optab op_optab)
 {
   rtx op0;
@@ -4593,7 +4739,7 @@ expand_builtin_trap (void)
 #ifdef HAVE_trap
   if (HAVE_trap)
     {
-      rtx insn = emit_insn (gen_trap ());
+      rtx_insn *insn = emit_insn (gen_trap ());
       /* For trap insns when not accumulating outgoing args force
         REG_ARGS_SIZE note to prevent crossjumping of calls with
         different args sizes.  */
@@ -4626,7 +4772,7 @@ expand_builtin_unreachable (void)
 static rtx
 expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
 {
-  enum machine_mode mode;
+  machine_mode mode;
   tree arg;
   rtx op0;
 
@@ -4823,7 +4969,7 @@ static rtx
 expand_builtin_signbit (tree exp, rtx target)
 {
   const struct real_format *fmt;
-  enum machine_mode fmode, imode, rmode;
+  machine_mode fmode, imode, rmode;
   tree arg;
   int word, bitpos;
   enum insn_code icode;
@@ -4848,7 +4994,7 @@ expand_builtin_signbit (tree exp, rtx target)
   icode = optab_handler (signbit_optab, fmode);
   if (icode != CODE_FOR_nothing)
     {
-      rtx last = get_last_insn ();
+      rtx_insn *last = get_last_insn ();
       target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
       if (maybe_emit_unop_insn (icode, target, temp, UNKNOWN))
        return target;
@@ -4996,7 +5142,7 @@ expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
    FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
    group of builtins.  This gives us log2 of the mode size.  */
 
-static inline enum machine_mode
+static inline machine_mode
 get_builtin_sync_mode (int fcode_diff)
 {
   /* The size is not negotiable, so ask not to get BLKmode in return
@@ -5008,7 +5154,7 @@ get_builtin_sync_mode (int fcode_diff)
    for the builtin_sync operations.  */
 
 static rtx
-get_builtin_sync_mem (tree loc, enum machine_mode mode)
+get_builtin_sync_mem (tree loc, machine_mode mode)
 {
   rtx addr, mem;
 
@@ -5034,10 +5180,10 @@ get_builtin_sync_mem (tree loc, enum machine_mode mode)
    MODE is the mode it should be in.  */
 
 static rtx
-expand_expr_force_mode (tree exp, enum machine_mode mode)
+expand_expr_force_mode (tree exp, machine_mode mode)
 {
   rtx val;
-  enum machine_mode old_mode;
+  machine_mode old_mode;
 
   val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
@@ -5059,7 +5205,7 @@ expand_expr_force_mode (tree exp, enum machine_mode mode)
    fetch_and_xxx form.  */
 
 static rtx
-expand_builtin_sync_operation (enum machine_mode mode, tree exp,
+expand_builtin_sync_operation (machine_mode mode, tree exp,
                               enum rtx_code code, bool after,
                               rtx target)
 {
@@ -5110,7 +5256,7 @@ expand_builtin_sync_operation (enum machine_mode mode, tree exp,
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
 
-  return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SEQ_CST,
+  return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SYNC_SEQ_CST,
                                 after);
 }
 
@@ -5120,7 +5266,7 @@ expand_builtin_sync_operation (enum machine_mode mode, tree exp,
    results; this is NOT optional if IS_BOOL is true.  */
 
 static rtx
-expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
+expand_builtin_compare_and_swap (machine_mode mode, tree exp,
                                 bool is_bool, rtx target)
 {
   rtx old_val, new_val, mem;
@@ -5140,8 +5286,8 @@ expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
        poval = &target;
     }
   if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
-                                      false, MEMMODEL_SEQ_CST,
-                                      MEMMODEL_SEQ_CST))
+                                      false, MEMMODEL_SYNC_SEQ_CST,
+                                      MEMMODEL_SYNC_SEQ_CST))
     return NULL_RTX;
 
   return target;
@@ -5154,7 +5300,7 @@ expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
    the results.  */
 
 static rtx
-expand_builtin_sync_lock_test_and_set (enum machine_mode mode, tree exp,
+expand_builtin_sync_lock_test_and_set (machine_mode mode, tree exp,
                                       rtx target)
 {
   rtx val, mem;
@@ -5169,14 +5315,14 @@ expand_builtin_sync_lock_test_and_set (enum machine_mode mode, tree exp,
 /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
 
 static void
-expand_builtin_sync_lock_release (enum machine_mode mode, tree exp)
+expand_builtin_sync_lock_release (machine_mode mode, tree exp)
 {
   rtx mem;
 
   /* Expand the operands.  */
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
 
-  expand_atomic_store (mem, const0_rtx, MEMMODEL_RELEASE, true);
+  expand_atomic_store (mem, const0_rtx, MEMMODEL_SYNC_RELEASE, true);
 }
 
 /* Given an integer representing an ``enum memmodel'', verify its
@@ -5205,13 +5351,19 @@ get_memmodel (tree exp)
       return MEMMODEL_SEQ_CST;
     }
 
-  if ((INTVAL (op) & MEMMODEL_MASK) >= MEMMODEL_LAST)
+  /* Should never see a user explicit SYNC memodel model, so >= LAST works. */
+  if (memmodel_base (val) >= MEMMODEL_LAST)
     {
       warning (OPT_Winvalid_memory_model,
               "invalid memory model argument to builtin");
       return MEMMODEL_SEQ_CST;
     }
 
+  /* Workaround for Bugzilla 59448. GCC doesn't track consume properly, so
+     be conservative and promote consume to acquire.  */
+  if (val == MEMMODEL_CONSUME)
+    val = MEMMODEL_ACQUIRE;
+
   return (enum memmodel) val;
 }
 
@@ -5221,17 +5373,12 @@ get_memmodel (tree exp)
    TARGET is an optional place for us to store the results.  */
 
 static rtx
-expand_builtin_atomic_exchange (enum machine_mode mode, tree exp, rtx target)
+expand_builtin_atomic_exchange (machine_mode mode, tree exp, rtx target)
 {
   rtx val, mem;
   enum memmodel model;
 
   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
-  if ((model & MEMMODEL_MASK) == MEMMODEL_CONSUME)
-    {
-      error ("invalid memory model for %<__atomic_exchange%>");
-      return NULL_RTX;
-    }
 
   if (!flag_inline_atomics)
     return NULL_RTX;
@@ -5252,10 +5399,11 @@ expand_builtin_atomic_exchange (enum machine_mode mode, tree exp, rtx target)
    TARGET is an optional place for us to store the results.  */
 
 static rtx
-expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp, 
+expand_builtin_atomic_compare_exchange (machine_mode mode, tree exp, 
                                        rtx target)
 {
-  rtx expect, desired, mem, oldval, label;
+  rtx expect, desired, mem, oldval;
+  rtx_code_label *label;
   enum memmodel success, failure;
   tree weak;
   bool is_weak;
@@ -5263,20 +5411,24 @@ expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
   success = get_memmodel (CALL_EXPR_ARG (exp, 4));
   failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
 
-  if ((failure & MEMMODEL_MASK) == MEMMODEL_RELEASE
-      || (failure & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+  if (failure > success)
     {
-      error ("invalid failure memory model for %<__atomic_compare_exchange%>");
-      return NULL_RTX;
+      warning (OPT_Winvalid_memory_model,
+              "failure memory model cannot be stronger than success memory "
+              "model for %<__atomic_compare_exchange%>");
+      success = MEMMODEL_SEQ_CST;
     }
-
-  if (failure > success)
+  if (is_mm_release (failure) || is_mm_acq_rel (failure))
     {
-      error ("failure memory model cannot be stronger than success "
-            "memory model for %<__atomic_compare_exchange%>");
-      return NULL_RTX;
+      warning (OPT_Winvalid_memory_model,
+              "invalid failure memory model for "
+              "%<__atomic_compare_exchange%>");
+      failure = MEMMODEL_SEQ_CST;
+      success = MEMMODEL_SEQ_CST;
     }
-  
+
   if (!flag_inline_atomics)
     return NULL_RTX;
 
@@ -5310,7 +5462,8 @@ expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
      the normal case where EXPECT is totally private, i.e. a register.  At
      which point the store can be unconditional.  */
   label = gen_label_rtx ();
-  emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL, VOIDmode, 1, label);
+  emit_cmp_and_jump_insns (target, const0_rtx, NE, NULL,
+                          GET_MODE (target), 1, label);
   emit_move_insn (expect, oldval);
   emit_label (label);
 
@@ -5323,17 +5476,17 @@ expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
    TARGET is an optional place for us to store the results.  */
 
 static rtx
-expand_builtin_atomic_load (enum machine_mode mode, tree exp, rtx target)
+expand_builtin_atomic_load (machine_mode mode, tree exp, rtx target)
 {
   rtx mem;
   enum memmodel model;
 
   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
-  if ((model & MEMMODEL_MASK) == MEMMODEL_RELEASE
-      || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+  if (is_mm_release (model) || is_mm_acq_rel (model))
     {
-      error ("invalid memory model for %<__atomic_load%>");
-      return NULL_RTX;
+      warning (OPT_Winvalid_memory_model,
+              "invalid memory model for %<__atomic_load%>");
+      model = MEMMODEL_SEQ_CST;
     }
 
   if (!flag_inline_atomics)
@@ -5352,18 +5505,18 @@ expand_builtin_atomic_load (enum machine_mode mode, tree exp, rtx target)
    TARGET is an optional place for us to store the results.  */
 
 static rtx
-expand_builtin_atomic_store (enum machine_mode mode, tree exp)
+expand_builtin_atomic_store (machine_mode mode, tree exp)
 {
   rtx mem, val;
   enum memmodel model;
 
   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
-  if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED
-      && (model & MEMMODEL_MASK) != MEMMODEL_SEQ_CST
-      && (model & MEMMODEL_MASK) != MEMMODEL_RELEASE)
+  if (!(is_mm_relaxed (model) || is_mm_seq_cst (model)
+       || is_mm_release (model)))
     {
-      error ("invalid memory model for %<__atomic_store%>");
-      return NULL_RTX;
+      warning (OPT_Winvalid_memory_model,
+              "invalid memory model for %<__atomic_store%>");
+      model = MEMMODEL_SEQ_CST;
     }
 
   if (!flag_inline_atomics)
@@ -5388,7 +5541,7 @@ expand_builtin_atomic_store (enum machine_mode mode, tree exp)
    resolved to an instruction sequence.  */
 
 static rtx
-expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target,
+expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target,
                                enum rtx_code code, bool fetch_after,
                                bool ignore, enum built_in_function ext_call)
 {
@@ -5458,7 +5611,7 @@ expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target,
 static rtx
 expand_builtin_atomic_clear (tree exp) 
 {
-  enum machine_mode mode;
+  machine_mode mode;
   rtx mem, ret;
   enum memmodel model;
 
@@ -5466,11 +5619,11 @@ expand_builtin_atomic_clear (tree exp)
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
 
-  if ((model & MEMMODEL_MASK) == MEMMODEL_ACQUIRE
-      || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+  if (is_mm_consume (model) || is_mm_acquire (model) || is_mm_acq_rel (model))
     {
-      error ("invalid memory model for %<__atomic_store%>");
-      return const0_rtx;
+      warning (OPT_Winvalid_memory_model,
+              "invalid memory model for %<__atomic_store%>");
+      model = MEMMODEL_SEQ_CST;
     }
 
   if (HAVE_atomic_clear)
@@ -5499,7 +5652,7 @@ expand_builtin_atomic_test_and_set (tree exp, rtx target)
 {
   rtx mem;
   enum memmodel model;
-  enum machine_mode mode;
+  machine_mode mode;
 
   mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
@@ -5516,7 +5669,7 @@ static tree
 fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
 {
   int size;
-  enum machine_mode mode;
+  machine_mode mode;
   unsigned int mode_align, type_align;
 
   if (TREE_CODE (arg0) != INTEGER_CST)
@@ -5536,7 +5689,7 @@ fold_builtin_atomic_always_lock_free (tree arg0, tree arg1)
         end before anything else has a chance to look at it.  The pointer
         parameter at this point is usually cast to a void *, so check for that
         and look past the cast.  */
-      if (TREE_CODE (arg1) == NOP_EXPR && POINTER_TYPE_P (ttype)
+      if (CONVERT_EXPR_P (arg1) && POINTER_TYPE_P (ttype)
          && VOID_TYPE_P (TREE_TYPE (ttype)))
        arg1 = TREE_OPERAND (arg1, 0);
 
@@ -5662,7 +5815,7 @@ expand_builtin_atomic_signal_fence (tree exp)
 static void
 expand_builtin_sync_synchronize (void)
 {
-  expand_mem_thread_fence (MEMMODEL_SEQ_CST);
+  expand_mem_thread_fence (MEMMODEL_SYNC_SEQ_CST);
 }
 
 static rtx
@@ -5713,16 +5866,19 @@ expand_builtin_set_thread_pointer (tree exp)
 static void
 expand_stack_restore (tree var)
 {
-  rtx prev, sa = expand_normal (var);
+  rtx_insn *prev;
+  rtx sa = expand_normal (var);
 
   sa = convert_memory_address (Pmode, sa);
 
   prev = get_last_insn ();
   emit_stack_restore (SAVE_BLOCK, sa);
+
+  record_new_stack_level ();
+
   fixup_args_size_notes (prev, get_last_insn (), 0);
 }
 
-
 /* Emit code to save the current value of stack.  */
 
 static rtx
@@ -5730,11 +5886,51 @@ expand_stack_save (void)
 {
   rtx ret = NULL_RTX;
 
-  do_pending_stack_adjust ();
   emit_stack_save (SAVE_BLOCK, &ret);
   return ret;
 }
 
+
+/* Expand OpenACC acc_on_device.
+
+   This has to happen late (that is, not in early folding; expand_builtin_*,
+   rather than fold_builtin_*), as we have to act differently for host and
+   acceleration device (ACCEL_COMPILER conditional).  */
+
+static rtx
+expand_builtin_acc_on_device (tree exp ATTRIBUTE_UNUSED,
+                             rtx target ATTRIBUTE_UNUSED)
+{
+#ifdef ACCEL_COMPILER
+  if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
+    return NULL_RTX;
+
+  tree arg = CALL_EXPR_ARG (exp, 0);
+
+  /* Return (arg == v1 || arg == v2) ? 1 : 0.  */
+  machine_mode v_mode = TYPE_MODE (TREE_TYPE (arg));
+  rtx v = expand_normal (arg), v1, v2;
+  v1 = GEN_INT (GOMP_DEVICE_NOT_HOST);
+  v2 = GEN_INT (ACCEL_COMPILER_acc_device);
+  machine_mode target_mode = TYPE_MODE (integer_type_node);
+  if (!target || !register_operand (target, target_mode))
+    target = gen_reg_rtx (target_mode);
+  emit_move_insn (target, const1_rtx);
+  rtx_code_label *done_label = gen_label_rtx ();
+  do_compare_rtx_and_jump (v, v1, EQ, false, v_mode, NULL_RTX,
+                          NULL, done_label, PROB_EVEN);
+  do_compare_rtx_and_jump (v, v2, EQ, false, v_mode, NULL_RTX,
+                          NULL, done_label, PROB_EVEN);
+  emit_move_insn (target, const0_rtx);
+  emit_label (done_label);
+
+  return target;
+#else
+  return NULL;
+#endif
+}
+
+
 /* Expand an expression EXP that calls a built-in function,
    with result going to TARGET if that's convenient
    (and in mode MODE if that's convenient).
@@ -5742,17 +5938,25 @@ expand_stack_save (void)
    IGNORE is nonzero if the value is to be ignored.  */
 
 rtx
-expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
+expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
                int ignore)
 {
   tree fndecl = get_callee_fndecl (exp);
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
-  enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
+  machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
   int flags;
 
   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
     return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
 
+  /* When ASan is enabled, we don't want to expand some memory/string
+     builtins and rely on libsanitizer's hooks.  This allows us to avoid
+     redundant checks and be sure, that possible overflow will be detected
+     by ASan.  */
+
+  if ((flag_sanitize & SANITIZE_ADDRESS) && asan_intercepted_p (fcode))
+    return expand_call (exp, target, ignore);
+
   /* When not optimizing, generate calls to library functions for a certain
      set of builtins.  */
   if (!optimize
@@ -5766,7 +5970,19 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       && fcode != BUILT_IN_EXECVE
       && fcode != BUILT_IN_ALLOCA
       && fcode != BUILT_IN_ALLOCA_WITH_ALIGN
-      && fcode != BUILT_IN_FREE)
+      && fcode != BUILT_IN_FREE
+      && fcode != BUILT_IN_CHKP_SET_PTR_BOUNDS
+      && fcode != BUILT_IN_CHKP_INIT_PTR_BOUNDS
+      && fcode != BUILT_IN_CHKP_NULL_PTR_BOUNDS
+      && fcode != BUILT_IN_CHKP_COPY_PTR_BOUNDS
+      && fcode != BUILT_IN_CHKP_NARROW_PTR_BOUNDS
+      && fcode != BUILT_IN_CHKP_STORE_PTR_BOUNDS
+      && fcode != BUILT_IN_CHKP_CHECK_PTR_LBOUNDS
+      && fcode != BUILT_IN_CHKP_CHECK_PTR_UBOUNDS
+      && fcode != BUILT_IN_CHKP_CHECK_PTR_BOUNDS
+      && fcode != BUILT_IN_CHKP_GET_PTR_LBOUND
+      && fcode != BUILT_IN_CHKP_GET_PTR_UBOUND
+      && fcode != BUILT_IN_CHKP_BNDRET)
     return expand_call (exp, target, ignore);
 
   /* The built-in function expanders test for target == const0_rtx
@@ -5800,6 +6016,10 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        }
     }
 
+  /* expand_builtin_with_bounds is supposed to be used for
+     instrumented builtin calls.  */
+  gcc_assert (!CALL_WITH_BOUNDS_P (exp));
+
   switch (fcode)
     {
     CASE_FLT_FN (BUILT_IN_FABS):
@@ -6168,12 +6388,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
          rtx buf_addr = expand_expr (CALL_EXPR_ARG (exp, 0), subtarget,
                                      VOIDmode, EXPAND_NORMAL);
          tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 1), 0);
-         rtx label_r = label_rtx (label);
+         rtx_insn *label_r = label_rtx (label);
 
          /* This is copied from the handling of non-local gotos.  */
          expand_builtin_setjmp_setup (buf_addr, label_r);
          nonlocal_goto_handler_labels
-           = gen_rtx_EXPR_LIST (VOIDmode, label_r,
+           = gen_rtx_INSN_LIST (VOIDmode, label_r,
                                 nonlocal_goto_handler_labels);
          /* ??? Do not let expand_label treat us as such since we would
             not want to be both on the list of non-local labels and on
@@ -6188,7 +6408,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       if (validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
        {
          tree label = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0);
-         rtx label_r = label_rtx (label);
+         rtx_insn *label_r = label_rtx (label);
 
          expand_builtin_setjmp_receiver (label_r);
          return const0_rtx;
@@ -6273,10 +6493,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       expand_builtin_eh_return (CALL_EXPR_ARG (exp, 0),
                                CALL_EXPR_ARG (exp, 1));
       return const0_rtx;
-#ifdef EH_RETURN_DATA_REGNO
     case BUILT_IN_EH_RETURN_DATA_REGNO:
       return expand_builtin_eh_return_data_regno (exp);
-#endif
     case BUILT_IN_EXTEND_POINTER:
       return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0));
     case BUILT_IN_EH_POINTER:
@@ -6804,6 +7022,57 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       expand_builtin_cilk_pop_frame (exp);
       return const0_rtx;
 
+    case BUILT_IN_CHKP_INIT_PTR_BOUNDS:
+    case BUILT_IN_CHKP_NULL_PTR_BOUNDS:
+    case BUILT_IN_CHKP_COPY_PTR_BOUNDS:
+    case BUILT_IN_CHKP_CHECK_PTR_LBOUNDS:
+    case BUILT_IN_CHKP_CHECK_PTR_UBOUNDS:
+    case BUILT_IN_CHKP_CHECK_PTR_BOUNDS:
+    case BUILT_IN_CHKP_SET_PTR_BOUNDS:
+    case BUILT_IN_CHKP_NARROW_PTR_BOUNDS:
+    case BUILT_IN_CHKP_STORE_PTR_BOUNDS:
+    case BUILT_IN_CHKP_GET_PTR_LBOUND:
+    case BUILT_IN_CHKP_GET_PTR_UBOUND:
+      /* We allow user CHKP builtins if Pointer Bounds
+        Checker is off.  */
+      if (!chkp_function_instrumented_p (current_function_decl))
+       {
+         if (fcode == BUILT_IN_CHKP_SET_PTR_BOUNDS
+             || fcode == BUILT_IN_CHKP_NARROW_PTR_BOUNDS
+             || fcode == BUILT_IN_CHKP_INIT_PTR_BOUNDS
+             || fcode == BUILT_IN_CHKP_NULL_PTR_BOUNDS
+             || fcode == BUILT_IN_CHKP_COPY_PTR_BOUNDS)
+           return expand_normal (CALL_EXPR_ARG (exp, 0));
+         else if (fcode == BUILT_IN_CHKP_GET_PTR_LBOUND)
+           return expand_normal (size_zero_node);
+         else if (fcode == BUILT_IN_CHKP_GET_PTR_UBOUND)
+           return expand_normal (size_int (-1));
+         else
+           return const0_rtx;
+       }
+      /* FALLTHROUGH */
+
+    case BUILT_IN_CHKP_BNDMK:
+    case BUILT_IN_CHKP_BNDSTX:
+    case BUILT_IN_CHKP_BNDCL:
+    case BUILT_IN_CHKP_BNDCU:
+    case BUILT_IN_CHKP_BNDLDX:
+    case BUILT_IN_CHKP_BNDRET:
+    case BUILT_IN_CHKP_INTERSECT:
+    case BUILT_IN_CHKP_NARROW:
+    case BUILT_IN_CHKP_EXTRACT_LOWER:
+    case BUILT_IN_CHKP_EXTRACT_UPPER:
+      /* Software implementation of Pointer Bounds Checker is NYI.
+        Target support is required.  */
+      error ("Your target platform does not support -fcheck-pointer-bounds");
+      break;
+
+    case BUILT_IN_ACC_ON_DEVICE:
+      target = expand_builtin_acc_on_device (exp, target);
+      if (target)
+       return target;
+      break;
+
     default:   /* just do library call, if unknown builtin */
       break;
     }
@@ -6813,6 +7082,53 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
   return expand_call (exp, target, ignore);
 }
 
+/* Similar to expand_builtin but is used for instrumented calls.  */
+
+rtx
+expand_builtin_with_bounds (tree exp, rtx target,
+                           rtx subtarget ATTRIBUTE_UNUSED,
+                           machine_mode mode, int ignore)
+{
+  tree fndecl = get_callee_fndecl (exp);
+  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+
+  gcc_assert (CALL_WITH_BOUNDS_P (exp));
+
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+    return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
+
+  gcc_assert (fcode > BEGIN_CHKP_BUILTINS
+             && fcode < END_CHKP_BUILTINS);
+
+  switch (fcode)
+    {
+    case BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP:
+      target = expand_builtin_memcpy_with_bounds (exp, target);
+      if (target)
+       return target;
+      break;
+
+    case BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK_CHKP:
+      target = expand_builtin_mempcpy_with_bounds (exp, target, mode);
+      if (target)
+       return target;
+      break;
+
+    case BUILT_IN_CHKP_MEMSET_NOBND_NOCHK_CHKP:
+      target = expand_builtin_memset_with_bounds (exp, target, mode);
+      if (target)
+       return target;
+      break;
+
+    default:
+      break;
+    }
+
+  /* The switch statement above can drop through to cause the function
+     to be called normally.  */
+  return expand_call (exp, target, ignore);
+ }
+
 /* Determine whether a tree node represents a call to a built-in
    function.  If the tree T is a call to a built-in function with
    the right number of arguments of the appropriate types, return
@@ -6965,7 +7281,7 @@ fold_builtin_expect (location_t loc, tree arg0, tree arg1, tree arg2)
   /* Distribute the expected value over short-circuiting operators.
      See through the cast from truthvalue_type_node to long.  */
   inner_arg0 = arg0;
-  while (TREE_CODE (inner_arg0) == NOP_EXPR
+  while (CONVERT_EXPR_P (inner_arg0)
         && INTEGRAL_TYPE_P (TREE_TYPE (inner_arg0))
         && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (inner_arg0, 0))))
     inner_arg0 = TREE_OPERAND (inner_arg0, 0);
@@ -7131,7 +7447,7 @@ integer_valued_real_p (tree t)
     case REAL_CST:
       return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE (t)));
 
-    case NOP_EXPR:
+    CASE_CONVERT:
       {
        tree type = TREE_TYPE (TREE_OPERAND (t, 0));
        if (TREE_CODE (type) == INTEGER_TYPE)
@@ -7417,7 +7733,7 @@ fold_builtin_cproj (location_t loc, tree arg, tree type)
     return NULL_TREE;
 
   /* If there are no infinities, return arg.  */
-  if (! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type))))
+  if (! HONOR_INFINITIES (type))
     return non_lvalue_loc (loc, arg);
 
   /* Calculate the result when the argument is a constant.  */
@@ -8109,111 +8425,18 @@ fold_builtin_bswap (tree fndecl, tree arg)
   return NULL_TREE;
 }
 
-/* A subroutine of fold_builtin to fold the various logarithmic
-   functions.  Return NULL_TREE if no simplification can me made.
-   FUNC is the corresponding MPFR logarithm function.  */
+/* Fold a builtin function call to hypot, hypotf, or hypotl.  Return
+   NULL_TREE if no simplification can be made.  */
 
 static tree
-fold_builtin_logarithm (location_t loc, tree fndecl, tree arg,
-                       int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t))
+fold_builtin_hypot (location_t loc, tree fndecl,
+                   tree arg0, tree arg1, tree type)
 {
-  if (validate_arg (arg, REAL_TYPE))
-    {
-      tree type = TREE_TYPE (TREE_TYPE (fndecl));
-      tree res;
-      const enum built_in_function fcode = builtin_mathfn_code (arg);
+  tree res, narg0, narg1;
 
-      /* Calculate the result when the argument is a constant.  */
-      if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false)))
-       return res;
-
-      /* Special case, optimize logN(expN(x)) = x.  */
-      if (flag_unsafe_math_optimizations
-         && ((func == mpfr_log
-              && (fcode == BUILT_IN_EXP
-                  || fcode == BUILT_IN_EXPF
-                  || fcode == BUILT_IN_EXPL))
-             || (func == mpfr_log2
-                 && (fcode == BUILT_IN_EXP2
-                     || fcode == BUILT_IN_EXP2F
-                     || fcode == BUILT_IN_EXP2L))
-             || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode)))))
-       return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0));
-
-      /* Optimize logN(func()) for various exponential functions.  We
-        want to determine the value "x" and the power "exponent" in
-        order to transform logN(x**exponent) into exponent*logN(x).  */
-      if (flag_unsafe_math_optimizations)
-       {
-         tree exponent = 0, x = 0;
-
-         switch (fcode)
-         {
-         CASE_FLT_FN (BUILT_IN_EXP):
-           /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
-           x = build_real (type, real_value_truncate (TYPE_MODE (type),
-                                                       dconst_e ()));
-           exponent = CALL_EXPR_ARG (arg, 0);
-           break;
-         CASE_FLT_FN (BUILT_IN_EXP2):
-           /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
-           x = build_real (type, dconst2);
-           exponent = CALL_EXPR_ARG (arg, 0);
-           break;
-         CASE_FLT_FN (BUILT_IN_EXP10):
-         CASE_FLT_FN (BUILT_IN_POW10):
-           /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
-           {
-             REAL_VALUE_TYPE dconst10;
-             real_from_integer (&dconst10, VOIDmode, 10, SIGNED);
-             x = build_real (type, dconst10);
-           }
-           exponent = CALL_EXPR_ARG (arg, 0);
-           break;
-         CASE_FLT_FN (BUILT_IN_SQRT):
-           /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
-           x = CALL_EXPR_ARG (arg, 0);
-           exponent = build_real (type, dconsthalf);
-           break;
-         CASE_FLT_FN (BUILT_IN_CBRT):
-           /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
-           x = CALL_EXPR_ARG (arg, 0);
-           exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
-                                                             dconst_third ()));
-           break;
-         CASE_FLT_FN (BUILT_IN_POW):
-           /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x).  */
-           x = CALL_EXPR_ARG (arg, 0);
-           exponent = CALL_EXPR_ARG (arg, 1);
-           break;
-         default:
-           break;
-         }
-
-         /* Now perform the optimization.  */
-         if (x && exponent)
-           {
-             tree logfn = build_call_expr_loc (loc, fndecl, 1, x);
-             return fold_build2_loc (loc, MULT_EXPR, type, exponent, logfn);
-           }
-       }
-    }
-
-  return NULL_TREE;
-}
-
-/* Fold a builtin function call to hypot, hypotf, or hypotl.  Return
-   NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_hypot (location_t loc, tree fndecl,
-                   tree arg0, tree arg1, tree type)
-{
-  tree res, narg0, narg1;
-
-  if (!validate_arg (arg0, REAL_TYPE)
-      || !validate_arg (arg1, REAL_TYPE))
-    return NULL_TREE;
+  if (!validate_arg (arg0, REAL_TYPE)
+      || !validate_arg (arg1, REAL_TYPE))
+    return NULL_TREE;
 
   /* Calculate the result when the argument is a constant.  */
   if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
@@ -8489,47 +8712,6 @@ fold_builtin_exponent (location_t loc, tree fndecl, tree arg,
   return NULL_TREE;
 }
 
-/* Fold function call to builtin stpcpy with arguments DEST and SRC.
-   Return NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src)
-{
-  tree fn, len, lenp1, call, type;
-
-  if (!validate_arg (dest, POINTER_TYPE)
-      || !validate_arg (src, POINTER_TYPE))
-    return NULL_TREE;
-
-  len = c_strlen (src, 1);
-  if (!len
-      || TREE_CODE (len) != INTEGER_CST)
-    return NULL_TREE;
-
-  if (optimize_function_for_size_p (cfun)
-      /* If length is zero it's small enough.  */
-      && !integer_zerop (len))
-    return NULL_TREE;
-
-  fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
-  if (!fn)
-    return NULL_TREE;
-
-  lenp1 = size_binop_loc (loc, PLUS_EXPR,
-                         fold_convert_loc (loc, size_type_node, len),
-                         build_int_cst (size_type_node, 1));
-  /* We use dest twice in building our expression.  Save it from
-     multiple expansions.  */
-  dest = builtin_save_expr (dest);
-  call = build_call_expr_loc (loc, fn, 3, dest, src, lenp1);
-
-  type = TREE_TYPE (TREE_TYPE (fndecl));
-  dest = fold_build_pointer_plus_loc (loc, dest, len);
-  dest = fold_convert_loc (loc, type, dest);
-  dest = omit_one_operand_loc (loc, type, dest, call);
-  return dest;
-}
-
 /* Fold function call to builtin memchr.  ARG1, ARG2 and LEN are the
    arguments to the call, and TYPE is its return type.
    Return NULL_TREE if no simplification can be made.  */
@@ -8822,7 +9004,7 @@ fold_builtin_signbit (location_t loc, tree arg, tree type)
     return omit_one_operand_loc (loc, type, integer_zero_node, arg);
 
   /* If ARG's format doesn't have signed zeros, return "arg < 0.0".  */
-  if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
+  if (!HONOR_SIGNED_ZEROS (arg))
     return fold_convert (type,
                         fold_build2_loc (loc, LT_EXPR, boolean_type_node, arg,
                        build_real (TREE_TYPE (arg), dconst0)));
@@ -9016,12 +9198,12 @@ fold_builtin_fmin_fmax (location_t loc, tree arg0, tree arg1,
         omit_one_operand() ensures we create a non-lvalue.  */
       if (TREE_CODE (arg0) == REAL_CST
          && real_isnan (&TREE_REAL_CST (arg0))
-         && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+         && (! HONOR_SNANS (arg0)
              || ! TREE_REAL_CST (arg0).signalling))
        return omit_one_operand_loc (loc, type, arg1, arg0);
       if (TREE_CODE (arg1) == REAL_CST
          && real_isnan (&TREE_REAL_CST (arg1))
-         && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
+         && (! HONOR_SNANS (arg1)
              || ! TREE_REAL_CST (arg1).signalling))
        return omit_one_operand_loc (loc, type, arg0, arg1);
 
@@ -9335,7 +9517,7 @@ fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype)
 static tree
 fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
 {
-  enum machine_mode mode;
+  machine_mode mode;
 
   if (!validate_arg (arg, REAL_TYPE))
     return NULL_TREE;
@@ -9432,7 +9614,7 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
   switch (builtin_index)
     {
     case BUILT_IN_ISINF:
-      if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
+      if (!HONOR_INFINITIES (arg))
        return omit_one_operand_loc (loc, type, integer_zero_node, arg);
 
       if (TREE_CODE (arg) == REAL_CST)
@@ -9480,8 +9662,8 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
       }
 
     case BUILT_IN_ISFINITE:
-      if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
-         && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
+      if (!HONOR_NANS (arg)
+         && !HONOR_INFINITIES (arg))
        return omit_one_operand_loc (loc, type, integer_one_node, arg);
 
       if (TREE_CODE (arg) == REAL_CST)
@@ -9493,7 +9675,7 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
       return NULL_TREE;
 
     case BUILT_IN_ISNAN:
-      if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
+      if (!HONOR_NANS (arg))
        return omit_one_operand_loc (loc, type, integer_zero_node, arg);
 
       if (TREE_CODE (arg) == REAL_CST)
@@ -9519,26 +9701,30 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
    one floating point argument which is "type generic".  */
 
 static tree
-fold_builtin_fpclassify (location_t loc, tree exp)
+fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
 {
   tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero,
     arg, type, res, tmp;
-  enum machine_mode mode;
+  machine_mode mode;
   REAL_VALUE_TYPE r;
   char buf[128];
 
   /* Verify the required arguments in the original call.  */
-  if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
-                        INTEGER_TYPE, INTEGER_TYPE,
-                        INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
+  if (nargs != 6
+      || !validate_arg (args[0], INTEGER_TYPE)
+      || !validate_arg (args[1], INTEGER_TYPE)
+      || !validate_arg (args[2], INTEGER_TYPE)
+      || !validate_arg (args[3], INTEGER_TYPE)
+      || !validate_arg (args[4], INTEGER_TYPE)
+      || !validate_arg (args[5], REAL_TYPE))
     return NULL_TREE;
 
-  fp_nan = CALL_EXPR_ARG (exp, 0);
-  fp_infinite = CALL_EXPR_ARG (exp, 1);
-  fp_normal = CALL_EXPR_ARG (exp, 2);
-  fp_subnormal = CALL_EXPR_ARG (exp, 3);
-  fp_zero = CALL_EXPR_ARG (exp, 4);
-  arg = CALL_EXPR_ARG (exp, 5);
+  fp_nan = args[0];
+  fp_infinite = args[1];
+  fp_normal = args[2];
+  fp_subnormal = args[3];
+  fp_zero = args[4];
+  arg = args[5];
   type = TREE_TYPE (arg);
   mode = TYPE_MODE (type);
   arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
@@ -9617,23 +9803,77 @@ fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
 
   if (unordered_code == UNORDERED_EXPR)
     {
-      if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+      if (!HONOR_NANS (arg0))
        return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
       return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
     }
 
-  code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
-                                                  : ordered_code;
+  code = HONOR_NANS (arg0) ? unordered_code : ordered_code;
   return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
                      fold_build2_loc (loc, code, type, arg0, arg1));
 }
 
+/* Fold __builtin_{,s,u}{add,sub,mul}{,l,ll}_overflow, either into normal
+   arithmetics if it can never overflow, or into internal functions that
+   return both result of arithmetics and overflowed boolean flag in
+   a complex integer result, or some other check for overflow.  */
+
+static tree
+fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
+                            tree arg0, tree arg1, tree arg2)
+{
+  enum internal_fn ifn = IFN_LAST;
+  tree type = TREE_TYPE (TREE_TYPE (arg2));
+  tree mem_arg2 = build_fold_indirect_ref_loc (loc, arg2);
+  switch (fcode)
+    {
+    case BUILT_IN_ADD_OVERFLOW:
+    case BUILT_IN_SADD_OVERFLOW:
+    case BUILT_IN_SADDL_OVERFLOW:
+    case BUILT_IN_SADDLL_OVERFLOW:
+    case BUILT_IN_UADD_OVERFLOW:
+    case BUILT_IN_UADDL_OVERFLOW:
+    case BUILT_IN_UADDLL_OVERFLOW:
+      ifn = IFN_ADD_OVERFLOW;
+      break;
+    case BUILT_IN_SUB_OVERFLOW:
+    case BUILT_IN_SSUB_OVERFLOW:
+    case BUILT_IN_SSUBL_OVERFLOW:
+    case BUILT_IN_SSUBLL_OVERFLOW:
+    case BUILT_IN_USUB_OVERFLOW:
+    case BUILT_IN_USUBL_OVERFLOW:
+    case BUILT_IN_USUBLL_OVERFLOW:
+      ifn = IFN_SUB_OVERFLOW;
+      break;
+    case BUILT_IN_MUL_OVERFLOW:
+    case BUILT_IN_SMUL_OVERFLOW:
+    case BUILT_IN_SMULL_OVERFLOW:
+    case BUILT_IN_SMULLL_OVERFLOW:
+    case BUILT_IN_UMUL_OVERFLOW:
+    case BUILT_IN_UMULL_OVERFLOW:
+    case BUILT_IN_UMULLL_OVERFLOW:
+      ifn = IFN_MUL_OVERFLOW;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  tree ctype = build_complex_type (type);
+  tree call = build_call_expr_internal_loc (loc, ifn, ctype,
+                                           2, arg0, arg1);
+  tree tgt = save_expr (call);
+  tree intres = build1_loc (loc, REALPART_EXPR, type, tgt);
+  tree ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt);
+  ovfres = fold_convert_loc (loc, boolean_type_node, ovfres);
+  tree store
+    = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, mem_arg2, intres);
+  return build2_loc (loc, COMPOUND_EXPR, boolean_type_node, store, ovfres);
+}
+
 /* Fold a call to built-in function FNDECL with 0 arguments.
-   IGNORE is true if the result of the function call is ignored.  This
-   function returns NULL_TREE if no simplification was possible.  */
+   This function returns NULL_TREE if no simplification was possible.  */
 
 static tree
-fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED)
+fold_builtin_0 (location_t loc, tree fndecl)
 {
   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
@@ -9651,14 +9891,6 @@ fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED)
     case BUILT_IN_CLASSIFY_TYPE:
       return fold_builtin_classify_type (NULL_TREE);
 
-    case BUILT_IN_UNREACHABLE:
-      if (flag_sanitize & SANITIZE_UNREACHABLE
-         && (current_function_decl == NULL
-             || !lookup_attribute ("no_sanitize_undefined",
-                                   DECL_ATTRIBUTES (current_function_decl))))
-       return ubsan_instrument_unreachable (loc);
-      break;
-
     default:
       break;
     }
@@ -9666,11 +9898,10 @@ fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED)
 }
 
 /* Fold a call to built-in function FNDECL with 1 argument, ARG0.
-   IGNORE is true if the result of the function call is ignored.  This
-   function returns NULL_TREE if no simplification was possible.  */
+   This function returns NULL_TREE if no simplification was possible.  */
 
 static tree
-fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
+fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
 {
   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
@@ -9716,7 +9947,7 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
     CASE_FLT_FN (BUILT_IN_CREAL):
       if (validate_arg (arg0, COMPLEX_TYPE)
        && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
-       return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));;
+       return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));
     break;
 
     CASE_FLT_FN (BUILT_IN_CIMAG):
@@ -9912,16 +10143,22 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
     CASE_FLT_FN (BUILT_IN_EXPM1):
       if (validate_arg (arg0, REAL_TYPE))
        return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
-    break;
+      break;
 
     CASE_FLT_FN (BUILT_IN_LOG):
-    return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log);
+      if (validate_arg (arg0, REAL_TYPE))
+        return do_mpfr_arg1 (arg0, type, mpfr_log, &dconst0, NULL, false);
+      break;
 
     CASE_FLT_FN (BUILT_IN_LOG2):
-      return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log2);
+      if (validate_arg (arg0, REAL_TYPE))
+        return do_mpfr_arg1 (arg0, type, mpfr_log2, &dconst0, NULL, false);
+      break;
 
     CASE_FLT_FN (BUILT_IN_LOG10):
-      return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log10);
+      if (validate_arg (arg0, REAL_TYPE))
+        return do_mpfr_arg1 (arg0, type, mpfr_log10, &dconst0, NULL, false);
+      break;
 
     CASE_FLT_FN (BUILT_IN_LOG1P):
       if (validate_arg (arg0, REAL_TYPE))
@@ -10061,11 +10298,6 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
     case BUILT_IN_ISNAND128:
       return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN);
 
-    case BUILT_IN_PRINTF:
-    case BUILT_IN_PRINTF_UNLOCKED:
-    case BUILT_IN_VPRINTF:
-      return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, fcode);
-
     case BUILT_IN_FREE:
       if (integer_zerop (arg0))
        return build_empty_stmt (loc);
@@ -10080,11 +10312,10 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
 }
 
 /* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
-   IGNORE is true if the result of the function call is ignored.  This
-   function returns NULL_TREE if no simplification was possible.  */
+   This function returns NULL_TREE if no simplification was possible.  */
 
 static tree
-fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
+fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1)
 {
   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
@@ -10171,19 +10402,6 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
     case BUILT_IN_RINDEX:
       return fold_builtin_strrchr (loc, arg0, arg1, type);
 
-    case BUILT_IN_STPCPY:
-      if (ignore)
-       {
-         tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
-         if (!fn)
-           break;
-
-         return build_call_expr_loc (loc, fn, 2, arg0, arg1);
-       }
-      else
-       return fold_builtin_stpcpy (loc, fndecl, arg0, arg1);
-      break;
-
     case BUILT_IN_STRCMP:
       return fold_builtin_strcmp (loc, arg0, arg1);
 
@@ -10235,27 +10453,6 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
     case BUILT_IN_OBJECT_SIZE:
       return fold_builtin_object_size (arg0, arg1);
 
-    case BUILT_IN_PRINTF:
-    case BUILT_IN_PRINTF_UNLOCKED:
-    case BUILT_IN_VPRINTF:
-      return fold_builtin_printf (loc, fndecl, arg0, arg1, ignore, fcode);
-
-    case BUILT_IN_PRINTF_CHK:
-    case BUILT_IN_VPRINTF_CHK:
-      if (!validate_arg (arg0, INTEGER_TYPE)
-         || TREE_SIDE_EFFECTS (arg0))
-       return NULL_TREE;
-      else
-       return fold_builtin_printf (loc, fndecl,
-                                   arg1, NULL_TREE, ignore, fcode);
-    break;
-
-    case BUILT_IN_FPRINTF:
-    case BUILT_IN_FPRINTF_UNLOCKED:
-    case BUILT_IN_VFPRINTF:
-      return fold_builtin_fprintf (loc, fndecl, arg0, arg1, NULL_TREE,
-                                  ignore, fcode);
-
     case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
       return fold_builtin_atomic_always_lock_free (arg0, arg1);
 
@@ -10269,12 +10466,12 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
 }
 
 /* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
-   and ARG2.  IGNORE is true if the result of the function call is ignored.
+   and ARG2.
    This function returns NULL_TREE if no simplification was possible.  */
 
 static tree
 fold_builtin_3 (location_t loc, tree fndecl,
-               tree arg0, tree arg1, tree arg2, bool ignore)
+               tree arg0, tree arg1, tree arg2)
 {
   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
@@ -10295,9 +10492,6 @@ fold_builtin_3 (location_t loc, tree fndecl,
        return do_mpfr_remquo (arg0, arg1, arg2);
     break;
 
-    case BUILT_IN_STRNCAT:
-      return fold_builtin_strncat (loc, arg0, arg1, arg2);
-
     case BUILT_IN_STRNCMP:
       return fold_builtin_strncmp (loc, arg0, arg1, arg2);
 
@@ -10308,67 +10502,31 @@ fold_builtin_3 (location_t loc, tree fndecl,
     case BUILT_IN_MEMCMP:
       return fold_builtin_memcmp (loc, arg0, arg1, arg2);;
 
-    case BUILT_IN_STRCAT_CHK:
-      return fold_builtin_strcat_chk (loc, fndecl, arg0, arg1, arg2);
-
-    case BUILT_IN_PRINTF_CHK:
-    case BUILT_IN_VPRINTF_CHK:
-      if (!validate_arg (arg0, INTEGER_TYPE)
-         || TREE_SIDE_EFFECTS (arg0))
-       return NULL_TREE;
-      else
-       return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode);
-    break;
-
-    case BUILT_IN_FPRINTF:
-    case BUILT_IN_FPRINTF_UNLOCKED:
-    case BUILT_IN_VFPRINTF:
-      return fold_builtin_fprintf (loc, fndecl, arg0, arg1, arg2,
-                                  ignore, fcode);
-
-    case BUILT_IN_FPRINTF_CHK:
-    case BUILT_IN_VFPRINTF_CHK:
-      if (!validate_arg (arg1, INTEGER_TYPE)
-         || TREE_SIDE_EFFECTS (arg1))
-       return NULL_TREE;
-      else
-       return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE,
-                                    ignore, fcode);
-
     case BUILT_IN_EXPECT:
       return fold_builtin_expect (loc, arg0, arg1, arg2);
 
-    default:
-      break;
-    }
-  return NULL_TREE;
-}
-
-/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1,
-   ARG2, and ARG3.  IGNORE is true if the result of the function call is
-   ignored.  This function returns NULL_TREE if no simplification was
-   possible.  */
-
-static tree
-fold_builtin_4 (location_t loc, tree fndecl,
-               tree arg0, tree arg1, tree arg2, tree arg3, bool ignore)
-{
-  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
-
-  switch (fcode)
-    {
-    case BUILT_IN_STRNCAT_CHK:
-      return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3);
-
-    case BUILT_IN_FPRINTF_CHK:
-    case BUILT_IN_VFPRINTF_CHK:
-      if (!validate_arg (arg1, INTEGER_TYPE)
-         || TREE_SIDE_EFFECTS (arg1))
-       return NULL_TREE;
-      else
-       return fold_builtin_fprintf (loc, fndecl, arg0, arg2, arg3,
-                                    ignore, fcode);
-    break;
+    case BUILT_IN_ADD_OVERFLOW:
+    case BUILT_IN_SUB_OVERFLOW:
+    case BUILT_IN_MUL_OVERFLOW:
+    case BUILT_IN_SADD_OVERFLOW:
+    case BUILT_IN_SADDL_OVERFLOW:
+    case BUILT_IN_SADDLL_OVERFLOW:
+    case BUILT_IN_SSUB_OVERFLOW:
+    case BUILT_IN_SSUBL_OVERFLOW:
+    case BUILT_IN_SSUBLL_OVERFLOW:
+    case BUILT_IN_SMUL_OVERFLOW:
+    case BUILT_IN_SMULL_OVERFLOW:
+    case BUILT_IN_SMULLL_OVERFLOW:
+    case BUILT_IN_UADD_OVERFLOW:
+    case BUILT_IN_UADDL_OVERFLOW:
+    case BUILT_IN_UADDLL_OVERFLOW:
+    case BUILT_IN_USUB_OVERFLOW:
+    case BUILT_IN_USUBL_OVERFLOW:
+    case BUILT_IN_USUBLL_OVERFLOW:
+    case BUILT_IN_UMUL_OVERFLOW:
+    case BUILT_IN_UMULL_OVERFLOW:
+    case BUILT_IN_UMULLL_OVERFLOW:
+      return fold_builtin_arith_overflow (loc, fcode, arg0, arg1, arg2);
 
     default:
       break;
@@ -10377,39 +10535,31 @@ fold_builtin_4 (location_t loc, tree fndecl,
 }
 
 /* Fold a call to built-in function FNDECL.  ARGS is an array of NARGS
-    arguments, where NARGS <= 4.  IGNORE is true if the result of the
-    function call is ignored.  This function returns NULL_TREE if no
-    simplification was possible.  Note that this only folds builtins with
-    fixed argument patterns.  Foldings that do varargs-to-varargs
-    transformations, or that match calls with more than 4 arguments,
-    need to be handled with fold_builtin_varargs instead.  */
-
-#define MAX_ARGS_TO_FOLD_BUILTIN 4
+   arguments.  IGNORE is true if the result of the
+   function call is ignored.  This function returns NULL_TREE if no
+   simplification was possible.  */
 
-static tree
-fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
+tree
+fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool)
 {
   tree ret = NULL_TREE;
 
   switch (nargs)
     {
     case 0:
-      ret = fold_builtin_0 (loc, fndecl, ignore);
+      ret = fold_builtin_0 (loc, fndecl);
       break;
     case 1:
-      ret = fold_builtin_1 (loc, fndecl, args[0], ignore);
+      ret = fold_builtin_1 (loc, fndecl, args[0]);
       break;
     case 2:
-      ret = fold_builtin_2 (loc, fndecl, args[0], args[1], ignore);
+      ret = fold_builtin_2 (loc, fndecl, args[0], args[1]);
       break;
     case 3:
-      ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore);
-      break;
-    case 4:
-      ret = fold_builtin_4 (loc, fndecl, args[0], args[1], args[2], args[3],
-                           ignore);
+      ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2]);
       break;
     default:
+      ret = fold_builtin_varargs (loc, fndecl, args, nargs);
       break;
     }
   if (ret)
@@ -10506,13 +10656,8 @@ fold_call_expr (location_t loc, tree exp, bool ignore)
                                     CALL_EXPR_ARGP (exp), ignore);
       else
        {
-         if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
-           {
-             tree *args = CALL_EXPR_ARGP (exp);
-             ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
-           }
-         if (!ret)
-           ret = fold_builtin_varargs (loc, fndecl, exp, ignore);
+         tree *args = CALL_EXPR_ARGP (exp);
+         ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
          if (ret)
            return ret;
        }
@@ -10520,62 +10665,43 @@ fold_call_expr (location_t loc, tree exp, bool ignore)
   return NULL_TREE;
 }
 
-/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
-   N arguments are passed in the array ARGARRAY.  */
+/* Fold a CALL_EXPR with type TYPE with FN as the function expression.
+   N arguments are passed in the array ARGARRAY.  Return a folded
+   expression or NULL_TREE if no simplification was possible.  */
 
 tree
-fold_builtin_call_array (location_t loc, tree type,
+fold_builtin_call_array (location_t loc, tree,
                         tree fn,
                         int n,
                         tree *argarray)
 {
-  tree ret = NULL_TREE;
-   tree exp;
-
-  if (TREE_CODE (fn) == ADDR_EXPR)
-  {
-    tree fndecl = TREE_OPERAND (fn, 0);
-    if (TREE_CODE (fndecl) == FUNCTION_DECL
-        && DECL_BUILT_IN (fndecl))
-      {
-       /* If last argument is __builtin_va_arg_pack (), arguments to this
-          function are not finalized yet.  Defer folding until they are.  */
-       if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
-         {
-           tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
-           if (fndecl2
-               && TREE_CODE (fndecl2) == FUNCTION_DECL
-               && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
-               && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
-             return build_call_array_loc (loc, type, fn, n, argarray);
-         }
-       if (avoid_folding_inline_builtin (fndecl))
-         return build_call_array_loc (loc, type, fn, n, argarray);
-        if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
-          {
-           ret = targetm.fold_builtin (fndecl, n, argarray, false);
-           if (ret)
-             return ret;
+  if (TREE_CODE (fn) != ADDR_EXPR)
+    return NULL_TREE;
 
-           return build_call_array_loc (loc, type, fn, n, argarray);
-          }
-        else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
-          {
-            /* First try the transformations that don't require consing up
-               an exp.  */
-            ret = fold_builtin_n (loc, fndecl, argarray, n, false);
-            if (ret)
-              return ret;
-          }
-
-        /* If we got this far, we need to build an exp.  */
-        exp = build_call_array_loc (loc, type, fn, n, argarray);
-        ret = fold_builtin_varargs (loc, fndecl, exp, false);
-        return ret ? ret : exp;
-      }
-  }
+  tree fndecl = TREE_OPERAND (fn, 0);
+  if (TREE_CODE (fndecl) == FUNCTION_DECL
+      && DECL_BUILT_IN (fndecl))
+    {
+      /* If last argument is __builtin_va_arg_pack (), arguments to this
+        function are not finalized yet.  Defer folding until they are.  */
+      if (n && TREE_CODE (argarray[n - 1]) == CALL_EXPR)
+       {
+         tree fndecl2 = get_callee_fndecl (argarray[n - 1]);
+         if (fndecl2
+             && TREE_CODE (fndecl2) == FUNCTION_DECL
+             && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL
+             && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
+           return NULL_TREE;
+       }
+      if (avoid_folding_inline_builtin (fndecl))
+       return NULL_TREE;
+      if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+       return targetm.fold_builtin (fndecl, n, argarray, false);
+      else
+       return fold_builtin_n (loc, fndecl, argarray, n, false);
+    }
 
-  return build_call_array_loc (loc, type, fn, n, argarray);
+  return NULL_TREE;
 }
 
 /* Construct a new CALL_EXPR using the tail of the argument list of EXP
@@ -10622,7 +10748,7 @@ validate_arg (const_tree arg, enum tree_code code)
    validate_arglist will then be removed.  */
 
 bool
-validate_gimple_arglist (const_gimple call, ...)
+validate_gimple_arglist (const gcall *call, ...)
 {
   enum tree_code code;
   bool res = 0;
@@ -10673,7 +10799,7 @@ rtx
 default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
                        rtx target ATTRIBUTE_UNUSED,
                        rtx subtarget ATTRIBUTE_UNUSED,
-                       enum machine_mode mode ATTRIBUTE_UNUSED,
+                       machine_mode mode ATTRIBUTE_UNUSED,
                        int ignore ATTRIBUTE_UNUSED)
 {
   return NULL_RTX;
@@ -10955,58 +11081,6 @@ fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type)
     }
 }
 
-/* Simplify a call to the strncat builtin.  DST, SRC, and LEN are the
-   arguments to the call.
-
-   Return NULL_TREE if no simplification was possible, otherwise return the
-   simplified form of the call as a tree.
-
-   The simplified form may be a constant or other expression which
-   computes the same value, but in a more efficient manner (including
-   calls to other builtin functions).
-
-   The call may contain arguments which need to be evaluated, but
-   which are not useful to determine the result of the call.  In
-   this case we return a chain of COMPOUND_EXPRs.  The LHS of each
-   COMPOUND_EXPR will be an argument which must be evaluated.
-   COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
-   COMPOUND_EXPR in the chain will contain the tree for the simplified
-   form of the builtin function call.  */
-
-static tree
-fold_builtin_strncat (location_t loc, tree dst, tree src, tree len)
-{
-  if (!validate_arg (dst, POINTER_TYPE)
-      || !validate_arg (src, POINTER_TYPE)
-      || !validate_arg (len, INTEGER_TYPE))
-    return NULL_TREE;
-  else
-    {
-      const char *p = c_getstr (src);
-
-      /* If the requested length is zero, or the src parameter string
-        length is zero, return the dst parameter.  */
-      if (integer_zerop (len) || (p && *p == '\0'))
-       return omit_two_operands_loc (loc, TREE_TYPE (dst), dst, src, len);
-
-      /* If the requested len is greater than or equal to the string
-        length, call strcat.  */
-      if (TREE_CODE (len) == INTEGER_CST && p
-         && compare_tree_int (len, strlen (p)) >= 0)
-       {
-         tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
-
-         /* If the replacement _DECL isn't initialized, don't do the
-            transformation.  */
-         if (!fn)
-           return NULL_TREE;
-
-         return build_call_expr_loc (loc, fn, 2, dst, src);
-       }
-      return NULL_TREE;
-    }
-}
-
 /* Simplify a call to the strspn builtin.  S1 and S2 are the arguments
    to the call.
 
@@ -11265,7 +11339,7 @@ expand_builtin_object_size (tree exp)
    mode MODE if that's convenient).  */
 
 static rtx
-expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
+expand_builtin_memory_chk (tree exp, rtx target, machine_mode mode,
                           enum built_in_function fcode)
 {
   tree dest, src, len, size;
@@ -11575,99 +11649,14 @@ fold_builtin_object_size (tree ptr, tree ost)
   return NULL_TREE;
 }
 
-/* Fold a call to the __strcat_chk builtin FNDECL.  DEST, SRC, and SIZE
-   are the arguments to the call.  */
-
-static tree
-fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest,
-                        tree src, tree size)
-{
-  tree fn;
-  const char *p;
-
-  if (!validate_arg (dest, POINTER_TYPE)
-      || !validate_arg (src, POINTER_TYPE)
-      || !validate_arg (size, INTEGER_TYPE))
-    return NULL_TREE;
-
-  p = c_getstr (src);
-  /* If the SRC parameter is "", return DEST.  */
-  if (p && *p == '\0')
-    return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
-
-  if (! tree_fits_uhwi_p (size) || ! integer_all_onesp (size))
-    return NULL_TREE;
-
-  /* If __builtin_strcat_chk is used, assume strcat is available.  */
-  fn = builtin_decl_explicit (BUILT_IN_STRCAT);
-  if (!fn)
-    return NULL_TREE;
-
-  return build_call_expr_loc (loc, fn, 2, dest, src);
-}
-
-/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
-   LEN, and SIZE.  */
-
-static tree
-fold_builtin_strncat_chk (location_t loc, tree fndecl,
-                         tree dest, tree src, tree len, tree size)
-{
-  tree fn;
-  const char *p;
-
-  if (!validate_arg (dest, POINTER_TYPE)
-      || !validate_arg (src, POINTER_TYPE)
-      || !validate_arg (size, INTEGER_TYPE)
-      || !validate_arg (size, INTEGER_TYPE))
-    return NULL_TREE;
-
-  p = c_getstr (src);
-  /* If the SRC parameter is "" or if LEN is 0, return DEST.  */
-  if (p && *p == '\0')
-    return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
-  else if (integer_zerop (len))
-    return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
-
-  if (! tree_fits_uhwi_p (size))
-    return NULL_TREE;
-
-  if (! integer_all_onesp (size))
-    {
-      tree src_len = c_strlen (src, 1);
-      if (src_len
-         && tree_fits_uhwi_p (src_len)
-         && tree_fits_uhwi_p (len)
-         && ! tree_int_cst_lt (len, src_len))
-       {
-         /* If LEN >= strlen (SRC), optimize into __strcat_chk.  */
-         fn = builtin_decl_explicit (BUILT_IN_STRCAT_CHK);
-         if (!fn)
-           return NULL_TREE;
-
-         return build_call_expr_loc (loc, fn, 3, dest, src, size);
-       }
-      return NULL_TREE;
-    }
-
-  /* If __builtin_strncat_chk is used, assume strncat is available.  */
-  fn = builtin_decl_explicit (BUILT_IN_STRNCAT);
-  if (!fn)
-    return NULL_TREE;
-
-  return build_call_expr_loc (loc, fn, 3, dest, src, len);
-}
-
 /* Builtins with folding operations that operate on "..." arguments
    need special handling; we need to store the arguments in a convenient
    data structure before attempting any folding.  Fortunately there are
    only a few builtins that fall into this category.  FNDECL is the
-   function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
-   result of the function call is ignored.  */
+   function, EXP is the CALL_EXPR for the call.  */
 
 static tree
-fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
-                     bool ignore ATTRIBUTE_UNUSED)
+fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs)
 {
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   tree ret = NULL_TREE;
@@ -11675,7 +11664,7 @@ fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
   switch (fcode)
     {
     case BUILT_IN_FPCLASSIFY:
-      ret = fold_builtin_fpclassify (loc, exp);
+      ret = fold_builtin_fpclassify (loc, args, nargs);
       break;
 
     default:
@@ -11691,254 +11680,6 @@ fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
   return NULL_TREE;
 }
 
-/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
-   FMT and ARG are the arguments to the call; we don't fold cases with
-   more than 2 arguments, and ARG may be null if this is a 1-argument case.
-
-   Return NULL_TREE if no simplification was possible, otherwise return the
-   simplified form of the call as a tree.  FCODE is the BUILT_IN_*
-   code of the function to be simplified.  */
-
-static tree
-fold_builtin_printf (location_t loc, tree fndecl, tree fmt,
-                    tree arg, bool ignore,
-                    enum built_in_function fcode)
-{
-  tree fn_putchar, fn_puts, newarg, call = NULL_TREE;
-  const char *fmt_str = NULL;
-
-  /* If the return value is used, don't do the transformation.  */
-  if (! ignore)
-    return NULL_TREE;
-
-  /* Verify the required arguments in the original call.  */
-  if (!validate_arg (fmt, POINTER_TYPE))
-    return NULL_TREE;
-
-  /* Check whether the format is a literal string constant.  */
-  fmt_str = c_getstr (fmt);
-  if (fmt_str == NULL)
-    return NULL_TREE;
-
-  if (fcode == BUILT_IN_PRINTF_UNLOCKED)
-    {
-      /* If we're using an unlocked function, assume the other
-        unlocked functions exist explicitly.  */
-      fn_putchar = builtin_decl_explicit (BUILT_IN_PUTCHAR_UNLOCKED);
-      fn_puts = builtin_decl_explicit (BUILT_IN_PUTS_UNLOCKED);
-    }
-  else
-    {
-      fn_putchar = builtin_decl_implicit (BUILT_IN_PUTCHAR);
-      fn_puts = builtin_decl_implicit (BUILT_IN_PUTS);
-    }
-
-  if (!init_target_chars ())
-    return NULL_TREE;
-
-  if (strcmp (fmt_str, target_percent_s) == 0
-      || strchr (fmt_str, target_percent) == NULL)
-    {
-      const char *str;
-
-      if (strcmp (fmt_str, target_percent_s) == 0)
-       {
-         if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
-           return NULL_TREE;
-
-         if (!arg || !validate_arg (arg, POINTER_TYPE))
-           return NULL_TREE;
-
-         str = c_getstr (arg);
-         if (str == NULL)
-           return NULL_TREE;
-       }
-      else
-       {
-         /* The format specifier doesn't contain any '%' characters.  */
-         if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
-             && arg)
-           return NULL_TREE;
-         str = fmt_str;
-       }
-
-      /* If the string was "", printf does nothing.  */
-      if (str[0] == '\0')
-       return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
-
-      /* If the string has length of 1, call putchar.  */
-      if (str[1] == '\0')
-       {
-         /* Given printf("c"), (where c is any one character,)
-            convert "c"[0] to an int and pass that to the replacement
-            function.  */
-         newarg = build_int_cst (integer_type_node, str[0]);
-         if (fn_putchar)
-           call = build_call_expr_loc (loc, fn_putchar, 1, newarg);
-       }
-      else
-       {
-         /* If the string was "string\n", call puts("string").  */
-         size_t len = strlen (str);
-         if ((unsigned char)str[len - 1] == target_newline
-             && (size_t) (int) len == len
-             && (int) len > 0)
-           {
-             char *newstr;
-             tree offset_node, string_cst;
-
-             /* Create a NUL-terminated string that's one char shorter
-                than the original, stripping off the trailing '\n'.  */
-             newarg = build_string_literal (len, str);
-             string_cst = string_constant (newarg, &offset_node);
-             gcc_checking_assert (string_cst
-                                  && (TREE_STRING_LENGTH (string_cst)
-                                      == (int) len)
-                                  && integer_zerop (offset_node)
-                                  && (unsigned char)
-                                     TREE_STRING_POINTER (string_cst)[len - 1]
-                                     == target_newline);
-             /* build_string_literal creates a new STRING_CST,
-                modify it in place to avoid double copying.  */
-             newstr = CONST_CAST (char *, TREE_STRING_POINTER (string_cst));
-             newstr[len - 1] = '\0';
-             if (fn_puts)
-               call = build_call_expr_loc (loc, fn_puts, 1, newarg);
-           }
-         else
-           /* We'd like to arrange to call fputs(string,stdout) here,
-              but we need stdout and don't have a way to get it yet.  */
-           return NULL_TREE;
-       }
-    }
-
-  /* The other optimizations can be done only on the non-va_list variants.  */
-  else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
-    return NULL_TREE;
-
-  /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
-  else if (strcmp (fmt_str, target_percent_s_newline) == 0)
-    {
-      if (!arg || !validate_arg (arg, POINTER_TYPE))
-       return NULL_TREE;
-      if (fn_puts)
-       call = build_call_expr_loc (loc, fn_puts, 1, arg);
-    }
-
-  /* If the format specifier was "%c", call __builtin_putchar(arg).  */
-  else if (strcmp (fmt_str, target_percent_c) == 0)
-    {
-      if (!arg || !validate_arg (arg, INTEGER_TYPE))
-       return NULL_TREE;
-      if (fn_putchar)
-       call = build_call_expr_loc (loc, fn_putchar, 1, arg);
-    }
-
-  if (!call)
-    return NULL_TREE;
-
-  return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
-}
-
-/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
-   FP, FMT, and ARG are the arguments to the call.  We don't fold calls with
-   more than 3 arguments, and ARG may be null in the 2-argument case.
-
-   Return NULL_TREE if no simplification was possible, otherwise return the
-   simplified form of the call as a tree.  FCODE is the BUILT_IN_*
-   code of the function to be simplified.  */
-
-static tree
-fold_builtin_fprintf (location_t loc, tree fndecl, tree fp,
-                     tree fmt, tree arg, bool ignore,
-                     enum built_in_function fcode)
-{
-  tree fn_fputc, fn_fputs, call = NULL_TREE;
-  const char *fmt_str = NULL;
-
-  /* If the return value is used, don't do the transformation.  */
-  if (! ignore)
-    return NULL_TREE;
-
-  /* Verify the required arguments in the original call.  */
-  if (!validate_arg (fp, POINTER_TYPE))
-    return NULL_TREE;
-  if (!validate_arg (fmt, POINTER_TYPE))
-    return NULL_TREE;
-
-  /* Check whether the format is a literal string constant.  */
-  fmt_str = c_getstr (fmt);
-  if (fmt_str == NULL)
-    return NULL_TREE;
-
-  if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
-    {
-      /* If we're using an unlocked function, assume the other
-        unlocked functions exist explicitly.  */
-      fn_fputc = builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED);
-      fn_fputs = builtin_decl_explicit (BUILT_IN_FPUTS_UNLOCKED);
-    }
-  else
-    {
-      fn_fputc = builtin_decl_implicit (BUILT_IN_FPUTC);
-      fn_fputs = builtin_decl_implicit (BUILT_IN_FPUTS);
-    }
-
-  if (!init_target_chars ())
-    return NULL_TREE;
-
-  /* If the format doesn't contain % args or %%, use strcpy.  */
-  if (strchr (fmt_str, target_percent) == NULL)
-    {
-      if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
-         && arg)
-       return NULL_TREE;
-
-      /* If the format specifier was "", fprintf does nothing.  */
-      if (fmt_str[0] == '\0')
-       {
-         /* If FP has side-effects, just wait until gimplification is
-            done.  */
-         if (TREE_SIDE_EFFECTS (fp))
-           return NULL_TREE;
-
-         return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
-       }
-
-      /* When "string" doesn't contain %, replace all cases of
-        fprintf (fp, string) with fputs (string, fp).  The fputs
-        builtin will take care of special cases like length == 1.  */
-      if (fn_fputs)
-       call = build_call_expr_loc (loc, fn_fputs, 2, fmt, fp);
-    }
-
-  /* The other optimizations can be done only on the non-va_list variants.  */
-  else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
-    return NULL_TREE;
-
-  /* If the format specifier was "%s", call __builtin_fputs (arg, fp).  */
-  else if (strcmp (fmt_str, target_percent_s) == 0)
-    {
-      if (!arg || !validate_arg (arg, POINTER_TYPE))
-       return NULL_TREE;
-      if (fn_fputs)
-       call = build_call_expr_loc (loc, fn_fputs, 2, arg, fp);
-    }
-
-  /* If the format specifier was "%c", call __builtin_fputc (arg, fp).  */
-  else if (strcmp (fmt_str, target_percent_c) == 0)
-    {
-      if (!arg || !validate_arg (arg, INTEGER_TYPE))
-       return NULL_TREE;
-      if (fn_fputc)
-       call = build_call_expr_loc (loc, fn_fputc, 2, arg, fp);
-    }
-
-  if (!call)
-    return NULL_TREE;
-  return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call);
-}
-
 /* Initialize format string characters in the target charset.  */
 
 bool
@@ -12563,7 +12304,7 @@ do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
    call node earlier than the warning is generated.  */
 
 tree
-fold_call_stmt (gimple stmt, bool ignore)
+fold_call_stmt (gcall *stmt, bool ignore)
 {
   tree ret = NULL_TREE;
   tree fndecl = gimple_call_fndecl (stmt);
@@ -12586,8 +12327,7 @@ fold_call_stmt (gimple stmt, bool ignore)
         }
       else
        {
-         if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
-           ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
+         ret = fold_builtin_n (loc, fndecl, args, nargs, ignore);
          if (ret)
            {
              /* Propagate location information from original call to
@@ -12770,6 +12510,7 @@ is_inexpensive_builtin (tree decl)
       case BUILT_IN_LABS:
       case BUILT_IN_LLABS:
       case BUILT_IN_PREFETCH:
+      case BUILT_IN_ACC_ON_DEVICE:
        return true;
 
       default: