This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Update for cprop patch
- To: Bernd Schmidt <bernds at cygnus dot co dot uk>
- Subject: Re: Update for cprop patch
- From: Jeffrey A Law <law at cygnus dot com>
- Date: Tue, 24 Aug 1999 21:31:32 -0600
- cc: egcs-patches at egcs dot cygnus dot com
- Reply-To: law at cygnus dot com
In message <Pine.LNX.4.10.9907161109590.17496-100000@biriani.cygnus.co.uk>you
write:
> Here's a new version of the patch. Changes since the last one:
> - try to avoid entering obvious no-ops into the hash table
I installed this a while ago.
> - move the second oprs_not_set_p call into find_avail_set. This function
> now guarantees that the rtx it returns can safely be substituted.
I'm going to look at this shortly.
> * gcse.c
> (find_avail_set): Follow chains of register-register copies.
> Use oprs_not_set_p to guarantee that the returned value can be
> substituted.
> (cprop_jump): New function, broken out of cprop_insn.
> (cprop_cc0_jump): New function.
> (cprop_insn):
> Break out new function cprop_jump and use it.
> Also use cprop_cc0_jump for machines with CC0.
> Don't verify the return value of find_avail_set with oprs_not_set_p.
> (cprop): Don't crash if cprop_insn turned the insn into a NOTE.
I installed the code which deals with cprop into conditional jumps on cc0
machines. Attached is a copy of the patch that was installed.
* gcse.c (cprop_jump): New function, broken out of cprop_insn.
(cprop_cc0_jump): New function.
(cprop_insn): Break out new function cprop_jump and use it.
Also use cprop_cc0_jump for machines with CC0.
(cprop): Don't crash if cprop_insn turned the insn into a NOTE.
Index: gcse.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/gcse.c,v
retrieving revision 1.42
diff -c -3 -p -r1.42 gcse.c
*** gcse.c 1999/08/20 23:05:08 1.42
--- gcse.c 1999/08/25 03:29:56
*************** static char can_copy_p[(int) NUM_MACHINE
*** 310,315 ****
--- 310,319 ----
/* Non-zero if can_copy_p has been initialized. */
static int can_copy_init_p;
+ struct reg_use {
+ rtx reg_rtx;
+ };
+
/* Hash table of expressions. */
struct expr
*************** static void compute_cprop_data PROTO ((v
*** 572,577 ****
--- 576,583 ----
static void find_used_regs PROTO ((rtx));
static int try_replace_reg PROTO ((rtx, rtx, rtx));
static struct expr *find_avail_set PROTO ((int, rtx));
+ static int cprop_jump PROTO((rtx, rtx, struct reg_use *, rtx));
+ static int cprop_cc0_jump PROTO((rtx, struct reg_use *, rtx));
static int cprop_insn PROTO ((rtx, int));
static int cprop PROTO ((int));
static int one_cprop_pass PROTO ((int, int));
*************** compute_cprop_data ()
*** 3532,3541 ****
/* Copy/constant propagation. */
- struct reg_use {
- rtx reg_rtx;
- };
-
/* Maximum number of register uses in an insn that we handle. */
#define MAX_USES 8
--- 3538,3543 ----
*************** find_avail_set (regno, insn)
*** 3666,3671 ****
--- 3668,3781 ----
return set;
}
+ /* Subroutine of cprop_insn that tries to propagate constants into
+ JUMP_INSNS. INSN must be a conditional jump; COPY is a copy of it
+ that we can use for substitutions.
+ REG_USED is the use we will try to replace, SRC is the constant we
+ will try to substitute for it.
+ Returns nonzero if a change was made. */
+ static int
+ cprop_jump (insn, copy, reg_used, src)
+ rtx insn, copy;
+ struct reg_use *reg_used;
+ rtx src;
+ {
+ rtx set = PATTERN (copy);
+ rtx temp;
+
+ /* Replace the register with the appropriate constant. */
+ replace_rtx (SET_SRC (set), reg_used->reg_rtx, src);
+
+ temp = simplify_ternary_operation (GET_CODE (SET_SRC (set)),
+ GET_MODE (SET_SRC (set)),
+ GET_MODE (XEXP (SET_SRC (set), 0)),
+ XEXP (SET_SRC (set), 0),
+ XEXP (SET_SRC (set), 1),
+ XEXP (SET_SRC (set), 2));
+
+ /* If no simplification can be made, then try the next
+ register. */
+ if (temp == 0)
+ return 0;
+
+ SET_SRC (set) = temp;
+
+ /* That may have changed the structure of TEMP, so
+ force it to be rerecognized if it has not turned
+ into a nop or unconditional jump. */
+
+ INSN_CODE (copy) = -1;
+ if ((SET_DEST (set) == pc_rtx
+ && (SET_SRC (set) == pc_rtx
+ || GET_CODE (SET_SRC (set)) == LABEL_REF))
+ || recog (PATTERN (copy), copy, NULL) >= 0)
+ {
+ /* This has either become an unconditional jump
+ or a nop-jump. We'd like to delete nop jumps
+ here, but doing so confuses gcse. So we just
+ make the replacement and let later passes
+ sort things out. */
+ PATTERN (insn) = set;
+ INSN_CODE (insn) = -1;
+
+ /* One less use of the label this insn used to jump to
+ if we turned this into a NOP jump. */
+ if (SET_SRC (set) == pc_rtx && JUMP_LABEL (insn) != 0)
+ --LABEL_NUSES (JUMP_LABEL (insn));
+
+ /* If this has turned into an unconditional jump,
+ then put a barrier after it so that the unreachable
+ code will be deleted. */
+ if (GET_CODE (SET_SRC (set)) == LABEL_REF)
+ emit_barrier_after (insn);
+
+ run_jump_opt_after_gcse = 1;
+
+ const_prop_count++;
+ if (gcse_file != NULL)
+ {
+ int regno = REGNO (reg_used->reg_rtx);
+ fprintf (gcse_file, "CONST-PROP: Replacing reg %d in insn %d with constant ",
+ regno, INSN_UID (insn));
+ print_rtl (gcse_file, src);
+ fprintf (gcse_file, "\n");
+ }
+ return 1;
+ }
+ return 0;
+ }
+
+ #ifdef HAVE_cc0
+ /* Subroutine of cprop_insn that tries to propagate constants into
+ JUMP_INSNS for machines that have CC0. INSN is a single set that
+ stores into CC0; the insn following it is a conditional jump.
+ REG_USED is the use we will try to replace, SRC is the constant we
+ will try to substitute for it.
+ Returns nonzero if a change was made. */
+ static int
+ cprop_cc0_jump (insn, reg_used, src)
+ rtx insn;
+ struct reg_use *reg_used;
+ rtx src;
+ {
+ rtx jump = NEXT_INSN (insn);
+ rtx copy = copy_rtx (jump);
+ rtx set = PATTERN (copy);
+
+ /* We need to copy the source of the cc0 setter, as cprop_jump is going to
+ substitute into it. */
+ replace_rtx (SET_SRC (set), cc0_rtx, copy_rtx (SET_SRC (PATTERN (insn))));
+ if (! cprop_jump (jump, copy, reg_used, src))
+ return 0;
+
+ /* If we succeeded, delete the cc0 setter. */
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ return 1;
+ }
+ #endif
+
/* Perform constant and copy propagation on INSN.
The result is non-zero if a change was made. */
*************** cprop_insn (insn, alter_jumps)
*** 3743,3822 ****
code, we can extend this as necessary over time.
Right now the insn in question must look like
!
! (set (pc) (if_then_else ...))
!
! Note this does not currently handle machines which use cc0. */
else if (alter_jumps
&& GET_CODE (insn) == JUMP_INSN
&& condjump_p (insn)
&& ! simplejump_p (insn))
! {
! /* We want a copy of the JUMP_INSN so we can modify it
! in-place as needed without effecting the original. */
! rtx copy = copy_rtx (insn);
! rtx set = PATTERN (copy);
! rtx temp;
!
! /* Replace the register with the appropriate constant. */
! replace_rtx (SET_SRC (set), reg_used->reg_rtx, src);
!
! temp = simplify_ternary_operation (GET_CODE (SET_SRC (set)),
! GET_MODE (SET_SRC (set)),
! GET_MODE (XEXP (SET_SRC (set), 0)),
! XEXP (SET_SRC (set), 0),
! XEXP (SET_SRC (set), 1),
! XEXP (SET_SRC (set), 2));
!
! /* If no simplification can be made, then try the next
! register. */
! if (temp)
! SET_SRC (set) = temp;
! else
! continue;
!
! /* That may have changed the structure of TEMP, so
! force it to be rerecognized if it has not turned
! into a nop or unconditional jump. */
!
! INSN_CODE (copy) = -1;
! if ((SET_DEST (set) == pc_rtx
! && (SET_SRC (set) == pc_rtx
! || GET_CODE (SET_SRC (set)) == LABEL_REF))
! || recog (PATTERN (copy), copy, NULL) >= 0)
! {
! /* This has either become an unconditional jump
! or a nop-jump. We'd like to delete nop jumps
! here, but doing so confuses gcse. So we just
! make the replacement and let later passes
! sort things out. */
! PATTERN (insn) = set;
! INSN_CODE (insn) = -1;
!
! /* One less use of the label this insn used to jump to
! if we turned this into a NOP jump. */
! if (SET_SRC (set) == pc_rtx && JUMP_LABEL (insn) != 0)
! --LABEL_NUSES (JUMP_LABEL (insn));
!
! /* If this has turned into an unconditional jump,
! then put a barrier after it so that the unreachable
! code will be deleted. */
! if (GET_CODE (SET_SRC (set)) == LABEL_REF)
! emit_barrier_after (insn);
!
! run_jump_opt_after_gcse = 1;
!
! changed = 1;
! const_prop_count++;
! if (gcse_file != NULL)
! {
! fprintf (gcse_file, "CONST-PROP: Replacing reg %d in insn %d with constant ",
! regno, INSN_UID (insn));
! print_rtl (gcse_file, src);
! fprintf (gcse_file, "\n");
! }
! }
! }
}
else if (GET_CODE (src) == REG
&& REGNO (src) >= FIRST_PSEUDO_REGISTER
--- 3853,3875 ----
code, we can extend this as necessary over time.
Right now the insn in question must look like
! (set (pc) (if_then_else ...)) */
else if (alter_jumps
&& GET_CODE (insn) == JUMP_INSN
&& condjump_p (insn)
&& ! simplejump_p (insn))
! changed |= cprop_jump (insn, copy_rtx (insn), reg_used, src);
! #ifdef HAVE_cc0
! /* Similar code for machines that use a pair of CC0 setter and
! conditional jump insn. */
! else if (alter_jumps
! && GET_CODE (PATTERN (insn)) == SET
! && SET_DEST (PATTERN (insn)) == cc0_rtx
! && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
! && condjump_p (NEXT_INSN (insn))
! && ! simplejump_p (NEXT_INSN (insn)))
! changed |= cprop_cc0_jump (insn, reg_used, src);
! #endif
}
else if (GET_CODE (src) == REG
&& REGNO (src) >= FIRST_PSEUDO_REGISTER
*************** cprop (alter_jumps)
*** 3879,3886 ****
changed |= cprop_insn (insn, alter_jumps);
/* Keep track of everything modified by this insn. */
! /* ??? Need to be careful w.r.t. mods done to INSN. */
! mark_oprs_set (insn);
}
}
}
--- 3932,3941 ----
changed |= cprop_insn (insn, alter_jumps);
/* Keep track of everything modified by this insn. */
! /* ??? Need to be careful w.r.t. mods done to INSN. Don't
! call mark_oprs_set if we turned the insn into a NOTE. */
! if (GET_CODE (insn) != NOTE)
! mark_oprs_set (insn);
}
}
}