Segher Boessenkool <seg...@kernel.crashing.org> writes:
> On Fri, May 29, 2020 at 06:26:55PM +0100, Richard Sandiford wrote:
>> Segher Boessenkool <seg...@kernel.crashing.org> writes:
>> > Most patterns *do* FAIL on some target.  We cannot rewind time.
>> 
>> Sure.  But the point is that FAILing isn't “explicitly allowed” for vcond*.
>> In fact it's the opposite.
>
> It has FAILed on rs6000 since 2004.

But that just means that the powerpc bug has been there since 2004,
assuming these FAILs can actually trigger in practice.  At that time,
the corresponding expand code was:

/* Generate insns for VEC_COND_EXPR.  */

rtx
expand_vec_cond_expr (tree vec_cond_expr, rtx target)
{
  enum insn_code icode;
  rtx comparison, rtx_op1, rtx_op2, cc_op0, cc_op1;
  enum machine_mode mode = TYPE_MODE (TREE_TYPE (vec_cond_expr));
  bool unsignedp = TYPE_UNSIGNED (TREE_TYPE (vec_cond_expr));

  icode = get_vcond_icode (vec_cond_expr, mode);
  if (icode == CODE_FOR_nothing)
    return 0;

  if (!target)
    target = gen_reg_rtx (mode);

  /* Get comparison rtx.  First expand both cond expr operands.  */
  comparison = vector_compare_rtx (TREE_OPERAND (vec_cond_expr, 0), 
                                   unsignedp, icode);
  cc_op0 = XEXP (comparison, 0);
  cc_op1 = XEXP (comparison, 1);
  /* Expand both operands and force them in reg, if required.  */
  rtx_op1 = expand_expr (TREE_OPERAND (vec_cond_expr, 1),
                         NULL_RTX, VOIDmode, 1);
  if (!(*insn_data[icode].operand[1].predicate) (rtx_op1, mode)
      && mode != VOIDmode)
    rtx_op1 = force_reg (mode, rtx_op1);

  rtx_op2 = expand_expr (TREE_OPERAND (vec_cond_expr, 2),
                         NULL_RTX, VOIDmode, 1);
  if (!(*insn_data[icode].operand[2].predicate) (rtx_op2, mode)
      && mode != VOIDmode)
    rtx_op2 = force_reg (mode, rtx_op2);

  /* Emit instruction! */
  emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2, 
                              comparison, cc_op0,  cc_op1));

  return target;
}

i.e. no fallbacks, and no checking whether the expansion even
succeeded.  Since FAIL just causes the generator to return null,
and since emit_insn is a no-op for null insns, the effect for
FAILs was to emit no instructions and return an uninitialised
target register.

The silent use of an uninitialised register was changed in 2011
to an ICE, via the introduction of expand_insn.

>> If we ignore the docs and look at what the status quo actually is --
>> which I agree seems safest for GCC :-) -- then patterns are allowed to
>> FAIL if target-independent code provides an expand-time fallback for
>> the FAILing case.  But that isn't true for vcond either.
>
> That is a bug in the callers then :-)

It was a bug in the powerpc patch you cited that added the FAILs
without changing target-independent code to cope with them.

The fact that we've had no code to handle the FAILs for 15+ years
without apparent problems makes it even more likely that the FAILs
never happen in practice.

If you think the FAILs do trigger in practice, please provide an example.

Richard

Reply via email to