summaryrefslogtreecommitdiff
path: root/gcc/final.c
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1998-10-27 23:19:31 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1998-10-27 23:19:31 +0000
commitd740a1dd2870ba202cd288ed8714540b0b60912d (patch)
treec70a7a8b1e67a64ee37c4cbef242efc253b9a280 /gcc/final.c
parent1063433ee616c7b224b1625c8c05c6619ffc6a25 (diff)
downloadgcc-d740a1dd2870ba202cd288ed8714540b0b60912d.tar.gz
* final.c (cleanup_subreg_operands): New function.
(final_scan_insn): Use it. (alter_subreg): Clear the "used" field when we turn a SUBREG into a REG. * reload1.c (reload): Delete CLOBBER insns and also cleanup SUBREG operands when reload has finished. * reload.h (cleanup_subreg_operands): Declare.. * flow.c (life_analysis_1): No longer delete CLOBBER insns after reload. Handled in reload itself. Should fix sh, sparc and probably other problems with post-reload life pass and scheduling interactions. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@23377 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/final.c')
-rw-r--r--gcc/final.c64
1 files changed, 47 insertions, 17 deletions
diff --git a/gcc/final.c b/gcc/final.c
index 5b7874e7587..4c19c84a9fd 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -2844,23 +2844,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
insn_code_number = recog_memoized (insn);
insn_extract (insn);
- for (i = 0; i < insn_n_operands[insn_code_number]; i++)
- {
- if (GET_CODE (recog_operand[i]) == SUBREG)
- recog_operand[i] = alter_subreg (recog_operand[i]);
- else if (GET_CODE (recog_operand[i]) == PLUS
- || GET_CODE (recog_operand[i]) == MULT)
- recog_operand[i] = walk_alter_subreg (recog_operand[i]);
- }
-
- for (i = 0; i < insn_n_dups[insn_code_number]; i++)
- {
- if (GET_CODE (*recog_dup_loc[i]) == SUBREG)
- *recog_dup_loc[i] = alter_subreg (*recog_dup_loc[i]);
- else if (GET_CODE (*recog_dup_loc[i]) == PLUS
- || GET_CODE (*recog_dup_loc[i]) == MULT)
- *recog_dup_loc[i] = walk_alter_subreg (*recog_dup_loc[i]);
- }
+ cleanup_subreg_operands (insn);
#ifdef REGISTER_CONSTRAINTS
if (! constrain_operands (insn_code_number, 1))
@@ -3039,6 +3023,49 @@ output_source_line (file, insn)
}
}
+
+/* For each operand in INSN, simplify (subreg (reg)) so that it refers
+ directly to the desired hard register. */
+void
+cleanup_subreg_operands (insn)
+ rtx insn;
+{
+ int insn_code_number, i;
+
+ /* Ignore things we can not handle. */
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i'
+ || GET_CODE (PATTERN (insn)) == USE
+ || GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
+ || asm_noperands (PATTERN (insn)) >= 0)
+ return;
+
+ /* Try to recognize the instruction.
+ If successful, verify that the operands satisfy the
+ constraints for the instruction. Crash if they don't,
+ since `reload' should have changed them so that they do. */
+
+ insn_code_number = recog_memoized (insn);
+ insn_extract (insn);
+ for (i = 0; i < insn_n_operands[insn_code_number]; i++)
+ {
+ if (GET_CODE (recog_operand[i]) == SUBREG)
+ recog_operand[i] = alter_subreg (recog_operand[i]);
+ else if (GET_CODE (recog_operand[i]) == PLUS
+ || GET_CODE (recog_operand[i]) == MULT)
+ recog_operand[i] = walk_alter_subreg (recog_operand[i]);
+ }
+
+ for (i = 0; i < insn_n_dups[insn_code_number]; i++)
+ {
+ if (GET_CODE (*recog_dup_loc[i]) == SUBREG)
+ *recog_dup_loc[i] = alter_subreg (*recog_dup_loc[i]);
+ else if (GET_CODE (*recog_dup_loc[i]) == PLUS
+ || GET_CODE (*recog_dup_loc[i]) == MULT)
+ *recog_dup_loc[i] = walk_alter_subreg (*recog_dup_loc[i]);
+ }
+}
+
/* If X is a SUBREG, replace it with a REG or a MEM,
based on the thing it is a subreg of. */
@@ -3072,6 +3099,9 @@ alter_subreg (x)
#else
REGNO (x) = REGNO (y) + SUBREG_WORD (x);
#endif
+ /* This field has a different meaning for REGs and SUBREGs. Make sure
+ to clear it! */
+ x->used = 0;
}
else if (GET_CODE (y) == MEM)
{