re PR c++/66243 (enum class value is allowed to be initialized by value from other...
[gcc.git] / gcc / gimple-fold.c
index 8e0c9e055ef82e82cd2a1397586a455fa923a3e2..c91f218c218ca4a90d1b9ef403f0a7ae1b2908ee 100644 (file)
@@ -1,5 +1,5 @@
 /* Statement simplification on GIMPLE.
-   Copyright (C) 2010-2014 Free Software Foundation, Inc.
+   Copyright (C) 2010-2015 Free Software Foundation, Inc.
    Split out from tree-ssa-ccp.c.
 
 This file is part of GCC.
@@ -22,19 +22,36 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
 #include "tree.h"
+#include "fold-const.h"
 #include "stringpool.h"
-#include "expr.h"
-#include "stmt.h"
-#include "stor-layout.h"
-#include "flags.h"
 #include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "machmode.h"
 #include "hard-reg-set.h"
-#include "input.h"
 #include "function.h"
+#include "rtl.h"
+#include "flags.h"
+#include "statistics.h"
+#include "real.h"
+#include "fixed-value.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
+#include "expr.h"
+#include "stor-layout.h"
 #include "dumpfile.h"
 #include "bitmap.h"
 #include "predict.h"
@@ -254,8 +271,7 @@ get_symbol_constant_value (tree sym)
         have zero as the initializer if they may not be
         overridden at link or run time.  */
       if (!val
-          && (INTEGRAL_TYPE_P (TREE_TYPE (sym))
-              || SCALAR_FLOAT_TYPE_P (TREE_TYPE (sym))))
+          && is_gimple_reg_type (TREE_TYPE (sym)))
        return build_zero_cst (TREE_TYPE (sym));
     }
 
