summaryrefslogtreecommitdiff
path: root/gcc/cselib.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-03-28 23:53:46 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-03-28 23:53:46 +0000
commit06eb3ccd8a660aa8d0f6b113841813bbe867f84a (patch)
tree7d5601e9e49e4f8fa5cf78fc46ce899d76d94f4f /gcc/cselib.c
parent5150021e40056804a9215058c054b90cd7b92626 (diff)
downloadgcc-06eb3ccd8a660aa8d0f6b113841813bbe867f84a.tar.gz
PR debug/48203
* 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. * var-tracking.c (vt_add_function_parameter): Ensure cselib_lookup on ENTRY_VALUE is able to find the canonical parameter VALUE. * 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. (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. (preserve_only_constants): Don't clear VALUES forwaring ENTRY_VALUE to some other VALUE. * gcc.dg/pr48203.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@171640 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cselib.c')
-rw-r--r--gcc/cselib.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/gcc/cselib.c b/gcc/cselib.c
index f9e13ffffef..dff096752f5 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -305,7 +305,8 @@ cselib_clear_table (void)
cselib_reset_table (1);
}
-/* Remove from hash table all VALUEs except constants. */
+/* Remove from hash table all VALUEs except constants
+ and function invariants. */
static int
preserve_only_constants (void **x, void *info ATTRIBUTE_UNUSED)
@@ -329,6 +330,14 @@ preserve_only_constants (void **x, void *info ATTRIBUTE_UNUSED)
return 1;
}
}
+ /* Keep around VALUEs that forward function invariant ENTRY_VALUEs
+ to corresponding parameter VALUEs. */
+ 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 +813,9 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, enum machine_mode memmode)
== DEBUG_IMPLICIT_PTR_DECL (y);
case ENTRY_VALUE:
- return rtx_equal_for_cselib_1 (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y),
- memmode);
+ /* ENTRY_VALUEs are function invariant, it is thus undesirable to
+ use rtx_equal_for_cselib_1 to compare the operands. */
+ return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y));
case LABEL_REF:
return XEXP (x, 0) == XEXP (y, 0);
@@ -954,7 +964,22 @@ cselib_hash_rtx (rtx x, int create, enum machine_mode memmode)
return hash ? hash : (unsigned int) DEBUG_IMPLICIT_PTR;
case ENTRY_VALUE:
- hash += cselib_hash_rtx (ENTRY_VALUE_EXP (x), create, memmode);
+ /* ENTRY_VALUEs are function invariant, thus try to avoid
+ recursing on argument if ENTRY_VALUE is one of the
+ forms emitted by expand_debug_expr, otherwise
+ ENTRY_VALUE hash would depend on the current value
+ in some register or memory. */
+ 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: