> Why are the contents of this if statement wrong for COND_LEN?
> If the "else" value doesn't matter, then the masked form can use
> the "then" value for all elements.  I would have expected the same
> thing to be true of COND_LEN.

Right, that one was overly pessimistic.  Removed.

> But isn't the test whether res_op->code itself is an internal_function?
> In other words, shouldn't it just be:
> 
>       if (internal_fn_p (res_op->code)
>         && internal_fn_len_index (as_internal_fn (res_op->code)) != -1)
>       return true;
> 
> maybe_resimplify_conditional_op should already have converted to an
> internal function where possible, and if combined_fn (res_op->code)
> does any extra conversion on the fly, that conversion won't be reflected
> in res_op.

I went through some of our test cases and believe most of the problems
are due to situations like the following:

In vect-cond-arith-2.c we have (on riscv)
  vect_neg_xi_14.4_23 = -vect_xi_13.3_22;
  vect_res_2.5_24 = .COND_LEN_ADD ({ -1, ... }, vect_res_1.0_17, 
vect_neg_xi_14.4_23, vect_res_1.0_17, _29, 0);

On aarch64 this is a situation that matches the VEC_COND_EXPR
simplification that I disabled with this patch.  We valueized
to _26 = vect_res_1.0_17 - vect_xi_13.3_22 and then create
vect_res_2.5_24 = VEC_COND_EXPR <loop_mask_22, _26, vect_res_1.0_19>;
This is later re-assembled into a COND_SUB.

As we have two masks or COND_LEN we cannot use a VEC_COND_EXPR to
achieve the same thing.  Would it be possible to create a COND_OP
directly instead, though?  I tried the following (not very polished
obviously):

-      new_op.set_op (VEC_COND_EXPR, res_op->type,
-                    res_op->cond.cond, res_op->ops[0],
-                    res_op->cond.else_value);
-      *res_op = new_op;
-      return gimple_resimplify3 (seq, res_op, valueize);
+      if (!res_op->cond.len)
+       {
+         new_op.set_op (VEC_COND_EXPR, res_op->type,
+                        res_op->cond.cond, res_op->ops[0],
+                        res_op->cond.else_value);
+         *res_op = new_op;
+         return gimple_resimplify3 (seq, res_op, valueize);
+       }
+      else if (seq && *seq && is_gimple_assign (*seq))
+       {
+         new_op.code = gimple_assign_rhs_code (*seq);
+         new_op.type = res_op->type;
+         new_op.num_ops = gimple_num_ops (*seq) - 1;
+         new_op.ops[0] = gimple_assign_rhs1 (*seq);
+         if (new_op.num_ops > 1)
+           new_op.ops[1] = gimple_assign_rhs2 (*seq);
+         if (new_op.num_ops > 2)
+           new_op.ops[2] = gimple_assign_rhs2 (*seq);
+
+         new_op.cond = res_op->cond;
+
+         gimple_match_op bla2;
+         if (convert_conditional_op (&new_op, &bla2))
+           {
+             *res_op = bla2;
+             // SEQ should now be dead.
+             return true;
+           }
+       }

This would make the other hunk (check whether it was a LEN
and try to recreate it) redundant I hope.

I don't know enough about valueization, whether it's always
safe to do that and other implications.  On riscv this seems
to work, though and the other backends never go through the LEN
path.  If, however, this is a feasible direction it could also
be done for the non-LEN targets?

Regards
 Robin

Reply via email to