@@ -753,7 +769,7 @@ var_decl_component_p (tree var)
 }
 
 /* Fold function call to builtin mem{{,p}cpy,move}.  Return
-   NULL_TREE if no simplification can be made.
+   false if no simplification can be made.
    If ENDP is 0, return DEST (like memcpy).
    If ENDP is 1, return DEST+LEN (like mempcpy).
    If ENDP is 2, return DEST+LEN-1 (like stpcpy).
@@ -861,8 +877,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
                            srcmem = make_ssa_name (TREE_TYPE (srcmem),
                                                    new_stmt);
                          else
-                           srcmem = create_tmp_reg (TREE_TYPE (srcmem),
-                                                    NULL);
+                           srcmem = create_tmp_reg (TREE_TYPE (srcmem));
                          gimple_assign_set_lhs (new_stmt, srcmem);
                          gimple_set_vuse (new_stmt, gimple_vuse (stmt));
                          gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
@@ -1147,7 +1162,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
          if (gimple_in_ssa_p (cfun))
            srcvar = make_ssa_name (TREE_TYPE (srcvar), new_stmt);
          else
-           srcvar = create_tmp_reg (TREE_TYPE (srcvar), NULL);
+           srcvar = create_tmp_reg (TREE_TYPE (srcvar));
          gimple_assign_set_lhs (new_stmt, srcvar);
          gimple_set_vuse (new_stmt, gimple_vuse (stmt));
          gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
@@ -1555,9 +1570,9 @@ gimple_fold_builtin_strcat (gimple_stmt_iterator *gsi, tree dst, tree src)
   gimple repl = gimple_build_call (strlen_fn, 1, dst);
   gimple_set_location (repl, loc);
   if (gimple_in_ssa_p (cfun))
-    newdst = make_ssa_name (size_type_node, NULL);
+    newdst = make_ssa_name (size_type_node);
   else
-    newdst = create_tmp_reg (size_type_node, NULL);
+    newdst = create_tmp_reg (size_type_node);
   gimple_call_set_lhs (repl, newdst);
   gimple_seq_add_stmt_without_update (&stmts, repl);
 
@@ -1630,6 +1645,46 @@ gimple_fold_builtin_strcat_chk (gimple_stmt_iterator *gsi)
   return true;
 }
 
+/* Simplify a call to the strncat builtin.  */
+
+static bool
+gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
+{
+  gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+  tree dst = gimple_call_arg (stmt, 0);
+  tree src = gimple_call_arg (stmt, 1);
+  tree len = gimple_call_arg (stmt, 2);
+
+  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'))
+    {
+      replace_call_with_value (gsi, dst);
+      return true;
+    }
+
+  /* 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 false;
+
+      gcall *repl = gimple_build_call (fn, 2, dst, src);
+      replace_call_with_call_and_fold (gsi, repl);
+      return true;
+    }
+
+  return false;
+}
+
 /* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
    LEN, and SIZE.  */
 
@@ -2014,6 +2069,70 @@ gimple_fold_builtin_stxncpy_chk (gimple_stmt_iterator *gsi,
   return true;
 }
 
+/* Fold function call to builtin stpcpy with arguments DEST and SRC.
+   Return NULL_TREE if no simplification can be made.  */
+
+static bool
+gimple_fold_builtin_stpcpy (gimple_stmt_iterator *gsi)
+{
+  gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+  location_t loc = gimple_location (stmt);
+  tree dest = gimple_call_arg (stmt, 0);
+  tree src = gimple_call_arg (stmt, 1);
+  tree fn, len, lenp1;
+
+  /* If the result is unused, replace stpcpy with strcpy.  */
+  if (gimple_call_lhs (stmt) == NULL_TREE)
+    {
+      tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
+      if (!fn)
+       return false;
+      gimple_call_set_fndecl (stmt, fn);
+      fold_stmt (gsi);
+      return true;
+    }
+
+  len = c_strlen (src, 1);
+  if (!len
+      || TREE_CODE (len) != INTEGER_CST)
+    return false;
+
+  if (optimize_function_for_size_p (cfun)
+      /* If length is zero it's small enough.  */
+      && !integer_zerop (len))
+    return false;
+
+  /* If the source has a known length replace stpcpy with memcpy.  */
+  fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
+  if (!fn)
+    return false;
+
+  gimple_seq stmts = NULL;
+  tree tem = gimple_convert (&stmts, loc, size_type_node, len);
+  lenp1 = gimple_build (&stmts, loc, PLUS_EXPR, size_type_node,
+                       tem, build_int_cst (size_type_node, 1));
+  gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+  gcall *repl = gimple_build_call (fn, 3, dest, src, lenp1);
+  gimple_set_vuse (repl, gimple_vuse (stmt));
+  gimple_set_vdef (repl, gimple_vdef (stmt));
+  if (gimple_vdef (repl)
+      && TREE_CODE (gimple_vdef (repl)) == SSA_NAME)
+    SSA_NAME_DEF_STMT (gimple_vdef (repl)) = repl;
+  gsi_insert_before (gsi, repl, GSI_SAME_STMT);
+  /* Replace the result with dest + len.  */
+  stmts = NULL;
+  tem = gimple_convert (&stmts, loc, sizetype, len);
+  gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+  gassign *ret = gimple_build_assign (gimple_call_lhs (stmt),
+                                     POINTER_PLUS_EXPR, dest, tem);
+  gsi_replace (gsi, ret, true);
+  /* Finally fold the memcpy call.  */
+  gimple_stmt_iterator gsi2 = *gsi;
+  gsi_prev (&gsi2);
+  fold_stmt (&gsi2);
+  return true;
+}
+
 /* Fold a call EXP to {,v}snprintf having NARGS passed as ARGS.  Return
    NULL_TREE if a normal call should be emitted rather than expanding
    the function inline.  FCODE is either BUILT_IN_SNPRINTF_CHK or
@@ -2455,6 +2574,270 @@ gimple_fold_builtin_snprintf (gimple_stmt_iterator *gsi)
   return false;
 }
 
+/* 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 bool 
+gimple_fold_builtin_fprintf (gimple_stmt_iterator *gsi,
+                            tree fp, tree fmt, tree arg,
+                            enum built_in_function fcode)
+{
+  gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+  tree fn_fputc, fn_fputs;
+  const char *fmt_str = NULL;
+
+  /* If the return value is used, don't do the transformation.  */
+  if (gimple_call_lhs (stmt) != NULL_TREE)
+    return false;
+
+  /* Check whether the format is a literal string constant.  */
+  fmt_str = c_getstr (fmt);
+  if (fmt_str == NULL)
+    return false;
+
+  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 false;
+
+  /* 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 false;
+
+      /* If the format specifier was "", fprintf does nothing.  */
+      if (fmt_str[0] == '\0')
+       {
+         replace_call_with_value (gsi, NULL_TREE);
+         return true;
+       }
+
+      /* 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)
+       {
+         gcall *repl = gimple_build_call (fn_fputs, 2, fmt, fp);
+         replace_call_with_call_and_fold (gsi, repl);
+         return true;
+       }
+    }
+
+  /* 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 false;
+
+  /* If the format specifier was "%s", call __builtin_fputs (arg, fp).  */
+  else if (strcmp (fmt_str, target_percent_s) == 0)
+    {
+      if (!arg || ! POINTER_TYPE_P (TREE_TYPE (arg)))
+       return false;
+      if (fn_fputs)
+       {
+         gcall *repl = gimple_build_call (fn_fputs, 2, arg, fp);
+         replace_call_with_call_and_fold (gsi, repl);
+         return true;
+       }
+    }
+
+  /* If the format specifier was "%c", call __builtin_fputc (arg, fp).  */
+  else if (strcmp (fmt_str, target_percent_c) == 0)
+    {
+      if (!arg
+         || ! useless_type_conversion_p (integer_type_node, TREE_TYPE (arg)))
+       return false;
+      if (fn_fputc)
+       {
+         gcall *repl = gimple_build_call (fn_fputc, 2, arg, fp);
+         replace_call_with_call_and_fold (gsi, repl);
+         return true;
+       }
+    }
+
+  return false;
+}
+
+/* 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 bool
+gimple_fold_builtin_printf (gimple_stmt_iterator *gsi, tree fmt,
+                           tree arg, enum built_in_function fcode)
+{
+  gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+  tree fn_putchar, fn_puts, newarg;
+  const char *fmt_str = NULL;
+
+  /* If the return value is used, don't do the transformation.  */
+  if (gimple_call_lhs (stmt) != NULL_TREE)
+    return false;
+
+  /* Check whether the format is a literal string constant.  */
+  fmt_str = c_getstr (fmt);
+  if (fmt_str == NULL)
+    return false;
+
+  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 false;
+
+  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 false;
+
+         if (!arg || ! POINTER_TYPE_P (TREE_TYPE (arg)))
+           return false;
+
+         str = c_getstr (arg);
+         if (str == NULL)
+           return false;
+       }
+      else
+       {
+         /* The format specifier doesn't contain any '%' characters.  */
+         if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
+             && arg)
+           return false;
+         str = fmt_str;
+       }
+
+      /* If the string was "", printf does nothing.  */
+      if (str[0] == '\0')
+       {
+         replace_call_with_value (gsi, NULL_TREE);
+         return true;
+       }
+
+      /* 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)
+           {
+             gcall *repl = gimple_build_call (fn_putchar, 1, newarg);
+             replace_call_with_call_and_fold (gsi, repl);
+             return true;
+           }
+       }
+      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)
+               {
+                 gcall *repl = gimple_build_call (fn_puts, 1, newarg);
+                 replace_call_with_call_and_fold (gsi, repl);
+                 return true;
+               }
+           }
+         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 false;
+       }
+    }
+
+  /* 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 false;
+
+  /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
+  else if (strcmp (fmt_str, target_percent_s_newline) == 0)
+    {
+      if (!arg || ! POINTER_TYPE_P (TREE_TYPE (arg)))
+       return false;
+      if (fn_puts)
+       {
+         gcall *repl = gimple_build_call (fn_puts, 1, arg);
+         replace_call_with_call_and_fold (gsi, repl);
+         return true;
+       }
+    }
+
+  /* If the format specifier was "%c", call __builtin_putchar(arg).  */
+  else if (strcmp (fmt_str, target_percent_c) == 0)
+    {
+      if (!arg || ! useless_type_conversion_p (integer_type_node,
+                                              TREE_TYPE (arg)))
+       return false;
+      if (fn_putchar)
+       {
+         gcall *repl = gimple_build_call (fn_putchar, 1, arg);
+         replace_call_with_call_and_fold (gsi, repl);
+         return true;
+       }
+    }
+
+  return false;
+}
+
+
 
 /* Fold a call to __builtin_strlen with known length LEN.  */
 
