+/* If X refers to a register that equals REG in value, replace these
+ references with REG. */
+static rtx
+canon_reg_for_combine (rtx x, rtx reg)
+{
+ rtx op0, op1, op2;
+ const char *fmt;
+ int i;
+ bool copied;
+
+ enum rtx_code code = GET_CODE (x);
+ switch (GET_RTX_CLASS (code))
+ {
+ case RTX_UNARY:
+ op0 = canon_reg_for_combine (XEXP (x, 0), reg);
+ if (op0 != XEXP (x, 0))
+ return simplify_gen_unary (GET_CODE (x), GET_MODE (x), op0,
+ GET_MODE (reg));
+ break;
+
+ case RTX_BIN_ARITH:
+ case RTX_COMM_ARITH:
+ op0 = canon_reg_for_combine (XEXP (x, 0), reg);
+ op1 = canon_reg_for_combine (XEXP (x, 1), reg);
+ if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
+ return simplify_gen_binary (GET_CODE (x), GET_MODE (x), op0, op1);
+ break;
+
+ case RTX_COMPARE:
+ case RTX_COMM_COMPARE:
+ op0 = canon_reg_for_combine (XEXP (x, 0), reg);
+ op1 = canon_reg_for_combine (XEXP (x, 1), reg);
+ if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
+ return simplify_gen_relational (GET_CODE (x), GET_MODE (x),
+ GET_MODE (op0), op0, op1);
+ break;
+
+ case RTX_TERNARY:
+ case RTX_BITFIELD_OPS:
+ op0 = canon_reg_for_combine (XEXP (x, 0), reg);
+ op1 = canon_reg_for_combine (XEXP (x, 1), reg);
+ op2 = canon_reg_for_combine (XEXP (x, 2), reg);
+ if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1) || op2 != XEXP (x, 2))
+ return simplify_gen_ternary (GET_CODE (x), GET_MODE (x),
+ GET_MODE (op0), op0, op1, op2);
+
+ case RTX_OBJ:
+ if (REG_P (x))
+ {
+ if (rtx_equal_p (get_last_value (reg), x)
+ || rtx_equal_p (reg, get_last_value (x)))
+ return reg;
+ else
+ break;
+ }
+
+ /* fall through */
+
+ default:
+ fmt = GET_RTX_FORMAT (code);
+ copied = false;
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ if (fmt[i] == 'e')
+ {
+ rtx op = canon_reg_for_combine (XEXP (x, i), reg);
+ if (op != XEXP (x, i))
+ {
+ if (!copied)
+ {
+ copied = true;
+ x = copy_rtx (x);
+ }
+ XEXP (x, i) = op;
+ }
+ }
+ else if (fmt[i] == 'E')
+ {
+ int j;
+ for (j = 0; j < XVECLEN (x, i); j++)
+ {
+ rtx op = canon_reg_for_combine (XVECEXP (x, i, j), reg);
+ if (op != XVECEXP (x, i, j))
+ {
+ if (!copied)
+ {
+ copied = true;
+ x = copy_rtx (x);
+ }
+ XVECEXP (x, i, j) = op;
+ }
+ }
+ }
+
+ break;
+ }
+
+ return x;
+}
+