+2003-11-28 Jan Hubicka <jh@suse.cz>
+
+ * emit-rtl.c (set_used_flags): New.
+ (verify_rtx_sharing, verify_rtl_sharing): New.
+ (unshare_all_rtl_1): Rename to....
+ (unshare_all_rtl_in_chain): ... this one; make static.
+ (copy_rtx_if_shared): LABEL_REF chan be shared.
+ * ifcvt.c (unshare_ifcvt_sequence): New.
+ (noce_try_move, noce_try_store_flag, noce_try_store_flag_constants,
+ noce_try_addcc, noce_try_addcc, noce_try_store_flag_mask,
+ noce_try_cmove, noce_try_store_flag_mask, noce_try_minmax,
+ noce_try_abs, noce_process_if_block, find_cond_trap
+ * rtl.h (verify_rtl_sharing, set_used_flags, unshare_all_rtl_in_chain):
+ Declare.
+
2003-11-28 Kazu Hirata <kazu@cs.umass.edu>
* config/h8300/h8300.md: Fix a comment typo.
2003-11-24 Jan Hubicka <jh@suse.cz>
- * fold-const.c (fold): Do not return early when optimizing COMPONENT_REF
- and constant.
+ * fold-const.c (fold): Do not return early when optimizing
+ COMPONENT_REF and constant.
2003-11-24 Kazu Hirata <kazu@cs.umass.edu>
static rtx make_call_insn_raw (rtx);
static rtx find_line_note (rtx);
static rtx change_address_1 (rtx, enum machine_mode, rtx, int);
-static void unshare_all_rtl_1 (rtx);
static void unshare_all_decls (tree);
static void reset_used_decls (tree);
static void mark_label_nuses (rtx);
unshare_all_decls (DECL_INITIAL (fndecl));
/* Unshare just about everything else. */
- unshare_all_rtl_1 (insn);
+ unshare_all_rtl_in_chain (insn);
/* Make sure the addresses of stack slots found outside the insn chain
(such as, in DECL_RTL of a variable) are not shared
unshare_all_rtl (cfun->decl, insn);
}
+/* Check that ORIG is not marked when it should not be and mark ORIG as in use,
+ Recursively does the same for subexpressions. */
+
+static void
+verify_rtx_sharing (rtx orig, rtx insn)
+{
+ rtx x = orig;
+ int i;
+ enum rtx_code code;
+ const char *format_ptr;
+
+ if (x == 0)
+ return;
+
+ code = GET_CODE (x);
+
+ /* These types may be freely shared. */
+
+ switch (code)
+ {
+ case REG:
+ case QUEUED:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST_VECTOR:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CODE_LABEL:
+ case PC:
+ case CC0:
+ case SCRATCH:
+ /* SCRATCH must be shared because they represent distinct values. */
+ return;
+
+ case CONST:
+ /* CONST can be shared if it contains a SYMBOL_REF. If it contains
+ a LABEL_REF, it isn't sharable. */
+ if (GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+ return;
+ break;
+
+ case MEM:
+ /* A MEM is allowed to be shared if its address is constant. */
+ if (CONSTANT_ADDRESS_P (XEXP (x, 0))
+ || reload_completed || reload_in_progress)
+ return;
+
+ break;
+
+ default:
+ break;
+ }
+
+ /* This rtx may not be shared. If it has already been seen,
+ replace it with a copy of itself. */
+
+ if (RTX_FLAG (x, used))
+ {
+ error ("Invalid rtl sharing found in the insn");
+ debug_rtx (insn);
+ error ("Shared rtx");
+ debug_rtx (x);
+ abort ();
+ }
+ RTX_FLAG (x, used) = 1;
+
+ /* Now scan the subexpressions recursively. */
+
+ format_ptr = GET_RTX_FORMAT (code);
+
+ for (i = 0; i < GET_RTX_LENGTH (code); i++)
+ {
+ switch (*format_ptr++)
+ {
+ case 'e':
+ verify_rtx_sharing (XEXP (x, i), insn);
+ break;
+
+ case 'E':
+ if (XVEC (x, i) != NULL)
+ {
+ int j;
+ int len = XVECLEN (x, i);
+
+ for (j = 0; j < len; j++)
+ {
+ /* We allow sharing of ASM_OPERANDS inside single instruction. */
+ if (j && GET_CODE (XVECEXP (x, i, j)) == SET
+ && GET_CODE (SET_SRC (XVECEXP (x, i, j))) == ASM_OPERANDS)
+ verify_rtx_sharing (SET_DEST (XVECEXP (x, i, j)), insn);
+ else
+ verify_rtx_sharing (XVECEXP (x, i, j), insn);
+ }
+ }
+ break;
+ }
+ }
+ return;
+}
+
+/* Go through all the RTL insn bodies and chec that there is no inexpected
+ sharing in between the subexpressions. */
+
+void
+verify_rtl_sharing (void)
+{
+ rtx p;
+
+ for (p = get_insns (); p; p = NEXT_INSN (p))
+ if (INSN_P (p))
+ {
+ reset_used_flags (PATTERN (p));
+ reset_used_flags (REG_NOTES (p));
+ reset_used_flags (LOG_LINKS (p));
+ }
+
+ for (p = get_insns (); p; p = NEXT_INSN (p))
+ if (INSN_P (p))
+ {
+ verify_rtx_sharing (PATTERN (p), p);
+ verify_rtx_sharing (REG_NOTES (p), p);
+ verify_rtx_sharing (LOG_LINKS (p), p);
+ }
+}
+
/* Go through all the RTL insn bodies and copy any invalid shared structure.
Assumes the mark bits are cleared at entry. */
-static void
-unshare_all_rtl_1 (rtx insn)
+void
+unshare_all_rtl_in_chain (rtx insn)
{
for (; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn))
case CONST_DOUBLE:
case CONST_VECTOR:
case SYMBOL_REF:
+ case LABEL_REF:
case CODE_LABEL:
case PC:
case CC0:
}
}
}
+
+/* Set all the USED bits in X to allow copy_rtx_if_shared to be used
+ to look for shared sub-parts. */
+
+void
+set_used_flags (rtx x)
+{
+ int i, j;
+ enum rtx_code code;
+ const char *format_ptr;
+
+ if (x == 0)
+ return;
+
+ code = GET_CODE (x);
+
+ /* These types may be freely shared so we needn't do any resetting
+ for them. */
+
+ switch (code)
+ {
+ case REG:
+ case QUEUED:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST_VECTOR:
+ case SYMBOL_REF:
+ case CODE_LABEL:
+ case PC:
+ case CC0:
+ return;
+
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case NOTE:
+ case LABEL_REF:
+ case BARRIER:
+ /* The chain of insns is not being copied. */
+ return;
+
+ default:
+ break;
+ }
+
+ RTX_FLAG (x, used) = 1;
+
+ format_ptr = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++)
+ {
+ switch (*format_ptr++)
+ {
+ case 'e':
+ set_used_flags (XEXP (x, i));
+ break;
+
+ case 'E':
+ for (j = 0; j < XVECLEN (x, i); j++)
+ set_used_flags (XVECEXP (x, i, j));
+ break;
+ }
+ }
+}
\f
/* Copy X if necessary so that it won't be altered by changes in OTHER.
Return X or the rtx for the pseudo reg the value of X was copied into.
GET_MODE_BITSIZE (inmode));
}
+/* Unshare sequence SEQ produced by if conversion. We care to mark
+ all arguments that may be shared with outer instruction stream. */
+static void
+unshare_ifcvt_sequence (struct noce_if_info *if_info, rtx seq)
+{
+ set_used_flags (if_info->x);
+ set_used_flags (if_info->cond);
+ unshare_all_rtl_in_chain (seq);
+}
+
/* Convert "if (a != b) x = a; else x = b" into "x = a" and
"if (a == b) x = a; else x = b" into "x = b". */
start_sequence ();
noce_emit_move_insn (if_info->x, y);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
emit_insn_before_setloc (seq, if_info->jump,
INSN_LOCATOR (if_info->insn_a));
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
if (seq_contains_jump (seq))
{
start_sequence ();
target = emit_conditional_add (if_info->x, code,
- XEXP (cond, 0), XEXP (cond, 1),
+ XEXP (cond, 0),
+ XEXP (cond, 1),
VOIDmode,
- if_info->b, XEXP (if_info->a, 1),
+ if_info->b,
+ XEXP (if_info->a, 1),
GET_MODE (if_info->x),
(code == LTU || code == GEU
|| code == LEU || code == GTU));
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
emit_insn_before_setloc (seq, if_info->jump,
INSN_LOCATOR (if_info->insn_a));
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
if (seq_contains_jump (seq))
reversep, -1);
if (target)
target = expand_simple_binop (GET_MODE (if_info->x), AND,
- if_info->x, target, if_info->x, 0,
+ if_info->x,
+ target, if_info->x, 0,
OPTAB_WIDEN);
if (target)
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
if (seq_contains_jump (seq))
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
emit_insn_before_setloc (seq, if_info->jump,
INSN_LOCATOR (if_info->insn_a));
if (is_mem)
{
tmp = gen_reg_rtx (GET_MODE (b));
- tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, b));
+ tmp = emit_insn (gen_rtx_SET (VOIDmode,
+ tmp,
+ b));
}
else if (! insn_b)
goto end_seq_and_fail;
noce_emit_move_insn (x, target);
tmp = get_insns ();
+ unshare_ifcvt_sequence (if_info, tmp);
end_sequence ();
emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR (if_info->insn_a));
return TRUE;
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
if (seq_contains_jump (seq))
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
if (seq_contains_jump (seq))
if (orig_x != x)
{
start_sequence ();
- noce_emit_move_insn (copy_rtx (orig_x), x);
+ noce_emit_move_insn (orig_x, x);
insn_b = get_insns ();
+ set_used_flags (orig_x);
+ unshare_all_rtl_in_chain (insn_b);
end_sequence ();
emit_insn_after_setloc (insn_b, test_bb->end, INSN_LOCATOR (insn_a));
}
/* Attempt to generate the conditional trap. */
- seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1),
+ seq = gen_cond_trap (code, XEXP (cond, 0),
+ XEXP (cond, 1),
TRAP_CODE (PATTERN (trap)));
if (seq == NULL)
return FALSE;
extern void mark_reg_pointer (rtx, int);
extern void mark_user_reg (rtx);
extern void reset_used_flags (rtx);
+extern void set_used_flags (rtx);
extern void reorder_insns (rtx, rtx, rtx);
extern void reorder_insns_nobb (rtx, rtx, rtx);
extern int get_max_uid (void);
extern void set_new_first_and_last_label_num (int, int);
extern void set_new_last_label_num (int);
extern void unshare_all_rtl_again (rtx);
+extern void unshare_all_rtl_in_chain (rtx);
+extern void verify_rtl_sharing (void);
extern void set_first_insn (rtx);
extern void set_last_insn (rtx);
extern void link_cc0_insns (rtx);