@@ -2485,7 +2868,9 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi)
   if (avoid_folding_inline_builtin (callee))
     return false;
 
-  switch (DECL_FUNCTION_CODE (callee))
+  unsigned n = gimple_call_num_args (stmt);
+  enum built_in_function fcode = DECL_FUNCTION_CODE (callee);
+  switch (fcode)
     {
     case BUILT_IN_BZERO:
       return gimple_fold_builtin_memset (gsi, integer_zero_node,
@@ -2508,7 +2893,7 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi)
                                            gimple_call_arg (stmt, 1), 3);
     case BUILT_IN_SPRINTF_CHK:
     case BUILT_IN_VSPRINTF_CHK:
-      return gimple_fold_builtin_sprintf_chk (gsi, DECL_FUNCTION_CODE (callee));
+      return gimple_fold_builtin_sprintf_chk (gsi, fcode);
     case BUILT_IN_STRCAT_CHK:
       return gimple_fold_builtin_strcat_chk (gsi);
     case BUILT_IN_STRNCAT_CHK:
@@ -2527,6 +2912,8 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi)
     case BUILT_IN_STRCAT:
       return gimple_fold_builtin_strcat (gsi, gimple_call_arg (stmt, 0),
                                         gimple_call_arg (stmt, 1));
+    case BUILT_IN_STRNCAT:
+      return gimple_fold_builtin_strncat (gsi);
     case BUILT_IN_FPUTS:
       return gimple_fold_builtin_fputs (gsi, gimple_call_arg (stmt, 0),
                                        gimple_call_arg (stmt, 1), false);
