This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Proposed fix for 3.1 branch
- From: kenner at vlsi1 dot ultra dot nyu dot edu (Richard Kenner)
- To: mark at codesourcery dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 28 May 02 08:08:50 EDT
- Subject: Proposed fix for 3.1 branch
RTH and I were discussing the bug in compiling ada/make.adb for ia64 and
came up with this as the best solution for 3.1. There is another solution
proposed for 3.2 which I don't fully understand.
Although this is not a regression, we both feel it's safe enough for the
branch and is important since it fixes a code generation problem (the restore
of GP after a call may be scheduled after insns that use it).
Is this OK for the branch?
Tue May 28 08:04:58 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* sched-deps.c (sched_analyze_insn): Move post-barrier handling
before reg_pending_barrier handling and set reg_pending_barrier if
call was in previous basic block.
(sched_analyze): If insn before this basic block is a CALL_INSN,
set in_post_call_group_p and (new) cal_in_previous_bb_p.
(init_deps): Initialize call_in_previous_bb_p.
* sched-int.h (struct deps): New field call_in_previous_bb_p.
*** sched-deps.c 19 Feb 2002 02:53:10 -0000 1.34
--- sched-deps.c 27 May 2002 15:59:20 -0000
*************** sched_analyze_insn (deps, x, insn, loop_
*** 1038,1041 ****
--- 1038,1093 ----
reg_pending_barrier = true;
+ /* If a post-call group is still open, see if it should remain so.
+ This insn must be a simple move of a hard reg to a pseudo or
+ vice-versa.
+
+ We must avoid moving these insns for correctness on
+ SMALL_REGISTER_CLASS machines, and for special registers like
+ PIC_OFFSET_TABLE_REGNUM. For simplicity, extend this to all
+ hard regs for all targets. */
+
+ if (deps->in_post_call_group_p)
+ {
+ rtx tmp, set = single_set (insn);
+ int src_regno, dest_regno;
+
+ if (set == NULL)
+ goto end_call_group;
+
+ tmp = SET_DEST (set);
+ if (GET_CODE (tmp) == SUBREG)
+ tmp = SUBREG_REG (tmp);
+ if (GET_CODE (tmp) == REG)
+ dest_regno = REGNO (tmp);
+ else
+ goto end_call_group;
+
+ tmp = SET_SRC (set);
+ if (GET_CODE (tmp) == SUBREG)
+ tmp = SUBREG_REG (tmp);
+ if (GET_CODE (tmp) == REG)
+ src_regno = REGNO (tmp);
+ else
+ goto end_call_group;
+
+ if (src_regno < FIRST_PSEUDO_REGISTER
+ || dest_regno < FIRST_PSEUDO_REGISTER)
+ {
+ if (! deps->call_in_previous_bb_p)
+ {
+ set_sched_group_p (insn);
+ CANT_MOVE (insn) = 1;
+ }
+ else
+ reg_pending_barrier = true;
+ }
+ else
+ {
+ end_call_group:
+ deps->in_post_call_group_p = false;
+ deps->call_in_previous_bb_p = false;
+ }
+ }
+
/* Add dependencies if a scheduling barrier was found. */
if (reg_pending_barrier)
*************** sched_analyze_insn (deps, x, insn, loop_
*** 1163,1212 ****
CLEAR_REG_SET (reg_pending_clobbers);
CLEAR_REG_SET (reg_pending_sets);
-
- /* If a post-call group is still open, see if it should remain so.
- This insn must be a simple move of a hard reg to a pseudo or
- vice-versa.
-
- We must avoid moving these insns for correctness on
- SMALL_REGISTER_CLASS machines, and for special registers like
- PIC_OFFSET_TABLE_REGNUM. For simplicity, extend this to all
- hard regs for all targets. */
-
- if (deps->in_post_call_group_p)
- {
- rtx tmp, set = single_set (insn);
- int src_regno, dest_regno;
-
- if (set == NULL)
- goto end_call_group;
-
- tmp = SET_DEST (set);
- if (GET_CODE (tmp) == SUBREG)
- tmp = SUBREG_REG (tmp);
- if (GET_CODE (tmp) == REG)
- dest_regno = REGNO (tmp);
- else
- goto end_call_group;
-
- tmp = SET_SRC (set);
- if (GET_CODE (tmp) == SUBREG)
- tmp = SUBREG_REG (tmp);
- if (GET_CODE (tmp) == REG)
- src_regno = REGNO (tmp);
- else
- goto end_call_group;
-
- if (src_regno < FIRST_PSEUDO_REGISTER
- || dest_regno < FIRST_PSEUDO_REGISTER)
- {
- set_sched_group_p (insn);
- CANT_MOVE (insn) = 1;
- }
- else
- {
- end_call_group:
- deps->in_post_call_group_p = false;
- }
- }
}
--- 1215,1218 ----
*************** sched_analyze (deps, head, tail)
*** 1225,1228 ****
--- 1231,1243 ----
cselib_init ();
+ /* If the last real insn is a CALL_INSN, say we are in the post-call
+ group. */
+ if (prev_real_insn (head) != 0
+ && GET_CODE (prev_real_insn (head)) == CALL_INSN)
+ {
+ deps->in_post_call_group_p = true;
+ deps->call_in_previous_bb_p = true;
+ }
+
for (insn = head;; insn = NEXT_INSN (insn))
{
*************** init_deps (deps)
*** 1450,1453 ****
--- 1465,1469 ----
deps->sched_before_next_call = 0;
deps->in_post_call_group_p = false;
+ deps->call_in_previous_bb_p = false;
}
*** sched-int.h 28 Feb 2002 18:29:07 -0000 1.18.2.1
--- sched-int.h 27 May 2002 15:59:20 -0000
*************** struct deps
*** 83,86 ****
--- 83,87 ----
the call. */
bool in_post_call_group_p;
+ bool call_in_previous_bb_p;
/* The maximum register number for the following arrays. Before reload