Message ID | 20110320125738.GQ30899@tyan-ft48-01.lab.bos.redhat.com |
---|---|
State | New |
Headers | show |
On 03/20/2011 05:57 AM, Jakub Jelinek wrote: > * cfgexpand.c (expand_debug_expr) <case SSA_NAME>: Only > create ENTRY_VALUE if incoming or address of incoming's MEM > is a hard REG. > * dwarf2out.c (mem_loc_descriptor): Don't emit > DW_OP_GNU_entry_value of DW_OP_fbreg. Ok. > * var-tracking.c (vt_add_function_parameter): Ensure cselib_lookup > on ENTRY_VALUE is able to find the canonical parameter VALUE. I don't really understand what's going on here. Whatever it is, it could definitely use some more commentary; there's almost nothing in the surrounding context. I also suggest pulling some of this out into a new function. You've got 2 exact copies here in the patch, and 2 more that are nearly the same already in the code. > * cselib.c (rtx_equal_for_cselib_1) <case ENTRY_VALUE>: Use > rtx_equal_p instead of rtx_equal_for_cselib_1 to compare > ENTRY_VALUE_EXPs. Ok. > (cselib_hash_rtx) <case ENTRY_VALUE>: If ENTRY_VALUE_EXP > is a REG_P or MEM_P with REG_P address, compute hash directly > instead of calling cselib_hash_rtx on ENTRY_VALUE_EXP. Why? > (preserve_only_constants): Don't clear VALUES forwaring > ENTRY_VALUE to some other VALUE. Ok with a comment. I guess the reasoning being that even though this value isn't "constant", it's function invariant? r~
On Mon, Mar 28, 2011 at 09:58:38AM -0700, Richard Henderson wrote: > > * var-tracking.c (vt_add_function_parameter): Ensure cselib_lookup > > on ENTRY_VALUE is able to find the canonical parameter VALUE. > > I don't really understand what's going on here. Whatever it is, it > could definitely use some more commentary; there's almost nothing in > the surrounding context. I also suggest pulling some of this out into > a new function. You've got 2 exact copies here in the patch, and 2 > more that are nearly the same already in the code. As cfgexpand.c creates ENTRY_VALUEs (where the first hunk of this patch applies), when vt_initialization uses cselib to lookup those ENTRY_VALUEs, without the patch it will find a newly created cselib_val whose only location is the ENTRY_VALUE. Which means it will always use DW_OP_GNU_entry_value in the end. Sometimes that is the only usable choice, but e.g. the first function in gcc.dg/pr48203.c shows we can do better, because all the entry values are also held in the corresponding registers (the function doesn't clobber them), so we can instead of DW_OP_GNU_entry_value just refer to the registers itself, either in the whole function, or at least as long as the aren't clobbered by something else. The extra cselib_lookup calls give us those values that hash as those ENTRY_VALUE will hash and by telling that the value is live in the parameter's VALUE vt_expand_loc_callback will find it. Say vt_add_function_parameter is called for first parameter in %rdi, cselib_lookup_from_insn gives us VALUE 2:2 for it. We add (entry_value:DI (reg:DI %rdi)) to list of locations for that VALUE. The second cselib_lookup_from_insn gives us VALUE 3:217, which will have locations (value:DI 2:2) (the one we've injected there) and (entry_value:DI (reg:DI %rdi)). Then when (entry_value:DI (reg:DI %rdi)) appears in some DEBUG_INSNs, it will give (value:DI 3:217) and vt_expand_loc_callback will use the first location for it (i.e. (value:DI 2:2) ) and either it will see the value is still live in %rdi, some other register or memory, or, if nowhere else, in (entry_value:DI (reg:DI %rdi)). The 3 cselib.c changes from this patch ensure that the hash value for (entry_value:DI (reg:DI %rdi)) will always be the same and (value:DI 3:217) will never be flushed from the hash table, even when e.g. on next bb's boundary we flush all registers from the hash table, or e.g. when movl $123, %edi is seen in the insns. I could of course create another hash table and map ENTRY_VALUEs through that hash table back to the parameter VALUEs, but cselib already has a hash table which we can use and furthermore the ENTRY_VALUEs could be embedded in other RTLs. I will look into creating helper inlines to reduce code duplication. > > * cselib.c (rtx_equal_for_cselib_1) <case ENTRY_VALUE>: Use > > rtx_equal_p instead of rtx_equal_for_cselib_1 to compare > > ENTRY_VALUE_EXPs. > > Ok. > > > (cselib_hash_rtx) <case ENTRY_VALUE>: If ENTRY_VALUE_EXP > > is a REG_P or MEM_P with REG_P address, compute hash directly > > instead of calling cselib_hash_rtx on ENTRY_VALUE_EXP. > > Why? Because REG and MEM hash based on their current value in cselib: case MEM: case REG: e = cselib_lookup (x, GET_MODE (x), create, memmode); if (! e) return 0; return e->hash; In ENTRY_VALUEs which are function invariant I want it to hash always the same. > > (preserve_only_constants): Don't clear VALUES forwaring > > ENTRY_VALUE to some other VALUE. > > Ok with a comment. I guess the reasoning being that even though this > value isn't "constant", it's function invariant? Yeah. Perhaps preserve_only_constants could be renamed to preserve_only_function_invariants or similar (and likewise for cselib_preserve_constants and CSELIB_PRESERVE_CONSTANTS). Jakub
On 03/28/2011 10:32 AM, Jakub Jelinek wrote: > Say vt_add_function_parameter is called for first parameter in %rdi, > cselib_lookup_from_insn gives us VALUE 2:2 for it. We add > (entry_value:DI (reg:DI %rdi)) to list of locations for that VALUE. > The second cselib_lookup_from_insn gives us VALUE 3:217, which will > have locations (value:DI 2:2) (the one we've injected there) and > (entry_value:DI (reg:DI %rdi)). Then when (entry_value:DI (reg:DI %rdi)) > appears in some DEBUG_INSNs, it will give (value:DI 3:217) > and vt_expand_loc_callback will use the first location for it > (i.e. (value:DI 2:2) ) and either it will see the value is still live > in %rdi, some other register or memory, or, if nowhere else, in > (entry_value:DI (reg:DI %rdi)). The 3 cselib.c changes from this > patch ensure that the hash value for (entry_value:DI (reg:DI %rdi)) > will always be the same and (value:DI 3:217) will never be flushed from > the hash table, even when e.g. on next bb's boundary we flush > all registers from the hash table, or e.g. when movl $123, %edi > is seen in the insns. Ok, thanks for the explanation. All the changes make sense now. > I will look into creating helper inlines to reduce code duplication. Please. You can do this as a follow-up if you prefer. >>> (cselib_hash_rtx) <case ENTRY_VALUE>: If ENTRY_VALUE_EXP >>> is a REG_P or MEM_P with REG_P address, compute hash directly >>> instead of calling cselib_hash_rtx on ENTRY_VALUE_EXP. >> >> Why? > > Because REG and MEM hash based on their current value in cselib: > case MEM: > case REG: > e = cselib_lookup (x, GET_MODE (x), create, memmode); > if (! e) > return 0; > > return e->hash; > In ENTRY_VALUEs which are function invariant I want it to hash always > the same. Ok, with something akin to this as a comment. r~
--- gcc/cfgexpand.c.jj 2011-03-17 09:37:59.000000000 +0100 +++ gcc/cfgexpand.c 2011-03-19 17:45:32.000000000 +0100 @@ -3182,8 +3182,10 @@ expand_debug_expr (tree exp) rtx incoming = DECL_INCOMING_RTL (SSA_NAME_VAR (exp)); if (incoming && GET_MODE (incoming) != BLKmode - && (REG_P (incoming) - || (MEM_P (incoming) && REG_P (XEXP (incoming, 0))))) + && ((REG_P (incoming) && HARD_REGISTER_P (incoming)) + || (MEM_P (incoming) + && REG_P (XEXP (incoming, 0)) + && HARD_REGISTER_P (XEXP (incoming, 0))))) { op0 = gen_rtx_ENTRY_VALUE (GET_MODE (incoming)); ENTRY_VALUE_EXP (op0) = incoming; --- gcc/dwarf2out.c.jj 2011-03-19 17:28:32.000000000 +0100 +++ gcc/dwarf2out.c 2011-03-19 17:48:42.000000000 +0100 @@ -13877,7 +13877,7 @@ mem_loc_descriptor (rtx rtl, enum machin dw_loc_descr_ref ref = mem_loc_descriptor (ENTRY_VALUE_EXP (rtl), GET_MODE (rtl), VAR_INIT_STATUS_INITIALIZED); - if (ref == NULL) + if (ref == NULL || ref->dw_loc_opc == DW_OP_fbreg) return NULL; mem_loc_result->dw_loc_oprnd1.v.val_loc = ref; } --- gcc/var-tracking.c.jj 2011-03-19 16:20:26.000000000 +0100 +++ gcc/var-tracking.c 2011-03-19 18:49:48.000000000 +0100 @@ -8472,7 +8472,7 @@ vt_add_function_parameter (tree parm) VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); if (dv_is_value_p (dv)) { - cselib_val *val = CSELIB_VAL_PTR (dv_as_value (dv)); + cselib_val *val = CSELIB_VAL_PTR (dv_as_value (dv)), *val2; struct elt_loc_list *el; el = (struct elt_loc_list *) ggc_alloc_cleared_atomic (sizeof (*el)); @@ -8481,6 +8481,23 @@ vt_add_function_parameter (tree parm) ENTRY_VALUE_EXP (el->loc) = incoming; el->setting_insn = get_insns (); val->locs = el; + val2 = cselib_lookup_from_insn (el->loc, GET_MODE (incoming), + true, VOIDmode, get_insns ()); + if (val2 + && val2 != val + && val2->locs + && rtx_equal_p (val2->locs->loc, el->loc)) + { + struct elt_loc_list *el2; + + preserve_value (val2); + el2 = (struct elt_loc_list *) + ggc_alloc_cleared_atomic (sizeof (*el2)); + el2->next = val2->locs; + el2->loc = dv_as_value (dv); + el2->setting_insn = get_insns (); + val2->locs = el2; + } if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (parm)))) { @@ -8499,6 +8516,24 @@ vt_add_function_parameter (tree parm) ENTRY_VALUE_EXP (el->loc) = mem; el->setting_insn = get_insns (); val->locs = el; + val2 = cselib_lookup_from_insn (el->loc, GET_MODE (incoming), + true, VOIDmode, + get_insns ()); + if (val2 + && val2 != val + && val2->locs + && rtx_equal_p (val2->locs->loc, el->loc)) + { + struct elt_loc_list *el2; + + preserve_value (val2); + el2 = (struct elt_loc_list *) + ggc_alloc_cleared_atomic (sizeof (*el2)); + el2->next = val2->locs; + el2->loc = val->val_rtx; + el2->setting_insn = get_insns (); + val2->locs = el2; + } } } } --- gcc/cselib.c.jj 2011-03-16 18:30:12.000000000 +0100 +++ gcc/cselib.c 2011-03-19 19:58:54.000000000 +0100 @@ -329,6 +329,12 @@ preserve_only_constants (void **x, void return 1; } } + if (v->locs != NULL + && v->locs->next != NULL + && v->locs->next->next == NULL + && GET_CODE (v->locs->next->loc) == ENTRY_VALUE + && GET_CODE (v->locs->loc) == VALUE) + return 1; htab_clear_slot (cselib_hash_table, x); return 1; @@ -804,8 +810,7 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, en == DEBUG_IMPLICIT_PTR_DECL (y); case ENTRY_VALUE: - return rtx_equal_for_cselib_1 (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y), - memmode); + return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y)); case LABEL_REF: return XEXP (x, 0) == XEXP (y, 0); @@ -954,7 +959,17 @@ cselib_hash_rtx (rtx x, int create, enum return hash ? hash : (unsigned int) DEBUG_IMPLICIT_PTR; case ENTRY_VALUE: - hash += cselib_hash_rtx (ENTRY_VALUE_EXP (x), create, memmode); + if (REG_P (ENTRY_VALUE_EXP (x))) + hash += (unsigned int) REG + + (unsigned int) GET_MODE (ENTRY_VALUE_EXP (x)) + + (unsigned int) REGNO (ENTRY_VALUE_EXP (x)); + else if (MEM_P (ENTRY_VALUE_EXP (x)) + && REG_P (XEXP (ENTRY_VALUE_EXP (x), 0))) + hash += (unsigned int) MEM + + (unsigned int) GET_MODE (XEXP (ENTRY_VALUE_EXP (x), 0)) + + (unsigned int) REGNO (XEXP (ENTRY_VALUE_EXP (x), 0)); + else + hash += cselib_hash_rtx (ENTRY_VALUE_EXP (x), create, memmode); return hash ? hash : (unsigned int) ENTRY_VALUE; case CONST_INT: --- gcc/testsuite/gcc.dg/pr48203.c.jj 2011-03-19 18:06:29.000000000 +0100 +++ gcc/testsuite/gcc.dg/pr48203.c 2011-03-19 18:06:01.000000000 +0100 @@ -0,0 +1,51 @@ +/* PR debug/48203 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -g" } */ + +volatile int v; + +void +foo (long a, long b, long c, long d, long e, long f, long g, long h, + long i, long j, long k, long l, long m, long n, long o, long p) +{ + long a2 = a; + long b2 = b; + long c2 = c; + long d2 = d; + long e2 = e; + long f2 = f; + long g2 = g; + long h2 = h; + long i2 = i; + long j2 = j; + long k2 = k; + long l2 = l; + long m2 = m; + long n2 = n; + long o2 = o; + long p2 = p; + v++; +} + +void +bar (int a, int b, int c, int d, int e, int f, int g, int h, + int i, int j, int k, int l, int m, int n, int o, int p) +{ + int a2 = a; + int b2 = b; + int c2 = c; + int d2 = d; + int e2 = e; + int f2 = f; + int g2 = g; + int h2 = h; + int i2 = i; + int j2 = j; + int k2 = k; + int l2 = l; + int m2 = m; + int n2 = n; + int o2 = o; + int p2 = p; + v++; +}