summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2016-12-06 09:23:51 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2016-12-06 09:23:51 +0000
commit9c104e19e88b8f472b9a4caf8ec099b20e65c082 (patch)
tree7a92a285d47f865cf7dc7522c6b591159d6a2013
parent085402d0e60421ef6051d0bc5ea8dae595cb34d0 (diff)
downloadgcc-9c104e19e88b8f472b9a4caf8ec099b20e65c082.tar.gz
2016-12-06 Jakub Jelinek <jakub@redhat.com>
PR c++/71537 * fold-const-call.c (fold_const_call_1): Remove memchr handling here. (fold_const_call) <case CFN_BUILT_IN_STRNCMP, case CFN_BUILT_IN_STRNCASECMP>: Formatting improvements. (fold_const_call) <case CFN_BUILT_IN_MEMCMP>: Likewise. If s2 is 0 and arguments have no side-effects, return 0. (fold_const_call): Handle CFN_BUILT_IN_MEMCHR. * g++.dg/cpp0x/constexpr-memchr.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@243285 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/fold-const-call.c100
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-memchr.C24
4 files changed, 81 insertions, 54 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 029dbdca00b..9ed8f5f8295 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,14 @@
2016-12-06 Jakub Jelinek <jakub@redhat.com>
PR c++/71537
+ * fold-const-call.c (fold_const_call_1): Remove memchr handling here.
+ (fold_const_call) <case CFN_BUILT_IN_STRNCMP,
+ case CFN_BUILT_IN_STRNCASECMP>: Formatting improvements.
+ (fold_const_call) <case CFN_BUILT_IN_MEMCMP>: Likewise. If s2 is 0
+ and arguments have no side-effects, return 0.
+ (fold_const_call): Handle CFN_BUILT_IN_MEMCHR.
+
+ PR c++/71537
* fold-const-call.c (fold_const_call): Handle
CFN_BUILT_IN_{INDEX,STRCHR,RINDEX,STRRCHR}.
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 439988d7170..c85fb41c09c 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -1491,36 +1491,6 @@ fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
return NULL_TREE;
}
- switch (fn)
- {
- case CFN_BUILT_IN_MEMCHR:
- {
- char c;
- if (integer_zerop (arg2)
- && !TREE_SIDE_EFFECTS (arg0)
- && !TREE_SIDE_EFFECTS (arg1))
- return build_int_cst (type, 0);
-
- if (!tree_fits_uhwi_p (arg2) || !target_char_cst_p (arg1, &c))
- return NULL_TREE;
-
- unsigned HOST_WIDE_INT length = tree_to_uhwi (arg2);
- unsigned HOST_WIDE_INT string_length;
- const char *p1 = c_getstr (arg0, &string_length);
- if (p1)
- {
- const char *r
- = (const char *)memchr (p1, c, MIN (length, string_length));
- if (r == NULL && length <= string_length)
- return build_int_cst (type, 0);
- }
-
- break;
- }
- default:
- break;
- }
-
return NULL_TREE;
}
@@ -1531,47 +1501,69 @@ tree
fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
{
const char *p0, *p1;
+ char c;
unsigned HOST_WIDE_INT s0, s1;
size_t s2 = 0;
switch (fn)
{
case CFN_BUILT_IN_STRNCMP:
- {
- bool const_size_p = host_size_t_cst_p (arg2, &s2);
- if (const_size_p && s2 == 0
- && !TREE_SIDE_EFFECTS (arg0)
- && !TREE_SIDE_EFFECTS (arg1))
- return build_int_cst (type, 0);
- else if (const_size_p
- && (p0 = c_getstr (arg0))
- && (p1 = c_getstr (arg1)))
- return build_int_cst (type, strncmp (p0, p1, s2));
+ if (!host_size_t_cst_p (arg2, &s2))
return NULL_TREE;
- }
+ if (s2 == 0
+ && !TREE_SIDE_EFFECTS (arg0)
+ && !TREE_SIDE_EFFECTS (arg1))
+ return build_int_cst (type, 0);
+ else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
+ return build_int_cst (type, strncmp (p0, p1, s2));
+ return NULL_TREE;
+
case CFN_BUILT_IN_STRNCASECMP:
- {
- bool const_size_p = host_size_t_cst_p (arg2, &s2);
- if (const_size_p && s2 == 0
- && !TREE_SIDE_EFFECTS (arg0)
- && !TREE_SIDE_EFFECTS (arg1))
- return build_int_cst (type, 0);
- else if (const_size_p
- && (p0 = c_getstr (arg0))
- && (p1 = c_getstr (arg1))
- && strncmp (p0, p1, s2) == 0)
- return build_int_cst (type, 0);
+ if (!host_size_t_cst_p (arg2, &s2))
return NULL_TREE;
- }
+ if (s2 == 0
+ && !TREE_SIDE_EFFECTS (arg0)
+ && !TREE_SIDE_EFFECTS (arg1))
+ return build_int_cst (type, 0);
+ else if ((p0 = c_getstr (arg0))
+ && (p1 = c_getstr (arg1))
+ && strncmp (p0, p1, s2) == 0)
+ return build_int_cst (type, 0);
+ return NULL_TREE;
+
case CFN_BUILT_IN_BCMP:
case CFN_BUILT_IN_MEMCMP:
+ if (!host_size_t_cst_p (arg2, &s2))
+ return NULL_TREE;
+ if (s2 == 0
+ && !TREE_SIDE_EFFECTS (arg0)
+ && !TREE_SIDE_EFFECTS (arg1))
+ return build_int_cst (type, 0);
if ((p0 = c_getstr (arg0, &s0))
&& (p1 = c_getstr (arg1, &s1))
- && host_size_t_cst_p (arg2, &s2)
&& s2 <= s0
&& s2 <= s1)
return build_cmp_result (type, memcmp (p0, p1, s2));
return NULL_TREE;
+ case CFN_BUILT_IN_MEMCHR:
+ if (!host_size_t_cst_p (arg2, &s2))
+ return NULL_TREE;
+ if (s2 == 0
+ && !TREE_SIDE_EFFECTS (arg0)
+ && !TREE_SIDE_EFFECTS (arg1))
+ return build_int_cst (type, 0);
+ if ((p0 = c_getstr (arg0, &s0))
+ && s2 <= s0
+ && target_char_cst_p (arg1, &c))
+ {
+ const char *r = (const char *) memchr (p0, c, s2);
+ if (r == NULL)
+ return build_int_cst (type, 0);
+ return fold_convert (type,
+ fold_build_pointer_plus_hwi (arg0, r - p0));
+ }
+ return NULL_TREE;
+
default:
return fold_const_call_1 (fn, type, arg0, arg1, arg2);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e6dfcdcf599..b44993b956b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,9 @@
2016-12-06 Jakub Jelinek <jakub@redhat.com>
PR c++/71537
+ * g++.dg/cpp0x/constexpr-memchr.C: New test.
+
+ PR c++/71537
* g++.dg/cpp0x/constexpr-strchr.C: New test.
PR tree-optimization/78675
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-memchr.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-memchr.C
new file mode 100644
index 00000000000..e5c07f177ea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-memchr.C
@@ -0,0 +1,24 @@
+// { dg-do compile { target c++11 } }
+
+typedef decltype (sizeof (0)) size_t;
+constexpr const void *f1 (const char *p, int q) { return __builtin_memchr (p, q, __builtin_strlen (p) + 1); }
+constexpr const void *f2 (const char *p, int q, size_t r) { return __builtin_memchr (p, q, r); }
+constexpr const char a[] = "abcdefedcba";
+static_assert (f1 ("abcde", 'f') == nullptr, "");
+static_assert (f1 (a, 'g') == nullptr, "");
+static_assert (f1 (a, 'f') == a + 5, "");
+static_assert (f1 (a, 'c') == a + 2, "");
+static_assert (f1 (a, '\0') == a + 11, "");
+static_assert (f2 ("abcde", 'f', 6) == nullptr, "");
+static_assert (f2 ("abcde", 'f', 1) == nullptr, "");
+static_assert (f2 ("abcde", 'f', 0) == nullptr, "");
+static_assert (f2 (a, 'g', 7) == nullptr, "");
+static_assert (f2 (a, 'g', 0) == nullptr, "");
+static_assert (f2 (a, 'f', 6) == a + 5, "");
+static_assert (f2 (a, 'f', 5) == nullptr, "");
+static_assert (f2 (a, 'c', 12) == a + 2, "");
+static_assert (f2 (a, 'c', 3) == a + 2, "");
+static_assert (f2 (a, 'c', 2) == nullptr, "");
+static_assert (f2 (a, '\0', 12) == a + 11, "");
+static_assert (f2 (a, '\0', 11) == nullptr, "");
+static_assert (f2 (a, '\0', 0) == nullptr, "");