* 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.
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);
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
+ }
}
}
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)
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. */
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)))
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
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
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