@@ -2542,14 +2929,16 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi)
                                             gimple_call_arg (stmt, 1),
                                             gimple_call_arg (stmt, 2),
                                             gimple_call_arg (stmt, 3),
-                                            DECL_FUNCTION_CODE (callee));
+                                            fcode);
+    case BUILT_IN_STPCPY:
+      return gimple_fold_builtin_stpcpy (gsi);
     case BUILT_IN_STRCPY_CHK:
     case BUILT_IN_STPCPY_CHK:
       return gimple_fold_builtin_stxcpy_chk (gsi,
                                             gimple_call_arg (stmt, 0),
                                             gimple_call_arg (stmt, 1),
                                             gimple_call_arg (stmt, 2),
-                                            DECL_FUNCTION_CODE (callee));
+                                            fcode);
     case BUILT_IN_STRNCPY_CHK:
     case BUILT_IN_STPNCPY_CHK:
       return gimple_fold_builtin_stxncpy_chk (gsi,
@@ -2557,15 +2946,53 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi)
                                              gimple_call_arg (stmt, 1),
                                              gimple_call_arg (stmt, 2),
                                              gimple_call_arg (stmt, 3),
-                                             DECL_FUNCTION_CODE (callee));
+                                             fcode);
     case BUILT_IN_SNPRINTF_CHK:
     case BUILT_IN_VSNPRINTF_CHK:
-      return gimple_fold_builtin_snprintf_chk (gsi,
-                                              DECL_FUNCTION_CODE (callee));
+      return gimple_fold_builtin_snprintf_chk (gsi, fcode);
     case BUILT_IN_SNPRINTF:
       return gimple_fold_builtin_snprintf (gsi);
     case BUILT_IN_SPRINTF:
       return gimple_fold_builtin_sprintf (gsi);
+    case BUILT_IN_FPRINTF:
+    case BUILT_IN_FPRINTF_UNLOCKED:
+    case BUILT_IN_VFPRINTF:
+      if (n == 2 || n == 3)
+       return gimple_fold_builtin_fprintf (gsi,
+                                           gimple_call_arg (stmt, 0),
+                                           gimple_call_arg (stmt, 1),
+                                           n == 3
+                                           ? gimple_call_arg (stmt, 2)
+                                           : NULL_TREE,
+                                           fcode);
+      break;
+    case BUILT_IN_FPRINTF_CHK:
+    case BUILT_IN_VFPRINTF_CHK:
+      if (n == 3 || n == 4)
+       return gimple_fold_builtin_fprintf (gsi,
+                                           gimple_call_arg (stmt, 0),
+                                           gimple_call_arg (stmt, 2),
+                                           n == 4
+                                           ? gimple_call_arg (stmt, 3)
+                                           : NULL_TREE,
+                                           fcode);
+      break;
+    case BUILT_IN_PRINTF:
+    case BUILT_IN_PRINTF_UNLOCKED:
+    case BUILT_IN_VPRINTF:
+      if (n == 1 || n == 2)
+       return gimple_fold_builtin_printf (gsi, gimple_call_arg (stmt, 0),
+                                          n == 2
+                                          ? gimple_call_arg (stmt, 1)
+                                          : NULL_TREE, fcode);
+      break;
+    case BUILT_IN_PRINTF_CHK:
+    case BUILT_IN_VPRINTF_CHK:
+      if (n == 2 || n == 3)
+       return gimple_fold_builtin_printf (gsi, gimple_call_arg (stmt, 1),
+                                          n == 3
+                                          ? gimple_call_arg (stmt, 2)
+                                          : NULL_TREE, fcode);
     default:;
     }
 
@@ -2686,13 +3113,14 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
                    {
                      if (TREE_CODE (lhs) == SSA_NAME)
                        {
-                         tree var = create_tmp_var (TREE_TYPE (lhs), NULL);
+                         tree var = create_tmp_var (TREE_TYPE (lhs));
                          tree def = get_or_create_ssa_default_def (cfun, var);
                          gimple new_stmt = gimple_build_assign (lhs, def);
                          gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
                        }
                      gimple_call_set_lhs (stmt, NULL_TREE);
                    }
