From 7fcd72187907e12fa670d7c4794641691b30e825 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Mon, 19 Nov 2001 18:08:48 +0100 Subject: [PATCH] gcse.c (try_replace_reg): Copy RTX before creating note. * gcse.c (try_replace_reg): Copy RTX before creating note. * df.h (df_ref_flags): New uenum. (DF_REF_FLAGS): New macro. (struct ref): Add field "flags". * df.c (HANDLE_SUBREG): Remove. (df_ref_create): Likewise; set flags field of ref. (df_def_record_1): Strip down read_write subreg; remove commented out code; set READ_WRITE flag. (read_modify_subreg_p): New static function. (df_uses_record): Cleanup SET handling; set READ_WRITE flag; new argument "flags". (df_insn_refs_record): Update call of df_uses_record. (df_insn_modify): Avoid #if 0 around comment. (df_dump): Dump the read/write flag. * predict.c (propagate_freq): Make cyclic_probability and frequency volatile * i386.c (ix86_cc_mode): Accept USE. * cfgrtl.c (purge_dead_edges): Cleanup EDGE_ABNORMAL flag if computed jump is turned into simplejump. From-SVN: r47175 --- gcc/ChangeLog | 26 +++++ gcc/cfgrtl.c | 5 + gcc/config/i386/i386.c | 4 + gcc/df.c | 228 +++++++++++++++++++---------------------- gcc/df.h | 6 ++ gcc/gcse.c | 2 +- gcc/predict.c | 11 +- 7 files changed, 152 insertions(+), 130 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7def69a79d69..12f897d29b61 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +Mon Nov 19 18:06:21 CET 2001 Jan Hubicka + + * gcse.c (try_replace_reg): Copy RTX before creating note. + + * df.h (df_ref_flags): New uenum. + (DF_REF_FLAGS): New macro. + (struct ref): Add field "flags". + * df.c (HANDLE_SUBREG): Remove. + (df_ref_create): Likewise; set flags field of ref. + (df_def_record_1): Strip down read_write subreg; remove + commented out code; set READ_WRITE flag. + (read_modify_subreg_p): New static function. + (df_uses_record): Cleanup SET handling; set READ_WRITE flag; + new argument "flags". + (df_insn_refs_record): Update call of df_uses_record. + (df_insn_modify): Avoid #if 0 around comment. + (df_dump): Dump the read/write flag. + + * predict.c (propagate_freq): Make cyclic_probability and frequency + volatile + + * i386.c (ix86_cc_mode): Accept USE. + + * cfgrtl.c (purge_dead_edges): Cleanup EDGE_ABNORMAL flag if computed + jump is turned into simplejump. + 2001-11-19 Joseph S. Myers * doc/fragments.texi, doc/trouble.texi: Remove links to old diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index e6170f0bf236..2687e73d358e 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -1837,6 +1837,11 @@ purge_dead_edges (bb) { next = e->succ_next; + /* Avoid abnormal flags to leak from computed jumps turned + into simplejumps. */ + + e->flags &= EDGE_ABNORMAL; + /* Check purposes we can have edge. */ if ((e->flags & EDGE_FALLTHRU) && any_condjump_p (insn)) diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index caccc7eede23..46ef9f0afb76 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -7099,6 +7099,10 @@ ix86_cc_mode (code, op0, op1) return CCNOmode; else return CCGCmode; + /* strcmp pattern do (use flags) and combine may ask us for proper + mode. */ + case USE: + return CCmode; default: abort (); } diff --git a/gcc/df.c b/gcc/df.c index 9af3518e2fe1..97184c58cf21 100644 --- a/gcc/df.c +++ b/gcc/df.c @@ -227,15 +227,18 @@ static void df_refs_unlink PARAMS ((struct df *, bitmap)); static struct ref *df_ref_create PARAMS((struct df *, rtx, rtx *, basic_block, rtx, - enum df_ref_type)); + enum df_ref_type, enum df_ref_flags)); static void df_ref_record_1 PARAMS((struct df *, rtx, rtx *, - basic_block, rtx, enum df_ref_type)); + basic_block, rtx, enum df_ref_type, + enum df_ref_flags)); static void df_ref_record PARAMS((struct df *, rtx, rtx *, - basic_block bb, rtx, enum df_ref_type)); + basic_block bb, rtx, enum df_ref_type, + enum df_ref_flags)); static void df_def_record_1 PARAMS((struct df *, rtx, basic_block, rtx)); static void df_defs_record PARAMS((struct df *, rtx, basic_block, rtx)); static void df_uses_record PARAMS((struct df *, rtx *, - enum df_ref_type, basic_block, rtx)); + enum df_ref_type, basic_block, rtx, + enum df_ref_flags)); static void df_insn_refs_record PARAMS((struct df *, basic_block, rtx)); static void df_bb_refs_record PARAMS((struct df *, basic_block)); static void df_refs_record PARAMS((struct df *, bitmap)); @@ -298,6 +301,7 @@ static void df_ru_transfer_function PARAMS ((int, int *, bitmap, bitmap, bitmap, bitmap, void *)); static void df_lr_transfer_function PARAMS ((int, int *, bitmap, bitmap, bitmap, bitmap, void *)); +static inline bool read_modify_subreg_p PARAMS ((rtx)); /* Local memory allocation/deallocation routines. */ @@ -780,13 +784,14 @@ df_use_unlink (df, use) /* Create a new ref of type DF_REF_TYPE for register REG at address LOC within INSN of BB. */ static struct ref * -df_ref_create (df, reg, loc, bb, insn, ref_type) +df_ref_create (df, reg, loc, bb, insn, ref_type, ref_flags) struct df *df; rtx reg; rtx *loc; basic_block bb; rtx insn; enum df_ref_type ref_type; + enum df_ref_flags ref_flags; { struct ref *this_ref; unsigned int uid; @@ -799,6 +804,7 @@ df_ref_create (df, reg, loc, bb, insn, ref_type) DF_REF_INSN (this_ref) = insn; DF_REF_CHAIN (this_ref) = 0; DF_REF_TYPE (this_ref) = ref_type; + DF_REF_FLAGS (this_ref) = ref_flags; uid = INSN_UID (insn); if (ref_type == DF_REF_REG_DEF) @@ -832,28 +838,30 @@ df_ref_create (df, reg, loc, bb, insn, ref_type) /* Create a new reference of type DF_REF_TYPE for a single register REG, used inside the LOC rtx of INSN. */ static void -df_ref_record_1 (df, reg, loc, bb, insn, ref_type) +df_ref_record_1 (df, reg, loc, bb, insn, ref_type, ref_flags) struct df *df; rtx reg; rtx *loc; basic_block bb; rtx insn; enum df_ref_type ref_type; + enum df_ref_flags ref_flags; { - df_ref_create (df, reg, loc, bb, insn, ref_type); + df_ref_create (df, reg, loc, bb, insn, ref_type, ref_flags); } /* Create new references of type DF_REF_TYPE for each part of register REG at address LOC within INSN of BB. */ static void -df_ref_record (df, reg, loc, bb, insn, ref_type) +df_ref_record (df, reg, loc, bb, insn, ref_type, ref_flags) struct df *df; rtx reg; rtx *loc; basic_block bb; rtx insn; enum df_ref_type ref_type; + enum df_ref_flags ref_flags; { unsigned int regno; @@ -892,14 +900,30 @@ df_ref_record (df, reg, loc, bb, insn, ref_type) for (i = regno; i < endregno; i++) df_ref_record_1 (df, gen_rtx_REG (reg_raw_mode[i], i), - loc, bb, insn, ref_type); + loc, bb, insn, ref_type, ref_flags); } else { - df_ref_record_1 (df, reg, loc, bb, insn, ref_type); + df_ref_record_1 (df, reg, loc, bb, insn, ref_type, ref_flags); } } +/* Writes to SUBREG of inndermode wider than word and outermode shorter than + word are read-modify-write. */ + +static inline bool +read_modify_subreg_p (x) + rtx x; +{ + if (GET_CODE (x) != SUBREG) + return false; + if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) <= UNITS_PER_WORD) + return false; + if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) + return false; + return true; +} + /* Process all the registers defined in the rtx, X. */ static void df_def_record_1 (df, x, bb, insn) @@ -910,6 +934,7 @@ df_def_record_1 (df, x, bb, insn) { rtx *loc = &SET_DEST (x); rtx dst = *loc; + enum df_ref_flags flags = 0; /* Some targets place small structures in registers for return values of functions. */ @@ -924,38 +949,26 @@ df_def_record_1 (df, x, bb, insn) /* May be, we should flag the use of strict_low_part somehow. Might be handy for the reg allocator. */ -#ifdef HANDLE_SUBREG while (GET_CODE (dst) == STRICT_LOW_PART || GET_CODE (dst) == ZERO_EXTRACT - || GET_CODE (dst) == SIGN_EXTRACT) - { - loc = &XEXP (dst, 0); - dst = *loc; - } - /* For the reg allocator we are interested in exact register references. - This means, we want to know, if only a part of a register is - used/defd. */ -/* - if (GET_CODE (dst) == SUBREG) - { - loc = &XEXP (dst, 0); - dst = *loc; - } */ -#else - - while (GET_CODE (dst) == SUBREG - || GET_CODE (dst) == ZERO_EXTRACT || GET_CODE (dst) == SIGN_EXTRACT - || GET_CODE (dst) == STRICT_LOW_PART) + || read_modify_subreg_p (dst)) { + /* Strict low part allways contains SUBREG, but we don't want to make + it appear outside, as whole register is allways considered. */ + if (GET_CODE (dst) == STRICT_LOW_PART) + { + loc = &XEXP (dst, 0); + dst = *loc; + } loc = &XEXP (dst, 0); dst = *loc; + flags |= DF_REF_READ_WRITE; } -#endif if (GET_CODE (dst) == REG || (GET_CODE (dst) == SUBREG && GET_CODE (SUBREG_REG (dst)) == REG)) - df_ref_record (df, dst, loc, bb, insn, DF_REF_REG_DEF); + df_ref_record (df, dst, loc, bb, insn, DF_REF_REG_DEF, flags); } @@ -991,18 +1004,21 @@ df_defs_record (df, x, bb, insn) /* Process all the registers used in the rtx at address LOC. */ static void -df_uses_record (df, loc, ref_type, bb, insn) +df_uses_record (df, loc, ref_type, bb, insn, flags) struct df *df; rtx *loc; enum df_ref_type ref_type; basic_block bb; rtx insn; + enum df_ref_flags flags; { RTX_CODE code; rtx x; retry: x = *loc; + if (!x) + return; code = GET_CODE (x); switch (code) { @@ -1021,120 +1037,78 @@ df_uses_record (df, loc, ref_type, bb, insn) as being used. */ if (GET_CODE (XEXP (x, 0)) == MEM) df_uses_record (df, &XEXP (XEXP (x, 0), 0), - DF_REF_REG_MEM_STORE, bb, insn); + DF_REF_REG_MEM_STORE, bb, insn, flags); /* If we're clobbering a REG then we have a def so ignore. */ return; case MEM: - df_uses_record (df, &XEXP (x, 0), DF_REF_REG_MEM_LOAD, bb, insn); + df_uses_record (df, &XEXP (x, 0), DF_REF_REG_MEM_LOAD, bb, insn, flags); return; case SUBREG: /* While we're here, optimize this case. */ -#if defined(HANDLE_SUBREG) /* In case the SUBREG is not of a register, don't optimize. */ if (GET_CODE (SUBREG_REG (x)) != REG) { loc = &SUBREG_REG (x); - df_uses_record (df, loc, ref_type, bb, insn); + df_uses_record (df, loc, ref_type, bb, insn, flags); return; } -#else - loc = &SUBREG_REG (x); - x = *loc; - if (GET_CODE (x) != REG) - { - df_uses_record (df, loc, ref_type, bb, insn); - return; - } -#endif /* ... Fall through ... */ case REG: /* See a register (or subreg) other than being set. */ - df_ref_record (df, x, loc, bb, insn, ref_type); + df_ref_record (df, x, loc, bb, insn, ref_type, flags); return; case SET: { rtx dst = SET_DEST (x); - int use_dst = 0; - /* If storing into MEM, don't show it as being used. But do - show the address as being used. */ - if (GET_CODE (dst) == MEM) - { - df_uses_record (df, &XEXP (dst, 0), - DF_REF_REG_MEM_STORE, - bb, insn); - df_uses_record (df, &SET_SRC (x), DF_REF_REG_USE, bb, insn); - return; - } + df_uses_record (df, &SET_SRC (x), DF_REF_REG_USE, bb, insn, 0); -#if 1 && defined(HANDLE_SUBREG) - /* Look for sets that perform a read-modify-write. */ - while (GET_CODE (dst) == STRICT_LOW_PART - || GET_CODE (dst) == ZERO_EXTRACT - || GET_CODE (dst) == SIGN_EXTRACT) + switch (GET_CODE (dst)) { - if (GET_CODE (dst) == STRICT_LOW_PART) - { - dst = XEXP (dst, 0); - if (GET_CODE (dst) != SUBREG) - abort (); - /* A strict_low_part uses the whole reg not only the subreg. */ - df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb, insn); - } - else - { - df_uses_record (df, &XEXP (dst, 0), DF_REF_REG_USE, bb, insn); - dst = XEXP (dst, 0); - } - } - if (GET_CODE (dst) == SUBREG) - { - /* Paradoxical or too small subreg's are read-mod-write. */ - if (GET_MODE_SIZE (GET_MODE (dst)) < GET_MODE_SIZE (word_mode) - || GET_MODE_SIZE (GET_MODE (dst)) - >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (dst)))) - use_dst = 1; - } - /* In the original code also some SUBREG rtx's were considered - read-modify-write (those with - REG_SIZE(SUBREG_REG(dst)) > REG_SIZE(dst) ) - e.g. a (subreg:QI (reg:SI A) 0). I can't see this. The only - reason for a read cycle for reg A would be to somehow preserve - the bits outside of the subreg:QI. But for this a strict_low_part - was necessary anyway, and this we handled already. */ -#else - while (GET_CODE (dst) == STRICT_LOW_PART - || GET_CODE (dst) == ZERO_EXTRACT - || GET_CODE (dst) == SIGN_EXTRACT - || GET_CODE (dst) == SUBREG) - { - /* A SUBREG of a smaller size does not use the old value. */ - if (GET_CODE (dst) != SUBREG - || (REG_SIZE (SUBREG_REG (dst)) > REG_SIZE (dst))) - use_dst = 1; - dst = XEXP (dst, 0); - } -#endif - - if ((GET_CODE (dst) == PARALLEL && GET_MODE (dst) == BLKmode) - || GET_CODE (dst) == REG || GET_CODE (dst) == SUBREG) - { -#if 1 || !defined(HANDLE_SUBREG) - if (use_dst) - df_uses_record (df, &SET_DEST (x), DF_REF_REG_USE, bb, insn); -#endif - df_uses_record (df, &SET_SRC (x), DF_REF_REG_USE, bb, insn); - return; + case SUBREG: + if (read_modify_subreg_p (dst)) + { + df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb, + insn, DF_REF_READ_WRITE); + break; + } + /* ... FALLTHRU ... */ + case REG: + case PC: + break; + case MEM: + df_uses_record (df, &XEXP (dst, 0), + DF_REF_REG_MEM_STORE, + bb, insn, 0); + break; + case STRICT_LOW_PART: + /* A strict_low_part uses the whole reg not only the subreg. */ + dst = XEXP (dst, 0); + if (GET_CODE (dst) != SUBREG) + abort (); + df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb, + insn, DF_REF_READ_WRITE); + break; + case ZERO_EXTRACT: + case SIGN_EXTRACT: + df_uses_record (df, &XEXP (dst, 0), DF_REF_REG_USE, bb, insn, + DF_REF_READ_WRITE); + df_uses_record (df, &XEXP (dst, 1), DF_REF_REG_USE, bb, insn, 0); + df_uses_record (df, &XEXP (dst, 2), DF_REF_REG_USE, bb, insn, 0); + dst = XEXP (dst, 0); + break; + default: + abort (); } + return; } - break; case RETURN: break; @@ -1165,7 +1139,7 @@ df_uses_record (df, loc, ref_type, bb, insn) for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++) df_uses_record (df, &ASM_OPERANDS_INPUT (x, j), - DF_REF_REG_USE, bb, insn); + DF_REF_REG_USE, bb, insn, 0); return; } break; @@ -1178,7 +1152,7 @@ df_uses_record (df, loc, ref_type, bb, insn) case PRE_MODIFY: case POST_MODIFY: /* Catch the def of the register being modified. */ - df_ref_record (df, XEXP (x, 0), &XEXP (x, 0), bb, insn, DF_REF_REG_DEF); + df_ref_record (df, XEXP (x, 0), &XEXP (x, 0), bb, insn, DF_REF_REG_DEF, DF_REF_READ_WRITE); /* ... Fall through to handle uses ... */ @@ -1201,14 +1175,14 @@ df_uses_record (df, loc, ref_type, bb, insn) loc = &XEXP (x, 0); goto retry; } - df_uses_record (df, &XEXP (x, i), ref_type, bb, insn); + df_uses_record (df, &XEXP (x, i), ref_type, bb, insn, flags); } else if (fmt[i] == 'E') { int j; for (j = 0; j < XVECLEN (x, i); j++) df_uses_record (df, &XVECEXP (x, i, j), ref_type, - bb, insn); + bb, insn, flags); } } } @@ -1240,7 +1214,7 @@ df_insn_refs_record (df, bb, insn) case REG_EQUIV: case REG_EQUAL: df_uses_record (df, &XEXP (note, 0), DF_REF_REG_USE, - bb, insn); + bb, insn, 0); default: break; } @@ -1257,12 +1231,12 @@ df_insn_refs_record (df, bb, insn) { if (GET_CODE (XEXP (note, 0)) == USE) df_uses_record (df, &SET_DEST (XEXP (note, 0)), DF_REF_REG_USE, - bb, insn); + bb, insn, 0); } /* The stack ptr is used (honorarily) by a CALL insn. */ x = df_reg_use_gen (STACK_POINTER_REGNUM); - df_uses_record (df, &SET_DEST (x), DF_REF_REG_USE, bb, insn); + df_uses_record (df, &SET_DEST (x), DF_REF_REG_USE, bb, insn, 0); if (df->flags & DF_HARD_REGS) { @@ -1273,14 +1247,14 @@ df_insn_refs_record (df, bb, insn) { x = df_reg_use_gen (i); df_uses_record (df, &SET_DEST (x), - DF_REF_REG_USE, bb, insn); + DF_REF_REG_USE, bb, insn, 0); } } } /* Record the register uses. */ df_uses_record (df, &PATTERN (insn), - DF_REF_REG_USE, bb, insn); + DF_REF_REG_USE, bb, insn, 0); if (GET_CODE (insn) == CALL_INSN) @@ -3339,6 +3313,8 @@ df_dump (df, flags, file) DF_INSN_LUID (df, DF_REF_INSN (df->defs[j])), DF_REF_INSN_UID (df->defs[j]), DF_REF_REGNO (df->defs[j])); + if (df->defs[j]->flags & DF_REF_READ_WRITE) + fprintf (file, "read/write "); df_chain_dump (DF_REF_CHAIN (df->defs[j]), file); fprintf (file, "\n"); } @@ -3379,6 +3355,8 @@ df_dump (df, flags, file) DF_INSN_LUID (df, DF_REF_INSN (df->uses[j])), DF_REF_INSN_UID (df->uses[j]), DF_REF_REGNO (df->uses[j])); + if (df->uses[j]->flags & DF_REF_READ_WRITE) + fprintf (file, "read/write "); df_chain_dump (DF_REF_CHAIN (df->uses[j]), file); fprintf (file, "\n"); } diff --git a/gcc/df.h b/gcc/df.h index 89c62883a0a4..4d9ea0f30f5e 100644 --- a/gcc/df.h +++ b/gcc/df.h @@ -48,6 +48,10 @@ struct df_link struct ref *ref; }; +enum df_ref_flags + { + DF_REF_READ_WRITE = 1 + }; /* Define a register reference structure. */ struct ref @@ -59,6 +63,7 @@ struct ref struct df_link *chain; /* Head of def-use or use-def chain. */ enum df_ref_type type; /* Type of ref. */ int id; /* Ref index. */ + enum df_ref_flags flags; /* Various flags. */ }; @@ -177,6 +182,7 @@ struct df_map #define DF_REF_TYPE(REF) ((REF)->type) #define DF_REF_CHAIN(REF) ((REF)->chain) #define DF_REF_ID(REF) ((REF)->id) +#define DF_REF_FLAGS(REF) ((REF)->flags) /* Macros to determine the reference type. */ diff --git a/gcc/gcse.c b/gcc/gcse.c index 0bd96e02e4e5..a69ed8345710 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -3929,7 +3929,7 @@ try_replace_reg (from, to, insn) /* If we've failed to do replacement, have a single SET, and don't already have a note, add a REG_EQUAL note to not lose information. */ if (!success && note == 0 && set != 0) - note = set_unique_reg_note (insn, REG_EQUAL, src); + note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src)); /* If there is already a NOTE, update the expression in it with our replacement. */ diff --git a/gcc/predict.c b/gcc/predict.c index c5cc0a4a27b3..dacefbe4ab9c 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -602,7 +602,7 @@ expected_value_to_br_prob () typedef struct block_info_def { /* Estimated frequency of execution of basic_block. */ - double frequency; + volatile double frequency; /* To keep queue of basic blocks to process. */ basic_block next; @@ -619,8 +619,11 @@ typedef struct edge_info_def { /* In case edge is an loopback edge, the probability edge will be reached in case header is. Estimated number of iterations of the loop can be - then computed as 1 / (1 - back_edge_prob). */ - double back_edge_prob; + then computed as 1 / (1 - back_edge_prob). + + Volatile is needed to avoid differences in the optimized and unoptimized + builds on machines where FP registers are wider than double. */ + volatile double back_edge_prob; /* True if the edge is an loopback edge in the natural loop. */ int back_edge:1; } *edge_info; @@ -663,7 +666,7 @@ propagate_freq (head) BLOCK_INFO (head)->frequency = 1; for (; bb; bb = nextbb) { - double cyclic_probability = 0, frequency = 0; + volatile double cyclic_probability = 0, frequency = 0; nextbb = BLOCK_INFO (bb)->next; BLOCK_INFO (bb)->next = NULL; -- 2.43.5