Mercurial > hg > CbC > CbC_gcc
diff gcc/cselib.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/cselib.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/cselib.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* Common subexpression elimination library for GNU compiler. - Copyright (C) 1987-2017 Free Software Foundation, Inc. + Copyright (C) 1987-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -54,7 +54,8 @@ static cselib_val *new_cselib_val (unsigned int, machine_mode, rtx); static void add_mem_for_addr (cselib_val *, cselib_val *, rtx); static cselib_val *cselib_lookup_mem (rtx, int); -static void cselib_invalidate_regno (unsigned int, machine_mode); +static void cselib_invalidate_regno (unsigned int, machine_mode, + const_rtx = NULL); static void cselib_invalidate_mem (rtx); static void cselib_record_set (rtx, cselib_val *, cselib_val *); static void cselib_record_sets (rtx_insn *); @@ -805,14 +806,14 @@ if (memmode == VOIDmode) return x; - *off = GEN_INT (-GET_MODE_SIZE (memmode)); + *off = gen_int_mode (-GET_MODE_SIZE (memmode), GET_MODE (x)); return XEXP (x, 0); case PRE_INC: if (memmode == VOIDmode) return x; - *off = GEN_INT (GET_MODE_SIZE (memmode)); + *off = gen_int_mode (GET_MODE_SIZE (memmode), GET_MODE (x)); return XEXP (x, 0); case PRE_MODIFY: @@ -987,6 +988,11 @@ return 0; break; + case 'p': + if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y))) + return 0; + break; + case 'V': case 'E': /* Two vectors must have the same length. */ @@ -1063,6 +1069,7 @@ cselib_hash_rtx (rtx x, int create, machine_mode memmode) { cselib_val *e; + poly_int64 offset; int i, j; enum rtx_code code; const char *fmt; @@ -1128,6 +1135,15 @@ hash += CONST_WIDE_INT_ELT (x, i); return hash; + case CONST_POLY_INT: + { + inchash::hash h; + h.add_int (hash); + for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i) + h.add_wide_int (CONST_POLY_INT_COEFFS (x)[i]); + return h.end (); + } + case CONST_DOUBLE: /* This is like the general case, except that it only counts the integers representing the constant. */ @@ -1149,11 +1165,11 @@ int units; rtx elt; - units = CONST_VECTOR_NUNITS (x); + units = const_vector_encoded_nelts (x); for (i = 0; i < units; ++i) { - elt = CONST_VECTOR_ELT (x, i); + elt = CONST_VECTOR_ENCODED_ELT (x, i); hash += cselib_hash_rtx (elt, 0, memmode); } @@ -1189,14 +1205,15 @@ case PRE_INC: /* We can't compute these without knowing the MEM mode. */ gcc_assert (memmode != VOIDmode); - i = GET_MODE_SIZE (memmode); + offset = GET_MODE_SIZE (memmode); if (code == PRE_DEC) - i = -i; + offset = -offset; /* Adjust the hash so that (mem:MEMMODE (pre_* (reg))) hashes like (mem:MEMMODE (plus (reg) (const_int I))). */ hash += (unsigned) PLUS - (unsigned)code + cselib_hash_rtx (XEXP (x, 0), create, memmode) - + cselib_hash_rtx (GEN_INT (i), create, memmode); + + cselib_hash_rtx (gen_int_mode (offset, GET_MODE (x)), + create, memmode); return hash ? hash : 1 + (unsigned) PLUS; case PRE_MODIFY: @@ -1269,6 +1286,10 @@ hash += XINT (x, i); break; + case 'p': + hash += constant_lower_bound (SUBREG_BYTE (x)); + break; + case '0': case 't': /* unused */ @@ -1641,6 +1662,7 @@ /* SCRATCH must be shared because they represent distinct values. */ return orig; case CLOBBER: + case CLOBBER_HIGH: if (REG_P (XEXP (orig, 0)) && HARD_REGISTER_NUM_P (REGNO (XEXP (orig, 0)))) return orig; break; @@ -1853,6 +1875,7 @@ struct elt_list *l; rtx copy = x; int i; + poly_int64 offset; switch (code) { @@ -1889,11 +1912,11 @@ case PRE_DEC: case PRE_INC: gcc_assert (memmode != VOIDmode); - i = GET_MODE_SIZE (memmode); + offset = GET_MODE_SIZE (memmode); if (code == PRE_DEC) - i = -i; + offset = -offset; return cselib_subst_to_values (plus_constant (GET_MODE (x), - XEXP (x, 0), i), + XEXP (x, 0), offset), memmode); case PRE_MODIFY: @@ -2142,7 +2165,8 @@ invalidating call clobbered registers across a call. */ static void -cselib_invalidate_regno (unsigned int regno, machine_mode mode) +cselib_invalidate_regno (unsigned int regno, machine_mode mode, + const_rtx setter) { unsigned int endregno; unsigned int i; @@ -2165,6 +2189,9 @@ i = regno - max_value_regs; endregno = end_hard_regno (mode, regno); + + if (setter && GET_CODE (setter) == CLOBBER_HIGH) + gcc_assert (endregno == regno + 1); } else { @@ -2197,6 +2224,19 @@ continue; } + /* Ignore if clobber high and the register isn't clobbered. */ + if (setter && GET_CODE (setter) == CLOBBER_HIGH) + { + gcc_assert (endregno == regno + 1); + const_rtx x = XEXP (setter, 0); + if (!reg_is_clobbered_by_clobber_high (i, GET_MODE (v->val_rtx), + x)) + { + l = &(*l)->next; + continue; + } + } + /* We have an overlap. */ if (*l == REG_VALUES (i)) { @@ -2331,10 +2371,10 @@ *vp = &dummy_val; } -/* Invalidate DEST, which is being assigned to or clobbered. */ +/* Invalidate DEST, which is being assigned to or clobbered by SETTER. */ void -cselib_invalidate_rtx (rtx dest) +cselib_invalidate_rtx (rtx dest, const_rtx setter) { while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == ZERO_EXTRACT @@ -2342,7 +2382,7 @@ dest = XEXP (dest, 0); if (REG_P (dest)) - cselib_invalidate_regno (REGNO (dest), GET_MODE (dest)); + cselib_invalidate_regno (REGNO (dest), GET_MODE (dest), setter); else if (MEM_P (dest)) cselib_invalidate_mem (dest); } @@ -2350,10 +2390,10 @@ /* A wrapper for cselib_invalidate_rtx to be called via note_stores. */ static void -cselib_invalidate_rtx_note_stores (rtx dest, const_rtx ignore ATTRIBUTE_UNUSED, +cselib_invalidate_rtx_note_stores (rtx dest, const_rtx setter, void *data ATTRIBUTE_UNUSED) { - cselib_invalidate_rtx (dest); + cselib_invalidate_rtx (dest, setter); } /* Record the result of a SET instruction. DEST is being set; the source @@ -2481,6 +2521,7 @@ rtx body = PATTERN (insn); rtx cond = 0; int n_sets_before_autoinc; + int n_strict_low_parts = 0; struct cselib_record_autoinc_data data; body = PATTERN (insn); @@ -2535,6 +2576,7 @@ for (i = 0; i < n_sets; i++) { rtx dest = sets[i].dest; + rtx orig = dest; /* A STRICT_LOW_PART can be ignored; we'll record the equivalence for the low part after invalidating any knowledge about larger modes. */ @@ -2560,6 +2602,55 @@ else sets[i].dest_addr_elt = 0; } + + /* Improve handling of STRICT_LOW_PART if the current value is known + to be const0_rtx, then the low bits will be set to dest and higher + bits will remain zero. Used in code like: + + {di:SI=0;clobber flags:CC;} + flags:CCNO=cmp(bx:SI,0) + strict_low_part(di:QI)=flags:CCNO<=0 + + where we can note both that di:QI=flags:CCNO<=0 and + also that because di:SI is known to be 0 and strict_low_part(di:QI) + preserves the upper bits that di:SI=zero_extend(flags:CCNO<=0). */ + scalar_int_mode mode; + if (dest != orig + && cselib_record_sets_hook + && REG_P (dest) + && HARD_REGISTER_P (dest) + && is_a <scalar_int_mode> (GET_MODE (dest), &mode) + && n_sets + n_strict_low_parts < MAX_SETS) + { + opt_scalar_int_mode wider_mode_iter; + FOR_EACH_WIDER_MODE (wider_mode_iter, mode) + { + scalar_int_mode wider_mode = wider_mode_iter.require (); + if (GET_MODE_PRECISION (wider_mode) > BITS_PER_WORD) + break; + + rtx reg = gen_lowpart (wider_mode, dest); + if (!REG_P (reg)) + break; + + cselib_val *v = cselib_lookup (reg, wider_mode, 0, VOIDmode); + if (!v) + continue; + + struct elt_loc_list *l; + for (l = v->locs; l; l = l->next) + if (l->loc == const0_rtx) + break; + + if (!l) + continue; + + sets[n_sets + n_strict_low_parts].dest = reg; + sets[n_sets + n_strict_low_parts].src = dest; + sets[n_sets + n_strict_low_parts++].src_elt = sets[i].src_elt; + break; + } + } } if (cselib_record_sets_hook) @@ -2604,6 +2695,20 @@ || (MEM_P (dest) && cselib_record_memory)) cselib_record_set (dest, sets[i].src_elt, sets[i].dest_addr_elt); } + + /* And deal with STRICT_LOW_PART. */ + for (i = 0; i < n_strict_low_parts; i++) + { + if (! PRESERVED_VALUE_P (sets[n_sets + i].src_elt->val_rtx)) + continue; + machine_mode dest_mode = GET_MODE (sets[n_sets + i].dest); + cselib_val *v + = cselib_lookup (sets[n_sets + i].dest, dest_mode, 1, VOIDmode); + cselib_preserve_value (v); + rtx r = gen_rtx_ZERO_EXTEND (dest_mode, + sets[n_sets + i].src_elt->val_rtx); + cselib_add_permanent_equiv (v, r, insn); + } } /* Return true if INSN in the prologue initializes hard_frame_pointer_rtx. */ @@ -2689,9 +2794,12 @@ if (CALL_P (insn)) { for (x = CALL_INSN_FUNCTION_USAGE (insn); x; x = XEXP (x, 1)) - if (GET_CODE (XEXP (x, 0)) == CLOBBER) - cselib_invalidate_rtx (XEXP (XEXP (x, 0), 0)); - /* Flush evertything on setjmp. */ + { + gcc_assert (GET_CODE (XEXP (x, 0)) != CLOBBER_HIGH); + if (GET_CODE (XEXP (x, 0)) == CLOBBER) + cselib_invalidate_rtx (XEXP (XEXP (x, 0), 0)); + } + /* Flush everything on setjmp. */ if (cselib_preserve_constants && find_reg_note (insn, REG_SETJMP, NULL)) {