From e472781227253bf87e273512026256fb563b1646 Mon Sep 17 00:00:00 2001 From: Ilya Enkovich Date: Mon, 17 Nov 2014 13:52:37 +0000 Subject: [PATCH] tree-chkp-opt.c (chkp_get_nobnd_fndecl): New. gcc/ * tree-chkp-opt.c (chkp_get_nobnd_fndecl): New. (chkp_get_nochk_fndecl): New. (chkp_optimize_string_function_calls): New. (chkp_opt_execute): Call chkp_optimize_string_function_calls. * tree-cfg.h (insert_cond_bb): New. * tree-cfg.c (insert_cond_bb): New. gcc/testsuite/ * gcc.target/i386/chkp-stropt-1.c: New. * gcc.target/i386/chkp-stropt-2.c: New. * gcc.target/i386/chkp-stropt-3.c: New. * gcc.target/i386/chkp-stropt-4.c: New. * gcc.target/i386/chkp-stropt-5.c: New. * gcc.target/i386/chkp-stropt-6.c: New. * gcc.target/i386/chkp-stropt-7.c: New. * gcc.target/i386/chkp-stropt-8.c: New. * gcc.target/i386/chkp-stropt-9.c: New. * gcc.target/i386/chkp-stropt-10.c: New. * gcc.target/i386/chkp-stropt-11.c: New. * gcc.target/i386/chkp-stropt-12.c: New. * gcc.target/i386/chkp-stropt-13.c: New. * gcc.target/i386/chkp-stropt-14.c: New. * gcc.target/i386/chkp-stropt-15.c: New. * gcc.target/i386/chkp-stropt-16.c: New. From-SVN: r217656 --- gcc/ChangeLog | 9 + gcc/testsuite/ChangeLog | 19 ++ gcc/testsuite/gcc.target/i386/chkp-stropt-1.c | 12 + .../gcc.target/i386/chkp-stropt-10.c | 12 + .../gcc.target/i386/chkp-stropt-11.c | 12 + .../gcc.target/i386/chkp-stropt-12.c | 12 + .../gcc.target/i386/chkp-stropt-13.c | 12 + .../gcc.target/i386/chkp-stropt-14.c | 12 + .../gcc.target/i386/chkp-stropt-15.c | 12 + .../gcc.target/i386/chkp-stropt-16.c | 12 + gcc/testsuite/gcc.target/i386/chkp-stropt-2.c | 12 + gcc/testsuite/gcc.target/i386/chkp-stropt-3.c | 12 + gcc/testsuite/gcc.target/i386/chkp-stropt-4.c | 12 + gcc/testsuite/gcc.target/i386/chkp-stropt-5.c | 12 + gcc/testsuite/gcc.target/i386/chkp-stropt-6.c | 12 + gcc/testsuite/gcc.target/i386/chkp-stropt-7.c | 12 + gcc/testsuite/gcc.target/i386/chkp-stropt-8.c | 12 + gcc/testsuite/gcc.target/i386/chkp-stropt-9.c | 12 + gcc/tree-cfg.c | 40 +++ gcc/tree-cfg.h | 1 + gcc/tree-chkp-opt.c | 264 ++++++++++++++++++ 21 files changed, 525 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-1.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-10.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-11.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-12.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-13.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-14.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-15.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-16.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-2.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-3.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-4.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-5.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-6.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-7.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-8.c create mode 100644 gcc/testsuite/gcc.target/i386/chkp-stropt-9.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 123166c9562..a67defd5bda 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2014-11-17 Ilya Enkovich + + * tree-chkp-opt.c (chkp_get_nobnd_fndecl): New. + (chkp_get_nochk_fndecl): New. + (chkp_optimize_string_function_calls): New. + (chkp_opt_execute): Call chkp_optimize_string_function_calls. + * tree-cfg.h (insert_cond_bb): New. + * tree-cfg.c (insert_cond_bb): New. + 2014-11-17 Ilya Enkovich * tree-core.h (built_in_class): Add builtin codes to be used diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2a5f8fc47ad..2701c114a4e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,22 @@ +2014-11-17 Ilya Enkovich + + * gcc.target/i386/chkp-stropt-1.c: New. + * gcc.target/i386/chkp-stropt-2.c: New. + * gcc.target/i386/chkp-stropt-3.c: New. + * gcc.target/i386/chkp-stropt-4.c: New. + * gcc.target/i386/chkp-stropt-5.c: New. + * gcc.target/i386/chkp-stropt-6.c: New. + * gcc.target/i386/chkp-stropt-7.c: New. + * gcc.target/i386/chkp-stropt-8.c: New. + * gcc.target/i386/chkp-stropt-9.c: New. + * gcc.target/i386/chkp-stropt-10.c: New. + * gcc.target/i386/chkp-stropt-11.c: New. + * gcc.target/i386/chkp-stropt-12.c: New. + * gcc.target/i386/chkp-stropt-13.c: New. + * gcc.target/i386/chkp-stropt-14.c: New. + * gcc.target/i386/chkp-stropt-15.c: New. + * gcc.target/i386/chkp-stropt-16.c: New. + 2014-11-17 H.J. Lu * g++.dg/ipa/pr63894.C (new): Replace unsigned long with diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-1.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-1.c new file mode 100644 index 00000000000..c0050412401 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions" } */ +/* { dg-final { scan-tree-dump "memcpy_nochk" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int *buf2, size_t len) +{ + memcpy (buf1, buf2, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-10.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-10.c new file mode 100644 index 00000000000..9b3c15fdc59 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-10.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */ +/* { dg-final { scan-tree-dump-not "memset_nobnd" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (void *buf1, int c, size_t len) +{ + memset (buf1, c, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-11.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-11.c new file mode 100644 index 00000000000..7ef079c7ca4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-11.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */ +/* { dg-final { scan-tree-dump-not "memmove_nobnd" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (void *buf1, void *buf2, size_t len) +{ + memmove (buf1, buf2, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-12.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-12.c new file mode 100644 index 00000000000..94e936d83c2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-12.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions -D_GNU_SOURCE" } */ +/* { dg-final { scan-tree-dump-not "mempcpy_nobnd" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (void *buf1, void *buf2, size_t len) +{ + mempcpy (buf1, buf2, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-13.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-13.c new file mode 100644 index 00000000000..f6d38c819da --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-13.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions -fchkp-use-fast-string-functions" } */ +/* { dg-final { scan-tree-dump "memcpy_nobnd_nochk" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int *buf2, size_t len) +{ + memcpy (buf1, buf2, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-14.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-14.c new file mode 100644 index 00000000000..a7f43cbb7d9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-14.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions -fchkp-use-fast-string-functions" } */ +/* { dg-final { scan-tree-dump "memset_nobnd_nochk" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int c, size_t len) +{ + memset (buf1, c, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-15.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-15.c new file mode 100644 index 00000000000..041e8855599 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-15.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions -fchkp-use-fast-string-functions" } */ +/* { dg-final { scan-tree-dump "memmove_nobnd_nochk" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int *buf2, size_t len) +{ + memmove (buf1, buf2, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-16.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-16.c new file mode 100644 index 00000000000..4b26d5820a6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-16.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions -fchkp-use-fast-string-functions -D_GNU_SOURCE" } */ +/* { dg-final { scan-tree-dump "mempcpy_nobnd_nochk" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int *buf2, size_t len) +{ + mempcpy (buf1, buf2, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-2.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-2.c new file mode 100644 index 00000000000..c56656ed255 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-2.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions" } */ +/* { dg-final { scan-tree-dump "memset_nochk" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int c, size_t len) +{ + memset (buf1, c, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-3.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-3.c new file mode 100644 index 00000000000..a91f0070f39 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-3.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions" } */ +/* { dg-final { scan-tree-dump "memmove_nochk" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int *buf2, size_t len) +{ + memmove (buf1, buf2, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-4.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-4.c new file mode 100644 index 00000000000..4ee2390c04d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-4.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions -D_GNU_SOURCE" } */ +/* { dg-final { scan-tree-dump "mempcpy_nochk" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int *buf2, size_t len) +{ + mempcpy (buf1, buf2, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-5.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-5.c new file mode 100644 index 00000000000..8d08ee60e74 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-5.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */ +/* { dg-final { scan-tree-dump "memcpy_nobnd" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int *buf2, size_t len) +{ + memcpy (buf1, buf2, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-6.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-6.c new file mode 100644 index 00000000000..92f187eb0e5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-6.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */ +/* { dg-final { scan-tree-dump "memset_nobnd" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int c, size_t len) +{ + memset (buf1, c, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-7.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-7.c new file mode 100644 index 00000000000..eb1e61cc35e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-7.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */ +/* { dg-final { scan-tree-dump "memmove_nobnd" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int *buf2, size_t len) +{ + memmove (buf1, buf2, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-8.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-8.c new file mode 100644 index 00000000000..8c3b15d2025 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-8.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions -D_GNU_SOURCE" } */ +/* { dg-final { scan-tree-dump "mempcpy_nobnd" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (int *buf1, int *buf2, size_t len) +{ + mempcpy (buf1, buf2, len); +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-9.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-9.c new file mode 100644 index 00000000000..da54c9ca5bd --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-9.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target mpx } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */ +/* { dg-final { scan-tree-dump-not "memcpy_nobnd" "chkpopt" } } */ +/* { dg-final { cleanup-tree-dump "chkpopt" } } */ + +#include "string.h" + +void test (void *buf1, void *buf2, size_t len) +{ + memcpy (buf1, buf2, len); +} diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index ae7734c5c6a..9dd8961cb8f 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -8178,6 +8178,46 @@ make_pass_split_crit_edges (gcc::context *ctxt) } +/* Insert COND expression which is GIMPLE_COND after STMT + in basic block BB with appropriate basic block split + and creation of a new conditionally executed basic block. + Return created basic block. */ +basic_block +insert_cond_bb (basic_block bb, gimple stmt, gimple cond) +{ + edge fall = split_block (bb, stmt); + gimple_stmt_iterator iter = gsi_last_bb (bb); + basic_block new_bb; + + /* Insert cond statement. */ + gcc_assert (gimple_code (cond) == GIMPLE_COND); + if (gsi_end_p (iter)) + gsi_insert_before (&iter, cond, GSI_CONTINUE_LINKING); + else + gsi_insert_after (&iter, cond, GSI_CONTINUE_LINKING); + + /* Create conditionally executed block. */ + new_bb = create_empty_bb (bb); + make_edge (bb, new_bb, EDGE_TRUE_VALUE); + make_single_succ_edge (new_bb, fall->dest, EDGE_FALLTHRU); + + /* Fix edge for split bb. */ + fall->flags = EDGE_FALSE_VALUE; + + /* Update dominance info. */ + if (dom_info_available_p (CDI_DOMINATORS)) + { + set_immediate_dominator (CDI_DOMINATORS, new_bb, bb); + set_immediate_dominator (CDI_DOMINATORS, fall->dest, bb); + } + + /* Update loop info. */ + if (current_loops) + add_bb_to_loop (new_bb, bb->loop_father); + + return new_bb; +} + /* Build a ternary operation and gimplify it. Emit code before GSI. Return the gimple_val holding the result. */ diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h index 1e23fac923d..bc5967be0bc 100644 --- a/gcc/tree-cfg.h +++ b/gcc/tree-cfg.h @@ -100,5 +100,6 @@ extern tree gimplify_build1 (gimple_stmt_iterator *, enum tree_code, extern void extract_true_false_edges_from_block (basic_block, edge *, edge *); extern unsigned int execute_fixup_cfg (void); extern unsigned int split_critical_edges (void); +extern basic_block insert_cond_bb (basic_block, gimple, gimple); #endif /* _TREE_CFG_H */ diff --git a/gcc/tree-chkp-opt.c b/gcc/tree-chkp-opt.c index 383c66fcaa5..ff390d7bb3d 100644 --- a/gcc/tree-chkp-opt.c +++ b/gcc/tree-chkp-opt.c @@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify-me.h" #include "expr.h" #include "tree-chkp.h" +#include "ipa-chkp.h" #include "diagnostic.h" enum check_type @@ -845,6 +846,265 @@ chkp_remove_constant_checks (void) } } +/* Return fast version of string function FNCODE. */ +static tree +chkp_get_nobnd_fndecl (enum built_in_function fncode) +{ + /* Check if we are allowed to use fast string functions. */ + if (!flag_chkp_use_fast_string_functions) + return NULL_TREE; + + tree fndecl = NULL_TREE; + + switch (fncode) + { + case BUILT_IN_MEMCPY_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND); + break; + + case BUILT_IN_MEMPCPY_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOBND); + break; + + case BUILT_IN_MEMMOVE_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOBND); + break; + + case BUILT_IN_MEMSET_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOBND); + break; + + case BUILT_IN_CHKP_MEMCPY_NOCHK_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK); + break; + + case BUILT_IN_CHKP_MEMPCPY_NOCHK_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK); + break; + + case BUILT_IN_CHKP_MEMMOVE_NOCHK_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOBND_NOCHK); + break; + + case BUILT_IN_CHKP_MEMSET_NOCHK_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOBND_NOCHK); + break; + + default: + break; + } + + if (fndecl) + fndecl = chkp_maybe_clone_builtin_fndecl (fndecl); + + return fndecl; +} + + +/* Return no-check version of string function FNCODE. */ +static tree +chkp_get_nochk_fndecl (enum built_in_function fncode) +{ + /* Check if we are allowed to use fast string functions. */ + if (!flag_chkp_use_nochk_string_functions) + return NULL_TREE; + + tree fndecl = NULL_TREE; + + switch (fncode) + { + case BUILT_IN_MEMCPY_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOCHK); + break; + + case BUILT_IN_MEMPCPY_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOCHK); + break; + + case BUILT_IN_MEMMOVE_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOCHK); + break; + + case BUILT_IN_MEMSET_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOCHK); + break; + + case BUILT_IN_CHKP_MEMCPY_NOBND_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK); + break; + + case BUILT_IN_CHKP_MEMPCPY_NOBND_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK); + break; + + case BUILT_IN_CHKP_MEMMOVE_NOBND_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOBND_NOCHK); + break; + + case BUILT_IN_CHKP_MEMSET_NOBND_CHKP: + fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOBND_NOCHK); + break; + + default: + break; + } + + if (fndecl) + fndecl = chkp_maybe_clone_builtin_fndecl (fndecl); + + return fndecl; +} + +/* Find memcpy, mempcpy, memmove and memset calls, perform + checks before call and then call no_chk version of + functions. We do it on O2 to enable inlining of these + functions during expand. + + Also try to find memcpy, mempcpy, memmove and memset calls + which are known to not write pointers to memory and use + faster function versions for them. */ +static void +chkp_optimize_string_function_calls (void) +{ + basic_block bb; + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Searching for replaceable string function calls...\n"); + + FOR_EACH_BB_FN (bb, cfun) + { + gimple_stmt_iterator i; + + for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) + { + gimple stmt = gsi_stmt (i); + tree fndecl; + + if (gimple_code (stmt) != GIMPLE_CALL + || !gimple_call_with_bounds_p (stmt)) + continue; + + fndecl = gimple_call_fndecl (stmt); + + if (!fndecl || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL) + continue; + + if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMCPY_CHKP + || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMPCPY_CHKP + || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMMOVE_CHKP + || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHKP) + { + tree dst = gimple_call_arg (stmt, 0); + tree dst_bnd = gimple_call_arg (stmt, 1); + bool is_memset = DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHKP; + tree size = gimple_call_arg (stmt, is_memset ? 3 : 4); + tree fndecl_nochk; + gimple_stmt_iterator j; + basic_block check_bb; + address_t size_val; + int sign; + bool known; + + /* We may replace call with corresponding __chkp_*_nobnd + call in case destination pointer base type is not + void or pointer. */ + if (POINTER_TYPE_P (TREE_TYPE (dst)) + && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (dst))) + && !chkp_type_has_pointer (TREE_TYPE (TREE_TYPE (dst)))) + { + tree fndecl_nobnd + = chkp_get_nobnd_fndecl (DECL_FUNCTION_CODE (fndecl)); + + if (fndecl_nobnd) + fndecl = fndecl_nobnd; + } + + fndecl_nochk = chkp_get_nochk_fndecl (DECL_FUNCTION_CODE (fndecl)); + + if (fndecl_nochk) + fndecl = fndecl_nochk; + + if (fndecl != gimple_call_fndecl (stmt)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Replacing call: "); + print_gimple_stmt (dump_file, stmt, 0, + TDF_VOPS|TDF_MEMSYMS); + } + + gimple_call_set_fndecl (stmt, fndecl); + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "With a new call: "); + print_gimple_stmt (dump_file, stmt, 0, + TDF_VOPS|TDF_MEMSYMS); + } + } + + /* If there is no nochk version of function then + do nothing. Otherwise insert checks before + the call. */ + if (!fndecl_nochk) + continue; + + /* If size passed to call is known and > 0 + then we may insert checks unconditionally. */ + size_val.pol.create (0); + chkp_collect_value (size, size_val); + known = chkp_is_constant_addr (size_val, &sign); + size_val.pol.release (); + + /* If we are not sure size is not zero then we have + to perform runtime check for size and perform + checks only when size is not zero. */ + if (!known) + { + gimple check = gimple_build_cond (NE_EXPR, + size, + size_zero_node, + NULL_TREE, + NULL_TREE); + + /* Split block before string function call. */ + gsi_prev (&i); + check_bb = insert_cond_bb (bb, gsi_stmt (i), check); + + /* Set position for checks. */ + j = gsi_last_bb (check_bb); + + /* The block was splitted and therefore we + need to set iterator to its end. */ + i = gsi_last_bb (bb); + } + /* If size is known to be zero then no checks + should be performed. */ + else if (!sign) + continue; + else + j = i; + + size = size_binop (MINUS_EXPR, size, size_one_node); + if (!is_memset) + { + tree src = gimple_call_arg (stmt, 2); + tree src_bnd = gimple_call_arg (stmt, 3); + + chkp_check_mem_access (src, fold_build_pointer_plus (src, size), + src_bnd, j, gimple_location (stmt), + integer_zero_node); + } + + chkp_check_mem_access (dst, fold_build_pointer_plus (dst, size), + dst_bnd, j, gimple_location (stmt), + integer_one_node); + + } + } + } +} + /* Intrumentation pass inserts most of bounds creation code in the header of the function. We want to move bounds creation closer to bounds usage to reduce bounds lifetime. @@ -1026,6 +1286,10 @@ chkp_opt_execute (void) { chkp_opt_init(); + /* This optimization may introduce new checks + and thus we put it before checks search. */ + chkp_optimize_string_function_calls (); + chkp_gather_checks_info (); chkp_remove_excess_intersections (); -- 2.30.2