+                 maybe_remove_unused_call_args (cfun, stmt);
                }
              else
                {
@@ -2701,7 +3129,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
                  gimple_set_location (new_stmt, gimple_location (stmt));
                  if (lhs && TREE_CODE (lhs) == SSA_NAME)
                    {
-                     tree var = create_tmp_var (TREE_TYPE (lhs), NULL);
+                     tree var = create_tmp_var (TREE_TYPE (lhs));
                      tree def = get_or_create_ssa_default_def (cfun, var);
 
                      /* To satisfy condition for
@@ -3001,8 +3429,9 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi,
       if (gimple_has_lhs (stmt))
        {
          tree lhs = gimple_get_lhs (stmt);
-         maybe_push_res_to_seq (rcode, TREE_TYPE (lhs),
-                                ops, seq, lhs);
+         if (!maybe_push_res_to_seq (rcode, TREE_TYPE (lhs),
+                                     ops, seq, lhs))
+           return false;
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
              fprintf (dump_file, "gimple_simplified to ");
@@ -3062,7 +3491,8 @@ maybe_canonicalize_mem_ref_addr (tree *t)
      accessed is a decl that has the same access semantics as the MEM_REF.  */
   if (TREE_CODE (*t) == MEM_REF
       && TREE_CODE (TREE_OPERAND (*t, 0)) == ADDR_EXPR
-      && integer_zerop (TREE_OPERAND (*t, 1)))
+      && integer_zerop (TREE_OPERAND (*t, 1))
+      && MR_DEPENDENCE_CLIQUE (*t) == 0)
     {
       tree decl = TREE_OPERAND (TREE_OPERAND (*t, 0), 0);
       tree alias_type = TREE_TYPE (TREE_OPERAND (*t, 1));
@@ -3191,7 +3621,8 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree))
       gimple_seq seq = NULL;
       code_helper rcode;
       tree ops[3] = {};
