📄 sched.c
字号:
= (char *) oballoc ((maxreg -FIRST_PSEUDO_REGISTER) * sizeof (char)) - FIRST_PSEUDO_REGISTER; bzero (reg_known_equiv_p + FIRST_PSEUDO_REGISTER, (maxreg - FIRST_PSEUDO_REGISTER) * sizeof (char)); /* Fill in the entries with known constant values. */ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) if ((set = single_set (insn)) != 0 && GET_CODE (SET_DEST (set)) == REG && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0 && reg_n_sets[REGNO (SET_DEST (set))] == 1) || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0) && GET_CODE (XEXP (note, 0)) != EXPR_LIST) { int regno = REGNO (SET_DEST (set)); reg_known_value[regno] = XEXP (note, 0); reg_known_equiv_p[regno] = REG_NOTE_KIND (note) == REG_EQUIV; } /* Fill in the remaining entries. */ while (--maxreg >= FIRST_PSEUDO_REGISTER) if (reg_known_value[maxreg] == 0) reg_known_value[maxreg] = regno_reg_rtx[maxreg];}/* Return 1 if X and Y are identical-looking rtx's. We use the data in reg_known_value above to see if two registers with different numbers are, in fact, equivalent. */static intrtx_equal_for_memref_p (x, y) rtx x, y;{ register int i; register int j; register enum rtx_code code; register char *fmt; if (x == 0 && y == 0) return 1; if (x == 0 || y == 0) return 0; x = canon_rtx (x); y = canon_rtx (y); if (x == y) return 1; code = GET_CODE (x); /* Rtx's of different codes cannot be equal. */ if (code != GET_CODE (y)) return 0; /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. (REG:SI x) and (REG:HI x) are NOT equivalent. */ if (GET_MODE (x) != GET_MODE (y)) return 0; /* REG, LABEL_REF, and SYMBOL_REF can be compared nonrecursively. */ if (code == REG) return REGNO (x) == REGNO (y); if (code == LABEL_REF) return XEXP (x, 0) == XEXP (y, 0); if (code == SYMBOL_REF) return XSTR (x, 0) == XSTR (y, 0); /* For commutative operations, the RTX match if the operand match in any order. Also handle the simple binary and unary cases without a loop. */ if (code == EQ || code == NE || GET_RTX_CLASS (code) == 'c') return ((rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0)) && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1))) || (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 1)) && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 0)))); else if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == '2') return (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0)) && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1))); else if (GET_RTX_CLASS (code) == '1') return rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0)); /* Compare the elements. If any pair of corresponding elements fail to match, return 0 for the whole things. */ fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { switch (fmt[i]) { case 'w': if (XWINT (x, i) != XWINT (y, i)) return 0; break; case 'n': case 'i': if (XINT (x, i) != XINT (y, i)) return 0; break; case 'V': case 'E': /* Two vectors must have the same length. */ if (XVECLEN (x, i) != XVECLEN (y, i)) return 0; /* And the corresponding elements must match. */ for (j = 0; j < XVECLEN (x, i); j++) if (rtx_equal_for_memref_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0) return 0; break; case 'e': if (rtx_equal_for_memref_p (XEXP (x, i), XEXP (y, i)) == 0) return 0; break; case 'S': case 's': if (strcmp (XSTR (x, i), XSTR (y, i))) return 0; break; case 'u': /* These are just backpointers, so they don't matter. */ break; case '0': break; /* It is believed that rtx's at this level will never contain anything but integers and other rtx's, except for within LABEL_REFs and SYMBOL_REFs. */ default: abort (); } } return 1;}/* Given an rtx X, find a SYMBOL_REF or LABEL_REF within X and return it, or return 0 if none found. */static rtxfind_symbolic_term (x) rtx x;{ register int i; register enum rtx_code code; register char *fmt; code = GET_CODE (x); if (code == SYMBOL_REF || code == LABEL_REF) return x; if (GET_RTX_CLASS (code) == 'o') return 0; fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { rtx t; if (fmt[i] == 'e') { t = find_symbolic_term (XEXP (x, i)); if (t != 0) return t; } else if (fmt[i] == 'E') break; } return 0;}/* Return nonzero if X and Y (memory addresses) could reference the same location in memory. C is an offset accumulator. When C is nonzero, we are testing aliases between X and Y + C. XSIZE is the size in bytes of the X reference, similarly YSIZE is the size in bytes for Y. If XSIZE or YSIZE is zero, we do not know the amount of memory being referenced (the reference was BLKmode), so make the most pessimistic assumptions. We recognize the following cases of non-conflicting memory: (1) addresses involving the frame pointer cannot conflict with addresses involving static variables. (2) static variables with different addresses cannot conflict. Nice to notice that varying addresses cannot conflict with fp if no local variables had their addresses taken, but that's too hard now. *//* ??? In Fortran, references to a array parameter can never conflict with another array parameter. */static intmemrefs_conflict_p (xsize, x, ysize, y, c) rtx x, y; int xsize, ysize; HOST_WIDE_INT c;{ if (GET_CODE (x) == HIGH) x = XEXP (x, 0); else if (GET_CODE (x) == LO_SUM) x = XEXP (x, 1); else x = canon_rtx (x); if (GET_CODE (y) == HIGH) y = XEXP (y, 0); else if (GET_CODE (y) == LO_SUM) y = XEXP (y, 1); else y = canon_rtx (y); if (rtx_equal_for_memref_p (x, y)) return (xsize == 0 || ysize == 0 || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)); if (y == frame_pointer_rtx || y == hard_frame_pointer_rtx || y == stack_pointer_rtx) { rtx t = y; int tsize = ysize; y = x; ysize = xsize; x = t; xsize = tsize; } if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx || x == stack_pointer_rtx) { rtx y1; if (CONSTANT_P (y)) return 0; if (GET_CODE (y) == PLUS && canon_rtx (XEXP (y, 0)) == x && (y1 = canon_rtx (XEXP (y, 1))) && GET_CODE (y1) == CONST_INT) { c += INTVAL (y1); return (xsize == 0 || ysize == 0 || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)); } if (GET_CODE (y) == PLUS && (y1 = canon_rtx (XEXP (y, 0))) && CONSTANT_P (y1)) return 0; return 1; } if (GET_CODE (x) == PLUS) { /* The fact that X is canonicalized means that this PLUS rtx is canonicalized. */ rtx x0 = XEXP (x, 0); rtx x1 = XEXP (x, 1); if (GET_CODE (y) == PLUS) { /* The fact that Y is canonicalized means that this PLUS rtx is canonicalized. */ rtx y0 = XEXP (y, 0); rtx y1 = XEXP (y, 1); if (rtx_equal_for_memref_p (x1, y1)) return memrefs_conflict_p (xsize, x0, ysize, y0, c); if (rtx_equal_for_memref_p (x0, y0)) return memrefs_conflict_p (xsize, x1, ysize, y1, c); if (GET_CODE (x1) == CONST_INT) if (GET_CODE (y1) == CONST_INT) return memrefs_conflict_p (xsize, x0, ysize, y0, c - INTVAL (x1) + INTVAL (y1)); else return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1)); else if (GET_CODE (y1) == CONST_INT) return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1)); /* Handle case where we cannot understand iteration operators, but we notice that the base addresses are distinct objects. */ x = find_symbolic_term (x); if (x == 0) return 1; y = find_symbolic_term (y); if (y == 0) return 1; return rtx_equal_for_memref_p (x, y); } else if (GET_CODE (x1) == CONST_INT) return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1)); } else if (GET_CODE (y) == PLUS) { /* The fact that Y is canonicalized means that this PLUS rtx is canonicalized. */ rtx y0 = XEXP (y, 0); rtx y1 = XEXP (y, 1); if (GET_CODE (y1) == CONST_INT) return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1)); else return 1; } if (GET_CODE (x) == GET_CODE (y)) switch (GET_CODE (x)) { case MULT: { /* Handle cases where we expect the second operands to be the same, and check only whether the first operand would conflict or not. */ rtx x0, y0; rtx x1 = canon_rtx (XEXP (x, 1)); rtx y1 = canon_rtx (XEXP (y, 1)); if (! rtx_equal_for_memref_p (x1, y1)) return 1; x0 = canon_rtx (XEXP (x, 0)); y0 = canon_rtx (XEXP (y, 0)); if (rtx_equal_for_memref_p (x0, y0)) return (xsize == 0 || ysize == 0 || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)); /* Can't properly adjust our sizes. */ if (GET_CODE (x1) != CONST_INT) return 1; xsize /= INTVAL (x1); ysize /= INTVAL (x1); c /= INTVAL (x1); return memrefs_conflict_p (xsize, x0, ysize, y0, c); } } if (CONSTANT_P (x)) { if (GET_CODE (x) == CONST_INT && GET_CODE (y) == CONST_INT) { c += (INTVAL (y) - INTVAL (x)); return (xsize == 0 || ysize == 0 || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)); } if (GET_CODE (x) == CONST) { if (GET_CODE (y) == CONST) return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)), ysize, canon_rtx (XEXP (y, 0)), c); else return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)), ysize, y, c); } if (GET_CODE (y) == CONST) return memrefs_conflict_p (xsize, x, ysize, canon_rtx (XEXP (y, 0)), c); if (CONSTANT_P (y)) return (rtx_equal_for_memref_p (x, y) && (xsize == 0 || ysize == 0 || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0))); return 1; } return 1;}/* Functions to compute memory dependencies. Since we process the insns in execution order, we can build tables to keep track of what registers are fixed (and not aliased), what registers are varying in known ways, and what registers are varying in unknown ways. If both memory references are volatile, then there must always be a dependence between the two references, since their order can not be changed. A volatile and non-volatile reference can be interchanged though. A MEM_IN_STRUCT reference at a non-QImode varying address can never conflict with a non-MEM_IN_STRUCT reference at a fixed address. We must allow QImode aliasing because the ANSI C standard allows character pointers to alias anything. We are assuming that characters are always QImode here. *//* Read dependence: X is read after read in MEM takes place. There can only be a dependence here if both reads are volatile. */intread_dependence (mem, x) rtx mem; rtx x;{ return MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem);}/* True dependence: X is read after store in MEM takes place. */inttrue_dependence (mem, x) rtx mem; rtx x;{ /* If X is an unchanging read, then it can't possibly conflict with any non-unchanging store. It may conflict with an unchanging write though, because there may be a single store to this address to initialize it. Just fall through to the code below to resolve the case where we have both an unchanging read and an unchanging write. This won't handle all cases optimally, but the possible performance loss should be negligible. */ if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -