This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
unshare_all_rtl missed some rtl
- To: gcc-patches at gcc dot gnu dot org
- Subject: unshare_all_rtl missed some rtl
- From: Geoff Keating <geoffk at cygnus dot com>
- Date: Mon, 10 Jan 2000 10:10:30 -0800
The m68k port has a (broken) pattern that looks like this:
(define_insn "divmodsi4"
[(set (match_operand:SI 0 "general_operand" "=d")
(div:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
(set (match_operand:SI 3 "general_operand" "=d")
(mod:SI (match_dup 1) (match_dup 2)))]
"TARGET_68020 && !TARGET_5200"
"*
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
return \"divs%.l %2,%0\";
else
return \"divsl%.l %2,%3:%0\";
}")
and various test-cases were failing because:
- the constraint allows a memory operand, like an incoming argument;
- the rtx for incoming arguments are shared between the DECL_RTL of
the function's arguments as trees and the actual rtl of the
function;
- these rtx are (mem ...) and are therefore _not_ shared inside the
rtl of the function;
- what would happen is that with -O0, in a function like
int dodiv (int a, int b) { return a / b; }
you would get a divmodsi4 expansion with 'a' and 'b' as operands 1
and 2; then these would be unshared; then the first instance of 'a'
and 'b' in the pattern would be substituted by instantiate_decls
(because it is shared with the DECL_RTL of the arguments)
then instantiate_virtual_regs would substitute 'a' everywhere in the
pattern, notice it had been changed, and try to re-recognise it,
which would fail because 'b' had not been substituted for the second
time it was used.
This patch fixes one of the problems by not sharing RTL between
function parameters and RTL of the function. It also does some
tidying up. I have checked it on m68k and it fixes several
test failures. It was suggested by Jim Wilson (about a month ago).
Is it OK to commit?
Of course, this wouldn't have been happening if the m68k port had used
register_operand instead of general_operand. I will soon be
submitting a much more extensive patch to change this. The fix below
is still a good idea because one day someone will write some huge
pattern "yeah, I wanted to expand printf() inline" and will trip over
this.
--
- Geoffrey Keating <geoffk@cygnus.com>
===File ~geoffkc/patches/egcs-manymem-1.patch===============
md5sum: 3c90566426c14d0f 50cc4f33e479b20c 537996
Index: egcs/gcc/ChangeLog
0a
Sat Jan 8 17:15:04 2000 Geoffrey Keating <geoffk@makita.cygnus.com>
* emit-rtl.c (unshare_all_rtl): Unshare virtual parameters too.
Use unshare_all_rtl_1.
(unshare_all_rtl_again): New function.
(unshare_all_rtl_1): New function split out of unshare_all_rtl.
* function.c (purge_addressof_1): Use unshare_all_rtl_again
rather than resetting the 'used' flags ourself.
* toplev.c (rest_of_compilation): Add current_function_decl
to the unshare_all_rtl call.
* tree.h: Prototype unshare_all_rtl.
* rtl.h: Prototype unshare_all_rtl_again here.
.
Changed files:
egcs/gcc/ChangeLog
egcs/gcc/emit-rtl.c
egcs/gcc/function.c
egcs/gcc/integrate.c
egcs/gcc/rtl.h
egcs/gcc/toplev.c
egcs/gcc/tree.h
md5sum: 8053d8596b25820f 46b5fea988ff2b3b 105985
*** /bluey/co/egcs-mainline/egcs/gcc/emit-rtl.c Tue Dec 28 12:21:13 1999
--- egcs/gcc/emit-rtl.c Sat Jan 8 17:19:40 2000
*************** static rtx make_jump_insn_raw PROTO((rt
*** 170,175 ****
--- 170,176 ----
static rtx make_call_insn_raw PROTO((rtx));
static rtx find_line_note PROTO((rtx));
static void mark_sequence_stack PROTO((struct sequence_stack *));
+ static void unshare_all_rtl_1 PROTO((rtx));
/* There are some RTL codes that require special attention; the generation
functions do the raw handling. If you add to this list, modify
*************** free_emit_status (f)
*** 1601,1623 ****
f->emit = NULL;
}
! /* Go through all the RTL insn bodies and copy any invalid shared structure.
! It does not work to do this twice, because the mark bits set here
! are not cleared afterwards. */
void
! unshare_all_rtl (insn)
! register rtx insn;
{
! for (; insn; insn = NEXT_INSN (insn))
! if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
! || GET_CODE (insn) == CALL_INSN)
! {
! PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
! REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn));
! LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn));
! }
/* Make sure the addresses of stack slots found outside the insn chain
(such as, in DECL_RTL of a variable) are not shared
with the insn chain.
--- 1602,1626 ----
f->emit = NULL;
}
! /* Go through all the RTL insn bodies and copy any invalid shared
! structure. This routine should only be called once. */
void
! unshare_all_rtl (fndecl, insn)
! tree fndecl;
! rtx insn;
{
! tree decl;
!
! /* Make sure that virtual parameters are not shared. */
! for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
! {
! copy_rtx_if_shared (DECL_RTL (decl));
! }
+ /* 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
with the insn chain.
*************** unshare_all_rtl (insn)
*** 1625,1632 ****
This special care is necessary when the stack slot MEM does not
actually appear in the insn chain. If it does appear, its address
is unshared from all else at that point. */
-
copy_rtx_if_shared (stack_slot_list);
}
/* Mark ORIG as in use, and return a copy of it if it was already in use.
--- 1628,1669 ----
This special care is necessary when the stack slot MEM does not
actually appear in the insn chain. If it does appear, its address
is unshared from all else at that point. */
copy_rtx_if_shared (stack_slot_list);
+ }
+
+ /* Go through all the RTL insn bodies and copy any invalid shared
+ structure, again. This is a fairly expensive thing to do so it
+ should be done sparingly. */
+
+ void
+ unshare_all_rtl_again (insn)
+ rtx insn;
+ {
+ rtx p;
+ for (p = insn; p; p = NEXT_INSN (p))
+ if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
+ {
+ reset_used_flags (PATTERN (p));
+ reset_used_flags (REG_NOTES (p));
+ reset_used_flags (LOG_LINKS (p));
+ }
+ unshare_all_rtl_1 (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 (insn)
+ rtx insn;
+ {
+ for (; insn; insn = NEXT_INSN (insn))
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
+ REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn));
+ LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn));
+ }
}
/* Mark ORIG as in use, and return a copy of it if it was already in use.
md5sum: 05d7d61afe467419 babe70ada008e89c 216132
*** /bluey/co/egcs-mainline/egcs/gcc/function.c Mon Jan 3 15:34:55 2000
--- egcs/gcc/function.c Sat Jan 8 17:12:21 2000
*************** static boolean
*** 2970,2982 ****
/* Make sure to unshare any shared rtl that store_bit_field
might have created. */
! for (p = get_insns(); p; p = NEXT_INSN (p))
! {
! reset_used_flags (PATTERN (p));
! reset_used_flags (REG_NOTES (p));
! reset_used_flags (LOG_LINKS (p));
! }
! unshare_all_rtl (get_insns ());
seq = gen_sequence ();
end_sequence ();
--- 2970,2976 ----
/* Make sure to unshare any shared rtl that store_bit_field
might have created. */
! unshare_all_rtl_again (get_insns ());
seq = gen_sequence ();
end_sequence ();
md5sum: 80aec68dcf2a4980 80aec68dcf2a4980 86797
md5sum: 282ae4586b820548 b534cd3561b6e8ac 69317
*** /bluey/co/egcs-mainline/egcs/gcc/rtl.h Tue Dec 28 12:21:15 1999
--- egcs/gcc/rtl.h Sat Jan 8 17:12:21 2000
*************** extern void reverse_comparison PROTO (
*** 1444,1450 ****
extern void set_new_first_and_last_insn PROTO ((rtx, rtx));
extern void set_new_first_and_last_label_num PROTO ((int, int));
extern void set_new_last_label_num PROTO ((int));
! extern void unshare_all_rtl PROTO ((rtx));
extern void set_last_insn PROTO ((rtx));
extern void link_cc0_insns PROTO ((rtx));
extern void add_insn PROTO ((rtx));
--- 1444,1450 ----
extern void set_new_first_and_last_insn PROTO ((rtx, rtx));
extern void set_new_first_and_last_label_num PROTO ((int, int));
extern void set_new_last_label_num PROTO ((int));
! extern void unshare_all_rtl_again PROTO ((rtx));
extern void set_last_insn PROTO ((rtx));
extern void link_cc0_insns PROTO ((rtx));
extern void add_insn PROTO ((rtx));
md5sum: c65334929ead051d a87504eef523d8c4 148305
*** /bluey/co/egcs-mainline/egcs/gcc/toplev.c Tue Dec 28 12:21:15 1999
--- egcs/gcc/toplev.c Sat Jan 8 17:12:21 2000
*************** rest_of_compilation (decl)
*** 2948,2954 ****
/* Copy any shared structure that should not be shared. */
! unshare_all_rtl (insns);
init_EXPR_INSN_LIST_cache ();
--- 2948,2954 ----
/* Copy any shared structure that should not be shared. */
! unshare_all_rtl (current_function_decl, insns);
init_EXPR_INSN_LIST_cache ();
md5sum: 3f02da04d06b9e78 d7ce262c4357c793 98748
*** /bluey/co/egcs-mainline/egcs/gcc/tree.h Mon Jan 3 12:11:36 2000
--- egcs/gcc/tree.h Sat Jan 8 17:12:21 2000
*************** extern int aggregate_value_p PROTO ((tr
*** 2379,2384 ****
--- 2379,2385 ----
extern tree reorder_blocks PROTO ((tree,
struct rtx_def *));
extern void free_temps_for_rtl_expr PROTO ((tree));
+ extern void unshare_all_rtl PROTO ((tree, struct rtx_def *));
extern void instantiate_virtual_regs PROTO ((tree, struct rtx_def *));
extern int max_parm_reg_num PROTO ((void));
extern void push_function_context PROTO ((void));
============================================================