-      if (gimple_simplify (stmt, &rcode, ops, inplace ? NULL : &seq, valueize))
+      if (gimple_simplify (stmt, &rcode, ops, inplace ? NULL : &seq,
+                          valueize, valueize))
        {
          if (replace_stmt_with_simplification (gsi, rcode, ops, &seq, inplace))
            changed = true;
@@ -3415,7 +3846,7 @@ canonicalize_bool (tree expr, bool invert)
       else if (TREE_CODE (expr) == SSA_NAME)
        return fold_build2 (EQ_EXPR, boolean_type_node, expr,
                            build_int_cst (TREE_TYPE (expr), 0));
-      else if (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_comparison)
+      else if (COMPARISON_CLASS_P (expr))
        return fold_build2 (invert_tree_comparison (TREE_CODE (expr), false),
                            boolean_type_node,
                            TREE_OPERAND (expr, 0),
@@ -3434,7 +3865,7 @@ canonicalize_bool (tree expr, bool invert)
       else if (TREE_CODE (expr) == SSA_NAME)
        return fold_build2 (NE_EXPR, boolean_type_node, expr,
                            build_int_cst (TREE_TYPE (expr), 0));
-      else if (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_comparison)
+      else if (COMPARISON_CLASS_P (expr))
        return fold_build2 (TREE_CODE (expr),
                            boolean_type_node,
                            TREE_OPERAND (expr, 0),
@@ -3515,12 +3946,12 @@ same_bool_result_p (const_tree op1, const_tree op2)
   /* Check the cases where at least one of the operands is a comparison.
      These are a bit smarter than operand_equal_p in that they apply some
      identifies on SSA_NAMEs.  */
-  if (TREE_CODE_CLASS (TREE_CODE (op2)) == tcc_comparison
+  if (COMPARISON_CLASS_P (op2)
       && same_bool_comparison_p (op1, TREE_CODE (op2),
                                 TREE_OPERAND (op2, 0),
                                 TREE_OPERAND (op2, 1)))
     return true;
-  if (TREE_CODE_CLASS (TREE_CODE (op1)) == tcc_comparison
+  if (COMPARISON_CLASS_P (op1)
       && same_bool_comparison_p (op2, TREE_CODE (op1),
                                 TREE_OPERAND (op1, 0),
                                 TREE_OPERAND (op1, 1)))
@@ -4498,7 +4929,7 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree),
      edges if there are intermediate VARYING defs.  For this reason
      do not follow SSA edges here even though SCCVN can technically
      just deal fine with that.  */
-  if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize)
+  if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize)
       && rcode.is_tree_code ()
       && (TREE_CODE_LENGTH ((tree_code) rcode) == 0
          || ((tree_code) rcode) == ADDR_EXPR)
@@ -4745,14 +5176,13 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree),
                                                       TREE_OPERAND (fn, 0)))
          {
            tree *args = XALLOCAVEC (tree, gimple_call_num_args (stmt));
-           tree call, retval;
+           tree retval;
            unsigned i;
            for (i = 0; i < gimple_call_num_args (stmt); ++i)
              args[i] = (*valueize) (gimple_call_arg (stmt, i));
-           call = build_call_array_loc (loc,
+           retval = fold_builtin_call_array (loc,
                                         gimple_call_return_type (call_stmt),
                                         fn, gimple_call_num_args (stmt), args);
-           retval = fold_call_expr (EXPR_LOCATION (call), call, false);
            if (retval)
              {
                /* fold_call_expr wraps the result inside a NOP_EXPR.  */
@@ -4787,10 +5217,6 @@ gimple_fold_stmt_to_constant (gimple stmt, tree (*valueize) (tree))
 /* The following set of functions are supposed to fold references using
    their constant initializers.  */
 
-static tree fold_ctor_reference (tree type, tree ctor,
-                                unsigned HOST_WIDE_INT offset,
-                                unsigned HOST_WIDE_INT size, tree);
-
 /* See if we can find constructor defining value of BASE.
    When we know the consructor with constant offset (such as
    base is array[40] and we do know constructor of array), then
@@ -5026,7 +5452,7 @@ fold_nonarray_ctor_reference (tree type, tree ctor,
 /* CTOR is value initializing memory, fold reference of type TYPE and size SIZE
    to the memory at bit OFFSET.  */
 
-static tree
+tree
 fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
                     unsigned HOST_WIDE_INT size, tree from_decl)
 {
@@ -5047,7 +5473,7 @@ fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
       ret = canonicalize_constructor_val (unshare_expr (ctor), from_decl);
       ret = fold_unary (VIEW_CONVERT_EXPR, type, ret);
       if (ret)
-       STRIP_NOPS (ret);
+       STRIP_USELESS_TYPE_CONVERSION (ret);
       return ret;
     }
   /* For constants and byte-aligned/sized reads try to go through
@@ -5092,7 +5518,7 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
   if (TREE_THIS_VOLATILE (t))
     return NULL_TREE;
 
-  if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration)
+  if (DECL_P (t))
     return get_symbol_constant_value (t);
 
   tem = fold_read_from_constant_string (t);
@@ -5225,7 +5651,6 @@ gimple_get_virt_method_for_vtable (HOST_WIDE_INT token,
   if (TREE_CODE (v) != VAR_DECL
       || !DECL_VIRTUAL_P (v))
     {
-      gcc_assert (in_lto_p);
       /* Pass down that we lost track of the target.  */
       if (can_refer)
        *can_refer = false;
@@ -5425,7 +5850,7 @@ gimple_val_nonnegative_real_p (tree val)
            CASE_FLT_FN (BUILT_IN_SQRT):
              /* sqrt(-0.0) is -0.0, and sqrt is not defined over other
                 nonnegative inputs.  */
-             if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (val))))
+             if (!HONOR_SIGNED_ZEROS (val))
                return true;
 
              break;
@@ -5647,40 +6072,48 @@ rewrite_to_defined_overflow (gimple stmt)
   if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
     gimple_assign_set_rhs_code (stmt, PLUS_EXPR);
   gimple_seq_add_stmt (&stmts, stmt);
-  gimple cvt = gimple_build_assign_with_ops (NOP_EXPR, lhs,
-                                            gimple_assign_lhs (stmt));
+  gimple cvt = gimple_build_assign (lhs, NOP_EXPR, gimple_assign_lhs (stmt));
   gimple_seq_add_stmt (&stmts, cvt);
 
   return stmts;
 }
 
 
