diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/calls.c | 29 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.h | 12 | ||||
-rw-r--r-- | gcc/cse.c | 17 |
4 files changed, 51 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 39323eec7..b3f3f84 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -17,6 +17,14 @@ Thu Dec 9 11:36:24 MET 1999 Jan Hubicka <hubicka@freesoft.cz> * genmultilib: Accept | as alternative separator within a set in MULTILIB_OPTIONS. + * config/sparc/sparc.h (PROMOTE_FOR_CALL_ONLY): Define. + + * calls.c (precompute_arguments): Make sure initial_value contains + value pseudo which CSE expects. + * cse.c (struct set): New entry orig_src. + (cse_insn): Set it early on entry, use it for libcall EQUIV note + replacement. + Wed Dec 8 22:24:15 1999 Richard Henderson <rth@cygnus.com> * flow.c (count_basic_blocks): Don't add (use (const_int 0)) insns. diff --git a/gcc/calls.c b/gcc/calls.c index 33b425d..e19f787 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1267,7 +1267,7 @@ precompute_arguments (is_const, must_preallocate, num_actuals, args, args_size) push_temp_slots (); - args[i].initial_value = args[i].value + args[i].value = expand_expr (args[i].tree_value, NULL_RTX, VOIDmode, 0); preserve_temp_slots (args[i].value); @@ -1278,13 +1278,30 @@ precompute_arguments (is_const, must_preallocate, num_actuals, args, args_size) emit_queue (); args[i].initial_value = args[i].value - = protect_from_queue (args[i].initial_value, 0); + = protect_from_queue (args[i].value, 0); if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode) - args[i].value - = convert_modes (args[i].mode, - TYPE_MODE (TREE_TYPE (args[i].tree_value)), - args[i].value, args[i].unsignedp); + { + args[i].value + = convert_modes (args[i].mode, + TYPE_MODE (TREE_TYPE (args[i].tree_value)), + args[i].value, args[i].unsignedp); +#ifdef PROMOTE_FOR_CALL_ONLY + /* CSE will replace this only if it contains args[i].value + pseudo, so convert it down to the declared mode using + a SUBREG. */ + if (GET_CODE (args[i].value) == REG + && GET_MODE_CLASS (args[i].mode) == MODE_INT) + { + args[i].initial_value + = gen_rtx_SUBREG (TYPE_MODE (TREE_TYPE (args[i].tree_value)), + args[i].value, 0); + SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1; + SUBREG_PROMOTED_UNSIGNED_P (args[i].initial_value) + = args[i].unsignedp; + } +#endif + } } } diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index 1a44547..4387fc8 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -777,6 +777,18 @@ if (TARGET_ARCH64 \ for this value. */ #define PROMOTE_FUNCTION_RETURN +/* Define this macro if the promotion described by PROMOTE_MODE + should _only_ be performed for outgoing function arguments or + function return values, as specified by PROMOTE_FUNCTION_ARGS + and PROMOTE_FUNCTION_RETURN, respectively. */ +/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op + for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime test + for this value. For TARGET_ARCH64 we need it, as we don't have instructions + for arithmetic operations which do zero/sign extension at the same time, + so without this we end up with a srl/sra after every assignment to an + user variable, which means very very bad code. */ +#define PROMOTE_FOR_CALL_ONLY + /* Allocation boundary (in *bits*) for storing arguments in argument list. */ #define PARM_BOUNDARY (TARGET_ARCH64 ? 64 : 32) @@ -4426,6 +4426,8 @@ struct set enum machine_mode mode; /* A constant equivalent for SET_SRC, if any. */ rtx src_const; + /* Original SET_SRC value used for libcall notes. */ + rtx orig_src; /* Hash value of constant equivalent for SET_SRC. */ unsigned src_const_hash; /* Table entry for constant equivalent for SET_SRC, if any. */ @@ -4624,6 +4626,7 @@ cse_insn (insn, libcall_insn) rtx new = canon_reg (src, insn); int insn_code; + sets[i].orig_src = src; if ((GET_CODE (new) == REG && GET_CODE (src) == REG && ((REGNO (new) < FIRST_PSEUDO_REGISTER) != (REGNO (src) < FIRST_PSEUDO_REGISTER))) @@ -5123,7 +5126,7 @@ cse_insn (insn, libcall_insn) the current contents will be tested and will always be valid. */ while (1) { - rtx trial, old_src; + rtx trial; /* Skip invalid entries. */ while (elt && GET_CODE (elt->exp) != REG @@ -5189,10 +5192,6 @@ cse_insn (insn, libcall_insn) insert the substitution here and we will delete and re-emit the insn later. */ - /* Keep track of the original SET_SRC so that we can fix notes - on libcall instructions. */ - old_src = SET_SRC (sets[i].rtl); - if (n_sets == 1 && dest == pc_rtx && (trial == pc_rtx || (GET_CODE (trial) == LABEL_REF @@ -5221,10 +5220,10 @@ cse_insn (insn, libcall_insn) need to make the same substitution in any notes attached to the RETVAL insn. */ if (libcall_insn - && (GET_CODE (old_src) == REG - || GET_CODE (old_src) == SUBREG - || GET_CODE (old_src) == MEM)) - replace_rtx (REG_NOTES (libcall_insn), old_src, + && (GET_CODE (sets[i].orig_src) == REG + || GET_CODE (sets[i].orig_src) == SUBREG + || GET_CODE (sets[i].orig_src) == MEM)) + replace_rtx (REG_NOTES (libcall_insn), sets[i].orig_src, canon_reg (SET_SRC (sets[i].rtl), insn)); /* The result of apply_change_group can be ignored; see |