mirror of git://gcc.gnu.org/git/gcc.git
re PR rtl-optimization/15921 (gcc.c-torture/compile/920501-4.c fails on powerpc-*)
2004-07-12 Vladimir Makarov <vmakarov@redhat.com> PR rtl-optimization/15921 * Makefile.in (global.o): Add recog.h. * global.c (recog.h): Add the include-clause. (bb_info): New member earlyclobber. (allocate_bb_info, free_bb_info): Initialize/finish the new member. (earlyclobber_regclass, earlyclobber_regclass_length): The new global variables. (check_earlyclobber, regclass_intersect, mark_reg_use_for_earlyclobber, mark_reg_use_for_earlyclobber_1): New functions. (calculate_local_reg_bb_info): Calculate value of earlyclobber. (make_accurate_live_analysis): Modify pavin. From-SVN: r84569
This commit is contained in:
parent
3143d517e4
commit
fdbda73fc7
|
@ -1,3 +1,20 @@
|
||||||
|
2004-07-12 Vladimir Makarov <vmakarov@redhat.com>
|
||||||
|
|
||||||
|
PR rtl-optimization/15921
|
||||||
|
* Makefile.in (global.o): Add recog.h.
|
||||||
|
|
||||||
|
* global.c (recog.h): Add the include-clause.
|
||||||
|
(bb_info): New member earlyclobber.
|
||||||
|
(allocate_bb_info, free_bb_info): Initialize/finish the new
|
||||||
|
member.
|
||||||
|
(earlyclobber_regclass, earlyclobber_regclass_length): The new
|
||||||
|
global variables.
|
||||||
|
(check_earlyclobber, regclass_intersect,
|
||||||
|
mark_reg_use_for_earlyclobber, mark_reg_use_for_earlyclobber_1):
|
||||||
|
New functions.
|
||||||
|
(calculate_local_reg_bb_info): Calculate value of earlyclobber.
|
||||||
|
(make_accurate_live_analysis): Modify pavin.
|
||||||
|
|
||||||
2004-07-12 Diego Novillo <dnovillo@redhat.com>
|
2004-07-12 Diego Novillo <dnovillo@redhat.com>
|
||||||
|
|
||||||
* tree-cfg.c (find_taken_edge): Statically compute the truth
|
* tree-cfg.c (find_taken_edge): Statically compute the truth
|
||||||
|
|
|
@ -2006,9 +2006,9 @@ local-alloc.o : local-alloc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_
|
||||||
bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) $(RTL_H) $(FLAGS_H) \
|
bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) $(RTL_H) $(FLAGS_H) \
|
||||||
$(BASIC_BLOCK_H) $(REGS_H) $(GGC_H)
|
$(BASIC_BLOCK_H) $(REGS_H) $(GGC_H)
|
||||||
$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
|
$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
|
||||||
global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \
|
global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
|
||||||
reload.h function.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h \
|
reload.h function.h $(RECOG_H) $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h\
|
||||||
toplev.h $(TM_P_H)
|
insn-config.h output.h toplev.h $(TM_P_H)
|
||||||
varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) varray.h $(GGC_H) errors.h \
|
varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) varray.h $(GGC_H) errors.h \
|
||||||
$(HASHTAB_H)
|
$(HASHTAB_H)
|
||||||
vec.o : vec.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) coretypes.h vec.h $(GGC_H) errors.h
|
vec.o : vec.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) coretypes.h vec.h $(GGC_H) errors.h
|
||||||
|
|
162
gcc/global.c
162
gcc/global.c
|
@ -34,6 +34,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||||
#include "regs.h"
|
#include "regs.h"
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
#include "insn-config.h"
|
#include "insn-config.h"
|
||||||
|
#include "recog.h"
|
||||||
#include "reload.h"
|
#include "reload.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "toplev.h"
|
#include "toplev.h"
|
||||||
|
@ -309,6 +310,10 @@ static void reg_dies (int, enum machine_mode, struct insn_chain *);
|
||||||
|
|
||||||
static void allocate_bb_info (void);
|
static void allocate_bb_info (void);
|
||||||
static void free_bb_info (void);
|
static void free_bb_info (void);
|
||||||
|
static void check_earlyclobber (rtx);
|
||||||
|
static bool regclass_intersect (enum reg_class, enum reg_class);
|
||||||
|
static void mark_reg_use_for_earlyclobber_1 (rtx *, void *);
|
||||||
|
static int mark_reg_use_for_earlyclobber (rtx *, void *);
|
||||||
static void calculate_local_reg_bb_info (void);
|
static void calculate_local_reg_bb_info (void);
|
||||||
static void set_up_bb_rts_numbers (void);
|
static void set_up_bb_rts_numbers (void);
|
||||||
static int rpost_cmp (const void *, const void *);
|
static int rpost_cmp (const void *, const void *);
|
||||||
|
@ -2000,6 +2005,9 @@ struct bb_info
|
||||||
{
|
{
|
||||||
/* The basic block reverse post-order number. */
|
/* The basic block reverse post-order number. */
|
||||||
int rts_number;
|
int rts_number;
|
||||||
|
/* Registers used uninitialized in an insn in which there is an
|
||||||
|
early clobbered register might get the same hard register. */
|
||||||
|
bitmap earlyclobber;
|
||||||
/* Registers correspondingly killed (clobbered) and defined but not
|
/* Registers correspondingly killed (clobbered) and defined but not
|
||||||
killed afterward in the basic block. */
|
killed afterward in the basic block. */
|
||||||
bitmap killed, avloc;
|
bitmap killed, avloc;
|
||||||
|
@ -2032,6 +2040,7 @@ allocate_bb_info (void)
|
||||||
FOR_EACH_BB (bb)
|
FOR_EACH_BB (bb)
|
||||||
{
|
{
|
||||||
bb_info = bb->aux;
|
bb_info = bb->aux;
|
||||||
|
bb_info->earlyclobber = BITMAP_XMALLOC ();
|
||||||
bb_info->avloc = BITMAP_XMALLOC ();
|
bb_info->avloc = BITMAP_XMALLOC ();
|
||||||
bb_info->killed = BITMAP_XMALLOC ();
|
bb_info->killed = BITMAP_XMALLOC ();
|
||||||
bb_info->pavin = BITMAP_XMALLOC ();
|
bb_info->pavin = BITMAP_XMALLOC ();
|
||||||
|
@ -2057,6 +2066,7 @@ free_bb_info (void)
|
||||||
BITMAP_XFREE (bb_info->pavin);
|
BITMAP_XFREE (bb_info->pavin);
|
||||||
BITMAP_XFREE (bb_info->killed);
|
BITMAP_XFREE (bb_info->killed);
|
||||||
BITMAP_XFREE (bb_info->avloc);
|
BITMAP_XFREE (bb_info->avloc);
|
||||||
|
BITMAP_XFREE (bb_info->earlyclobber);
|
||||||
}
|
}
|
||||||
free_aux_for_blocks ();
|
free_aux_for_blocks ();
|
||||||
}
|
}
|
||||||
|
@ -2086,6 +2096,144 @@ mark_reg_change (rtx reg, rtx setter, void *data)
|
||||||
bitmap_clear_bit (bb_info->avloc, regno);
|
bitmap_clear_bit (bb_info->avloc, regno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Classes of registers which could be early clobbered in the current
|
||||||
|
insn. */
|
||||||
|
|
||||||
|
static varray_type earlyclobber_regclass;
|
||||||
|
|
||||||
|
/* The function stores classes of registers which could be early
|
||||||
|
clobbered in INSN. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_earlyclobber (rtx insn)
|
||||||
|
{
|
||||||
|
int opno;
|
||||||
|
|
||||||
|
extract_insn (insn);
|
||||||
|
|
||||||
|
VARRAY_POP_ALL (earlyclobber_regclass);
|
||||||
|
for (opno = 0; opno < recog_data.n_operands; opno++)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
bool amp_p;
|
||||||
|
int i;
|
||||||
|
enum reg_class class;
|
||||||
|
const char *p = recog_data.constraints[opno];
|
||||||
|
|
||||||
|
class = NO_REGS;
|
||||||
|
amp_p = false;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
c = *p;
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '=': case '+': case '?':
|
||||||
|
case '#': case '!':
|
||||||
|
case '*': case '%':
|
||||||
|
case 'm': case '<': case '>': case 'V': case 'o':
|
||||||
|
case 'E': case 'F': case 'G': case 'H':
|
||||||
|
case 's': case 'i': case 'n':
|
||||||
|
case 'I': case 'J': case 'K': case 'L':
|
||||||
|
case 'M': case 'N': case 'O': case 'P':
|
||||||
|
case 'X':
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
/* These don't say anything we care about. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '&':
|
||||||
|
amp_p = true;
|
||||||
|
break;
|
||||||
|
case '\0':
|
||||||
|
case ',':
|
||||||
|
if (amp_p && class != NO_REGS)
|
||||||
|
{
|
||||||
|
for (i = VARRAY_ACTIVE_SIZE (earlyclobber_regclass) - 1;
|
||||||
|
i >= 0; i--)
|
||||||
|
if (VARRAY_INT (earlyclobber_regclass, i) == (int) class)
|
||||||
|
break;
|
||||||
|
if (i < 0)
|
||||||
|
VARRAY_PUSH_INT (earlyclobber_regclass, (int) class);
|
||||||
|
}
|
||||||
|
|
||||||
|
amp_p = false;
|
||||||
|
class = NO_REGS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
class = GENERAL_REGS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
class = REG_CLASS_FROM_CONSTRAINT (c, p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == '\0')
|
||||||
|
break;
|
||||||
|
p += CONSTRAINT_LEN (c, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The function returns true if register classes C1 and C2 inetrsect. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
regclass_intersect (enum reg_class c1, enum reg_class c2)
|
||||||
|
{
|
||||||
|
HARD_REG_SET rs, zero;
|
||||||
|
|
||||||
|
CLEAR_HARD_REG_SET (zero);
|
||||||
|
COPY_HARD_REG_SET(rs, reg_class_contents [c1]);
|
||||||
|
AND_HARD_REG_SET (rs, reg_class_contents [c2]);
|
||||||
|
GO_IF_HARD_REG_EQUAL (zero, rs, yes);
|
||||||
|
return true;
|
||||||
|
yes:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The function checks that pseudo-register *X has a class
|
||||||
|
intersecting with the class of pseudo-register could be early
|
||||||
|
clobbered in the same insn. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
mark_reg_use_for_earlyclobber (rtx *x, void *data ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
enum reg_class pref_class, alt_class;
|
||||||
|
int i, regno;
|
||||||
|
basic_block bb = data;
|
||||||
|
struct bb_info *bb_info = BB_INFO (bb);
|
||||||
|
|
||||||
|
if (GET_CODE (*x) == REG && REGNO (*x) >= FIRST_PSEUDO_REGISTER)
|
||||||
|
{
|
||||||
|
regno = REGNO (*x);
|
||||||
|
if (bitmap_bit_p (bb_info->killed, regno)
|
||||||
|
|| bitmap_bit_p (bb_info->avloc, regno))
|
||||||
|
return 0;
|
||||||
|
pref_class = reg_preferred_class (regno);
|
||||||
|
alt_class = reg_alternate_class (regno);
|
||||||
|
for (i = VARRAY_ACTIVE_SIZE (earlyclobber_regclass) - 1; i >= 0; i--)
|
||||||
|
if (regclass_intersect (VARRAY_INT (earlyclobber_regclass, i),
|
||||||
|
pref_class)
|
||||||
|
|| (VARRAY_INT (earlyclobber_regclass, i) != NO_REGS
|
||||||
|
&& regclass_intersect (VARRAY_INT (earlyclobber_regclass, i),
|
||||||
|
alt_class)))
|
||||||
|
{
|
||||||
|
bitmap_set_bit (bb_info->earlyclobber, regno);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The function processes all pseudo-registers in *X with the aid of
|
||||||
|
previous function. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
mark_reg_use_for_earlyclobber_1 (rtx *x, void *data)
|
||||||
|
{
|
||||||
|
for_each_rtx (x, mark_reg_use_for_earlyclobber, data);
|
||||||
|
}
|
||||||
|
|
||||||
/* The function calculates local info for each basic block. */
|
/* The function calculates local info for each basic block. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2094,12 +2242,18 @@ calculate_local_reg_bb_info (void)
|
||||||
basic_block bb;
|
basic_block bb;
|
||||||
rtx insn, bound;
|
rtx insn, bound;
|
||||||
|
|
||||||
|
VARRAY_INT_INIT (earlyclobber_regclass, 20,
|
||||||
|
"classes of registers early clobbered in an insn");
|
||||||
FOR_EACH_BB (bb)
|
FOR_EACH_BB (bb)
|
||||||
{
|
{
|
||||||
bound = NEXT_INSN (BB_END (bb));
|
bound = NEXT_INSN (BB_END (bb));
|
||||||
for (insn = BB_HEAD (bb); insn != bound; insn = NEXT_INSN (insn))
|
for (insn = BB_HEAD (bb); insn != bound; insn = NEXT_INSN (insn))
|
||||||
if (INSN_P (insn))
|
if (INSN_P (insn))
|
||||||
note_stores (PATTERN (insn), mark_reg_change, bb);
|
{
|
||||||
|
note_stores (PATTERN (insn), mark_reg_change, bb);
|
||||||
|
check_earlyclobber (insn);
|
||||||
|
note_uses (&PATTERN (insn), mark_reg_use_for_earlyclobber_1, bb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2229,6 +2383,12 @@ make_accurate_live_analysis (void)
|
||||||
{
|
{
|
||||||
bb_info = BB_INFO (bb);
|
bb_info = BB_INFO (bb);
|
||||||
|
|
||||||
|
/* Reload can assign the same hard register to uninitialized
|
||||||
|
pseudo-register and early clobbered pseudo-register in an
|
||||||
|
insn if the pseudo-register is used first time in given BB
|
||||||
|
and not lived at the BB start. To prevent this we don't
|
||||||
|
change life information for such pseudo-registers. */
|
||||||
|
bitmap_a_or_b (bb_info->pavin, bb_info->pavin, bb_info->earlyclobber);
|
||||||
bitmap_a_and_b (bb->global_live_at_start, bb->global_live_at_start,
|
bitmap_a_and_b (bb->global_live_at_start, bb->global_live_at_start,
|
||||||
bb_info->pavin);
|
bb_info->pavin);
|
||||||
bitmap_a_and_b (bb->global_live_at_end, bb->global_live_at_end,
|
bitmap_a_and_b (bb->global_live_at_end, bb->global_live_at_end,
|
||||||
|
|
Loading…
Reference in New Issue