On Fri, Sep 05, 2014 at 11:00:04AM +0930, Alan Modra wrote:
> Of course it would be better to repair the damage done to debug info
> rather than rejecting it outright..

This cures PR60655 on PowerPC by passing the horrible debug_loc
expressions we have through simplify_rtx.  Not only do we get
        reg10 + &.LANCHOR0 + const(0x14f - &.LANCHOR0) and
        reg10 + &modulus + const(~&d_data),
the two expressions that cause the PR due to (CONST (MINUS ..)) and
(CONST (NOT ..)), but also things like
       ~reg5 - reg31 + reg5 + reg10 + &modulus
where "~reg5 + reg5" is an inefficient way to write "-1".

It turns out that merely passing these expression through simplify_rtx
isn't enough.  Some tweaking is necessary to make (CONST (NOT ..)) and
(CONST (MINUS ..)) recognised by simplify_plus_minus, and even after
doing that, the two reg5 terms are not cancelled.

The reg5 case starts off with the simplify_plus_minus sorted ops array
effectively containing the expression
-reg31 + reg10 + reg5 + -reg5 + &modulus + -1

The first combination tried is &modulus + -1, which is rejected to
prevent recursion.  The next combination tried is -reg5 + -1, which is
simlified to ~reg5.  Well, that is a valid simplification, but the
trouble is that this prevents "reg5 + -reg5" being simplified to 0.
What's more, "&modulus + -1" is no more expensive than "&modulus",
since they are both emitted as an address field with a symbol+addend
relocation.  For that reason, I believe we should not consider
combining a const_int with any other term after finding that it can be
combined with a symbol_ref or other similar term.

Bootstrapped and regression tested powerpc64-linux and x86_64-linux.
I measured before/after bootstrap times on x86_64-linux because I was
concerned about the extra simplify_rtx calls, and was pleasantly
surprised to see a 0.23% improvement in bootstrap time.  (Which of
course is likely just noise.)  OK to apply?

        PR debug/60655
        * simplify-rtx.c (simplify_plus_minus): Delete unused "input_ops".
        Handle CONST wrapped NOT, NEG and MINUS.  Break out of innermost
        loop when finding a trivial CONST expression.
        * var-tracking.c (vt_expand_var_loc_chain): Call simplify_rtx.

Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c  (revision 214487)
+++ gcc/simplify-rtx.c  (working copy)
@@ -3960,7 +3960,7 @@ simplify_plus_minus (enum rtx_code code, enum mach
 {
   struct simplify_plus_minus_op_data ops[8];
   rtx result, tem;
-  int n_ops = 2, input_ops = 2;
+  int n_ops = 2;
   int changed, n_constants = 0, canonicalized = 0;
   int i, j;
 
@@ -3997,7 +3997,6 @@ simplify_plus_minus (enum rtx_code code, enum mach
              n_ops++;
 
              ops[i].op = XEXP (this_op, 0);
-             input_ops++;
              changed = 1;
              canonicalized |= this_neg;
              break;
@@ -4010,14 +4009,35 @@ simplify_plus_minus (enum rtx_code code, enum mach
              break;
 
            case CONST:
-             if (n_ops < 7
-                 && GET_CODE (XEXP (this_op, 0)) == PLUS
-                 && CONSTANT_P (XEXP (XEXP (this_op, 0), 0))
-                 && CONSTANT_P (XEXP (XEXP (this_op, 0), 1)))
+             if (GET_CODE (XEXP (this_op, 0)) == NEG
+                 && CONSTANT_P (XEXP (XEXP (this_op, 0), 0)))
                {
                  ops[i].op = XEXP (XEXP (this_op, 0), 0);
+                 ops[i].neg = !this_neg;
+                 changed = 1;
+                 canonicalized = 1;
+               }
+             else if (n_ops < 7
+                      && GET_CODE (XEXP (this_op, 0)) == NOT
+                      && CONSTANT_P (XEXP (XEXP (this_op, 0), 0)))
+               {
+                 ops[n_ops].op = CONSTM1_RTX (mode);
+                 ops[n_ops++].neg = this_neg;
+                 ops[i].op = XEXP (XEXP (this_op, 0), 0);
+                 ops[i].neg = !this_neg;
+                 changed = 1;
+                 canonicalized = 1;
+               }
+             else if (n_ops < 7
+                      && (GET_CODE (XEXP (this_op, 0)) == PLUS
+                          || GET_CODE (XEXP (this_op, 0)) == MINUS)
+                      && CONSTANT_P (XEXP (XEXP (this_op, 0), 0))
+                      && CONSTANT_P (XEXP (XEXP (this_op, 0), 1)))
+               {
+                 ops[i].op = XEXP (XEXP (this_op, 0), 0);
                  ops[n_ops].op = XEXP (XEXP (this_op, 0), 1);
-                 ops[n_ops].neg = this_neg;
+                 ops[n_ops].neg
+                   = (GET_CODE (XEXP (this_op, 0)) == MINUS) ^ this_neg;
                  n_ops++;
                  changed = 1;
                  canonicalized = 1;
@@ -4141,16 +4161,21 @@ simplify_plus_minus (enum rtx_code code, enum mach
                else
                  tem = simplify_binary_operation (ncode, mode, lhs, rhs);
 
-               /* Reject "simplifications" that just wrap the two
-                  arguments in a CONST.  Failure to do so can result
-                  in infinite recursion with simplify_binary_operation
-                  when it calls us to simplify CONST operations.  */
-               if (tem
-                   && ! (GET_CODE (tem) == CONST
-                         && GET_CODE (XEXP (tem, 0)) == ncode
-                         && XEXP (XEXP (tem, 0), 0) == lhs
-                         && XEXP (XEXP (tem, 0), 1) == rhs))
+               if (tem)
                  {
+                   /* Reject "simplifications" that just wrap the two
+                      arguments in a CONST.  Failure to do so can result
+                      in infinite recursion with simplify_binary_operation
+                      when it calls us to simplify CONST operations.
+                      Also, if we find such a simplification, don't try
+                      any more combinations with this rhs:  We must have
+                      something like symbol+offset, ie. one of the
+                      trivial CONST expressions we handle later.  */
+                   if (GET_CODE (tem) == CONST
+                       && GET_CODE (XEXP (tem, 0)) == ncode
+                       && XEXP (XEXP (tem, 0), 0) == lhs
+                       && XEXP (XEXP (tem, 0), 1) == rhs)
+                     break;
                    lneg &= rneg;
                    if (GET_CODE (tem) == NEG)
                      tem = XEXP (tem, 0), lneg = !lneg;
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c  (revision 214898)
+++ gcc/var-tracking.c  (working copy)
@@ -8375,7 +8375,15 @@ vt_expand_var_loc_chain (variable var, bitmap regs
     *pendrecp = pending_recursion;
 
   if (!pendrecp || !pending_recursion)
-    var->var_part[0].cur_loc = result;
+    {
+      if (result)
+       {
+         rtx tem = simplify_rtx (result);
+         if (tem)
+           result = tem;
+       }
+      var->var_part[0].cur_loc = result;
+    }
 
   return result;
 }

-- 
Alan Modra
Australia Development Lab, IBM

Reply via email to