This fixes 2 related bugs. The user marks memmove as noreturn
so when we simplify the memmove to a memory load/store there
is no longer a statement that can alter the CFG and things go
down hill.
The same is true for removing the call in DSE.
So the fix is not to simplify/take into account the call from
gimple-fold and DSE.
Bootstrapped and tested on x86_64-linux-gnu.
PR tree-optimization/121103
gcc/ChangeLog:
* gimple-fold.cc (gimple_fold_call): Don't simplify
noreturn functions.
* tree-ssa-dse.cc (dse_optimize_stmt): Don't handle
calls to noreturn functions.
gcc/testsuite/ChangeLog:
* gcc.dg/torture/pr121103-1.c: New test.
Signed-off-by: Andrew Pinski <[email protected]>
---
gcc/gimple-fold.cc | 4 +++
gcc/testsuite/gcc.dg/torture/pr121103-1.c | 40 +++++++++++++++++++++++
gcc/tree-ssa-dse.cc | 3 +-
3 files changed, 46 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/torture/pr121103-1.c
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index ec6831a20a0..7ae5425376f 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -6068,6 +6068,10 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool
inplace)
if (inplace)
return changed;
+ /* Don't constant fold functions which are marked as noreturn. */
+ if (gimple_call_flags (stmt) & ECF_NORETURN)
+ return changed;
+
/* Check for builtins that CCP can handle using information not
available in the generic fold routines. */
if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
diff --git a/gcc/testsuite/gcc.dg/torture/pr121103-1.c
b/gcc/testsuite/gcc.dg/torture/pr121103-1.c
new file mode 100644
index 00000000000..22f76c528df
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr121103-1.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* PR tree-optimization/121103 */
+
+extern void *memmove(void *, const void *, __SIZE_TYPE__)
__attribute__((noreturn));
+
+struct A {
+ const char *s;
+ int n;
+};
+
+void f(void *);
+
+struct B {
+ char d[5];
+ int n;
+};
+
+__attribute__((always_inline)) inline void g(struct B *p, struct A a) {
+ int i = a.n;
+ if (i <= 5)
+ p->n = i;
+ else {
+ p->n = -1;
+ f(p);
+ }
+
+ if (p->n >= 0)
+ memmove(p->d, a.s, a.n); /* { dg-bogus "\\\[-Warray-bounds" } */
+}
+
+void h(void) {
+ char c[8] = "";
+
+ struct A a;
+ a.s = c;
+ a.n = 8;
+
+ struct B b;
+ g(&b, a);
+}
diff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc
index 13266310ebe..10ae5d6e2ac 100644
--- a/gcc/tree-ssa-dse.cc
+++ b/gcc/tree-ssa-dse.cc
@@ -1501,7 +1501,8 @@ dse_optimize_stmt (function *fun, gimple_stmt_iterator
*gsi, sbitmap live_bytes)
/* We know we have virtual definitions. We can handle assignments and
some builtin calls. */
- if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+ if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
+ && !(gimple_call_flags (stmt) & ECF_NORETURN))
{
tree fndecl = gimple_call_fndecl (stmt);
switch (DECL_FUNCTION_CODE (fndecl))
--
2.43.0