This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
ifcvt RTL sharing patch updated
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: gcc-patches at gcc dot gnu dot org, rth at redhat dot com
- Date: Fri, 28 Nov 2003 18:01:56 +0100
- Subject: ifcvt RTL sharing patch updated
Hi,
I tought I sent this one already, but apparently I didn't, so here is
updated patch for RTL sharing problems, so it apply to current tree and
pass testing on i686-pc-gnu-linux and x86_64-linux.
It contains also the checking bits but they are disabled so we are not
immediately bit by the latent problems elsewhere in the compiler.
OK?
Honza
2003-11-09 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.
* toplev.c (rest_of_compilation): Check for RTL sharing.
Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.352
diff -c -3 -p -r1.352 emit-rtl.c
*** emit-rtl.c 4 Nov 2003 09:14:18 -0000 1.352
--- emit-rtl.c 9 Nov 2003 15:19:37 -0000
*************** static rtx make_jump_insn_raw (rtx);
*** 180,186 ****
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);
--- 180,185 ----
*************** unshare_all_rtl (tree fndecl, rtx insn)
*** 2448,2454 ****
unshare_all_decls (DECL_INITIAL (fndecl));
/* Unshare just about everything else. */
! unshare_all_rtl_1 (insn);
/* Make sure the addresses of stack slots found outside the insn chain
(such as, in DECL_RTL of a variable) are not shared
--- 2447,2453 ----
unshare_all_decls (DECL_INITIAL (fndecl));
/* Unshare just about everything else. */
! 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_again (rtx insn)
*** 2490,2500 ****
unshare_all_rtl (cfun->decl, insn);
}
/* 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)
{
for (; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn))
--- 2489,2626 ----
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. */
! void
! unshare_all_rtl_in_chain (rtx insn)
{
for (; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn))
*************** copy_rtx_if_shared (rtx orig)
*** 2666,2671 ****
--- 2792,2798 ----
case CONST_DOUBLE:
case CONST_VECTOR:
case SYMBOL_REF:
+ case LABEL_REF:
case CODE_LABEL:
case PC:
case CC0:
*************** reset_used_flags (rtx x)
*** 2798,2803 ****
--- 2925,2993 ----
case 'E':
for (j = 0; j < XVECLEN (x, i); j++)
reset_used_flags (XVECEXP (x, i, j));
+ break;
+ }
+ }
+ }
+
+ /* 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;
}
}
Index: ifcvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ifcvt.c,v
retrieving revision 1.129
diff -c -3 -p -r1.129 ifcvt.c
*** ifcvt.c 2 Nov 2003 13:56:40 -0000 1.129
--- ifcvt.c 9 Nov 2003 15:19:38 -0000
*************** noce_emit_move_insn (rtx x, rtx y)
*** 700,705 ****
--- 700,715 ----
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". */
*************** noce_try_move (struct noce_if_info *if_i
*** 734,739 ****
--- 744,750 ----
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_try_store_flag (struct noce_if_info
*** 777,782 ****
--- 788,794 ----
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_try_store_flag_constants (struct no
*** 907,912 ****
--- 919,925 ----
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_try_addcc (struct noce_if_info *if_
*** 944,952 ****
{
start_sequence ();
target = emit_conditional_add (if_info->x, code,
! XEXP (cond, 0), XEXP (cond, 1),
VOIDmode,
! if_info->b, XEXP (if_info->a, 1),
GET_MODE (if_info->x),
(code == LTU || code == GEU
|| code == LEU || code == GTU));
--- 957,967 ----
{
start_sequence ();
target = emit_conditional_add (if_info->x, code,
! XEXP (cond, 0),
! XEXP (cond, 1),
VOIDmode,
! if_info->b,
! XEXP (if_info->a, 1),
GET_MODE (if_info->x),
(code == LTU || code == GEU
|| code == LEU || code == GTU));
*************** noce_try_addcc (struct noce_if_info *if_
*** 956,961 ****
--- 971,977 ----
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_try_addcc (struct noce_if_info *if_
*** 994,999 ****
--- 1010,1016 ----
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_try_store_flag_mask (struct noce_if
*** 1037,1043 ****
reversep, -1);
if (target)
target = expand_simple_binop (GET_MODE (if_info->x), AND,
! if_info->x, target, if_info->x, 0,
OPTAB_WIDEN);
if (target)
--- 1054,1061 ----
reversep, -1);
if (target)
target = expand_simple_binop (GET_MODE (if_info->x), AND,
! if_info->x,
! target, if_info->x, 0,
OPTAB_WIDEN);
if (target)
*************** noce_try_store_flag_mask (struct noce_if
*** 1046,1051 ****
--- 1064,1070 ----
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_try_cmove (struct noce_if_info *if_
*** 1143,1148 ****
--- 1162,1168 ----
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_try_cmove_arith (struct noce_if_inf
*** 1260,1266 ****
if (is_mem)
{
tmp = gen_reg_rtx (GET_MODE (b));
! tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, b));
}
else if (! insn_b)
goto end_seq_and_fail;
--- 1280,1288 ----
if (is_mem)
{
tmp = gen_reg_rtx (GET_MODE (b));
! tmp = emit_insn (gen_rtx_SET (VOIDmode,
! tmp,
! b));
}
else if (! insn_b)
goto end_seq_and_fail;
*************** noce_try_cmove_arith (struct noce_if_inf
*** 1305,1310 ****
--- 1327,1333 ----
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_try_minmax (struct noce_if_info *if
*** 1550,1555 ****
--- 1573,1579 ----
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_try_abs (struct noce_if_info *if_in
*** 1667,1672 ****
--- 1691,1697 ----
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_process_if_block (struct ce_if_bloc
*** 1988,1995 ****
if (orig_x != x)
{
start_sequence ();
! noce_emit_move_insn (copy_rtx (orig_x), x);
insn_b = get_insns ();
end_sequence ();
emit_insn_after_setloc (insn_b, test_bb->end, INSN_LOCATOR (insn_a));
--- 2013,2022 ----
if (orig_x != x)
{
start_sequence ();
! 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));
*************** find_cond_trap (basic_block test_bb, edg
*** 2585,2591 ****
}
/* Attempt to generate the conditional trap. */
! seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1),
TRAP_CODE (PATTERN (trap)));
if (seq == NULL)
return FALSE;
--- 2612,2619 ----
}
/* Attempt to generate the conditional trap. */
! seq = gen_cond_trap (code, XEXP (cond, 0),
! XEXP (cond, 1),
TRAP_CODE (PATTERN (trap)));
if (seq == NULL)
return FALSE;
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.437
diff -c -3 -p -r1.437 rtl.h
*** rtl.h 18 Oct 2003 18:45:15 -0000 1.437
--- rtl.h 9 Nov 2003 15:19:39 -0000
*************** extern void delete_insns_since (rtx);
*** 2036,2041 ****
--- 2036,2042 ----
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_insn
*** 2051,2056 ****
--- 2052,2059 ----
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);