+/* The valueization hook we use for the gimple_build API simplification.
+   This makes us match fold_buildN behavior by only combining with
+   statements in the sequence(s) we are currently building.  */
+
+static tree
+gimple_build_valueize (tree op)
+{
+  if (gimple_bb (SSA_NAME_DEF_STMT (op)) == NULL)
+    return op;
+  return NULL_TREE;
+}
+
 /* Build the expression CODE OP0 of type TYPE with location LOC,
-   simplifying it first if possible using VALUEIZE if not NULL.
-   OP0 is expected to be valueized already.  Returns the built
+   simplifying it first if possible.  Returns the built
    expression value and appends statements possibly defining it
    to SEQ.  */
 
 tree
 gimple_build (gimple_seq *seq, location_t loc,
-             enum tree_code code, tree type, tree op0,
-             tree (*valueize)(tree))
+             enum tree_code code, tree type, tree op0)
 {
-  tree res = gimple_simplify (code, type, op0, seq, valueize);
+  tree res = gimple_simplify (code, type, op0, seq, gimple_build_valueize);
   if (!res)
     {
       if (gimple_in_ssa_p (cfun))
-       res = make_ssa_name (type, NULL);
+       res = make_ssa_name (type);
       else
-       res = create_tmp_reg (type, NULL);
+       res = create_tmp_reg (type);
       gimple stmt;
       if (code == REALPART_EXPR
          || code == IMAGPART_EXPR
          || code == VIEW_CONVERT_EXPR)
-       stmt = gimple_build_assign_with_ops (code, res,
-                                            build1 (code, type, op0));
+       stmt = gimple_build_assign (res, code, build1 (code, type, op0));
       else
-       stmt = gimple_build_assign_with_ops (code, res, op0);
+       stmt = gimple_build_assign (res, code, op0);
       gimple_set_location (stmt, loc);
       gimple_seq_add_stmt_without_update (seq, stmt);
     }
@@ -5688,24 +6121,22 @@ gimple_build (gimple_seq *seq, location_t loc,
 }
 
 /* Build the expression OP0 CODE OP1 of type TYPE with location LOC,
-   simplifying it first if possible using VALUEIZE if not NULL.
-   OP0 and OP1 are expected to be valueized already.  Returns the built
+   simplifying it first if possible.  Returns the built
    expression value and appends statements possibly defining it
    to SEQ.  */
 
 tree
 gimple_build (gimple_seq *seq, location_t loc,
-             enum tree_code code, tree type, tree op0, tree op1,
-             tree (*valueize)(tree))
+             enum tree_code code, tree type, tree op0, tree op1)
 {
-  tree res = gimple_simplify (code, type, op0, op1, seq, valueize);
+  tree res = gimple_simplify (code, type, op0, op1, seq, gimple_build_valueize);
   if (!res)
     {
       if (gimple_in_ssa_p (cfun))
-       res = make_ssa_name (type, NULL);
+       res = make_ssa_name (type);
       else
-       res = create_tmp_reg (type, NULL);
-      gimple stmt = gimple_build_assign_with_ops (code, res, op0, op1);
+       res = create_tmp_reg (type);
+      gimple stmt = gimple_build_assign (res, code, op0, op1);
       gimple_set_location (stmt, loc);
       gimple_seq_add_stmt_without_update (seq, stmt);
     }
@@ -5713,31 +6144,28 @@ gimple_build (gimple_seq *seq, location_t loc,
 }
 
 /* Build the expression (CODE OP0 OP1 OP2) of type TYPE with location LOC,
-   simplifying it first if possible using VALUEIZE if not NULL.
-   OP0, OP1 and OP2 are expected to be valueized already.  Returns the built
+   simplifying it first if possible.  Returns the built
    expression value and appends statements possibly defining it
    to SEQ.  */
 
 tree
 gimple_build (gimple_seq *seq, location_t loc,
-             enum tree_code code, tree type, tree op0, tree op1, tree op2,
-             tree (*valueize)(tree))
+             enum tree_code code, tree type, tree op0, tree op1, tree op2)
 {
   tree res = gimple_simplify (code, type, op0, op1, op2,
-                             seq, valueize);
+                             seq, gimple_build_valueize);
   if (!res)
     {
       if (gimple_in_ssa_p (cfun))
-       res = make_ssa_name (type, NULL);
+       res = make_ssa_name (type);
       else
-       res = create_tmp_reg (type, NULL);
+       res = create_tmp_reg (type);
       gimple stmt;
       if (code == BIT_FIELD_REF)
-       stmt = gimple_build_assign_with_ops (code, res,
-                                            build3 (BIT_FIELD_REF, type,
-                                                    op0, op1, op2));
+       stmt = gimple_build_assign (res, code,
+                                   build3 (code, type, op0, op1, op2));
       else
-       stmt = gimple_build_assign_with_ops (code, res, op0, op1, op2);
+       stmt = gimple_build_assign (res, code, op0, op1, op2);
       gimple_set_location (stmt, loc);
       gimple_seq_add_stmt_without_update (seq, stmt);
     }
