void add_rtx (const_rtx x, hash &hstate) { enum rtx_code code; machine_mode mode; int i, j; const char *fmt; if (x == NULL_RTX) return; code = GET_CODE (x); hstate.add_object (code); mode = GET_MODE (x); hstate.add_object (mode); switch (code) { case REG: hstate.add_int (REGNO (x)); return; case CONST_INT: hstate.add_object (INTVAL (x)); return; case CONST_WIDE_INT: for (i = 0; i < CONST_WIDE_INT_NUNITS (x); i++) hstate.add_object (CONST_WIDE_INT_ELT (x, i)); return; case CONST_POLY_INT: for (i = 0; i < NUM_POLY_INT_COEFFS; ++i) hstate.add_wide_int (CONST_POLY_INT_COEFFS (x)[i]); break; case SYMBOL_REF: if (XSTR (x, 0)) hstate.add (XSTR (x, 0), strlen (XSTR (x, 0)) + 1); return; case LABEL_REF: case DEBUG_EXPR: case VALUE: case SCRATCH: case CONST_DOUBLE: case CONST_FIXED: case DEBUG_IMPLICIT_PTR: case DEBUG_PARAMETER_REF: return; default: break; } fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) switch (fmt[i]) { case 'w': hstate.add_hwi (XWINT (x, i)); break; case 'n': case 'i': hstate.add_int (XINT (x, i)); break; case 'p': hstate.add_poly_int (SUBREG_BYTE (x)); break; case 'V': case 'E': j = XVECLEN (x, i); hstate.add_int (j); for (j = 0; j < XVECLEN (x, i); j++) inchash::add_rtx (XVECEXP (x, i, j), hstate); break; case 'e': inchash::add_rtx (XEXP (x, i), hstate); break; case 'S': case 's': if (XSTR (x, i)) hstate.add (XSTR (x, 0), strlen (XSTR (x, 0)) + 1); break; default: break; } }
static void add_hashable_expr (const struct hashable_expr *expr, hash &hstate) { switch (expr->kind) { case EXPR_SINGLE: inchash::add_expr (expr->ops.single.rhs, hstate); break; case EXPR_UNARY: hstate.add_object (expr->ops.unary.op); /* Make sure to include signedness in the hash computation. Don't hash the type, that can lead to having nodes which compare equal according to operand_equal_p, but which have different hash codes. */ if (CONVERT_EXPR_CODE_P (expr->ops.unary.op) || expr->ops.unary.op == NON_LVALUE_EXPR) hstate.add_int (TYPE_UNSIGNED (expr->type)); inchash::add_expr (expr->ops.unary.opnd, hstate); break; case EXPR_BINARY: hstate.add_object (expr->ops.binary.op); if (commutative_tree_code (expr->ops.binary.op)) inchash::add_expr_commutative (expr->ops.binary.opnd0, expr->ops.binary.opnd1, hstate); else { inchash::add_expr (expr->ops.binary.opnd0, hstate); inchash::add_expr (expr->ops.binary.opnd1, hstate); } break; case EXPR_TERNARY: hstate.add_object (expr->ops.ternary.op); if (commutative_ternary_tree_code (expr->ops.ternary.op)) inchash::add_expr_commutative (expr->ops.ternary.opnd0, expr->ops.ternary.opnd1, hstate); else { inchash::add_expr (expr->ops.ternary.opnd0, hstate); inchash::add_expr (expr->ops.ternary.opnd1, hstate); } inchash::add_expr (expr->ops.ternary.opnd2, hstate); break; case EXPR_CALL: { size_t i; enum tree_code code = CALL_EXPR; gcall *fn_from; hstate.add_object (code); fn_from = expr->ops.call.fn_from; if (gimple_call_internal_p (fn_from)) hstate.merge_hash ((hashval_t) gimple_call_internal_fn (fn_from)); else inchash::add_expr (gimple_call_fn (fn_from), hstate); for (i = 0; i < expr->ops.call.nargs; i++) inchash::add_expr (expr->ops.call.args[i], hstate); } break; case EXPR_PHI: { size_t i; for (i = 0; i < expr->ops.phi.nargs; i++) inchash::add_expr (expr->ops.phi.args[i], hstate); } break; default: gcc_unreachable (); } }