From f5fc4a042173fbb015e1a2b882a6bddb5d6dc146 Mon Sep 17 00:00:00 2001 From: Ilya Enkovich Date: Mon, 17 Nov 2014 13:55:49 +0000 Subject: [PATCH] tree-ssa-strlen.c: include ipa-chkp.h, cgraph.h, ipa-ref.h, plugin-api.h. gcc/ * tree-ssa-strlen.c: include ipa-chkp.h, cgraph.h, ipa-ref.h, plugin-api.h. (get_string_length): Handle calls with bounds. (adjust_last_stmt): Likewise. (handle_builtin_strchr): Likewise. (handle_builtin_strcpy): Likewise. (handle_builtin_memcpy): Likewise. (handle_builtin_strcat): Likewise. gcc/testsuite/ * gcc.target/i386/chkp-strlen-1.c: New. * gcc.target/i386/chkp-strlen-2.c: New. * gcc.target/i386/chkp-strlen-3.c: New. * gcc.target/i386/chkp-strlen-4.c: New. * gcc.target/i386/chkp-strlen-5.c: New. From-SVN: r217657 --- gcc/ChangeLog | 11 ++ gcc/testsuite/ChangeLog | 8 ++ gcc/testsuite/gcc.target/i386/chkp-strlen-1.c | 14 ++ gcc/testsuite/gcc.target/i386/chkp-strlen-2.c | 14 ++ gcc/testsuite/gcc.target/i386/chkp-strlen-3.c | 14 ++ gcc/testsuite/gcc.target/i386/chkp-strlen-4.c | 14 ++ gcc/testsuite/gcc.target/i386/chkp-strlen-5.c | 16 +++ gcc/tree-ssa-strlen.c | 132 +++++++++++++++--- 8 files changed, 204 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/chkp-strlen-1.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-strlen-2.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-strlen-3.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-strlen-4.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-strlen-5.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a67defd5bda..e4c10c90180 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2014-11-17 Ilya Enkovich + + * tree-ssa-strlen.c: include ipa-chkp.h, cgraph.h, + ipa-ref.h, plugin-api.h. + (get_string_length): Handle calls with bounds. + (adjust_last_stmt): Likewise. + (handle_builtin_strchr): Likewise. + (handle_builtin_strcpy): Likewise. + (handle_builtin_memcpy): Likewise. + (handle_builtin_strcat): Likewise. + 2014-11-17 Ilya Enkovich * tree-chkp-opt.c (chkp_get_nobnd_fndecl): New. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2701c114a4e..46ab25f8980 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2014-11-17 Ilya Enkovich + + * gcc.target/i386/chkp-strlen-1.c: New. + * gcc.target/i386/chkp-strlen-2.c: New. + * gcc.target/i386/chkp-strlen-3.c: New. + * gcc.target/i386/chkp-strlen-4.c: New. + * gcc.target/i386/chkp-strlen-5.c: New. + 2014-11-17 Ilya Enkovich * gcc.target/i386/chkp-stropt-1.c: New. diff --git a/gcc/testsuite/gcc.target/i386/chkp-strlen-1.c b/gcc/testsuite/gcc.target/i386/chkp-strlen-1.c new file mode 100644 index 00000000000..ffb4f16bac3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-strlen-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-strlen" } */ +/* { dg-final { scan-tree-dump "memcpy.chkp" "strlen" } } */ +/* { dg-final { cleanup-tree-dump "strlen" } } */ + +#include "string.h" + +char *test (char *str1, char *str2) +{ + size_t len = strlen (str2); + strcpy (str1, str2); + return str1 + len; +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-strlen-2.c b/gcc/testsuite/gcc.target/i386/chkp-strlen-2.c new file mode 100644 index 00000000000..1ce426d83bd --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-strlen-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-strlen" } */ +/* { dg-final { scan-tree-dump-not "strlen" "strlen" } } */ +/* { dg-final { cleanup-tree-dump "strlen" } } */ + +#include "string.h" + +char *test (char *str1, char *str2) +{ + char *p = stpcpy (str1, str2); + size_t len = strlen (str1); + return p + len; +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-strlen-3.c b/gcc/testsuite/gcc.target/i386/chkp-strlen-3.c new file mode 100644 index 00000000000..447b9be088a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-strlen-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-strlen" } */ +/* { dg-final { scan-tree-dump-times "strlen" 1 "strlen" } } */ +/* { dg-final { cleanup-tree-dump "strlen" } } */ + +#include "string.h" + +size_t test (char *str1, char *str2) +{ + size_t len = strlen (str2); + memcpy (str1, str2, len + 1); + return len + strlen (str1); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-strlen-4.c b/gcc/testsuite/gcc.target/i386/chkp-strlen-4.c new file mode 100644 index 00000000000..a9ebe2bbe3c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-strlen-4.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-strlen -D_GNU_SOURCE" } */ +/* { dg-final { scan-tree-dump-times "strlen" 1 "strlen" } } */ +/* { dg-final { cleanup-tree-dump "strlen" } } */ + +#include "string.h" + +char * test (char *str1, char *str2) +{ + size_t len = strlen (str2); + char *p = (char *)mempcpy (str1, str2, len + 1); + return p + len + strlen (str1); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-strlen-5.c b/gcc/testsuite/gcc.target/i386/chkp-strlen-5.c new file mode 100644 index 00000000000..37b664eb478 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-strlen-5.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-strlen" } */ +/* { dg-final { scan-tree-dump-times "strlen" 2 "strlen" } } */ +/* { dg-final { scan-tree-dump "memcpy" "strlen" } } */ +/* { dg-final { cleanup-tree-dump "strlen" } } */ + +#include "string.h" + +size_t test (char *str1, char *str2) +{ + size_t len1 = strlen (str1); + size_t len2 = strlen (str2); + strcat (str1, str2); + return len1 + len2 + strlen (str1); +} diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 3789e30449d..c327f89dada 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -62,6 +62,10 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "params.h" #include "expr.h" +#include "plugin-api.h" +#include "ipa-ref.h" +#include "cgraph.h" +#include "ipa-chkp.h" /* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value is an index into strinfo vector, negative value stands for @@ -417,6 +421,7 @@ get_string_length (strinfo si) if (si->stmt) { gimple stmt = si->stmt, lenstmt; + bool with_bounds = gimple_call_with_bounds_p (stmt); tree callee, lhs, fn, tem; location_t loc; gimple_stmt_iterator gsi; @@ -436,11 +441,20 @@ get_string_length (strinfo si) { case BUILT_IN_STRCAT: case BUILT_IN_STRCAT_CHK: + case BUILT_IN_STRCAT_CHKP: + case BUILT_IN_STRCAT_CHK_CHKP: gsi = gsi_for_stmt (stmt); fn = builtin_decl_implicit (BUILT_IN_STRLEN); gcc_assert (lhs == NULL_TREE); tem = unshare_expr (gimple_call_arg (stmt, 0)); - lenstmt = gimple_build_call (fn, 1, tem); + if (with_bounds) + { + lenstmt = gimple_build_call (chkp_maybe_create_clone (fn)->decl, + 2, tem, gimple_call_arg (stmt, 1)); + gimple_call_set_with_bounds (lenstmt, true); + } + else + lenstmt = gimple_build_call (fn, 1, tem); lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt); gimple_call_set_lhs (lenstmt, lhs); gimple_set_vuse (lenstmt, gimple_vuse (stmt)); @@ -463,10 +477,14 @@ get_string_length (strinfo si) /* FALLTHRU */ case BUILT_IN_STRCPY: case BUILT_IN_STRCPY_CHK: - if (gimple_call_num_args (stmt) == 2) + case BUILT_IN_STRCPY_CHKP: + case BUILT_IN_STRCPY_CHK_CHKP: + if (gimple_call_num_args (stmt) == (with_bounds ? 4 : 2)) fn = builtin_decl_implicit (BUILT_IN_STPCPY); else fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK); + if (with_bounds) + fn = chkp_maybe_create_clone (fn)->decl; gcc_assert (lhs == NULL_TREE); if (dump_file && (dump_flags & TDF_DETAILS) != 0) { @@ -485,6 +503,8 @@ get_string_length (strinfo si) /* FALLTHRU */ case BUILT_IN_STPCPY: case BUILT_IN_STPCPY_CHK: + case BUILT_IN_STPCPY_CHKP: + case BUILT_IN_STPCPY_CHK_CHKP: gcc_assert (lhs != NULL_TREE); loc = gimple_location (stmt); si->endptr = lhs; @@ -775,6 +795,7 @@ adjust_last_stmt (strinfo si, gimple stmt, bool is_strcat) tree vuse, callee, len; struct laststmt_struct last = laststmt; strinfo lastsi, firstsi; + unsigned len_arg_no = 2; laststmt.stmt = NULL; laststmt.len = NULL_TREE; @@ -846,11 +867,15 @@ adjust_last_stmt (strinfo si, gimple stmt, bool is_strcat) case BUILT_IN_MEMCPY: case BUILT_IN_MEMCPY_CHK: break; + case BUILT_IN_MEMCPY_CHKP: + case BUILT_IN_MEMCPY_CHK_CHKP: + len_arg_no = 4; + break; default: return; } - len = gimple_call_arg (last.stmt, 2); + len = gimple_call_arg (last.stmt, len_arg_no); if (tree_fits_uhwi_p (len)) { if (!tree_fits_uhwi_p (last.len) @@ -874,7 +899,7 @@ adjust_last_stmt (strinfo si, gimple stmt, bool is_strcat) else return; - gimple_call_set_arg (last.stmt, 2, last.len); + gimple_call_set_arg (last.stmt, len_arg_no, last.len); update_stmt (last.stmt); } @@ -965,11 +990,12 @@ handle_builtin_strchr (gimple_stmt_iterator *gsi) tree src; gimple stmt = gsi_stmt (*gsi); tree lhs = gimple_call_lhs (stmt); + bool with_bounds = gimple_call_with_bounds_p (stmt); if (lhs == NULL_TREE) return; - if (!integer_zerop (gimple_call_arg (stmt, 1))) + if (!integer_zerop (gimple_call_arg (stmt, with_bounds ? 2 : 1))) return; src = gimple_call_arg (stmt, 0); @@ -1076,8 +1102,9 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) gimple stmt = gsi_stmt (*gsi); strinfo si, dsi, olddsi, zsi; location_t loc; + bool with_bounds = gimple_call_with_bounds_p (stmt); - src = gimple_call_arg (stmt, 1); + src = gimple_call_arg (stmt, with_bounds ? 2 : 1); dst = gimple_call_arg (stmt, 0); lhs = gimple_call_lhs (stmt); idx = get_stridx (src); @@ -1108,11 +1135,15 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) { case BUILT_IN_STRCPY: case BUILT_IN_STRCPY_CHK: + case BUILT_IN_STRCPY_CHKP: + case BUILT_IN_STRCPY_CHK_CHKP: if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY)) return; break; case BUILT_IN_STPCPY: case BUILT_IN_STPCPY_CHK: + case BUILT_IN_STPCPY_CHKP: + case BUILT_IN_STPCPY_CHK_CHKP: if (lhs == NULL_TREE) return; else @@ -1211,16 +1242,19 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) switch (bcode) { case BUILT_IN_STRCPY: + case BUILT_IN_STRCPY_CHKP: fn = builtin_decl_implicit (BUILT_IN_MEMCPY); if (lhs) ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx; break; case BUILT_IN_STRCPY_CHK: + case BUILT_IN_STRCPY_CHK_CHKP: fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK); if (lhs) ssa_ver_to_stridx[SSA_NAME_VERSION (lhs)] = didx; break; case BUILT_IN_STPCPY: + case BUILT_IN_STPCPY_CHKP: /* This would need adjustment of the lhs (subtract one), or detection that the trailing '\0' doesn't need to be written, if it will be immediately overwritten. @@ -1232,6 +1266,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) } break; case BUILT_IN_STPCPY_CHK: + case BUILT_IN_STPCPY_CHK_CHKP: /* This would need adjustment of the lhs (subtract one), or detection that the trailing '\0' doesn't need to be written, if it will be immediately overwritten. @@ -1263,14 +1298,33 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) fprintf (dump_file, "Optimizing: "); print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); } - if (gimple_call_num_args (stmt) == 2) - success = update_gimple_call (gsi, fn, 3, dst, src, len); + if (with_bounds) + { + fn = chkp_maybe_create_clone (fn)->decl; + if (gimple_call_num_args (stmt) == 4) + success = update_gimple_call (gsi, fn, 5, dst, + gimple_call_arg (stmt, 1), + src, + gimple_call_arg (stmt, 3), + len); + else + success = update_gimple_call (gsi, fn, 6, dst, + gimple_call_arg (stmt, 1), + src, + gimple_call_arg (stmt, 3), + len, + gimple_call_arg (stmt, 4)); + } else - success = update_gimple_call (gsi, fn, 4, dst, src, len, - gimple_call_arg (stmt, 2)); + if (gimple_call_num_args (stmt) == 2) + success = update_gimple_call (gsi, fn, 3, dst, src, len); + else + success = update_gimple_call (gsi, fn, 4, dst, src, len, + gimple_call_arg (stmt, 2)); if (success) { stmt = gsi_stmt (*gsi); + gimple_call_set_with_bounds (stmt, with_bounds); update_stmt (stmt); if (dump_file && (dump_flags & TDF_DETAILS) != 0) { @@ -1298,9 +1352,10 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) tree src, dst, len, lhs, oldlen, newlen; gimple stmt = gsi_stmt (*gsi); strinfo si, dsi, olddsi; + bool with_bounds = gimple_call_with_bounds_p (stmt); - len = gimple_call_arg (stmt, 2); - src = gimple_call_arg (stmt, 1); + len = gimple_call_arg (stmt, with_bounds ? 4 : 2); + src = gimple_call_arg (stmt, with_bounds ? 2 : 1); dst = gimple_call_arg (stmt, 0); idx = get_stridx (src); if (idx == 0) @@ -1407,6 +1462,8 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) { case BUILT_IN_MEMCPY: case BUILT_IN_MEMCPY_CHK: + case BUILT_IN_MEMCPY_CHKP: + case BUILT_IN_MEMCPY_CHK_CHKP: /* Allow adjust_last_stmt to decrease this memcpy's size. */ laststmt.stmt = stmt; laststmt.len = dsi->length; @@ -1416,6 +1473,8 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi) break; case BUILT_IN_MEMPCPY: case BUILT_IN_MEMPCPY_CHK: + case BUILT_IN_MEMPCPY_CHKP: + case BUILT_IN_MEMPCPY_CHK_CHKP: break; default: gcc_unreachable (); @@ -1437,8 +1496,9 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi) gimple stmt = gsi_stmt (*gsi); strinfo si, dsi; location_t loc; + bool with_bounds = gimple_call_with_bounds_p (stmt); - src = gimple_call_arg (stmt, 1); + src = gimple_call_arg (stmt, with_bounds ? 2 : 1); dst = gimple_call_arg (stmt, 0); lhs = gimple_call_lhs (stmt); @@ -1534,17 +1594,19 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi) switch (bcode) { case BUILT_IN_STRCAT: + case BUILT_IN_STRCAT_CHKP: if (srclen != NULL_TREE) fn = builtin_decl_implicit (BUILT_IN_MEMCPY); else fn = builtin_decl_implicit (BUILT_IN_STRCPY); break; case BUILT_IN_STRCAT_CHK: + case BUILT_IN_STRCAT_CHK_CHKP: if (srclen != NULL_TREE) fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK); else fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK); - objsz = gimple_call_arg (stmt, 2); + objsz = gimple_call_arg (stmt, with_bounds ? 4 : 2); break; default: gcc_unreachable (); @@ -1579,15 +1641,35 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi) fprintf (dump_file, "Optimizing: "); print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); } - if (srclen != NULL_TREE) - success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE), - dst, src, len, objsz); + if (with_bounds) + { + fn = chkp_maybe_create_clone (fn)->decl; + if (srclen != NULL_TREE) + success = update_gimple_call (gsi, fn, 5 + (objsz != NULL_TREE), + dst, + gimple_call_arg (stmt, 1), + src, + gimple_call_arg (stmt, 3), + len, objsz); + else + success = update_gimple_call (gsi, fn, 4 + (objsz != NULL_TREE), + dst, + gimple_call_arg (stmt, 1), + src, + gimple_call_arg (stmt, 3), + objsz); + } else - success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE), - dst, src, objsz); + if (srclen != NULL_TREE) + success = update_gimple_call (gsi, fn, 3 + (objsz != NULL_TREE), + dst, src, len, objsz); + else + success = update_gimple_call (gsi, fn, 2 + (objsz != NULL_TREE), + dst, src, objsz); if (success) { stmt = gsi_stmt (*gsi); + gimple_call_set_with_bounds (stmt, with_bounds); update_stmt (stmt); if (dump_file && (dump_flags & TDF_DETAILS) != 0) { @@ -1901,25 +1983,37 @@ strlen_optimize_stmt (gimple_stmt_iterator *gsi) switch (DECL_FUNCTION_CODE (callee)) { case BUILT_IN_STRLEN: + case BUILT_IN_STRLEN_CHKP: handle_builtin_strlen (gsi); break; case BUILT_IN_STRCHR: + case BUILT_IN_STRCHR_CHKP: handle_builtin_strchr (gsi); break; case BUILT_IN_STRCPY: case BUILT_IN_STRCPY_CHK: case BUILT_IN_STPCPY: case BUILT_IN_STPCPY_CHK: + case BUILT_IN_STRCPY_CHKP: + case BUILT_IN_STRCPY_CHK_CHKP: + case BUILT_IN_STPCPY_CHKP: + case BUILT_IN_STPCPY_CHK_CHKP: handle_builtin_strcpy (DECL_FUNCTION_CODE (callee), gsi); break; case BUILT_IN_MEMCPY: case BUILT_IN_MEMCPY_CHK: case BUILT_IN_MEMPCPY: case BUILT_IN_MEMPCPY_CHK: + case BUILT_IN_MEMCPY_CHKP: + case BUILT_IN_MEMCPY_CHK_CHKP: + case BUILT_IN_MEMPCPY_CHKP: + case BUILT_IN_MEMPCPY_CHK_CHKP: handle_builtin_memcpy (DECL_FUNCTION_CODE (callee), gsi); break; case BUILT_IN_STRCAT: case BUILT_IN_STRCAT_CHK: + case BUILT_IN_STRCAT_CHKP: + case BUILT_IN_STRCAT_CHK_CHKP: handle_builtin_strcat (DECL_FUNCTION_CODE (callee), gsi); break; case BUILT_IN_MALLOC: -- 2.30.2