diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-05-31 19:14:21 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-05-31 19:14:21 +0000 |
commit | 0ee5bf3c39811c9469b6be259744e38e23e7b31a (patch) | |
tree | 2f0b491691c28732618def0868a08c868f96b580 /gcc/cselib.c | |
parent | 1bd906a3a94bb5d5420280fe4dd4878e34eac6b8 (diff) | |
download | gcc-0ee5bf3c39811c9469b6be259744e38e23e7b31a.tar.gz |
* cselib.c (promote_debug_loc): Allow l->next non-NULL for
cselib_preserve_constants.
(cselib_lookup_1): If cselib_preserve_constants,
a new VALUE is being created for REG and there is a VALUE for the
same register in wider mode, add another loc with lowpart SUBREG of
the wider VALUE.
(cselib_subst_to_values): Handle ENTRY_VALUE.
* var-tracking.c (replace_expr_with_values): Return NULL for
ENTRY_VALUE too.
* dwarf2out.c (convert_descriptor_to_signed): New function.
(mem_loc_descriptor) <case ZERO_EXTEND>: Optimize using DW_OP_and
instead of two shifts.
(mem_loc_descriptor) <do_shift>: ZERO_EXTEND second argument to
the right mode if needed.
(mem_loc_descriptor) <case MOD>: For typed ops just use DW_OP_mod.
(mem_loc_descriptor) <case UNSIGNED_FIX>: Use
convert_descriptor_to_signed.
(mem_loc_descriptor) <case UDIV, CLZ, CTZ, FFS, POPCOUNT, PARITY,
BSWAP, ROTATE, ROTATERT>: Handle these rtls.
* gcc.dg/guality/bswaptest.c: New test.
* gcc.dg/guality/clztest.c: New test.
* gcc.dg/guality/ctztest.c: New test.
* gcc.dg/guality/rotatetest.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@174508 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cselib.c')
-rw-r--r-- | gcc/cselib.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/gcc/cselib.c b/gcc/cselib.c index 56e6d178576..e0697ecfca8 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -257,7 +257,7 @@ promote_debug_loc (struct elt_loc_list *l) { n_debug_values--; l->setting_insn = cselib_current_insn; - gcc_assert (!l->next); + gcc_assert (!l->next || cselib_preserve_constants); } } @@ -1719,6 +1719,12 @@ cselib_subst_to_values (rtx x, enum machine_mode memmode) } return e->val_rtx; + case ENTRY_VALUE: + e = cselib_lookup (x, GET_MODE (x), 0, memmode); + if (! e) + break; + return e->val_rtx; + case CONST_DOUBLE: case CONST_VECTOR: case CONST_INT: @@ -1843,6 +1849,43 @@ cselib_lookup_1 (rtx x, enum machine_mode mode, used_regs[n_used_regs++] = i; REG_VALUES (i) = new_elt_list (REG_VALUES (i), NULL); } + else if (cselib_preserve_constants + && GET_MODE_CLASS (mode) == MODE_INT) + { + /* During var-tracking, try harder to find equivalences + for SUBREGs. If a setter sets say a DImode register + and user uses that register only in SImode, add a lowpart + subreg location. */ + struct elt_list *lwider = NULL; + l = REG_VALUES (i); + if (l && l->elt == NULL) + l = l->next; + for (; l; l = l->next) + if (GET_MODE_CLASS (GET_MODE (l->elt->val_rtx)) == MODE_INT + && GET_MODE_SIZE (GET_MODE (l->elt->val_rtx)) + > GET_MODE_SIZE (mode) + && (lwider == NULL + || GET_MODE_SIZE (GET_MODE (l->elt->val_rtx)) + < GET_MODE_SIZE (GET_MODE (lwider->elt->val_rtx)))) + { + struct elt_loc_list *el; + if (i < FIRST_PSEUDO_REGISTER + && hard_regno_nregs[i][GET_MODE (l->elt->val_rtx)] != 1) + continue; + for (el = l->elt->locs; el; el = el->next) + if (!REG_P (el->loc)) + break; + if (el) + lwider = l; + } + if (lwider) + { + rtx sub = lowpart_subreg (mode, lwider->elt->val_rtx, + GET_MODE (lwider->elt->val_rtx)); + if (sub) + e->locs->next = new_elt_loc_list (e->locs->next, sub); + } + } REG_VALUES (i)->next = new_elt_list (REG_VALUES (i)->next, e); slot = cselib_find_slot (x, e->hash, INSERT, memmode); *slot = e; |