Patchwork VEC_COND_EXPR

login
register
mail settings
Submitter Marc Glisse
Date Oct. 11, 2012, 10:48 p.m.
Message ID <alpine.DEB.2.02.1210120026320.23017@stedding.saclay.inria.fr>
Download mbox | patch
Permalink /patch/191015/
State New
Headers show

Comments

Marc Glisse - Oct. 11, 2012, 10:48 p.m.
Hello,

this patch brings VEC_COND_EXPR closer to what the doc now says. The 
non-comparison case and gimplification are dead paths currently, but it 
seems convenient to introduce them now. Note that by using the generic 
ternary gimplification code, it will produce VEC_COND_EXPR with an 
SSA_NAME as first argument ;-)

bootstrap+testsuite ok.

2012-10-12  Marc Glisse  <marc.glisse@inria.fr>

 	* optabs.c (vector_compare_rtx): Change prototype.
 	(expand_vec_cond_expr): Handle VEC_COND_EXPR whose first operand
 	is not a comparison.
 	* gimplify.c (gimplify_expr): Handle VEC_COND_EXPR.
Richard Guenther - Oct. 12, 2012, 8:32 a.m.
On Fri, Oct 12, 2012 at 12:48 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
> Hello,
>
> this patch brings VEC_COND_EXPR closer to what the doc now says. The
> non-comparison case and gimplification are dead paths currently, but it
> seems convenient to introduce them now. Note that by using the generic
> ternary gimplification code, it will produce VEC_COND_EXPR with an SSA_NAME
> as first argument ;-)

Eh, seems we didn't handle VEC_COND_EXPR in gimplification at all ...

> bootstrap+testsuite ok.

Ok.

Thanks,
Richard.

> 2012-10-12  Marc Glisse  <marc.glisse@inria.fr>
>
>         * optabs.c (vector_compare_rtx): Change prototype.
>         (expand_vec_cond_expr): Handle VEC_COND_EXPR whose first operand
>         is not a comparison.
>         * gimplify.c (gimplify_expr): Handle VEC_COND_EXPR.
>
> --
> Marc Glisse
> Index: gimplify.c
> ===================================================================
> --- gimplify.c  (revision 192378)
> +++ gimplify.c  (working copy)
> @@ -7676,20 +7676,21 @@ gimplify_expr (tree *expr_p, gimple_seq
>                                                             xop0);
>             if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
>               TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
>                                                             new_type,
>                                                             xop1);
>             /* Continue classified as tcc_binary.  */
>             goto expr_2;
>           }
>
>         case FMA_EXPR:
> +       case VEC_COND_EXPR:
>         case VEC_PERM_EXPR:
>           /* Classified as tcc_expression.  */
>           goto expr_3;
>
>         case POINTER_PLUS_EXPR:
>           {
>             enum gimplify_status r0, r1;
>             r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
>                                 post_p, is_gimple_val, fb_rvalue);
>             r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
> Index: optabs.c
> ===================================================================
> --- optabs.c    (revision 192378)
> +++ optabs.c    (working copy)
> @@ -6381,34 +6381,28 @@ get_rtx_code (enum tree_code tcode, bool
>      default:
>        gcc_unreachable ();
>      }
>    return code;
>  }
>
>  /* Return comparison rtx for COND. Use UNSIGNEDP to select signed or
>     unsigned operators. Do not generate compare instruction.  */
>
>  static rtx
> -vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
> +vector_compare_rtx (enum tree_code tcode, tree t_op0, tree t_op1,
> +                   bool unsignedp, enum insn_code icode)
>  {
>    struct expand_operand ops[2];
> -  enum rtx_code rcode;
> -  tree t_op0, t_op1;
>    rtx rtx_op0, rtx_op1;
> +  enum rtx_code rcode = get_rtx_code (tcode, unsignedp);
>
> -  /* This is unlikely. While generating VEC_COND_EXPR, auto vectorizer
> -     ensures that condition is a relational operation.  */
> -  gcc_assert (COMPARISON_CLASS_P (cond));
> -
> -  rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
> -  t_op0 = TREE_OPERAND (cond, 0);
> -  t_op1 = TREE_OPERAND (cond, 1);
> +  gcc_assert (TREE_CODE_CLASS (tcode) == tcc_comparison);
>
>    /* Expand operands.  */
>    rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)),
>                          EXPAND_STACK_PARM);
>    rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)),
>                          EXPAND_STACK_PARM);
>
>    create_input_operand (&ops[0], rtx_op0, GET_MODE (rtx_op0));
>    create_input_operand (&ops[1], rtx_op1, GET_MODE (rtx_op1));
>    if (!maybe_legitimize_operands (icode, 4, 2, ops))
> @@ -6677,34 +6671,49 @@ expand_vec_cond_expr_p (tree value_type,
>  rtx
>  expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
>                       rtx target)
>  {
>    struct expand_operand ops[6];
>    enum insn_code icode;
>    rtx comparison, rtx_op1, rtx_op2;
>    enum machine_mode mode = TYPE_MODE (vec_cond_type);
>    enum machine_mode cmp_op_mode;
>    bool unsignedp;
> +  tree op0a, op0b;
> +  enum tree_code tcode;
>
> -  gcc_assert (COMPARISON_CLASS_P (op0));
> +  if (COMPARISON_CLASS_P (op0))
> +    {
> +      op0a = TREE_OPERAND (op0, 0);
> +      op0b = TREE_OPERAND (op0, 1);
> +      tcode = TREE_CODE (op0);
> +    }
> +  else
> +    {
> +      /* Fake op0 < 0.  */
> +      gcc_assert (!TYPE_UNSIGNED (TREE_TYPE (op0)));
> +      op0a = op0;
> +      op0b = build_zero_cst (TREE_TYPE (op0));
> +      tcode = LT_EXPR;
> +    }
> +  unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
> +  cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));
>
> -  unsignedp = TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0)));
> -  cmp_op_mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (op0, 0)));
>
>    gcc_assert (GET_MODE_SIZE (mode) == GET_MODE_SIZE (cmp_op_mode)
>               && GET_MODE_NUNITS (mode) == GET_MODE_NUNITS (cmp_op_mode));
>
>    icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
>    if (icode == CODE_FOR_nothing)
>      return 0;
>
> -  comparison = vector_compare_rtx (op0, unsignedp, icode);
> +  comparison = vector_compare_rtx (tcode, op0a, op0b, unsignedp, icode);
>    rtx_op1 = expand_normal (op1);
>    rtx_op2 = expand_normal (op2);
>
>    create_output_operand (&ops[0], target, mode);
>    create_input_operand (&ops[1], rtx_op1, mode);
>    create_input_operand (&ops[2], rtx_op2, mode);
>    create_fixed_operand (&ops[3], comparison);
>    create_fixed_operand (&ops[4], XEXP (comparison, 0));
>    create_fixed_operand (&ops[5], XEXP (comparison, 1));
>    expand_insn (icode, 6, ops);
>

Patch

Index: gimplify.c

===================================================================
--- gimplify.c	(revision 192378)

+++ gimplify.c	(working copy)

@@ -7676,20 +7676,21 @@  gimplify_expr (tree *expr_p, gimple_seq

 	      						    xop0);
 	    if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
 	      TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
 							    new_type,
 	      						    xop1);
 	    /* Continue classified as tcc_binary.  */
 	    goto expr_2;
 	  }
 
 	case FMA_EXPR:
+	case VEC_COND_EXPR:

 	case VEC_PERM_EXPR:
 	  /* Classified as tcc_expression.  */
 	  goto expr_3;
 
 	case POINTER_PLUS_EXPR:
 	  {
 	    enum gimplify_status r0, r1;
 	    r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
 				post_p, is_gimple_val, fb_rvalue);
 	    r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
Index: optabs.c

===================================================================
--- optabs.c	(revision 192378)

+++ optabs.c	(working copy)

@@ -6381,34 +6381,28 @@  get_rtx_code (enum tree_code tcode, bool

     default:
       gcc_unreachable ();
     }
   return code;
 }
 
 /* Return comparison rtx for COND. Use UNSIGNEDP to select signed or
    unsigned operators. Do not generate compare instruction.  */
 
 static rtx
-vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)

+vector_compare_rtx (enum tree_code tcode, tree t_op0, tree t_op1,

+		    bool unsignedp, enum insn_code icode)

 {
   struct expand_operand ops[2];
-  enum rtx_code rcode;

-  tree t_op0, t_op1;

   rtx rtx_op0, rtx_op1;
+  enum rtx_code rcode = get_rtx_code (tcode, unsignedp);

 
-  /* This is unlikely. While generating VEC_COND_EXPR, auto vectorizer

-     ensures that condition is a relational operation.  */

-  gcc_assert (COMPARISON_CLASS_P (cond));

-

-  rcode = get_rtx_code (TREE_CODE (cond), unsignedp);

-  t_op0 = TREE_OPERAND (cond, 0);

-  t_op1 = TREE_OPERAND (cond, 1);

+  gcc_assert (TREE_CODE_CLASS (tcode) == tcc_comparison);

 
   /* Expand operands.  */
   rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)),
 			 EXPAND_STACK_PARM);
   rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)),
 			 EXPAND_STACK_PARM);
 
   create_input_operand (&ops[0], rtx_op0, GET_MODE (rtx_op0));
   create_input_operand (&ops[1], rtx_op1, GET_MODE (rtx_op1));
   if (!maybe_legitimize_operands (icode, 4, 2, ops))
@@ -6677,34 +6671,49 @@  expand_vec_cond_expr_p (tree value_type,

 rtx
 expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
 		      rtx target)
 {
   struct expand_operand ops[6];
   enum insn_code icode;
   rtx comparison, rtx_op1, rtx_op2;
   enum machine_mode mode = TYPE_MODE (vec_cond_type);
   enum machine_mode cmp_op_mode;
   bool unsignedp;
+  tree op0a, op0b;

+  enum tree_code tcode;

 
-  gcc_assert (COMPARISON_CLASS_P (op0));

+  if (COMPARISON_CLASS_P (op0))

+    {

+      op0a = TREE_OPERAND (op0, 0);

+      op0b = TREE_OPERAND (op0, 1);

+      tcode = TREE_CODE (op0);

+    }

+  else

+    {

+      /* Fake op0 < 0.  */

+      gcc_assert (!TYPE_UNSIGNED (TREE_TYPE (op0)));

+      op0a = op0;

+      op0b = build_zero_cst (TREE_TYPE (op0));

+      tcode = LT_EXPR;

+    }

+  unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));

+  cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));

 
-  unsignedp = TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0)));

-  cmp_op_mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (op0, 0)));

 
   gcc_assert (GET_MODE_SIZE (mode) == GET_MODE_SIZE (cmp_op_mode)
 	      && GET_MODE_NUNITS (mode) == GET_MODE_NUNITS (cmp_op_mode));
 
   icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
   if (icode == CODE_FOR_nothing)
     return 0;
 
-  comparison = vector_compare_rtx (op0, unsignedp, icode);

+  comparison = vector_compare_rtx (tcode, op0a, op0b, unsignedp, icode);

   rtx_op1 = expand_normal (op1);
   rtx_op2 = expand_normal (op2);
 
   create_output_operand (&ops[0], target, mode);
   create_input_operand (&ops[1], rtx_op1, mode);
   create_input_operand (&ops[2], rtx_op2, mode);
   create_fixed_operand (&ops[3], comparison);
   create_fixed_operand (&ops[4], XEXP (comparison, 0));
   create_fixed_operand (&ops[5], XEXP (comparison, 1));
   expand_insn (icode, 6, ops);