> Anyways, instead what I do here is normalize all expansions of
> conditional moves to be of the form:
>
> (set op0 (if_then_else (cmp X Y)
> op3
> op0))
>
> and in the instruction patterns I use "register_operand" and
> constraint "0" for operand 4.
>
> This is enough to keep the combiner from recognizing sequences
> like the above.
>
> Committed to trunk.
>
> gcc/
>
> * config/sparc/sparc-protos.h (sparc_expand_conditional_move): Declare.
> * config/sparc/sparc.md (mov<I:mode>cc, mov<F:mode>cc): Call it.
> (*mov<I:mode>_cc_v9): Normalize to expect operand 0 always in operand 4.
> (*mov<I:mode>_cc_reg_sp64): Likewise.
> (*movsf_cc_v9): Likewise.
> (*movsf_cc_reg_sp64): Likewise.
> (*movdf_cc_v9): Likewise.
> (*movdf_cc_reg_sp64): Likewise.
> (*movtf_cc_hq_v9): Likewise.
> (*movtf_cc_reg_hq_sp64): Likewise.
> (*movtf_cc_v9): Likewise.
> (*movtf_cc_reg_sp64): Likewise.
> * config/sparc/sparc.c (sparc_expand_conditional_move): New function.
> (sparc_print_operand): Delete 'c' and 'd' handling, no longer used.
This has reintroduced PR target/49965.
> @@ -11377,4 +11361,58 @@ sparc_secondary_reload (bool in_p, rtx x,
> reg_class_t rclass_i, return NO_REGS;
> }
>
> +bool
> +sparc_expand_conditional_move (enum machine_mode mode, rtx *operands)
> +{
> + enum rtx_code rc = GET_CODE (operands[1]);
> + enum machine_mode cmp_mode;
> + rtx cc_reg, dst, cmp;
> +
> + cmp = operands[1];
> + cmp_mode = GET_MODE (XEXP (cmp, 0));
> + if (cmp_mode == DImode && !TARGET_ARCH64)
> + return false;
> +
> + dst = operands[0];
> +
> + if (! rtx_equal_p (operands[2], dst)
> + && ! rtx_equal_p (operands[3], dst))
> + {
> + if (reg_overlap_mentioned_p (dst, cmp))
> + dst = gen_reg_rtx (mode);
> +
> + emit_move_insn (dst, operands[3]);
> + }
> + else if (operands[2] == dst)
> + {
> + operands[2] = operands[3];
> +
> + if (GET_MODE_CLASS (cmp_mode) == MODE_FLOAT)
> + rc = reverse_condition_maybe_unordered (rc);
> + else
> + rc = reverse_condition (rc);
> + }
> +
> + if (cmp_mode == TFmode && !TARGET_HARD_QUAD)
> + cmp = sparc_emit_float_lib_cmp (XEXP (cmp, 0), XEXP (cmp, 1), rc);
You cannot cache anything from operands[1] as sparc_emit_float_lib_cmp will
modify it, including RC.
> + if (XEXP (cmp, 1) == const0_rtx
> + && GET_CODE (XEXP (cmp, 0)) == REG
> + && cmp_mode == DImode
> + && v9_regcmp_p (rc))
> + cc_reg = XEXP (cmp, 0);
> + else
> + cc_reg = gen_compare_reg_1 (rc, XEXP (cmp, 0), XEXP (cmp, 1));
> +
> + cmp = gen_rtx_fmt_ee (rc, GET_MODE (cc_reg), cc_reg, const0_rtx);
RC is wrong here if we went through sparc_emit_float_lib_cmp above.
--
Eric Botcazou