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