diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cselib.c | 34 | ||||
-rw-r--r-- | gcc/reload1.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr94526.c | 21 |
5 files changed, 54 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dcdfae1..20fe7e2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2020-04-08 Jakub Jelinek <jakub@redhat.com> + PR middle-end/94526 + * cselib.c (autoinc_split): Handle e->val_rtx being SP_DERIVED_VALUE_P + with zero offset. + * reload1.c (eliminate_regs_1): Avoid creating + (plus (reg) (const_int 0)) in DEBUG_INSNs. + PR tree-optimization/94524 * tree-vect-generic.c (expand_vector_divmod): If any elt of op1 is negative for signed TRUNC_MOD_EXPR, multiply with absolute value of diff --git a/gcc/cselib.c b/gcc/cselib.c index 69c9ca5..0de6836 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -884,21 +884,29 @@ autoinc_split (rtx x, rtx *off, machine_mode memmode) else e = cselib_lookup (x, GET_MODE (x), 0, memmode); if (e) - for (struct elt_loc_list *l = e->locs; l; l = l->next) - if (GET_CODE (l->loc) == PLUS - && GET_CODE (XEXP (l->loc, 0)) == VALUE - && SP_DERIVED_VALUE_P (XEXP (l->loc, 0)) - && CONST_INT_P (XEXP (l->loc, 1))) + { + if (SP_DERIVED_VALUE_P (e->val_rtx) + && (*off == NULL_RTX || *off == const0_rtx)) { - if (*off == NULL_RTX) - *off = XEXP (l->loc, 1); - else - *off = plus_constant (Pmode, *off, - INTVAL (XEXP (l->loc, 1))); - if (*off == const0_rtx) - *off = NULL_RTX; - return XEXP (l->loc, 0); + *off = NULL_RTX; + return e->val_rtx; } + for (struct elt_loc_list *l = e->locs; l; l = l->next) + if (GET_CODE (l->loc) == PLUS + && GET_CODE (XEXP (l->loc, 0)) == VALUE + && SP_DERIVED_VALUE_P (XEXP (l->loc, 0)) + && CONST_INT_P (XEXP (l->loc, 1))) + { + if (*off == NULL_RTX) + *off = XEXP (l->loc, 1); + else + *off = plus_constant (Pmode, *off, + INTVAL (XEXP (l->loc, 1))); + if (*off == const0_rtx) + *off = NULL_RTX; + return XEXP (l->loc, 0); + } + } } return x; } diff --git a/gcc/reload1.c b/gcc/reload1.c index 2f02c3e..88f4727 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -2607,8 +2607,9 @@ eliminate_regs_1 (rtx x, machine_mode mem_mode, rtx insn, structure of the insn in a way that reload can't handle. We special-case the commonest situation in eliminate_regs_in_insn, so just replace a PLUS with a - PLUS here, unless inside a MEM. */ - if (mem_mode != 0 + PLUS here, unless inside a MEM. In DEBUG_INSNs, it is + always ok to replace a PLUS with just a REG. */ + if ((mem_mode != 0 || (insn && DEBUG_INSN_P (insn))) && CONST_INT_P (XEXP (x, 1)) && known_eq (INTVAL (XEXP (x, 1)), -ep->previous_offset)) return ep->to_rtx; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 134280d..6f26fc6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2020-04-08 Jakub Jelinek <jakub@redhat.com> + PR middle-end/94526 + * gcc.dg/pr94526.c: New test. + PR tree-optimization/94524 * gcc.c-torture/execute/pr94524-1.c: New test. * gcc.c-torture/execute/pr94524-2.c: New test. diff --git a/gcc/testsuite/gcc.dg/pr94526.c b/gcc/testsuite/gcc.dg/pr94526.c new file mode 100644 index 0000000..9864c4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr94526.c @@ -0,0 +1,21 @@ +/* PR middle-end/94526 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -g" } */ + +struct S { int val[8 * sizeof (int)]; }; + +void +foo (struct S *x) +{ + struct S *a = x; +} + +void baz (struct S); + +void +bar (void) +{ + struct S b; + foo (&b); + baz (b); +} |