aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2014-10-16 12:25:52 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2014-10-16 12:25:52 +0000
commit745583f9539f78be7db1d8c51f15cae7a5f80f03 (patch)
tree3075787c7fa50bcb39399d99d978e00cb128d266 /gcc/gimple-fold.c
parentb7359edc20cae432bb68f5f897ba485f34de6f9a (diff)
downloadgcc-745583f9539f78be7db1d8c51f15cae7a5f80f03.zip
gcc-745583f9539f78be7db1d8c51f15cae7a5f80f03.tar.gz
gcc-745583f9539f78be7db1d8c51f15cae7a5f80f03.tar.bz2
re PR c/63554 (ice in "execute_todo, at passes.c:1797" with -O3)
2014-10-16 Richard Biener <rguenther@suse.de> PR middle-end/63554 * builtins.c (fold_builtin_4): Do not call fold_builtin_strncat_chk. (fold_builtin_strncat_chk): Move ... * gimple-fold.c (gimple_fold_builtin_strncat_chk): ... here. (gimple_fold_builtin): Call gimple_fold_builtin_strncat_chk. * gcc.dg/torture/pr63554.c: New testcase. From-SVN: r216315
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index cc27cb9..2c79f8a 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1632,6 +1632,62 @@ gimple_fold_builtin_strcat_chk (gimple_stmt_iterator *gsi)
return true;
}
+/* Fold a call to the __strncat_chk builtin with arguments DEST, SRC,
+ LEN, and SIZE. */
+
+static bool
+gimple_fold_builtin_strncat_chk (gimple_stmt_iterator *gsi)
+{
+ gimple stmt = gsi_stmt (*gsi);
+ tree dest = gimple_call_arg (stmt, 0);
+ tree src = gimple_call_arg (stmt, 1);
+ tree len = gimple_call_arg (stmt, 2);
+ tree size = gimple_call_arg (stmt, 3);
+ tree fn;
+ const char *p;
+
+ p = c_getstr (src);
+ /* If the SRC parameter is "" or if LEN is 0, return DEST. */
+ if ((p && *p == '\0')
+ || integer_zerop (len))
+ {
+ replace_call_with_value (gsi, dest);
+ return true;
+ }
+
+ if (! tree_fits_uhwi_p (size))
+ return false;
+
+ 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 false;
+
+ gimple repl = gimple_build_call (fn, 3, dest, src, size);
+ replace_call_with_call_and_fold (gsi, repl);
+ return true;
+ }
+ return false;
+ }
+
+ /* If __builtin_strncat_chk is used, assume strncat is available. */
+ fn = builtin_decl_explicit (BUILT_IN_STRNCAT);
+ if (!fn)
+ return false;
+
+ gimple repl = gimple_build_call (fn, 3, dest, src, len);
+ replace_call_with_call_and_fold (gsi, repl);
+ return true;
+}
+
/* Fold a call to the fputs builtin. ARG0 and ARG1 are the arguments
to the call. IGNORE is true if the value returned
by the builtin will be ignored. UNLOCKED is true is true if this
@@ -2457,6 +2513,8 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi)
return gimple_fold_builtin_sprintf_chk (gsi, DECL_FUNCTION_CODE (callee));
case BUILT_IN_STRCAT_CHK:
return gimple_fold_builtin_strcat_chk (gsi);
+ case BUILT_IN_STRNCAT_CHK:
+ return gimple_fold_builtin_strncat_chk (gsi);
case BUILT_IN_STRLEN:
return gimple_fold_builtin_strlen (gsi);
case BUILT_IN_STRCPY: