diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2006-05-23 05:35:21 +0000 |
---|---|---|
committer | Alexandre Oliva <aoliva@gcc.gnu.org> | 2006-05-23 05:35:21 +0000 |
commit | dedc1e6d9ee0a0d5f28fcaef4200b6ba5c95f783 (patch) | |
tree | 75833789f320d2e562420bdc9a087314652e72bd /gcc | |
parent | 546be53558e5305b16b6239c6014d776a3d7a742 (diff) | |
download | gcc-dedc1e6d9ee0a0d5f28fcaef4200b6ba5c95f783.zip gcc-dedc1e6d9ee0a0d5f28fcaef4200b6ba5c95f783.tar.gz gcc-dedc1e6d9ee0a0d5f28fcaef4200b6ba5c95f783.tar.bz2 |
simplify-rtx.c (simplify_subreg): Adjust REG_OFFSET for big-endian paradoxical subregs.
* simplify-rtx.c (simplify_subreg): Adjust REG_OFFSET for
big-endian paradoxical subregs.
* var-tracking.c (struct micro_operation_def): Document that,
for modify micro operations, insn is the subsequent instruction.
(var_reg_delete_and_set, var_mem_delete_and_set): Split into...
(var_reg_set, var_mem_set): ... new functions.
(add_stores): Record subsequent insn.
(compute_bb_dataflow): Use new functions for MO_USE.
(emit_notes_in_bb): Use new functions for MO_USE. Emit use
notes after the insn, and modify notes before the insn known
to be the subsequent one.
(vt_initialize): Invert sorting of MO_CLOBBERs and MO_SETs.
From-SVN: r114013
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 17 | ||||
-rw-r--r-- | gcc/var-tracking.c | 85 |
3 files changed, 98 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4da9ce4..18c97a9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2006-05-23 Alexandre Oliva <aoliva@redhat.com> + + * simplify-rtx.c (simplify_subreg): Adjust REG_OFFSET for + big-endian paradoxical subregs. + * var-tracking.c (struct micro_operation_def): Document that, + for modify micro operations, insn is the subsequent instruction. + (var_reg_delete_and_set, var_mem_delete_and_set): Split into... + (var_reg_set, var_mem_set): ... new functions. + (add_stores): Record subsequent insn. + (compute_bb_dataflow): Use new functions for MO_USE. + (emit_notes_in_bb): Use new functions for MO_USE. Emit use + notes after the insn, and modify notes before the insn known + to be the subsequent one. + (vt_initialize): Invert sorting of MO_CLOBBERs and MO_SETs. + 2006-05-23 Kazu Hirata <kazu@codesourcery.com> PR target/27696 diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 6ab5cb7..7199316 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -4552,7 +4552,22 @@ simplify_subreg (enum machine_mode outermode, rtx op, if (HARD_REGNO_MODE_OK (final_regno, outermode) || ! HARD_REGNO_MODE_OK (regno, innermode)) { - rtx x = gen_rtx_REG_offset (op, outermode, final_regno, byte); + rtx x; + int final_offset = byte; + + /* Adjust offset for paradoxical subregs. */ + if (byte == 0 + && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) + { + int difference = (GET_MODE_SIZE (innermode) + - GET_MODE_SIZE (outermode)); + if (WORDS_BIG_ENDIAN) + final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; + if (BYTES_BIG_ENDIAN) + final_offset += difference % UNITS_PER_WORD; + } + + x = gen_rtx_REG_offset (op, outermode, final_regno, final_offset); /* Propagate original regno. We don't have any way to specify the offset inside original regno, so do so only for lowpart. diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 7e910d6..704d2f5 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -140,7 +140,11 @@ typedef struct micro_operation_def HOST_WIDE_INT adjust; } u; - /* The instruction which the micro operation is in. */ + /* The instruction which the micro operation is in, for MO_USE, + MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent + instruction or note in the original flow (before any var-tracking + notes are inserted, to simplify emission of notes), for MO_SET + and MO_CLOBBER. */ rtx insn; } micro_operation; @@ -291,9 +295,11 @@ static void vars_clear (htab_t); static variable unshare_variable (dataflow_set *set, variable var); static int vars_copy_1 (void **, void *); static void vars_copy (htab_t, htab_t); +static void var_reg_set (dataflow_set *, rtx); static void var_reg_delete_and_set (dataflow_set *, rtx); static void var_reg_delete (dataflow_set *, rtx); static void var_regno_delete (dataflow_set *, int); +static void var_mem_set (dataflow_set *, rtx); static void var_mem_delete_and_set (dataflow_set *, rtx); static void var_mem_delete (dataflow_set *, rtx); @@ -792,6 +798,19 @@ vars_copy (htab_t dst, htab_t src) htab_traverse (src, vars_copy_1, dst); } +/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ + +static void +var_reg_set (dataflow_set *set, rtx loc) +{ + tree decl = REG_EXPR (loc); + HOST_WIDE_INT offset = REG_OFFSET (loc); + + if (set->regs[REGNO (loc)] == NULL) + attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc); + set_variable_part (set, loc, decl, offset); +} + /* Delete current content of register LOC in dataflow set SET and set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ @@ -819,9 +838,7 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc) nextp = &node->next; } } - if (set->regs[REGNO (loc)] == NULL) - attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc); - set_variable_part (set, loc, decl, offset); + var_reg_set (set, loc); } /* Delete current content of register LOC in dataflow set SET. */ @@ -858,12 +875,12 @@ var_regno_delete (dataflow_set *set, int regno) *reg = NULL; } -/* Delete and set the location part of variable MEM_EXPR (LOC) - in dataflow set SET to LOC. +/* Set the location part of variable MEM_EXPR (LOC) in dataflow set + SET to LOC. Adjust the address first if it is stack pointer based. */ static void -var_mem_delete_and_set (dataflow_set *set, rtx loc) +var_mem_set (dataflow_set *set, rtx loc) { tree decl = MEM_EXPR (loc); HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0; @@ -871,6 +888,16 @@ var_mem_delete_and_set (dataflow_set *set, rtx loc) set_variable_part (set, loc, decl, offset); } +/* Delete and set the location part of variable MEM_EXPR (LOC) + in dataflow set SET to LOC. + Adjust the address first if it is stack pointer based. */ + +static void +var_mem_delete_and_set (dataflow_set *set, rtx loc) +{ + var_mem_set (set, loc); +} + /* Delete the location part LOC from dataflow set SET. Adjust the address first if it is stack pointer based. */ @@ -1547,7 +1574,7 @@ add_stores (rtx loc, rtx expr, void *insn) && track_expr_p (REG_EXPR (loc))) ? MO_SET : MO_CLOBBER); mo->u.loc = loc; - mo->insn = (rtx) insn; + mo->insn = NEXT_INSN ((rtx) insn); } else if (MEM_P (loc) && MEM_EXPR (loc) @@ -1558,7 +1585,7 @@ add_stores (rtx loc, rtx expr, void *insn) mo->type = GET_CODE (expr) == CLOBBER ? MO_CLOBBER : MO_SET; mo->u.loc = loc; - mo->insn = (rtx) insn; + mo->insn = NEXT_INSN ((rtx) insn); } } @@ -1589,6 +1616,16 @@ compute_bb_dataflow (basic_block bb) break; case MO_USE: + { + rtx loc = VTI (bb)->mos[i].u.loc; + + if (GET_CODE (loc) == REG) + var_reg_set (out, loc); + else if (GET_CODE (loc) == MEM) + var_mem_set (out, loc); + } + break; + case MO_SET: { rtx loc = VTI (bb)->mos[i].u.loc; @@ -2356,6 +2393,18 @@ emit_notes_in_bb (basic_block bb) break; case MO_USE: + { + rtx loc = VTI (bb)->mos[i].u.loc; + + if (GET_CODE (loc) == REG) + var_reg_set (&set, loc); + else + var_mem_set (&set, loc); + + emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); + } + break; + case MO_SET: { rtx loc = VTI (bb)->mos[i].u.loc; @@ -2365,10 +2414,7 @@ emit_notes_in_bb (basic_block bb) else var_mem_delete_and_set (&set, loc); - if (VTI (bb)->mos[i].type == MO_USE) - emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); - else - emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); + emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); } break; @@ -2383,9 +2429,9 @@ emit_notes_in_bb (basic_block bb) var_mem_delete (&set, loc); if (VTI (bb)->mos[i].type == MO_USE_NO_VAR) - emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); - else emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); + else + emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); } break; @@ -2598,15 +2644,18 @@ vt_initialize (void) } n1 = VTI (bb)->n_mos; + /* This will record NEXT_INSN (insn), such that we can + insert notes before it without worrying about any + notes that MO_USEs might emit after the insn. */ note_stores (PATTERN (insn), add_stores, insn); n2 = VTI (bb)->n_mos - 1; - /* Order the MO_SETs to be before MO_CLOBBERs. */ + /* Order the MO_CLOBBERs to be before MO_SETs. */ while (n1 < n2) { - while (n1 < n2 && VTI (bb)->mos[n1].type == MO_SET) + while (n1 < n2 && VTI (bb)->mos[n1].type == MO_CLOBBER) n1++; - while (n1 < n2 && VTI (bb)->mos[n2].type == MO_CLOBBER) + while (n1 < n2 && VTI (bb)->mos[n2].type == MO_SET) n2--; if (n1 < n2) { |