@@ -5746,17 +6174,15 @@ gimple_build (gimple_seq *seq, location_t loc,
 
 /* Build the call FN (ARG0) with a result of type TYPE
    (or no result if TYPE is void) with location LOC,
-   simplifying it first if possible using VALUEIZE if not NULL.
-   ARG0 is expected to be valueized already.  Returns the built
+   simplifying it first if possible.  Returns the built
    expression value (or NULL_TREE if TYPE is void) and appends
    statements possibly defining it to SEQ.  */
 
 tree
 gimple_build (gimple_seq *seq, location_t loc,
-             enum built_in_function fn, tree type, tree arg0,
-             tree (*valueize)(tree))
+             enum built_in_function fn, tree type, tree arg0)
 {
-  tree res = gimple_simplify (fn, type, arg0, seq, valueize);
+  tree res = gimple_simplify (fn, type, arg0, seq, gimple_build_valueize);
   if (!res)
     {
       tree decl = builtin_decl_implicit (fn);
@@ -5764,9 +6190,9 @@ gimple_build (gimple_seq *seq, location_t loc,
       if (!VOID_TYPE_P (type))
        {
          if (gimple_in_ssa_p (cfun))
-           res = make_ssa_name (type, NULL);
+           res = make_ssa_name (type);
          else
-           res = create_tmp_reg (type, NULL);
+           res = create_tmp_reg (type);
          gimple_call_set_lhs (stmt, res);
        }
       gimple_set_location (stmt, loc);
@@ -5777,17 +6203,15 @@ gimple_build (gimple_seq *seq, location_t loc,
 
 /* Build the call FN (ARG0, ARG1) with a result of type TYPE
    (or no result if TYPE is void) with location LOC,
-   simplifying it first if possible using VALUEIZE if not NULL.
-   ARG0 is expected to be valueized already.  Returns the built
+   simplifying it first if possible.  Returns the built
    expression value (or NULL_TREE if TYPE is void) and appends
    statements possibly defining it to SEQ.  */
 
 tree
 gimple_build (gimple_seq *seq, location_t loc,
-             enum built_in_function fn, tree type, tree arg0, tree arg1,
-             tree (*valueize)(tree))
+             enum built_in_function fn, tree type, tree arg0, tree arg1)
 {
-  tree res = gimple_simplify (fn, type, arg0, arg1, seq, valueize);
+  tree res = gimple_simplify (fn, type, arg0, arg1, seq, gimple_build_valueize);
   if (!res)
     {
       tree decl = builtin_decl_implicit (fn);
@@ -5795,9 +6219,9 @@ gimple_build (gimple_seq *seq, location_t loc,
       if (!VOID_TYPE_P (type))
        {
          if (gimple_in_ssa_p (cfun))
-           res = make_ssa_name (type, NULL);
+           res = make_ssa_name (type);
          else
-           res = create_tmp_reg (type, NULL);
+           res = create_tmp_reg (type);
          gimple_call_set_lhs (stmt, res);
        }
       gimple_set_location (stmt, loc);
@@ -5808,18 +6232,17 @@ gimple_build (gimple_seq *seq, location_t loc,
 
 /* Build the call FN (ARG0, ARG1, ARG2) with a result of type TYPE
    (or no result if TYPE is void) with location LOC,
-   simplifying it first if possible using VALUEIZE if not NULL.
-   ARG0 is expected to be valueized already.  Returns the built
+   simplifying it first if possible.  Returns the built
    expression value (or NULL_TREE if TYPE is void) and appends
    statements possibly defining it to SEQ.  */
 
 tree
 gimple_build (gimple_seq *seq, location_t loc,
              enum built_in_function fn, tree type,
-             tree arg0, tree arg1, tree arg2,
-             tree (*valueize)(tree))
+             tree arg0, tree arg1, tree arg2)
 {
-  tree res = gimple_simplify (fn, type, arg0, arg1, arg2, seq, valueize);
+  tree res = gimple_simplify (fn, type, arg0, arg1, arg2,
+                             seq, gimple_build_valueize);
   if (!res)
     {
       tree decl = builtin_decl_implicit (fn);
@@ -5827,9 +6250,9 @@ gimple_build (gimple_seq *seq, location_t loc,
       if (!VOID_TYPE_P (type))
        {
          if (gimple_in_ssa_p (cfun))
-           res = make_ssa_name (type, NULL);
+           res = make_ssa_name (type);
          else
-           res = create_tmp_reg (type, NULL);
+           res = create_tmp_reg (type);
          gimple_call_set_lhs (stmt, res);
        }
       gimple_set_location (stmt, loc);