From: Jeff Law Date: Thu, 5 Jan 2017 07:38:48 +0000 (-0700) Subject: re PR rtl-optimization/78812 (Wrong code generation due to hoisting memory load acros... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d80c6d02fdf0c37596e51392ade43414a350373a;p=gcc.git re PR rtl-optimization/78812 (Wrong code generation due to hoisting memory load across function call) PR tree-optimizatin/78812 * rtl.h (contains_mem_rtx_p): Prototype. * ifcvt.c (containts_mem_rtx_p): Move from here to... * rtlanal.c (contains_mem_rtx_p): Here and remvoe static linkage. * gcse.c (prune_expressions): Use contains_mem_rtx_p to discover and prune MEMs that are not at the toplevel of a SET_SRC rtx. Look through ZERO_EXTEND and SIGN_EXTEND when trying to avoid pruning MEMs. PR tree-optimization/78812 * g++.dg/torture/pr78812.C: New test. From-SVN: r244093 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ce11bc4ca0b..78b4412a061 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2017-01-04 Jeff Law + + PR tree-optimizatin/78812 + * rtl.h (contains_mem_rtx_p): Prototype. + * ifcvt.c (containts_mem_rtx_p): Move from here to... + * rtlanal.c (contains_mem_rtx_p): Here and remvoe static linkage. + * gcse.c (prune_expressions): Use contains_mem_rtx_p to discover + and prune MEMs that are not at the toplevel of a SET_SRC rtx. Look + through ZERO_EXTEND and SIGN_EXTEND when trying to avoid pruning + MEMs. + 2017-01-04 Alexandre Oliva * input.c (assert_char_at_range): Default-initialize diff --git a/gcc/gcse.c b/gcc/gcse.c index fbc770a48de..d28288df95c 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -1709,7 +1709,7 @@ prune_expressions (bool pre_p) continue; } - if (!pre_p && MEM_P (expr->expr)) + if (!pre_p && contains_mem_rtx_p (expr->expr)) /* Note memory references that can be clobbered by a call. We do not split abnormal edges in hoisting, so would a memory reference get hoisted along an abnormal edge, @@ -1717,15 +1717,28 @@ prune_expressions (bool pre_p) constant memory references can be hoisted along abnormal edges. */ { - if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF - && CONSTANT_POOL_ADDRESS_P (XEXP (expr->expr, 0))) - continue; - - if (MEM_READONLY_P (expr->expr) - && !MEM_VOLATILE_P (expr->expr) - && MEM_NOTRAP_P (expr->expr)) - /* Constant memory reference, e.g., a PIC address. */ - continue; + rtx x = expr->expr; + + /* Common cases where we might find the MEM which may allow us + to avoid pruning the expression. */ + while (GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND) + x = XEXP (x, 0); + + /* If we found the MEM, go ahead and look at it to see if it has + properties that allow us to avoid pruning its expression out + of the tables. */ + if (MEM_P (x)) + { + if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0))) + continue; + + if (MEM_READONLY_P (x) + && !MEM_VOLATILE_P (x) + && MEM_NOTRAP_P (x)) + /* Constant memory reference, e.g., a PIC address. */ + continue; + } /* ??? Optimally, we would use interprocedural alias analysis to determine if this mem is actually killed diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 56c785e3632..68c1a1d42c4 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -3010,19 +3010,6 @@ noce_operand_ok (const_rtx op) return ! may_trap_p (op); } -/* Return true if X contains a MEM subrtx. */ - -static bool -contains_mem_rtx_p (rtx x) -{ - subrtx_iterator::array_type array; - FOR_EACH_SUBRTX (iter, array, x, ALL) - if (MEM_P (*iter)) - return true; - - return false; -} - /* Return true iff basic block TEST_BB is valid for noce if-conversion. The condition used in this if-conversion is in COND. In practice, check that TEST_BB ends with a single set diff --git a/gcc/rtl.h b/gcc/rtl.h index 302afc0d1b0..b9a7989c0d7 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -3090,6 +3090,7 @@ extern bool rtx_referenced_p (const_rtx, const_rtx); extern bool tablejump_p (const rtx_insn *, rtx_insn **, rtx_jump_table_data **); extern int computed_jump_p (const rtx_insn *); extern bool tls_referenced_p (const_rtx); +extern bool contains_mem_rtx_p (rtx x); /* Overload for refers_to_regno_p for checking a single register. */ inline bool diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index ef93584449d..acb4230aac8 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -685,6 +685,19 @@ rtx_addr_can_trap_p (const_rtx x) return rtx_addr_can_trap_p_1 (x, 0, 0, VOIDmode, false); } +/* Return true if X contains a MEM subrtx. */ + +bool +contains_mem_rtx_p (rtx x) +{ + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, x, ALL) + if (MEM_P (*iter)) + return true; + + return false; +} + /* Return true if X is an address that is known to not be zero. */ bool diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 74e8d0dab3c..16b27e61d6f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-01-04 Jeff Law + + PR tree-optimization/78812 + * g++.dg/torture/pr78812.C: New test. + 2017-01-04 Michael Meissner PR target/71977 diff --git a/gcc/testsuite/g++.dg/torture/pr78812.C b/gcc/testsuite/g++.dg/torture/pr78812.C new file mode 100644 index 00000000000..efe0936767d --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr78812.C @@ -0,0 +1,24 @@ +// { dg-do run } +// { dg-options "-fpic" { target fpic } } + +struct T +{ + bool a; + T () : a (false) {} + ~T () { if (!a) __builtin_abort (); } +}; + +__attribute__((noinline)) +void +test (T &x) +{ + x.a = true; +} + +int +main () +{ + T T; + test (T); +} +