mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-11 02:44:30 +08:00
re PR target/1532 (-O3 generates (obviously) redundant tests and jumps)
PR gcc/1532 * cse.c (cse_change_cc_mode): New static function. (cse_change_cc_mode_insns, cse_cc_succs): Likewise. (cse_condition_code_reg): New function. * rtl.h (cse_condition_code_reg): Declare. * toplev.c (rest_of_handle_cse2): Call cse_condition_code_reg. * target.h (struct gcc_target): Add fixed_condition_code_regs and cc_modes_compatible. * target-def.h (TARGET_FIXED_CONDITION_CODE_REGS): Define. (TARGET_CC_MODES_COMPATIBLE): Define. (TARGET_INITIALIZER): Add new initializers. * targhooks.c (default_cc_modes_compatible): New function. * targhooks.c (default_cc_modes_compatible): Declare. * hooks.c (hook_bool_intp_intp_false): New function. * hooks.h (hook_bool_intp_intp_false): Declare. * config/i386/i386.c (TARGET_FIXED_CONDITION_CODE_REGS): Define. (TARGET_CC_MODES_COMPATIBLE): Define. (ix86_fixed_condition_code_regs): New static function. (ix86_cc_modes_compatible): Likewise. * doc/tm.texi (Condition Code): Document new hooks. From-SVN: r76454
This commit is contained in:
parent
f6c930a38a
commit
e129d93a7b
@ -1,3 +1,26 @@
|
||||
2004-01-23 Ian Lance Taylor <ian@wasabisystems.com>
|
||||
|
||||
PR gcc/1532
|
||||
* cse.c (cse_change_cc_mode): New static function.
|
||||
(cse_change_cc_mode_insns, cse_cc_succs): Likewise.
|
||||
(cse_condition_code_reg): New function.
|
||||
* rtl.h (cse_condition_code_reg): Declare.
|
||||
* toplev.c (rest_of_handle_cse2): Call cse_condition_code_reg.
|
||||
* target.h (struct gcc_target): Add fixed_condition_code_regs and
|
||||
cc_modes_compatible.
|
||||
* target-def.h (TARGET_FIXED_CONDITION_CODE_REGS): Define.
|
||||
(TARGET_CC_MODES_COMPATIBLE): Define.
|
||||
(TARGET_INITIALIZER): Add new initializers.
|
||||
* targhooks.c (default_cc_modes_compatible): New function.
|
||||
* targhooks.c (default_cc_modes_compatible): Declare.
|
||||
* hooks.c (hook_bool_intp_intp_false): New function.
|
||||
* hooks.h (hook_bool_intp_intp_false): Declare.
|
||||
* config/i386/i386.c (TARGET_FIXED_CONDITION_CODE_REGS): Define.
|
||||
(TARGET_CC_MODES_COMPATIBLE): Define.
|
||||
(ix86_fixed_condition_code_regs): New static function.
|
||||
(ix86_cc_modes_compatible): Likewise.
|
||||
* doc/tm.texi (Condition Code): Document new hooks.
|
||||
|
||||
2004-01-23 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
|
||||
|
||||
* fixinc/inclhack.def (bad_lval): Renamed to ...
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Subroutines used for code generation on IA-32.
|
||||
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003 Free Software Foundation, Inc.
|
||||
2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -793,6 +793,9 @@ static rtx maybe_get_pool_constant (rtx);
|
||||
static rtx ix86_expand_int_compare (enum rtx_code, rtx, rtx);
|
||||
static enum rtx_code ix86_prepare_fp_compare_args (enum rtx_code, rtx *,
|
||||
rtx *);
|
||||
static bool ix86_fixed_condition_code_regs (unsigned int *, unsigned int *);
|
||||
static enum machine_mode ix86_cc_modes_compatible (enum machine_mode,
|
||||
enum machine_mode);
|
||||
static rtx get_thread_pointer (int);
|
||||
static rtx legitimize_tls_address (rtx, enum tls_model, int);
|
||||
static void get_pc_thunk_name (char [32], unsigned int);
|
||||
@ -1010,6 +1013,11 @@ static void init_ext_80387_constants (void);
|
||||
#undef TARGET_ADDRESS_COST
|
||||
#define TARGET_ADDRESS_COST ix86_address_cost
|
||||
|
||||
#undef TARGET_FIXED_CONDITION_CODE_REGS
|
||||
#define TARGET_FIXED_CONDITION_CODE_REGS ix86_fixed_condition_code_regs
|
||||
#undef TARGET_CC_MODES_COMPATIBLE
|
||||
#define TARGET_CC_MODES_COMPATIBLE ix86_cc_modes_compatible
|
||||
|
||||
#undef TARGET_MACHINE_DEPENDENT_REORG
|
||||
#define TARGET_MACHINE_DEPENDENT_REORG ix86_reorg
|
||||
|
||||
@ -8723,6 +8731,64 @@ ix86_cc_mode (enum rtx_code code, rtx op0, rtx op1)
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the fixed registers used for condition codes. */
|
||||
|
||||
static bool
|
||||
ix86_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
|
||||
{
|
||||
*p1 = FLAGS_REG;
|
||||
*p2 = FPSR_REG;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If two condition code modes are compatible, return a condition code
|
||||
mode which is compatible with both. Otherwise, return
|
||||
VOIDmode. */
|
||||
|
||||
static enum machine_mode
|
||||
ix86_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
|
||||
{
|
||||
if (m1 == m2)
|
||||
return m1;
|
||||
|
||||
if (GET_MODE_CLASS (m1) != MODE_CC || GET_MODE_CLASS (m2) != MODE_CC)
|
||||
return VOIDmode;
|
||||
|
||||
if ((m1 == CCGCmode && m2 == CCGOCmode)
|
||||
|| (m1 == CCGOCmode && m2 == CCGCmode))
|
||||
return CCGCmode;
|
||||
|
||||
switch (m1)
|
||||
{
|
||||
default:
|
||||
abort ();
|
||||
|
||||
case CCmode:
|
||||
case CCGCmode:
|
||||
case CCGOCmode:
|
||||
case CCNOmode:
|
||||
case CCZmode:
|
||||
switch (m2)
|
||||
{
|
||||
default:
|
||||
return VOIDmode;
|
||||
|
||||
case CCmode:
|
||||
case CCGCmode:
|
||||
case CCGOCmode:
|
||||
case CCNOmode:
|
||||
case CCZmode:
|
||||
return CCmode;
|
||||
}
|
||||
|
||||
case CCFPmode:
|
||||
case CCFPUmode:
|
||||
/* These are only compatible with themselves, which we already
|
||||
checked above. */
|
||||
return VOIDmode;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if we should use an FCOMI instruction for this fp comparison. */
|
||||
|
||||
int
|
||||
|
316
gcc/cse.c
316
gcc/cse.c
@ -658,6 +658,9 @@ static void flush_hash_table (void);
|
||||
static bool insn_live_p (rtx, int *);
|
||||
static bool set_live_p (rtx, rtx, int *);
|
||||
static bool dead_libcall_p (rtx, int *);
|
||||
static int cse_change_cc_mode (rtx *, void *);
|
||||
static void cse_change_cc_mode_insns (rtx, rtx, rtx);
|
||||
static enum machine_mode cse_cc_succs (basic_block, rtx, rtx, bool);
|
||||
|
||||
/* Nonzero if X has the form (PLUS frame-pointer integer). We check for
|
||||
virtual regs here because the simplify_*_operation routines are called
|
||||
@ -7665,3 +7668,316 @@ delete_trivially_dead_insns (rtx insns, int nreg)
|
||||
timevar_pop (TV_DELETE_TRIVIALLY_DEAD);
|
||||
return ndead;
|
||||
}
|
||||
|
||||
/* This function is called via for_each_rtx. The argument, NEWREG, is
|
||||
a condition code register with the desired mode. If we are looking
|
||||
at the same register in a different mode, replace it with
|
||||
NEWREG. */
|
||||
|
||||
static int
|
||||
cse_change_cc_mode (rtx *loc, void *data)
|
||||
{
|
||||
rtx newreg = (rtx) data;
|
||||
|
||||
if (*loc
|
||||
&& GET_CODE (*loc) == REG
|
||||
&& REGNO (*loc) == REGNO (newreg)
|
||||
&& GET_MODE (*loc) != GET_MODE (newreg))
|
||||
{
|
||||
*loc = newreg;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Change the mode of any reference to the register REGNO (NEWREG) to
|
||||
GET_MODE (NEWREG), starting at START. Stop before END. Stop at
|
||||
any instruction after START which modifies NEWREG. */
|
||||
|
||||
static void
|
||||
cse_change_cc_mode_insns (rtx start, rtx end, rtx newreg)
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
for (insn = start; insn != end; insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (! INSN_P (insn))
|
||||
continue;
|
||||
|
||||
if (insn != start && reg_set_p (newreg, insn))
|
||||
return;
|
||||
|
||||
for_each_rtx (&PATTERN (insn), cse_change_cc_mode, newreg);
|
||||
for_each_rtx (®_NOTES (insn), cse_change_cc_mode, newreg);
|
||||
}
|
||||
}
|
||||
|
||||
/* BB is a basic block which finishes with CC_REG as a condition code
|
||||
register which is set to CC_SRC. Look through the successors of BB
|
||||
to find blocks which have a single predecessor (i.e., this one),
|
||||
and look through those blocks for an assignment to CC_REG which is
|
||||
equivalent to CC_SRC. CAN_CHANGE_MODE indicates whether we are
|
||||
permitted to change the mode of CC_SRC to a compatible mode. This
|
||||
returns VOIDmode if no equivalent assignments were found.
|
||||
Otherwise it returns the mode which CC_SRC should wind up with.
|
||||
|
||||
The main complexity in this function is handling the mode issues.
|
||||
We may have more than one duplicate which we can eliminate, and we
|
||||
try to find a mode which will work for multiple duplicates. */
|
||||
|
||||
static enum machine_mode
|
||||
cse_cc_succs (basic_block bb, rtx cc_reg, rtx cc_src, bool can_change_mode)
|
||||
{
|
||||
bool found_equiv;
|
||||
enum machine_mode mode;
|
||||
unsigned int insn_count;
|
||||
edge e;
|
||||
rtx insns[2];
|
||||
enum machine_mode modes[2];
|
||||
rtx last_insns[2];
|
||||
unsigned int i;
|
||||
rtx newreg;
|
||||
|
||||
/* We expect to have two successors. Look at both before picking
|
||||
the final mode for the comparison. If we have more successors
|
||||
(i.e., some sort of table jump, although that seems unlikely),
|
||||
then we require all beyond the first two to use the same
|
||||
mode. */
|
||||
|
||||
found_equiv = false;
|
||||
mode = GET_MODE (cc_src);
|
||||
insn_count = 0;
|
||||
for (e = bb->succ; e; e = e->succ_next)
|
||||
{
|
||||
rtx insn;
|
||||
rtx end;
|
||||
|
||||
if (e->flags & EDGE_COMPLEX)
|
||||
continue;
|
||||
|
||||
if (! e->dest->pred
|
||||
|| e->dest->pred->pred_next
|
||||
|| e->dest == EXIT_BLOCK_PTR)
|
||||
continue;
|
||||
|
||||
end = NEXT_INSN (BB_END (e->dest));
|
||||
for (insn = BB_HEAD (e->dest); insn != end; insn = NEXT_INSN (insn))
|
||||
{
|
||||
rtx set;
|
||||
|
||||
if (! INSN_P (insn))
|
||||
continue;
|
||||
|
||||
/* If CC_SRC is modified, we have to stop looking for
|
||||
something which uses it. */
|
||||
if (modified_in_p (cc_src, insn))
|
||||
break;
|
||||
|
||||
/* Check whether INSN sets CC_REG to CC_SRC. */
|
||||
set = single_set (insn);
|
||||
if (set
|
||||
&& GET_CODE (SET_DEST (set)) == REG
|
||||
&& REGNO (SET_DEST (set)) == REGNO (cc_reg))
|
||||
{
|
||||
bool found;
|
||||
enum machine_mode set_mode;
|
||||
enum machine_mode comp_mode;
|
||||
|
||||
found = false;
|
||||
set_mode = GET_MODE (SET_SRC (set));
|
||||
comp_mode = set_mode;
|
||||
if (rtx_equal_p (cc_src, SET_SRC (set)))
|
||||
found = true;
|
||||
else if (GET_CODE (cc_src) == COMPARE
|
||||
&& GET_CODE (SET_SRC (set)) == COMPARE
|
||||
&& GET_MODE (cc_src) != set_mode
|
||||
&& rtx_equal_p (XEXP (cc_src, 0),
|
||||
XEXP (SET_SRC (set), 0))
|
||||
&& rtx_equal_p (XEXP (cc_src, 1),
|
||||
XEXP (SET_SRC (set), 1)))
|
||||
|
||||
{
|
||||
comp_mode = (*targetm.cc_modes_compatible) (mode, set_mode);
|
||||
if (comp_mode != VOIDmode
|
||||
&& (can_change_mode || comp_mode == mode))
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
found_equiv = true;
|
||||
if (insn_count < sizeof insns / sizeof insn[0])
|
||||
{
|
||||
insns[insn_count] = insn;
|
||||
modes[insn_count] = set_mode;
|
||||
last_insns[insn_count] = end;
|
||||
++insn_count;
|
||||
|
||||
/* Sanity check. */
|
||||
if (! can_change_mode && mode != comp_mode)
|
||||
abort ();
|
||||
|
||||
mode = comp_mode;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (set_mode != mode)
|
||||
break;
|
||||
/* INSN sets CC_REG to a value equal to CC_SRC
|
||||
with the right mode. We can simply delete
|
||||
it. */
|
||||
delete_insn (insn);
|
||||
}
|
||||
|
||||
/* We found an instruction to delete. Keep looking,
|
||||
in the hopes of finding a three-way jump. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We found an instruction which sets the condition
|
||||
code, so don't look any farther. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* If INSN sets CC_REG in some other way, don't look any
|
||||
farther. */
|
||||
if (reg_set_p (cc_reg, insn))
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we fell off the bottom of the block, we can keep looking
|
||||
through successors. We pass CAN_CHANGE_MODE as false because
|
||||
we aren't prepared to handle compatibility between the
|
||||
further blocks and this block. */
|
||||
if (insn == end)
|
||||
{
|
||||
if (cse_cc_succs (e->dest, cc_reg, cc_src, false) != VOIDmode)
|
||||
found_equiv = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! found_equiv)
|
||||
return VOIDmode;
|
||||
|
||||
/* Now INSN_COUNT is the number of instructions we found which set
|
||||
CC_REG to a value equivalent to CC_SRC. The instructions are in
|
||||
INSNS. The modes used by those instructions are in MODES. */
|
||||
|
||||
newreg = NULL_RTX;
|
||||
for (i = 0; i < insn_count; ++i)
|
||||
{
|
||||
if (modes[i] != mode)
|
||||
{
|
||||
/* We need to change the mode of CC_REG in INSNS[i] and
|
||||
subsequent instructions. */
|
||||
if (! newreg)
|
||||
{
|
||||
if (GET_MODE (cc_reg) == mode)
|
||||
newreg = cc_reg;
|
||||
else
|
||||
newreg = gen_rtx_REG (mode, REGNO (cc_reg));
|
||||
}
|
||||
cse_change_cc_mode_insns (NEXT_INSN (insns[i]), last_insns[i],
|
||||
newreg);
|
||||
}
|
||||
|
||||
delete_insn (insns[i]);
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
/* If we have a fixed condition code register (or two), walk through
|
||||
the instructions and try to eliminate duplicate assignments. */
|
||||
|
||||
void
|
||||
cse_condition_code_reg (void)
|
||||
{
|
||||
unsigned int cc_regno_1;
|
||||
unsigned int cc_regno_2;
|
||||
rtx cc_reg_1;
|
||||
rtx cc_reg_2;
|
||||
basic_block bb;
|
||||
|
||||
if (! (*targetm.fixed_condition_code_regs) (&cc_regno_1, &cc_regno_2))
|
||||
return;
|
||||
|
||||
cc_reg_1 = gen_rtx_REG (CCmode, cc_regno_1);
|
||||
if (cc_regno_2 != INVALID_REGNUM)
|
||||
cc_reg_2 = gen_rtx_REG (CCmode, cc_regno_2);
|
||||
else
|
||||
cc_reg_2 = NULL_RTX;
|
||||
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
rtx last_insn;
|
||||
rtx cc_reg;
|
||||
rtx insn;
|
||||
rtx cc_src_insn;
|
||||
rtx cc_src;
|
||||
enum machine_mode mode;
|
||||
|
||||
/* Look for blocks which end with a conditional jump based on a
|
||||
condition code register. Then look for the instruction which
|
||||
sets the condition code register. Then look through the
|
||||
successor blocks for instructions which set the condition
|
||||
code register to the same value. There are other possible
|
||||
uses of the condition code register, but these are by far the
|
||||
most common and the ones which we are most likely to be able
|
||||
to optimize. */
|
||||
|
||||
last_insn = BB_END (bb);
|
||||
if (GET_CODE (last_insn) != JUMP_INSN)
|
||||
continue;
|
||||
|
||||
if (reg_referenced_p (cc_reg_1, PATTERN (last_insn)))
|
||||
cc_reg = cc_reg_1;
|
||||
else if (cc_reg_2 && reg_referenced_p (cc_reg_2, PATTERN (last_insn)))
|
||||
cc_reg = cc_reg_2;
|
||||
else
|
||||
continue;
|
||||
|
||||
cc_src_insn = NULL_RTX;
|
||||
cc_src = NULL_RTX;
|
||||
for (insn = PREV_INSN (last_insn);
|
||||
insn && insn != PREV_INSN (BB_HEAD (bb));
|
||||
insn = PREV_INSN (insn))
|
||||
{
|
||||
rtx set;
|
||||
|
||||
if (! INSN_P (insn))
|
||||
continue;
|
||||
set = single_set (insn);
|
||||
if (set
|
||||
&& GET_CODE (SET_DEST (set)) == REG
|
||||
&& REGNO (SET_DEST (set)) == REGNO (cc_reg))
|
||||
{
|
||||
cc_src_insn = insn;
|
||||
cc_src = SET_SRC (set);
|
||||
break;
|
||||
}
|
||||
else if (reg_set_p (cc_reg, insn))
|
||||
break;
|
||||
}
|
||||
|
||||
if (! cc_src_insn)
|
||||
continue;
|
||||
|
||||
if (modified_between_p (cc_src, cc_src_insn, NEXT_INSN (last_insn)))
|
||||
continue;
|
||||
|
||||
/* Now CC_REG is a condition code register used for a
|
||||
conditional jump at the end of the block, and CC_SRC, in
|
||||
CC_SRC_INSN, is the value to which that condition code
|
||||
register is set, and CC_SRC is still meaningful at the end of
|
||||
the basic block. */
|
||||
|
||||
mode = cse_cc_succs (bb, cc_reg, cc_src, true);
|
||||
if (mode != GET_MODE (cc_src) && mode != VOIDmode)
|
||||
{
|
||||
PUT_MODE (cc_src, mode);
|
||||
cse_change_cc_mode_insns (cc_src_insn, NEXT_INSN (last_insn),
|
||||
gen_rtx_REG (mode, REGNO (cc_reg)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5177,6 +5177,34 @@ follows:
|
||||
@end smallexample
|
||||
@end defmac
|
||||
|
||||
@deftypefn {Target Hook} bool TARGET_FIXED_CONDITION_CODE_REGS (unsigned int *, unsigned int *)
|
||||
On targets which do not use @code{(cc0)}, and which use a hard
|
||||
register rather than a pseudo-register to hold condition codes, the
|
||||
regular CSE passes are often not able to identify cases in which the
|
||||
hard register is set to a common value. Use this hook to enable a
|
||||
small pass which optimizes such cases. This hook should return true
|
||||
to enable this pass, and it should set the integers to which its
|
||||
arguments point to the hard register numbers used for condition codes.
|
||||
When there is only one such register, as is true on most systems, the
|
||||
integer pointed to by the second argument should be set to
|
||||
@code{INVALID_REGNUM}.
|
||||
|
||||
The default version of this hook returns false.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} enum machine_mode TARGET_CC_MODES_COMPATIBLE (enum machine_mode, enum machine_mode)
|
||||
On targets which use multiple condition code modes in class
|
||||
@code{MODE_CC}, it is sometimes the case that a comparison can be
|
||||
validly done in more than one mode. On such a system, define this
|
||||
target hook to take two mode arguments and to return a mode in which
|
||||
both comparisons may be validly done. If there is no such mode,
|
||||
return @code{VOIDmode}.
|
||||
|
||||
The default version of this hook checks whether the modes are the
|
||||
same. If they are, it returns that mode. If they are different, it
|
||||
returns @code{VOIDmode}.
|
||||
@end deftypefn
|
||||
|
||||
@node Costs
|
||||
@section Describing Relative Costs of Operations
|
||||
@cindex costs of instructions
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* General-purpose hooks.
|
||||
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@ -176,6 +176,13 @@ hook_bool_rtx_false (rtx a ATTRIBUTE_UNUSED)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
hook_bool_uintp_uintp_false (unsigned int *a ATTRIBUTE_UNUSED,
|
||||
unsigned int *b ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
hook_bool_rtx_int_int_intp_false (rtx a ATTRIBUTE_UNUSED,
|
||||
int b ATTRIBUTE_UNUSED,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* General-purpose hooks.
|
||||
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@ -31,6 +31,7 @@ extern bool hook_bool_tree_hwi_hwi_tree_false (tree, HOST_WIDE_INT, HOST_WIDE_IN
|
||||
extern bool hook_bool_tree_hwi_hwi_tree_true (tree, HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
tree);
|
||||
extern bool hook_bool_rtx_false (rtx);
|
||||
extern bool hook_bool_uintp_uintp_false (unsigned int *, unsigned int *);
|
||||
extern bool hook_bool_rtx_int_int_intp_false (rtx, int, int, int *);
|
||||
extern bool hook_bool_constcharptr_size_t_false (const char *, size_t);
|
||||
|
||||
|
@ -2013,6 +2013,7 @@ extern int cse_main (rtx, int, int, FILE *);
|
||||
#endif
|
||||
extern void cse_end_of_basic_block (rtx, struct cse_basic_block_data *,
|
||||
int, int, int);
|
||||
extern void cse_condition_code_reg (void);
|
||||
|
||||
/* In jump.c */
|
||||
extern int comparison_dominates_p (enum rtx_code, enum rtx_code);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Default initializers for a generic GCC target.
|
||||
Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@ -314,6 +314,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#define TARGET_ENCODE_SECTION_INFO default_encode_section_info
|
||||
#endif
|
||||
|
||||
#define TARGET_FIXED_CONDITION_CODE_REGS hook_bool_uintp_uintp_false
|
||||
|
||||
#define TARGET_CC_MODES_COMPATIBLE default_cc_modes_compatible
|
||||
|
||||
#define TARGET_MACHINE_DEPENDENT_REORG 0
|
||||
|
||||
#define TARGET_BUILD_BUILTIN_VA_LIST std_build_builtin_va_list
|
||||
@ -380,6 +384,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
TARGET_RTX_COSTS, \
|
||||
TARGET_ADDRESS_COST, \
|
||||
TARGET_DWARF_REGISTER_SPAN, \
|
||||
TARGET_FIXED_CONDITION_CODE_REGS, \
|
||||
TARGET_CC_MODES_COMPATIBLE, \
|
||||
TARGET_MACHINE_DEPENDENT_REORG, \
|
||||
TARGET_BUILD_BUILTIN_VA_LIST, \
|
||||
TARGET_GET_PCH_VALIDITY, \
|
||||
|
17
gcc/target.h
17
gcc/target.h
@ -377,6 +377,23 @@ struct gcc_target
|
||||
hook should return NULL_RTX. */
|
||||
rtx (* dwarf_register_span) (rtx);
|
||||
|
||||
/* Fetch the fixed register(s) which hold condition codes, for
|
||||
targets where it makes sense to look for duplicate assignments to
|
||||
the condition codes. This should return true if there is such a
|
||||
register, false otherwise. The arguments should be set to the
|
||||
fixed register numbers. Up to two condition code registers are
|
||||
supported. If there is only one for this target, the int pointed
|
||||
at by the second argument should be set to -1. */
|
||||
bool (* fixed_condition_code_regs) (unsigned int *, unsigned int *);
|
||||
|
||||
/* If two condition code modes are compatible, return a condition
|
||||
code mode which is compatible with both, such that a comparison
|
||||
done in the returned mode will work for both of the original
|
||||
modes. If the condition code modes are not compatible, return
|
||||
VOIDmode. */
|
||||
enum machine_mode (* cc_modes_compatible) (enum machine_mode,
|
||||
enum machine_mode);
|
||||
|
||||
/* Do machine-dependent code transformations. Called just before
|
||||
delayed-branch scheduling. */
|
||||
void (* machine_dependent_reorg) (void);
|
||||
|
@ -70,6 +70,14 @@ default_external_libcall (rtx fun ATTRIBUTE_UNUSED)
|
||||
#endif
|
||||
}
|
||||
|
||||
enum machine_mode
|
||||
default_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
|
||||
{
|
||||
if (m1 == m2)
|
||||
return m1;
|
||||
return VOIDmode;
|
||||
}
|
||||
|
||||
bool
|
||||
default_promote_function_args (tree fntype ATTRIBUTE_UNUSED)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Default target hook functions.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -20,6 +20,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
|
||||
extern void default_external_libcall (rtx);
|
||||
|
||||
extern enum machine_mode default_cc_modes_compatible (enum machine_mode,
|
||||
enum machine_mode);
|
||||
|
||||
extern bool default_promote_function_args (tree);
|
||||
extern bool default_promote_function_return (tree);
|
||||
extern bool default_promote_prototypes (tree);
|
||||
|
@ -2902,6 +2902,13 @@ rest_of_handle_cse2 (tree decl, rtx insns)
|
||||
dump_flow_info (rtl_dump_file);
|
||||
/* CFG is no longer maintained up-to-date. */
|
||||
tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
|
||||
|
||||
/* Run a pass to eliminate duplicated assignments to condition code
|
||||
registers. We have to run this after bypass_jumps, because it
|
||||
makes it harder for that pass to determine whether a jump can be
|
||||
bypassed safely. */
|
||||
cse_condition_code_reg ();
|
||||
|
||||
purge_all_dead_edges (0);
|
||||
delete_trivially_dead_insns (insns, max_reg_num ());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user