public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Change vcond<mode> to vcond<mode1><mode2>
@ 2011-08-29 15:08 Richard Guenther
  2011-08-29 16:36 ` Richard Guenther
  2011-08-29 20:47 ` Uros Bizjak
  0 siblings, 2 replies; 16+ messages in thread
From: Richard Guenther @ 2011-08-29 15:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: uros, rth, artyom.shinkaroff


This patch makes a conversion optab from the direct optabs vcond
and vcondu.  This allows to specify different modes for the
actual comparison and the value that is selected.

All targets but i386 are trivially converted by 
s/vcond<mode>/vcond<mode><mode>/.  The i386 port is enhanced
to support a OP b ? c : d as ({ mask = a OP b; (c & mask) | (d & ~mask); 
}), constraining it to what the middle-end constrained itself to
(matching number of vector elements in the comparison operands with
the result vector types) would explode patterns too much.
Thus, only a subset of mode combinations will be excercised
(but none at the moment - a followup will fix the vectorizer,
and generic vectors from the C extensions have a patch pending).

Bootstrapped on x86_64-unknown-linux-gnu, tests are currently
running for {,-m32}.

Ok if that succeeds?

Thanks,
Richard.

2011-08-29  Richard Guenther  <rguenther@suse.de>

	* genopinit.c (optabs): Turn vcond{,u}_optab into a conversion
	optab with two modes.
	* optabs.h (enum convert_optab_index): Add COI_vcond, COI_vcondu.
	(enum direct_optab_index): Remove DOI_vcond, DOI_vcondu.
	(vcond_optab): Adjust.
	(vcondu_optab): Likewise.
	(expand_vec_cond_expr_p): Adjust prototype.
	* optabs.c (get_vcond_icode): Adjust.
	(expand_vec_cond_expr_p): Likewise.
	(expand_vec_cond_expr): Likewise.
	* tree-vect-stmt.c (vectorizable_condition): Adjust.

	* config/i386/sse.md (vcond<mode>): Split to
	vcond<V_256:mode><VF_256:mode>, vcond<V_128:mode><VF_128:mode>,
	vcond<V_128:mode><VI124_128:mode> and
	vcondu<V_128:mode><VI124_128:mode>.
	(vcondv2di): Change to vcond<VI8F_128:mode>v2di.
	(vconduv2di): Likewise.
	* config/arm/neon.md (vcond<mode>): Change to vcond*<mode><mode>.
	(vcondu<mode>): Likewise.
	* config/ia64/vect.md (vcond<mode>): Likewise.
	(vcondu<mode>): Likewise.
	(vcondv2sf): Likewise.
	* config/mips/mips-ps-3d.md (vcondv2sf): Likewise.
	* config/rs6000/paired.md (vcondv2sf): Likewise.
	* config/rs6000/vector.md (vcond<mode>): Likewise.
	(vcondu<mode>): Likewise.
	* config/spu/spu.md (vcond<mode>): Likewise.
	(vcondu<mode>): Likewise.

Index: trunk/gcc/config/arm/neon.md
===================================================================
*** trunk.orig/gcc/config/arm/neon.md	2011-08-15 14:15:34.000000000 +0200
--- trunk/gcc/config/arm/neon.md	2011-08-29 15:56:32.000000000 +0200
***************
*** 1600,1606 ****
  ;; where op3 is <, <=, ==, !=, >= or >.  Operations are performed
  ;; element-wise.
  
! (define_expand "vcond<mode>"
    [(set (match_operand:VDQW 0 "s_register_operand" "")
  	(if_then_else:VDQW
  	  (match_operator 3 "arm_comparison_operator"
--- 1600,1606 ----
  ;; where op3 is <, <=, ==, !=, >= or >.  Operations are performed
  ;; element-wise.
  
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VDQW 0 "s_register_operand" "")
  	(if_then_else:VDQW
  	  (match_operator 3 "arm_comparison_operator"
***************
*** 1680,1686 ****
    DONE;
  })
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VDQIW 0 "s_register_operand" "")
  	(if_then_else:VDQIW
  	  (match_operator 3 "arm_comparison_operator"
--- 1680,1686 ----
    DONE;
  })
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VDQIW 0 "s_register_operand" "")
  	(if_then_else:VDQIW
  	  (match_operator 3 "arm_comparison_operator"
Index: trunk/gcc/config/i386/sse.md
===================================================================
*** trunk.orig/gcc/config/i386/sse.md	2011-08-29 15:07:05.000000000 +0200
--- trunk/gcc/config/i386/sse.md	2011-08-29 15:55:44.000000000 +0200
***************
*** 1405,1418 ****
  		      (const_string "0")))
     (set_attr "mode" "<MODE>")])
  
! (define_expand "vcond<mode>"
!   [(set (match_operand:VF 0 "register_operand" "")
! 	(if_then_else:VF
  	  (match_operator 3 ""
! 	    [(match_operand:VF 4 "nonimmediate_operand" "")
! 	     (match_operand:VF 5 "nonimmediate_operand" "")])
! 	  (match_operand:VF 1 "general_operand" "")
! 	  (match_operand:VF 2 "general_operand" "")))]
    "TARGET_SSE"
  {
    bool ok = ix86_expand_fp_vcond (operands);
--- 1405,1433 ----
  		      (const_string "0")))
     (set_attr "mode" "<MODE>")])
  
! (define_expand "vcond<V_256:mode><VF_256:mode>"
!   [(set (match_operand:V_256 0 "register_operand" "")
! 	(if_then_else:V_256
  	  (match_operator 3 ""
! 	    [(match_operand:VF_256 4 "nonimmediate_operand" "")
! 	     (match_operand:VF_256 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_256 1 "general_operand" "")
! 	  (match_operand:V_256 2 "general_operand" "")))]
!   "TARGET_AVX"
! {
!   bool ok = ix86_expand_fp_vcond (operands);
!   gcc_assert (ok);
!   DONE;
! })
! 
! (define_expand "vcond<V_128:mode><VF_128:mode>"
!   [(set (match_operand:V_128 0 "register_operand" "")
! 	(if_then_else:V_128
! 	  (match_operator 3 ""
! 	    [(match_operand:VF_128 4 "nonimmediate_operand" "")
! 	     (match_operand:VF_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_128 1 "general_operand" "")
! 	  (match_operand:V_128 2 "general_operand" "")))]
    "TARGET_SSE"
  {
    bool ok = ix86_expand_fp_vcond (operands);
***************
*** 6091,6104 ****
     (set_attr "prefix" "orig,vex")
     (set_attr "mode" "TI")])
  
! (define_expand "vcond<mode>"
!   [(set (match_operand:VI124_128 0 "register_operand" "")
! 	(if_then_else:VI124_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI124_128 1 "general_operand" "")
! 	  (match_operand:VI124_128 2 "general_operand" "")))]
    "TARGET_SSE2"
  {
    bool ok = ix86_expand_int_vcond (operands);
--- 6106,6119 ----
     (set_attr "prefix" "orig,vex")
     (set_attr "mode" "TI")])
  
! (define_expand "vcond<V_128:mode><VI124_128:mode>"
!   [(set (match_operand:V_128 0 "register_operand" "")
! 	(if_then_else:V_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_128 1 "general_operand" "")
! 	  (match_operand:V_128 2 "general_operand" "")))]
    "TARGET_SSE2"
  {
    bool ok = ix86_expand_int_vcond (operands);
***************
*** 6106,6119 ****
    DONE;
  })
  
! (define_expand "vcondv2di"
!   [(set (match_operand:V2DI 0 "register_operand" "")
! 	(if_then_else:V2DI
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:V2DI 1 "general_operand" "")
! 	  (match_operand:V2DI 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
--- 6121,6134 ----
    DONE;
  })
  
! (define_expand "vcond<VI8F_128:mode>v2di"
!   [(set (match_operand:VI8F_128 0 "register_operand" "")
! 	(if_then_else:VI8F_128
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI8F_128 1 "general_operand" "")
! 	  (match_operand:VI8F_128 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
***************
*** 6121,6134 ****
    DONE;
  })
  
! (define_expand "vcondu<mode>"
!   [(set (match_operand:VI124_128 0 "register_operand" "")
! 	(if_then_else:VI124_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI124_128 1 "general_operand" "")
! 	  (match_operand:VI124_128 2 "general_operand" "")))]
    "TARGET_SSE2"
  {
    bool ok = ix86_expand_int_vcond (operands);
--- 6136,6149 ----
    DONE;
  })
  
! (define_expand "vcondu<V_128:mode><VI124_128:mode>"
!   [(set (match_operand:V_128 0 "register_operand" "")
! 	(if_then_else:V_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_128 1 "general_operand" "")
! 	  (match_operand:V_128 2 "general_operand" "")))]
    "TARGET_SSE2"
  {
    bool ok = ix86_expand_int_vcond (operands);
***************
*** 6136,6149 ****
    DONE;
  })
  
! (define_expand "vconduv2di"
!   [(set (match_operand:V2DI 0 "register_operand" "")
! 	(if_then_else:V2DI
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:V2DI 1 "general_operand" "")
! 	  (match_operand:V2DI 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
--- 6151,6164 ----
    DONE;
  })
  
! (define_expand "vcondu<VI8F_128:mode>v2di"
!   [(set (match_operand:VI8F_128 0 "register_operand" "")
! 	(if_then_else:VI8F_128
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI8F_128 1 "general_operand" "")
! 	  (match_operand:VI8F_128 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
Index: trunk/gcc/config/ia64/vect.md
===================================================================
*** trunk.orig/gcc/config/ia64/vect.md	2011-02-08 12:01:06.000000000 +0100
--- trunk/gcc/config/ia64/vect.md	2011-08-29 15:56:46.000000000 +0200
***************
*** 661,667 ****
    DONE;
  })
  
! (define_expand "vcond<mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
--- 661,667 ----
    DONE;
  })
  
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
***************
*** 675,681 ****
    DONE;
  })
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
--- 675,681 ----
    DONE;
  })
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
***************
*** 1382,1388 ****
    DONE;
  })
  
! (define_expand "vcondv2sf"
    [(set (match_operand:V2SF 0 "fr_register_operand" "")
  	(if_then_else:V2SF
  	  (match_operator 3 "" 
--- 1382,1388 ----
    DONE;
  })
  
! (define_expand "vcondv2sfv2sf"
    [(set (match_operand:V2SF 0 "fr_register_operand" "")
  	(if_then_else:V2SF
  	  (match_operator 3 "" 
Index: trunk/gcc/config/mips/mips-ps-3d.md
===================================================================
*** trunk.orig/gcc/config/mips/mips-ps-3d.md	2011-01-10 12:31:19.000000000 +0100
--- trunk/gcc/config/mips/mips-ps-3d.md	2011-08-29 15:56:56.000000000 +0200
***************
*** 597,603 ****
    [(set_attr "type" "frdiv2")
     (set_attr "mode" "<UNITMODE>")])
  
! (define_expand "vcondv2sf"
    [(set (match_operand:V2SF 0 "register_operand")
  	(if_then_else:V2SF
  	  (match_operator 3 ""
--- 597,603 ----
    [(set_attr "type" "frdiv2")
     (set_attr "mode" "<UNITMODE>")])
  
! (define_expand "vcondv2sfv2sf"
    [(set (match_operand:V2SF 0 "register_operand")
  	(if_then_else:V2SF
  	  (match_operator 3 ""
Index: trunk/gcc/config/rs6000/paired.md
===================================================================
*** trunk.orig/gcc/config/rs6000/paired.md	2011-03-22 12:22:01.000000000 +0100
--- trunk/gcc/config/rs6000/paired.md	2011-08-29 15:57:01.000000000 +0200
***************
*** 507,513 ****
    DONE;
  })
  
! (define_expand "vcondv2sf"
    [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
          (if_then_else:V2SF
           (match_operator 3 "gpc_reg_operand"
--- 507,513 ----
    DONE;
  })
  
! (define_expand "vcondv2sfv2sf"
    [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
          (if_then_else:V2SF
           (match_operator 3 "gpc_reg_operand"
Index: trunk/gcc/config/rs6000/vector.md
===================================================================
*** trunk.orig/gcc/config/rs6000/vector.md	2011-07-11 11:49:22.000000000 +0200
--- trunk/gcc/config/rs6000/vector.md	2011-08-29 15:57:17.000000000 +0200
***************
*** 370,376 ****
  
  \f
  ;; Vector comparisons
! (define_expand "vcond<mode>"
    [(set (match_operand:VEC_F 0 "vfloat_operand" "")
  	(if_then_else:VEC_F
  	 (match_operator 3 "comparison_operator"
--- 370,376 ----
  
  \f
  ;; Vector comparisons
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VEC_F 0 "vfloat_operand" "")
  	(if_then_else:VEC_F
  	 (match_operator 3 "comparison_operator"
***************
*** 388,394 ****
      FAIL;
  }")
  
! (define_expand "vcond<mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
--- 388,394 ----
      FAIL;
  }")
  
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
***************
*** 406,412 ****
      FAIL;
  }")
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
--- 406,412 ----
      FAIL;
  }")
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
Index: trunk/gcc/config/spu/spu.md
===================================================================
*** trunk.orig/gcc/config/spu/spu.md	2011-08-04 12:59:40.000000000 +0200
--- trunk/gcc/config/spu/spu.md	2011-08-29 15:57:25.000000000 +0200
*************** selb\t%0,%4,%0,%3"
*** 3874,3880 ****
  
  \f
  ;; vector conditional compare patterns
! (define_expand "vcond<mode>"
    [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
          (if_then_else:VCMP
            (match_operator 3 "comparison_operator"
--- 3874,3880 ----
  
  \f
  ;; vector conditional compare patterns
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
          (if_then_else:VCMP
            (match_operator 3 "comparison_operator"
*************** selb\t%0,%4,%0,%3"
*** 3891,3897 ****
      FAIL;
    })
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
          (if_then_else:VCMPU
            (match_operator 3 "comparison_operator"
--- 3891,3897 ----
      FAIL;
    })
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
          (if_then_else:VCMPU
            (match_operator 3 "comparison_operator"
Index: trunk/gcc/genopinit.c
===================================================================
*** trunk.orig/gcc/genopinit.c	2011-08-19 16:26:24.000000000 +0200
--- trunk/gcc/genopinit.c	2011-08-29 15:01:06.000000000 +0200
*************** static const char * const optabs[] =
*** 253,260 ****
    "set_optab_handler (vec_shl_optab, $A, CODE_FOR_$(vec_shl_$a$))",
    "set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
    "set_optab_handler (vec_realign_load_optab, $A, CODE_FOR_$(vec_realign_load_$a$))",
!   "set_direct_optab_handler (vcond_optab, $A, CODE_FOR_$(vcond$a$))",
!   "set_direct_optab_handler (vcondu_optab, $A, CODE_FOR_$(vcondu$a$))",
    "set_optab_handler (ssum_widen_optab, $A, CODE_FOR_$(widen_ssum$I$a3$))",
    "set_optab_handler (usum_widen_optab, $A, CODE_FOR_$(widen_usum$I$a3$))",
    "set_optab_handler (udot_prod_optab, $A, CODE_FOR_$(udot_prod$I$a$))",
--- 253,260 ----
    "set_optab_handler (vec_shl_optab, $A, CODE_FOR_$(vec_shl_$a$))",
    "set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
    "set_optab_handler (vec_realign_load_optab, $A, CODE_FOR_$(vec_realign_load_$a$))",
!   "set_convert_optab_handler (vcond_optab, $A, $B, CODE_FOR_$(vcond$a$b$))",
!   "set_convert_optab_handler (vcondu_optab, $A, $B, CODE_FOR_$(vcondu$a$b$))",
    "set_optab_handler (ssum_widen_optab, $A, CODE_FOR_$(widen_ssum$I$a3$))",
    "set_optab_handler (usum_widen_optab, $A, CODE_FOR_$(widen_usum$I$a3$))",
    "set_optab_handler (udot_prod_optab, $A, CODE_FOR_$(udot_prod$I$a$))",
Index: trunk/gcc/optabs.c
===================================================================
*** trunk.orig/gcc/optabs.c	2011-08-29 14:58:24.000000000 +0200
--- trunk/gcc/optabs.c	2011-08-29 15:44:14.000000000 +0200
*************** vector_compare_rtx (tree cond, bool unsi
*** 6620,6646 ****
    return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
  }
  
! /* Return insn code for TYPE, the type of a VEC_COND_EXPR.  */
  
  static inline enum insn_code
! get_vcond_icode (tree type, enum machine_mode mode)
  {
    enum insn_code icode = CODE_FOR_nothing;
! 
!   if (TYPE_UNSIGNED (type))
!     icode = direct_optab_handler (vcondu_optab, mode);
    else
!     icode = direct_optab_handler (vcond_optab, mode);
    return icode;
  }
  
  /* Return TRUE iff, appropriate vector insns are available
!    for vector cond expr with type TYPE in VMODE mode.  */
  
  bool
! expand_vec_cond_expr_p (tree type, enum machine_mode vmode)
  {
!   if (get_vcond_icode (type, vmode) == CODE_FOR_nothing)
      return false;
    return true;
  }
--- 6620,6648 ----
    return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
  }
  
! /* Return insn code for a conditional operator with a comparison in
!    mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE.  */
  
  static inline enum insn_code
! get_vcond_icode (enum machine_mode vmode, enum machine_mode cmode, bool uns)
  {
    enum insn_code icode = CODE_FOR_nothing;
!   if (uns)
!     icode = convert_optab_handler (vcondu_optab, vmode, cmode);
    else
!     icode = convert_optab_handler (vcond_optab, vmode, cmode);
    return icode;
  }
  
  /* Return TRUE iff, appropriate vector insns are available
!    for vector cond expr with vector type VALUE_TYPE and a comparison
!    with operand vector types in CMP_OP_TYPE.  */
  
  bool
! expand_vec_cond_expr_p (tree value_type, tree cmp_op_type)
  {
!   if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
! 		       TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing)
      return false;
    return true;
  }
*************** expand_vec_cond_expr (tree vec_cond_type
*** 6656,6664 ****
    enum insn_code icode;
    rtx comparison, rtx_op1, rtx_op2;
    enum machine_mode mode = TYPE_MODE (vec_cond_type);
!   bool unsignedp = TYPE_UNSIGNED (vec_cond_type);
! 
!   icode = get_vcond_icode (vec_cond_type, mode);
    if (icode == CODE_FOR_nothing)
      return 0;
  
--- 6658,6670 ----
    enum insn_code icode;
    rtx comparison, rtx_op1, rtx_op2;
    enum machine_mode mode = TYPE_MODE (vec_cond_type);
!   bool unsignedp;
!   
!   gcc_assert (COMPARISON_CLASS_P (op0));
! 
!   unsignedp = TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0)));
!   icode = get_vcond_icode (mode, TYPE_MODE (TREE_TYPE (TREE_OPERAND (op0, 0))),
! 			   unsignedp);
    if (icode == CODE_FOR_nothing)
      return 0;
  
Index: trunk/gcc/optabs.h
===================================================================
*** trunk.orig/gcc/optabs.h	2011-08-19 16:26:24.000000000 +0200
--- trunk/gcc/optabs.h	2011-08-29 15:35:54.000000000 +0200
*************** enum convert_optab_index
*** 589,594 ****
--- 589,598 ----
    COI_vec_load_lanes,
    COI_vec_store_lanes,
  
+   /* Vector conditional operations.  */
+   COI_vcond,
+   COI_vcondu,
+ 
    COI_MAX
  };
  
*************** enum convert_optab_index
*** 611,616 ****
--- 615,622 ----
  #define satfractuns_optab (&convert_optab_table[COI_satfractuns])
  #define vec_load_lanes_optab (&convert_optab_table[COI_vec_load_lanes])
  #define vec_store_lanes_optab (&convert_optab_table[COI_vec_store_lanes])
+ #define vcond_optab (&convert_optab_table[(int) COI_vcond])
+ #define vcondu_optab (&convert_optab_table[(int) COI_vcondu])
  
  /* Contains the optab used for each rtx code.  */
  extern optab code_to_optab[NUM_RTX_CODE + 1];
*************** enum direct_optab_index
*** 632,641 ****
    DOI_reload_in,
    DOI_reload_out,
  
-   /* Vector conditional operations.  */
-   DOI_vcond,
-   DOI_vcondu,
- 
    /* Block move operation.  */
    DOI_movmem,
  
--- 638,643 ----
*************** typedef struct direct_optab_d *direct_op
*** 699,706 ****
  #endif
  #define reload_in_optab (&direct_optab_table[(int) DOI_reload_in])
  #define reload_out_optab (&direct_optab_table[(int) DOI_reload_out])
- #define vcond_optab (&direct_optab_table[(int) DOI_vcond])
- #define vcondu_optab (&direct_optab_table[(int) DOI_vcondu])
  #define movmem_optab (&direct_optab_table[(int) DOI_movmem])
  #define setmem_optab (&direct_optab_table[(int) DOI_setmem])
  #define cmpstr_optab (&direct_optab_table[(int) DOI_cmpstr])
--- 701,706 ----
*************** extern bool expand_sfix_optab (rtx, rtx,
*** 877,883 ****
  extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab);
  
  /* Return tree if target supports vector operations for COND_EXPR.  */
! bool expand_vec_cond_expr_p (tree, enum machine_mode);
  
  /* Generate code for VEC_COND_EXPR.  */
  extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
--- 877,883 ----
  extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab);
  
  /* Return tree if target supports vector operations for COND_EXPR.  */
! bool expand_vec_cond_expr_p (tree, tree);
  
  /* Generate code for VEC_COND_EXPR.  */
  extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
Index: trunk/gcc/tree-vect-stmts.c
===================================================================
*** trunk.orig/gcc/tree-vect-stmts.c	2011-08-29 14:58:24.000000000 +0200
--- trunk/gcc/tree-vect-stmts.c	2011-08-29 15:06:48.000000000 +0200
*************** vectorizable_condition (gimple stmt, gim
*** 4749,4755 ****
    tree vec_compare, vec_cond_expr;
    tree new_temp;
    loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
-   enum machine_mode vec_mode;
    tree def;
    enum vect_def_type dt, dts[4];
    int nunits = TYPE_VECTOR_SUBPARTS (vectype);
--- 4749,4754 ----
*************** vectorizable_condition (gimple stmt, gim
*** 4833,4845 ****
  	   && TREE_CODE (else_clause) != FIXED_CST)
      return false;
  
- 
-   vec_mode = TYPE_MODE (vectype);
- 
    if (!vec_stmt)
      {
        STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
!       return expand_vec_cond_expr_p (TREE_TYPE (op), vec_mode);
      }
  
    /* Transform */
--- 4832,4841 ----
  	   && TREE_CODE (else_clause) != FIXED_CST)
      return false;
  
    if (!vec_stmt)
      {
        STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
!       return expand_vec_cond_expr_p (vectype, vectype);
      }
  
    /* Transform */

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-29 15:08 [PATCH] Change vcond<mode> to vcond<mode1><mode2> Richard Guenther
@ 2011-08-29 16:36 ` Richard Guenther
  2011-08-29 20:47 ` Uros Bizjak
  1 sibling, 0 replies; 16+ messages in thread
From: Richard Guenther @ 2011-08-29 16:36 UTC (permalink / raw)
  To: gcc-patches; +Cc: uros, rth, artyom.shinkaroff

On Mon, 29 Aug 2011, Richard Guenther wrote:

> 
> This patch makes a conversion optab from the direct optabs vcond
> and vcondu.  This allows to specify different modes for the
> actual comparison and the value that is selected.
> 
> All targets but i386 are trivially converted by 
> s/vcond<mode>/vcond<mode><mode>/.  The i386 port is enhanced
> to support a OP b ? c : d as ({ mask = a OP b; (c & mask) | (d & ~mask); 
> }), constraining it to what the middle-end constrained itself to
> (matching number of vector elements in the comparison operands with
> the result vector types) would explode patterns too much.
> Thus, only a subset of mode combinations will be excercised
> (but none at the moment - a followup will fix the vectorizer,
> and generic vectors from the C extensions have a patch pending).
> 
> Bootstrapped on x86_64-unknown-linux-gnu, tests are currently
> running for {,-m32}.
> 
> Ok if that succeeds?

And this is the followup implementing the auto-vectorization part.
For i386 I avoided to rewrite the vector comparison insn patterns
to allow any result mode by doing a separate conversion emitted
from ix86_expand_sse_cmp.

Bootstrap and regtest pending on x86_64-unknown-linux-gnu.

I'm considering to merge the two patches to avoid the unexcercisable
new code.

Comments?  Ok?

Thanks,
Richard.

2011-08-29  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/27460
	* gcc/config/i386/i386.c (ix86_expand_sse_cmp): Use proper mode
	for the comparison.
	* tree-vect-stmts.c (vect_is_simple_cond): Return the comparison
	vector type.
	(vectorizable_condition): Allow differing types for comparison
	and result.

	* gcc.dg/vect/vect-cond-7.c: New testcase.

Index: trunk/gcc/config/i386/i386.c
===================================================================
*** trunk.orig/gcc/config/i386/i386.c	2011-08-29 16:57:30.000000000 +0200
--- trunk/gcc/config/i386/i386.c	2011-08-29 17:05:32.000000000 +0200
*************** ix86_expand_sse_cmp (rtx dest, enum rtx_
*** 18412,18430 ****
  		     rtx op_true, rtx op_false)
  {
    enum machine_mode mode = GET_MODE (dest);
    rtx x;
  
!   cmp_op0 = force_reg (mode, cmp_op0);
!   if (!nonimmediate_operand (cmp_op1, mode))
!     cmp_op1 = force_reg (mode, cmp_op1);
  
    if (optimize
        || reg_overlap_mentioned_p (dest, op_true)
        || reg_overlap_mentioned_p (dest, op_false))
      dest = gen_reg_rtx (mode);
  
!   x = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
!   emit_insn (gen_rtx_SET (VOIDmode, dest, x));
  
    return dest;
  }
--- 18412,18437 ----
  		     rtx op_true, rtx op_false)
  {
    enum machine_mode mode = GET_MODE (dest);
+   enum machine_mode cmp_mode = GET_MODE (cmp_op0);
    rtx x;
  
!   cmp_op0 = force_reg (cmp_mode, cmp_op0);
!   if (!nonimmediate_operand (cmp_op1, cmp_mode))
!     cmp_op1 = force_reg (cmp_mode, cmp_op1);
  
    if (optimize
        || reg_overlap_mentioned_p (dest, op_true)
        || reg_overlap_mentioned_p (dest, op_false))
      dest = gen_reg_rtx (mode);
  
!   x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1);
!   if (cmp_mode != mode)
!     {
!       x = force_reg (cmp_mode, x);
!       convert_move (dest, x, false);
!     }
!   else
!     emit_insn (gen_rtx_SET (VOIDmode, dest, x));
  
    return dest;
  }
Index: trunk/gcc/tree-vect-stmts.c
===================================================================
*** trunk.orig/gcc/tree-vect-stmts.c	2011-08-29 16:57:29.000000000 +0200
--- trunk/gcc/tree-vect-stmts.c	2011-08-29 16:57:41.000000000 +0200
*************** vectorizable_load (gimple stmt, gimple_s
*** 4680,4694 ****
     LOOP - the loop that is being vectorized.
     COND - Condition that is checked for simple use.
  
     Returns whether a COND can be vectorized.  Checks whether
     condition operands are supportable using vec_is_simple_use.  */
  
  static bool
! vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
  {
    tree lhs, rhs;
    tree def;
    enum vect_def_type dt;
  
    if (!COMPARISON_CLASS_P (cond))
      return false;
--- 4680,4698 ----
     LOOP - the loop that is being vectorized.
     COND - Condition that is checked for simple use.
  
+    Output:
+    *COMP_VECTYPE - the vector type for the comparison.
+ 
     Returns whether a COND can be vectorized.  Checks whether
     condition operands are supportable using vec_is_simple_use.  */
  
  static bool
! vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype)
  {
    tree lhs, rhs;
    tree def;
    enum vect_def_type dt;
+   tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
  
    if (!COMPARISON_CLASS_P (cond))
      return false;
*************** vect_is_simple_cond (tree cond, loop_vec
*** 4699,4706 ****
    if (TREE_CODE (lhs) == SSA_NAME)
      {
        gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
!       if (!vect_is_simple_use (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
!                                &dt))
  	return false;
      }
    else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
--- 4703,4710 ----
    if (TREE_CODE (lhs) == SSA_NAME)
      {
        gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
!       if (!vect_is_simple_use_1 (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
! 				 &dt, &vectype1))
  	return false;
      }
    else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
*************** vect_is_simple_cond (tree cond, loop_vec
*** 4710,4723 ****
    if (TREE_CODE (rhs) == SSA_NAME)
      {
        gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
!       if (!vect_is_simple_use (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
!                                &dt))
  	return false;
      }
    else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
  	   && TREE_CODE (rhs) != FIXED_CST)
      return false;
  
    return true;
  }
  
--- 4714,4728 ----
    if (TREE_CODE (rhs) == SSA_NAME)
      {
        gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
!       if (!vect_is_simple_use_1 (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
! 				 &dt, &vectype2))
  	return false;
      }
    else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
  	   && TREE_CODE (rhs) != FIXED_CST)
      return false;
  
+   *comp_vectype = vectype1 ? vectype1 : vectype2;
    return true;
  }
  
*************** vectorizable_condition (gimple stmt, gim
*** 4744,4749 ****
--- 4749,4755 ----
    tree cond_expr, then_clause, else_clause;
    stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
    tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+   tree comp_vectype;
    tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
    tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
    tree vec_compare, vec_cond_expr;
*************** vectorizable_condition (gimple stmt, gim
*** 4799,4811 ****
    then_clause = TREE_OPERAND (op, 1);
    else_clause = TREE_OPERAND (op, 2);
  
!   if (!vect_is_simple_cond (cond_expr, loop_vinfo))
!     return false;
! 
!   /* We do not handle two different vector types for the condition
!      and the values.  */
!   if (!types_compatible_p (TREE_TYPE (TREE_OPERAND (cond_expr, 0)),
! 			   TREE_TYPE (vectype)))
      return false;
  
    if (TREE_CODE (then_clause) == SSA_NAME)
--- 4805,4812 ----
    then_clause = TREE_OPERAND (op, 1);
    else_clause = TREE_OPERAND (op, 2);
  
!   if (!vect_is_simple_cond (cond_expr, loop_vinfo, &comp_vectype)
!       || !comp_vectype)
      return false;
  
    if (TREE_CODE (then_clause) == SSA_NAME)
*************** vectorizable_condition (gimple stmt, gim
*** 4835,4841 ****
    if (!vec_stmt)
      {
        STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
!       return expand_vec_cond_expr_p (vectype, vectype);
      }
  
    /* Transform */
--- 4836,4842 ----
    if (!vec_stmt)
      {
        STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
!       return expand_vec_cond_expr_p (vectype, comp_vectype);
      }
  
    /* Transform */
Index: trunk/gcc/testsuite/gcc.dg/vect/vect-cond-7.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/vect/vect-cond-7.c	2011-08-29 17:04:38.000000000 +0200
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-require-effective-target vect_condition } */
+ 
+ int vis_type[128];
+ float vs_data[128];
+ void vis_clear_data ()
+ {
+   int i;
+   for (i = 0; i < 128; i++)
+     vs_data[i] = (vis_type[i] == 1);
+ }
+ 
+ /* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-29 15:08 [PATCH] Change vcond<mode> to vcond<mode1><mode2> Richard Guenther
  2011-08-29 16:36 ` Richard Guenther
@ 2011-08-29 20:47 ` Uros Bizjak
  2011-08-29 21:05   ` Richard Guenther
  1 sibling, 1 reply; 16+ messages in thread
From: Uros Bizjak @ 2011-08-29 20:47 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, uros, rth, artyom.shinkaroff

On Mon, Aug 29, 2011 at 4:31 PM, Richard Guenther <rguenther@suse.de> wrote:

> This patch makes a conversion optab from the direct optabs vcond
> and vcondu.  This allows to specify different modes for the
> actual comparison and the value that is selected.
>
> All targets but i386 are trivially converted by
> s/vcond<mode>/vcond<mode><mode>/.  The i386 port is enhanced
> to support a OP b ? c : d as ({ mask = a OP b; (c & mask) | (d & ~mask);
> }), constraining it to what the middle-end constrained itself to
> (matching number of vector elements in the comparison operands with
> the result vector types) would explode patterns too much.
> Thus, only a subset of mode combinations will be excercised
> (but none at the moment - a followup will fix the vectorizer,
> and generic vectors from the C extensions have a patch pending).
>
> Bootstrapped on x86_64-unknown-linux-gnu, tests are currently
> running for {,-m32}.
>
> Ok if that succeeds?
>
> Thanks,
> Richard.
>
> 2011-08-29  Richard Guenther  <rguenther@suse.de>
>
>        * genopinit.c (optabs): Turn vcond{,u}_optab into a conversion
>        optab with two modes.
>        * optabs.h (enum convert_optab_index): Add COI_vcond, COI_vcondu.
>        (enum direct_optab_index): Remove DOI_vcond, DOI_vcondu.
>        (vcond_optab): Adjust.
>        (vcondu_optab): Likewise.
>        (expand_vec_cond_expr_p): Adjust prototype.
>        * optabs.c (get_vcond_icode): Adjust.
>        (expand_vec_cond_expr_p): Likewise.
>        (expand_vec_cond_expr): Likewise.
>        * tree-vect-stmt.c (vectorizable_condition): Adjust.
>
>        * config/i386/sse.md (vcond<mode>): Split to
>        vcond<V_256:mode><VF_256:mode>, vcond<V_128:mode><VF_128:mode>,
>        vcond<V_128:mode><VI124_128:mode> and
>        vcondu<V_128:mode><VI124_128:mode>.
>        (vcondv2di): Change to vcond<VI8F_128:mode>v2di.
>        (vconduv2di): Likewise.
>        * config/arm/neon.md (vcond<mode>): Change to vcond*<mode><mode>.
>        (vcondu<mode>): Likewise.
>        * config/ia64/vect.md (vcond<mode>): Likewise.
>        (vcondu<mode>): Likewise.
>        (vcondv2sf): Likewise.
>        * config/mips/mips-ps-3d.md (vcondv2sf): Likewise.
>        * config/rs6000/paired.md (vcondv2sf): Likewise.
>        * config/rs6000/vector.md (vcond<mode>): Likewise.
>        (vcondu<mode>): Likewise.
>        * config/spu/spu.md (vcond<mode>): Likewise.
>        (vcondu<mode>): Likewise.

Do we really want to introduce stuff like:

! (define_expand "vcond<V_128:mode><VF_128:mode>"

You are in fact introducing 6x2 = 12 patterns, many of them (i.e.
v16qiv2df combination) invalid.

I'd prefer a pattern with mode-less operands 4 and 5, rejected in insn
constraints for invalid combinations:

(define_expand "vcond<mode>"
  [(set (match_operand:VI124_128 0 "register_operand" "")
      (if_then_else:VI124_128
        (match_operator 3 ""
          [(match_operand 4 "nonimmediate_operand" "")
           (match_operand 5 "nonimmediate_operand" "")])
         (match_operand:VI124_128 1 "general_operand" "")
         (match_operand:VI124_128 2 "general_operand" "")))]
   "TARGET_SSE && (... some constraint involving modes of op4 and op5 ...)"

We could also introduce VI1248_128 with conditional V2DImode for ops 0, 1 and 2:

(define_mode_iterator VI1248_128 [V16QI V8HI V4SI (V2DI "TARGET_SSE4_2")])

Uros.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-29 20:47 ` Uros Bizjak
@ 2011-08-29 21:05   ` Richard Guenther
  2011-08-30  9:00     ` Uros Bizjak
  0 siblings, 1 reply; 16+ messages in thread
From: Richard Guenther @ 2011-08-29 21:05 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches, uros, rth, artyom.shinkaroff

[-- Attachment #1: Type: TEXT/PLAIN, Size: 4383 bytes --]

On Mon, 29 Aug 2011, Uros Bizjak wrote:

> On Mon, Aug 29, 2011 at 4:31 PM, Richard Guenther <rguenther@suse.de> wrote:
> 
> > This patch makes a conversion optab from the direct optabs vcond
> > and vcondu.  This allows to specify different modes for the
> > actual comparison and the value that is selected.
> >
> > All targets but i386 are trivially converted by
> > s/vcond<mode>/vcond<mode><mode>/.  The i386 port is enhanced
> > to support a OP b ? c : d as ({ mask = a OP b; (c & mask) | (d & ~mask);
> > }), constraining it to what the middle-end constrained itself to
> > (matching number of vector elements in the comparison operands with
> > the result vector types) would explode patterns too much.
> > Thus, only a subset of mode combinations will be excercised
> > (but none at the moment - a followup will fix the vectorizer,
> > and generic vectors from the C extensions have a patch pending).
> >
> > Bootstrapped on x86_64-unknown-linux-gnu, tests are currently
> > running for {,-m32}.
> >
> > Ok if that succeeds?
> >
> > Thanks,
> > Richard.
> >
> > 2011-08-29  Richard Guenther  <rguenther@suse.de>
> >
> >        * genopinit.c (optabs): Turn vcond{,u}_optab into a conversion
> >        optab with two modes.
> >        * optabs.h (enum convert_optab_index): Add COI_vcond, COI_vcondu.
> >        (enum direct_optab_index): Remove DOI_vcond, DOI_vcondu.
> >        (vcond_optab): Adjust.
> >        (vcondu_optab): Likewise.
> >        (expand_vec_cond_expr_p): Adjust prototype.
> >        * optabs.c (get_vcond_icode): Adjust.
> >        (expand_vec_cond_expr_p): Likewise.
> >        (expand_vec_cond_expr): Likewise.
> >        * tree-vect-stmt.c (vectorizable_condition): Adjust.
> >
> >        * config/i386/sse.md (vcond<mode>): Split to
> >        vcond<V_256:mode><VF_256:mode>, vcond<V_128:mode><VF_128:mode>,
> >        vcond<V_128:mode><VI124_128:mode> and
> >        vcondu<V_128:mode><VI124_128:mode>.
> >        (vcondv2di): Change to vcond<VI8F_128:mode>v2di.
> >        (vconduv2di): Likewise.
> >        * config/arm/neon.md (vcond<mode>): Change to vcond*<mode><mode>.
> >        (vcondu<mode>): Likewise.
> >        * config/ia64/vect.md (vcond<mode>): Likewise.
> >        (vcondu<mode>): Likewise.
> >        (vcondv2sf): Likewise.
> >        * config/mips/mips-ps-3d.md (vcondv2sf): Likewise.
> >        * config/rs6000/paired.md (vcondv2sf): Likewise.
> >        * config/rs6000/vector.md (vcond<mode>): Likewise.
> >        (vcondu<mode>): Likewise.
> >        * config/spu/spu.md (vcond<mode>): Likewise.
> >        (vcondu<mode>): Likewise.
> 
> Do we really want to introduce stuff like:
> 
> ! (define_expand "vcond<V_128:mode><VF_128:mode>"
> 
> You are in fact introducing 6x2 = 12 patterns, many of them (i.e.
> v16qiv2df combination) invalid.

Well, in principle they are not "invalid" they would be a short-hand -
the example of (subreg:V16QI (vcond:V2DI (... )).

> I'd prefer a pattern with mode-less operands 4 and 5, rejected in insn
> constraints for invalid combinations:

Hm, ok - that was the first variant I tried (well, but with modeless
operands 1 and 2, to keep 4 and 5 selcting int vs. fp compare).  But
modeless operands get you that annoying warning from the gen* programs.

How'd you ask if a pattern is available for vcondv4si with v4sf
operands 4 and 5?  The vectorizer would need to be able to ask this
question.

In the end putting both mask generation and apply into one
instruction pattern causes all this issues - but it helps
not exposing the mask representation of the HW.

> (define_expand "vcond<mode>"
>   [(set (match_operand:VI124_128 0 "register_operand" "")
>       (if_then_else:VI124_128
>         (match_operator 3 ""
>           [(match_operand 4 "nonimmediate_operand" "")
>            (match_operand 5 "nonimmediate_operand" "")])
>          (match_operand:VI124_128 1 "general_operand" "")
>          (match_operand:VI124_128 2 "general_operand" "")))]
>    "TARGET_SSE && (... some constraint involving modes of op4 and op5 ...)"
> 
> We could also introduce VI1248_128 with conditional V2DImode for ops 0, 1 and 2:
> 
> (define_mode_iterator VI1248_128 [V16QI V8HI V4SI (V2DI "TARGET_SSE4_2")])

Yes, that sounds like a cleanup that is independently possible.

Richard.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-29 21:05   ` Richard Guenther
@ 2011-08-30  9:00     ` Uros Bizjak
  2011-08-30  9:19       ` Richard Guenther
  0 siblings, 1 reply; 16+ messages in thread
From: Uros Bizjak @ 2011-08-30  9:00 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, uros, rth, artyom.shinkaroff

On Mon, Aug 29, 2011 at 9:44 PM, Richard Guenther <rguenther@suse.de> wrote:

>> > This patch makes a conversion optab from the direct optabs vcond
>> > and vcondu.  This allows to specify different modes for the
>> > actual comparison and the value that is selected.
>> >
>> > All targets but i386 are trivially converted by
>> > s/vcond<mode>/vcond<mode><mode>/.  The i386 port is enhanced
>> > to support a OP b ? c : d as ({ mask = a OP b; (c & mask) | (d & ~mask);
>> > }), constraining it to what the middle-end constrained itself to
>> > (matching number of vector elements in the comparison operands with
>> > the result vector types) would explode patterns too much.
>> > Thus, only a subset of mode combinations will be excercised
>> > (but none at the moment - a followup will fix the vectorizer,
>> > and generic vectors from the C extensions have a patch pending).
>> >
>> > Bootstrapped on x86_64-unknown-linux-gnu, tests are currently
>> > running for {,-m32}.
>> >
>> > Ok if that succeeds?
>> >
>> > Thanks,
>> > Richard.
>> >
>> > 2011-08-29  Richard Guenther  <rguenther@suse.de>
>> >
>> >        * genopinit.c (optabs): Turn vcond{,u}_optab into a conversion
>> >        optab with two modes.
>> >        * optabs.h (enum convert_optab_index): Add COI_vcond, COI_vcondu.
>> >        (enum direct_optab_index): Remove DOI_vcond, DOI_vcondu.
>> >        (vcond_optab): Adjust.
>> >        (vcondu_optab): Likewise.
>> >        (expand_vec_cond_expr_p): Adjust prototype.
>> >        * optabs.c (get_vcond_icode): Adjust.
>> >        (expand_vec_cond_expr_p): Likewise.
>> >        (expand_vec_cond_expr): Likewise.
>> >        * tree-vect-stmt.c (vectorizable_condition): Adjust.
>> >
>> >        * config/i386/sse.md (vcond<mode>): Split to
>> >        vcond<V_256:mode><VF_256:mode>, vcond<V_128:mode><VF_128:mode>,
>> >        vcond<V_128:mode><VI124_128:mode> and
>> >        vcondu<V_128:mode><VI124_128:mode>.
>> >        (vcondv2di): Change to vcond<VI8F_128:mode>v2di.
>> >        (vconduv2di): Likewise.
>> >        * config/arm/neon.md (vcond<mode>): Change to vcond*<mode><mode>.
>> >        (vcondu<mode>): Likewise.
>> >        * config/ia64/vect.md (vcond<mode>): Likewise.
>> >        (vcondu<mode>): Likewise.
>> >        (vcondv2sf): Likewise.
>> >        * config/mips/mips-ps-3d.md (vcondv2sf): Likewise.
>> >        * config/rs6000/paired.md (vcondv2sf): Likewise.
>> >        * config/rs6000/vector.md (vcond<mode>): Likewise.
>> >        (vcondu<mode>): Likewise.
>> >        * config/spu/spu.md (vcond<mode>): Likewise.
>> >        (vcondu<mode>): Likewise.
>>
>> Do we really want to introduce stuff like:
>>
>> ! (define_expand "vcond<V_128:mode><VF_128:mode>"
>>
>> You are in fact introducing 6x2 = 12 patterns, many of them (i.e.
>> v16qiv2df combination) invalid.
>
> Well, in principle they are not "invalid" they would be a short-hand -
> the example of (subreg:V16QI (vcond:V2DI (... )).
>
>> I'd prefer a pattern with mode-less operands 4 and 5, rejected in insn
>> constraints for invalid combinations:
>
> Hm, ok - that was the first variant I tried (well, but with modeless
> operands 1 and 2, to keep 4 and 5 selcting int vs. fp compare).  But
> modeless operands get you that annoying warning from the gen* programs.

Only for define_insn, if your c_test does not include string "operands".

> How'd you ask if a pattern is available for vcondv4si with v4sf
> operands 4 and 5?  The vectorizer would need to be able to ask this
> question.

Maybe with something along the lines of:

(define_expand "vcond<mode>"
  [(set (match_operand:VI124_128 0 "register_operand" "")
	(if_then_else:VI124_128
	  (match_operator 3 ""
	    [(match_operand 4 "nonimmediate_operand" "")
	     (match_operand 5 "nonimmediate_operand" "")])
	  (match_operand:VI124_128 1 "general_operand" "")
	  (match_operand:VI124_128 2 "general_operand" "")))]
  "TARGET_SSE2"
{
  if (GET_MODE (operands[4]) != GET_MODE (operands[5])
      || (GET_MODE_NUNITS (GET_MODE (operands[4]))
      	  != GET_MODE_NUNITS (GET_MODE (operands[0]))))
    FAIL;

  bool ok = ix86_expand_int_vcond (operands);
  gcc_assert (ok);
  DONE;
})

This means that vcond pattern is allowed to FAIL, so when vectorizer
tentatively tries to expand the pattern, FAIL signalizes that operand
modes are not supported.

> In the end putting both mask generation and apply into one
> instruction pattern causes all this issues - but it helps
> not exposing the mask representation of the HW.

No, but we should be sure that the widths are the same...

Uros.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-30  9:00     ` Uros Bizjak
@ 2011-08-30  9:19       ` Richard Guenther
  2011-08-30  9:24         ` Uros Bizjak
  0 siblings, 1 reply; 16+ messages in thread
From: Richard Guenther @ 2011-08-30  9:19 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches, uros, rth, artyom.shinkaroff

[-- Attachment #1: Type: TEXT/PLAIN, Size: 6336 bytes --]

On Tue, 30 Aug 2011, Uros Bizjak wrote:

> On Mon, Aug 29, 2011 at 9:44 PM, Richard Guenther <rguenther@suse.de> wrote:
> 
> >> > This patch makes a conversion optab from the direct optabs vcond
> >> > and vcondu.  This allows to specify different modes for the
> >> > actual comparison and the value that is selected.
> >> >
> >> > All targets but i386 are trivially converted by
> >> > s/vcond<mode>/vcond<mode><mode>/.  The i386 port is enhanced
> >> > to support a OP b ? c : d as ({ mask = a OP b; (c & mask) | (d & ~mask);
> >> > }), constraining it to what the middle-end constrained itself to
> >> > (matching number of vector elements in the comparison operands with
> >> > the result vector types) would explode patterns too much.
> >> > Thus, only a subset of mode combinations will be excercised
> >> > (but none at the moment - a followup will fix the vectorizer,
> >> > and generic vectors from the C extensions have a patch pending).
> >> >
> >> > Bootstrapped on x86_64-unknown-linux-gnu, tests are currently
> >> > running for {,-m32}.
> >> >
> >> > Ok if that succeeds?
> >> >
> >> > Thanks,
> >> > Richard.
> >> >
> >> > 2011-08-29  Richard Guenther  <rguenther@suse.de>
> >> >
> >> >        * genopinit.c (optabs): Turn vcond{,u}_optab into a conversion
> >> >        optab with two modes.
> >> >        * optabs.h (enum convert_optab_index): Add COI_vcond, COI_vcondu.
> >> >        (enum direct_optab_index): Remove DOI_vcond, DOI_vcondu.
> >> >        (vcond_optab): Adjust.
> >> >        (vcondu_optab): Likewise.
> >> >        (expand_vec_cond_expr_p): Adjust prototype.
> >> >        * optabs.c (get_vcond_icode): Adjust.
> >> >        (expand_vec_cond_expr_p): Likewise.
> >> >        (expand_vec_cond_expr): Likewise.
> >> >        * tree-vect-stmt.c (vectorizable_condition): Adjust.
> >> >
> >> >        * config/i386/sse.md (vcond<mode>): Split to
> >> >        vcond<V_256:mode><VF_256:mode>, vcond<V_128:mode><VF_128:mode>,
> >> >        vcond<V_128:mode><VI124_128:mode> and
> >> >        vcondu<V_128:mode><VI124_128:mode>.
> >> >        (vcondv2di): Change to vcond<VI8F_128:mode>v2di.
> >> >        (vconduv2di): Likewise.
> >> >        * config/arm/neon.md (vcond<mode>): Change to vcond*<mode><mode>.
> >> >        (vcondu<mode>): Likewise.
> >> >        * config/ia64/vect.md (vcond<mode>): Likewise.
> >> >        (vcondu<mode>): Likewise.
> >> >        (vcondv2sf): Likewise.
> >> >        * config/mips/mips-ps-3d.md (vcondv2sf): Likewise.
> >> >        * config/rs6000/paired.md (vcondv2sf): Likewise.
> >> >        * config/rs6000/vector.md (vcond<mode>): Likewise.
> >> >        (vcondu<mode>): Likewise.
> >> >        * config/spu/spu.md (vcond<mode>): Likewise.
> >> >        (vcondu<mode>): Likewise.
> >>
> >> Do we really want to introduce stuff like:
> >>
> >> ! (define_expand "vcond<V_128:mode><VF_128:mode>"
> >>
> >> You are in fact introducing 6x2 = 12 patterns, many of them (i.e.
> >> v16qiv2df combination) invalid.
> >
> > Well, in principle they are not "invalid" they would be a short-hand -
> > the example of (subreg:V16QI (vcond:V2DI (... )).
> >
> >> I'd prefer a pattern with mode-less operands 4 and 5, rejected in insn
> >> constraints for invalid combinations:
> >
> > Hm, ok - that was the first variant I tried (well, but with modeless
> > operands 1 and 2, to keep 4 and 5 selcting int vs. fp compare).  But
> > modeless operands get you that annoying warning from the gen* programs.
> 
> Only for define_insn, if your c_test does not include string "operands".
> 
> > How'd you ask if a pattern is available for vcondv4si with v4sf
> > operands 4 and 5?  The vectorizer would need to be able to ask this
> > question.
> 
> Maybe with something along the lines of:
> 
> (define_expand "vcond<mode>"
>   [(set (match_operand:VI124_128 0 "register_operand" "")
> 	(if_then_else:VI124_128
> 	  (match_operator 3 ""
> 	    [(match_operand 4 "nonimmediate_operand" "")
> 	     (match_operand 5 "nonimmediate_operand" "")])
> 	  (match_operand:VI124_128 1 "general_operand" "")
> 	  (match_operand:VI124_128 2 "general_operand" "")))]
>   "TARGET_SSE2"
> {
>   if (GET_MODE (operands[4]) != GET_MODE (operands[5])
>       || (GET_MODE_NUNITS (GET_MODE (operands[4]))
>       	  != GET_MODE_NUNITS (GET_MODE (operands[0]))))
>     FAIL;
> 
>   bool ok = ix86_expand_int_vcond (operands);
>   gcc_assert (ok);
>   DONE;
> })
> 
> This means that vcond pattern is allowed to FAIL, so when vectorizer
> tentatively tries to expand the pattern, FAIL signalizes that operand
> modes are not supported.

Hmm.  But then I'd have to try emit an insn, right?  Currently
the vectorizer simply looks for an optab handler ... the
operands are not readily available (but their mode is known).
So I'd create some fake regs, setup operands and call GEN_FCN
on it?  If it succeds I'd have to delete emitted insns, etc.
Or I could add a target hook ...

That shifts the ugliness towards the users, for just saving
a few redundant patterns?

> > In the end putting both mask generation and apply into one
> > instruction pattern causes all this issues - but it helps
> > not exposing the mask representation of the HW.
> 
> No, but we should be sure that the widths are the same...

Yes.  We'd guarantee that we'd never try to expand something
where that doesn't hold.

I just saw PR29269 - vcond is not documented ... I'd document
it for the two-mode variant as

@cindex @code{vcond@var{m}@var{n}} instruction pattern
@item @samp{vcond@var{m}@var{n}}
Output a conditional vector move.  Operand 0 is the destination to
receive a combination of operand 1 and operand 2, which are of mode 
@var{m},
dependent on the outcome of the predicate in operand 3 which is a
vector comparison with operands of mode @var{n} in operands 4 and 5.  The
modes @var{m} and @var{n} should have the same size.  Operand 0
will be set to the value @var{op1} & @var{msk} | @var{op2} & ~@var{msk}
where @var{msk} is computed by element-wise evaluation of the vector
comparison with a truth value of all-ones and a false value of all-zeros.

not constraining the modes further than requiring the same size.

The two patches tested ok on x86_64-unknown-linux-gnu with {,-m32}.

Richard.

> Uros.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-30  9:19       ` Richard Guenther
@ 2011-08-30  9:24         ` Uros Bizjak
  2011-08-30  9:29           ` Jakub Jelinek
  0 siblings, 1 reply; 16+ messages in thread
From: Uros Bizjak @ 2011-08-30  9:24 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, uros, rth, artyom.shinkaroff

On Tue, Aug 30, 2011 at 10:50 AM, Richard Guenther <rguenther@suse.de> wrote:


>> > Hm, ok - that was the first variant I tried (well, but with modeless
>> > operands 1 and 2, to keep 4 and 5 selcting int vs. fp compare).  But
>> > modeless operands get you that annoying warning from the gen* programs.
>>
>> Only for define_insn, if your c_test does not include string "operands".
>>
>> > How'd you ask if a pattern is available for vcondv4si with v4sf
>> > operands 4 and 5?  The vectorizer would need to be able to ask this
>> > question.
>>
>> Maybe with something along the lines of:
>>
>> (define_expand "vcond<mode>"
>>   [(set (match_operand:VI124_128 0 "register_operand" "")
>>       (if_then_else:VI124_128
>>         (match_operator 3 ""
>>           [(match_operand 4 "nonimmediate_operand" "")
>>            (match_operand 5 "nonimmediate_operand" "")])
>>         (match_operand:VI124_128 1 "general_operand" "")
>>         (match_operand:VI124_128 2 "general_operand" "")))]
>>   "TARGET_SSE2"
>> {
>>   if (GET_MODE (operands[4]) != GET_MODE (operands[5])
>>       || (GET_MODE_NUNITS (GET_MODE (operands[4]))
>>                 != GET_MODE_NUNITS (GET_MODE (operands[0]))))
>>     FAIL;
>>
>>   bool ok = ix86_expand_int_vcond (operands);
>>   gcc_assert (ok);
>>   DONE;
>> })
>>
>> This means that vcond pattern is allowed to FAIL, so when vectorizer
>> tentatively tries to expand the pattern, FAIL signalizes that operand
>> modes are not supported.
>
> Hmm.  But then I'd have to try emit an insn, right?  Currently
> the vectorizer simply looks for an optab handler ... the
> operands are not readily available (but their mode is known).
> So I'd create some fake regs, setup operands and call GEN_FCN
> on it?  If it succeds I'd have to delete emitted insns, etc.
> Or I could add a target hook ...

Hm... indeed, too much complication...

I'd say, let's go with modeless operands and a target hook. IMO, this
is much more flexible than checking optab for supported modes.
Existing way is appropriate for single mode patterns, but we have
interdependent modes here, at least on x86.

The hook would have two input arguments, insn mode and compare mode,
where the hook returns suggested supported compare mode, or no mode,
if it really can't handle requested modes.

> That shifts the ugliness towards the users, for just saving
> a few redundant patterns?

I think that hook solves this in the most elegant way.

Uros.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-30  9:24         ` Uros Bizjak
@ 2011-08-30  9:29           ` Jakub Jelinek
  2011-08-30  9:39             ` Richard Guenther
  2011-08-30  9:42             ` Uros Bizjak
  0 siblings, 2 replies; 16+ messages in thread
From: Jakub Jelinek @ 2011-08-30  9:29 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: Richard Guenther, gcc-patches, uros, rth, artyom.shinkaroff

On Tue, Aug 30, 2011 at 11:02:02AM +0200, Uros Bizjak wrote:
> > Hmm.  But then I'd have to try emit an insn, right?  Currently
> > the vectorizer simply looks for an optab handler ... the
> > operands are not readily available (but their mode is known).
> > So I'd create some fake regs, setup operands and call GEN_FCN
> > on it?  If it succeds I'd have to delete emitted insns, etc.
> > Or I could add a target hook ...
> 
> Hm... indeed, too much complication...
> 
> I'd say, let's go with modeless operands and a target hook. IMO, this
> is much more flexible than checking optab for supported modes.
> Existing way is appropriate for single mode patterns, but we have
> interdependent modes here, at least on x86.
> 
> The hook would have two input arguments, insn mode and compare mode,
> where the hook returns suggested supported compare mode, or no mode,
> if it really can't handle requested modes.

I think a two mode vcond pattern is in fact much cleaner than
a one mode + modeless pattern which gen* will complain about and
a target hook.

	Jakub

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-30  9:29           ` Jakub Jelinek
@ 2011-08-30  9:39             ` Richard Guenther
  2011-08-30  9:42             ` Uros Bizjak
  1 sibling, 0 replies; 16+ messages in thread
From: Richard Guenther @ 2011-08-30  9:39 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Uros Bizjak, gcc-patches, uros, rth, artyom.shinkaroff

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1530 bytes --]

On Tue, 30 Aug 2011, Jakub Jelinek wrote:

> On Tue, Aug 30, 2011 at 11:02:02AM +0200, Uros Bizjak wrote:
> > > Hmm.  But then I'd have to try emit an insn, right?  Currently
> > > the vectorizer simply looks for an optab handler ... the
> > > operands are not readily available (but their mode is known).
> > > So I'd create some fake regs, setup operands and call GEN_FCN
> > > on it?  If it succeds I'd have to delete emitted insns, etc.
> > > Or I could add a target hook ...
> > 
> > Hm... indeed, too much complication...
> > 
> > I'd say, let's go with modeless operands and a target hook. IMO, this
> > is much more flexible than checking optab for supported modes.
> > Existing way is appropriate for single mode patterns, but we have
> > interdependent modes here, at least on x86.
> > 
> > The hook would have two input arguments, insn mode and compare mode,
> > where the hook returns suggested supported compare mode, or no mode,
> > if it really can't handle requested modes.
> 
> I think a two mode vcond pattern is in fact much cleaner than
> a one mode + modeless pattern which gen* will complain about and
> a target hook.

Btw, what I meant with lumping together two insns in vcond is
that it is really a combination of vcreatecondmask<mode> where
mode is the comparison and mask mode, a convert-move and a
vapplycondmask<mode> where the mode is now the mode of the values
and the converted mask.  But that would of course make it difficult
for targets with vector condition codes to support vcond.

Richard.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-30  9:29           ` Jakub Jelinek
  2011-08-30  9:39             ` Richard Guenther
@ 2011-08-30  9:42             ` Uros Bizjak
  2011-08-30 10:17               ` Richard Guenther
  1 sibling, 1 reply; 16+ messages in thread
From: Uros Bizjak @ 2011-08-30  9:42 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Richard Guenther, gcc-patches, uros, rth, artyom.shinkaroff

On Tue, Aug 30, 2011 at 11:07 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Tue, Aug 30, 2011 at 11:02:02AM +0200, Uros Bizjak wrote:
>> > Hmm.  But then I'd have to try emit an insn, right?  Currently
>> > the vectorizer simply looks for an optab handler ... the
>> > operands are not readily available (but their mode is known).
>> > So I'd create some fake regs, setup operands and call GEN_FCN
>> > on it?  If it succeds I'd have to delete emitted insns, etc.
>> > Or I could add a target hook ...
>>
>> Hm... indeed, too much complication...
>>
>> I'd say, let's go with modeless operands and a target hook. IMO, this
>> is much more flexible than checking optab for supported modes.
>> Existing way is appropriate for single mode patterns, but we have
>> interdependent modes here, at least on x86.
>>
>> The hook would have two input arguments, insn mode and compare mode,
>> where the hook returns suggested supported compare mode, or no mode,
>> if it really can't handle requested modes.
>
> I think a two mode vcond pattern is in fact much cleaner than
> a one mode + modeless pattern which gen* will complain about and
> a target hook.

OK, but in this case, do not use mode iterators too much in order to
avoid invalid patterns.

Uros.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-30  9:42             ` Uros Bizjak
@ 2011-08-30 10:17               ` Richard Guenther
  2011-08-30 10:48                 ` Uros Bizjak
  0 siblings, 1 reply; 16+ messages in thread
From: Richard Guenther @ 2011-08-30 10:17 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: Jakub Jelinek, gcc-patches, uros, rth, artyom.shinkaroff

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1551 bytes --]

On Tue, 30 Aug 2011, Uros Bizjak wrote:

> On Tue, Aug 30, 2011 at 11:07 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> > On Tue, Aug 30, 2011 at 11:02:02AM +0200, Uros Bizjak wrote:
> >> > Hmm.  But then I'd have to try emit an insn, right?  Currently
> >> > the vectorizer simply looks for an optab handler ... the
> >> > operands are not readily available (but their mode is known).
> >> > So I'd create some fake regs, setup operands and call GEN_FCN
> >> > on it?  If it succeds I'd have to delete emitted insns, etc.
> >> > Or I could add a target hook ...
> >>
> >> Hm... indeed, too much complication...
> >>
> >> I'd say, let's go with modeless operands and a target hook. IMO, this
> >> is much more flexible than checking optab for supported modes.
> >> Existing way is appropriate for single mode patterns, but we have
> >> interdependent modes here, at least on x86.
> >>
> >> The hook would have two input arguments, insn mode and compare mode,
> >> where the hook returns suggested supported compare mode, or no mode,
> >> if it really can't handle requested modes.
> >
> > I think a two mode vcond pattern is in fact much cleaner than
> > a one mode + modeless pattern which gen* will complain about and
> > a target hook.
> 
> OK, but in this case, do not use mode iterators too much in order to
> avoid invalid patterns.

I don't see them as "invalid".  They will be unused (maybe combine
would create them though?), but they have well-defined semantics
with my proposed documentation.  And x86 can handle them just fine.

Richard.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-30 10:17               ` Richard Guenther
@ 2011-08-30 10:48                 ` Uros Bizjak
  2011-08-30 11:59                   ` Richard Guenther
  0 siblings, 1 reply; 16+ messages in thread
From: Uros Bizjak @ 2011-08-30 10:48 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Jakub Jelinek, gcc-patches, uros, rth, artyom.shinkaroff

On Tue, Aug 30, 2011 at 11:15 AM, Richard Guenther <rguenther@suse.de> wrote:

>> >> > Hmm.  But then I'd have to try emit an insn, right?  Currently
>> >> > the vectorizer simply looks for an optab handler ... the
>> >> > operands are not readily available (but their mode is known).
>> >> > So I'd create some fake regs, setup operands and call GEN_FCN
>> >> > on it?  If it succeds I'd have to delete emitted insns, etc.
>> >> > Or I could add a target hook ...
>> >>
>> >> Hm... indeed, too much complication...
>> >>
>> >> I'd say, let's go with modeless operands and a target hook. IMO, this
>> >> is much more flexible than checking optab for supported modes.
>> >> Existing way is appropriate for single mode patterns, but we have
>> >> interdependent modes here, at least on x86.
>> >>
>> >> The hook would have two input arguments, insn mode and compare mode,
>> >> where the hook returns suggested supported compare mode, or no mode,
>> >> if it really can't handle requested modes.
>> >
>> > I think a two mode vcond pattern is in fact much cleaner than
>> > a one mode + modeless pattern which gen* will complain about and
>> > a target hook.
>>
>> OK, but in this case, do not use mode iterators too much in order to
>> avoid invalid patterns.
>
> I don't see them as "invalid".  They will be unused (maybe combine
> would create them though?), but they have well-defined semantics
> with my proposed documentation.  And x86 can handle them just fine.

OK, let's go this way then... We can clean up this later if at all.

Uros.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-30 10:48                 ` Uros Bizjak
@ 2011-08-30 11:59                   ` Richard Guenther
  2011-08-30 12:11                     ` Richard Guenther
  0 siblings, 1 reply; 16+ messages in thread
From: Richard Guenther @ 2011-08-30 11:59 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: Jakub Jelinek, gcc-patches, uros, rth, artyom.shinkaroff

[-- Attachment #1: Type: TEXT/PLAIN, Size: 32928 bytes --]

On Tue, 30 Aug 2011, Uros Bizjak wrote:

> On Tue, Aug 30, 2011 at 11:15 AM, Richard Guenther <rguenther@suse.de> wrote:
> 
> >> >> > Hmm.  But then I'd have to try emit an insn, right?  Currently
> >> >> > the vectorizer simply looks for an optab handler ... the
> >> >> > operands are not readily available (but their mode is known).
> >> >> > So I'd create some fake regs, setup operands and call GEN_FCN
> >> >> > on it?  If it succeds I'd have to delete emitted insns, etc.
> >> >> > Or I could add a target hook ...
> >> >>
> >> >> Hm... indeed, too much complication...
> >> >>
> >> >> I'd say, let's go with modeless operands and a target hook. IMO, this
> >> >> is much more flexible than checking optab for supported modes.
> >> >> Existing way is appropriate for single mode patterns, but we have
> >> >> interdependent modes here, at least on x86.
> >> >>
> >> >> The hook would have two input arguments, insn mode and compare mode,
> >> >> where the hook returns suggested supported compare mode, or no mode,
> >> >> if it really can't handle requested modes.
> >> >
> >> > I think a two mode vcond pattern is in fact much cleaner than
> >> > a one mode + modeless pattern which gen* will complain about and
> >> > a target hook.
> >>
> >> OK, but in this case, do not use mode iterators too much in order to
> >> avoid invalid patterns.
> >
> > I don't see them as "invalid".  They will be unused (maybe combine
> > would create them though?), but they have well-defined semantics
> > with my proposed documentation.  And x86 can handle them just fine.
> 
> OK, let's go this way then... We can clean up this later if at all.

Certainly what I prefer (less work for me now) ;)  The smallest
number of patterns would probably result from using vcond<mode><mode>
to cover the same-mode cases and then add the 12 other patterns
with the respective integer / float mode variant.  Thus we'd have
15 patterns in total (still much for my taste).

Ideally we could have a mode attribute that would map possibly
to an iterator, thus

(define_mode_attr matching [(V4SF ["V4SF" "V4SI"]) (V8HI "V8HI") ...])

or similar.  But I don't feel like adding this sort of mode
attr that really is a hidden iterator ... ;)

Thus, the following is the combined patch which bootstrapped and
tested ok on x86_64-unknown-linux-gnu with {,-m32} over night,
with the documentation for vcond added.

Ok for trunk?

Thanks,
Richard.

2011-08-30  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/27460
	PR middle-end/29269
	* doc/md.texi (vcond): Document.
	* genopinit.c (optabs): Turn vcond{,u}_optab into a conversion
	optab with two modes.
	* optabs.h (enum convert_optab_index): Add COI_vcond, COI_vcondu.
	(enum direct_optab_index): Remove DOI_vcond, DOI_vcondu.
	(vcond_optab): Adjust.
	(vcondu_optab): Likewise.
	(expand_vec_cond_expr_p): Adjust prototype.
	* optabs.c (get_vcond_icode): Adjust.
	(expand_vec_cond_expr_p): Likewise.
	(expand_vec_cond_expr): Likewise.
	* tree-vect-stmts.c (vect_is_simple_cond): Return the comparison
	vector type.
	(vectorizable_condition): Allow differing types for comparison
	and result.

	* config/i386/i386.c (ix86_expand_sse_cmp): Use proper mode
	for the comparison.
	* config/i386/sse.md (vcond<mode>): Split to
	vcond<V_256:mode><VF_256:mode>, vcond<V_128:mode><VF_128:mode>,
	vcond<V_128:mode><VI124_128:mode> and
	vcondu<V_128:mode><VI124_128:mode>.
	(vcondv2di): Change to vcond<VI8F_128:mode>v2di.
	(vconduv2di): Likewise.
	* config/arm/neon.md (vcond<mode>): Change to vcond*<mode><mode>.
	(vcondu<mode>): Likewise.
	* config/ia64/vect.md (vcond<mode>): Likewise.
	(vcondu<mode>): Likewise.
	(vcondv2sf): Likewise.
	* config/mips/mips-ps-3d.md (vcondv2sf): Likewise.
	* config/rs6000/paired.md (vcondv2sf): Likewise.
	* config/rs6000/vector.md (vcond<mode>): Likewise.
	(vcondu<mode>): Likewise.
	* config/spu/spu.md (vcond<mode>): Likewise.
	(vcondu<mode>): Likewise.

	* gcc.dg/vect/vect-cond-7.c: New testcase.

Index: trunk/gcc/config/arm/neon.md
===================================================================
*** trunk.orig/gcc/config/arm/neon.md	2011-08-30 10:50:52.000000000 +0200
--- trunk/gcc/config/arm/neon.md	2011-08-30 10:51:30.000000000 +0200
***************
*** 1600,1606 ****
  ;; where op3 is <, <=, ==, !=, >= or >.  Operations are performed
  ;; element-wise.
  
! (define_expand "vcond<mode>"
    [(set (match_operand:VDQW 0 "s_register_operand" "")
  	(if_then_else:VDQW
  	  (match_operator 3 "arm_comparison_operator"
--- 1600,1606 ----
  ;; where op3 is <, <=, ==, !=, >= or >.  Operations are performed
  ;; element-wise.
  
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VDQW 0 "s_register_operand" "")
  	(if_then_else:VDQW
  	  (match_operator 3 "arm_comparison_operator"
***************
*** 1680,1686 ****
    DONE;
  })
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VDQIW 0 "s_register_operand" "")
  	(if_then_else:VDQIW
  	  (match_operator 3 "arm_comparison_operator"
--- 1680,1686 ----
    DONE;
  })
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VDQIW 0 "s_register_operand" "")
  	(if_then_else:VDQIW
  	  (match_operator 3 "arm_comparison_operator"
Index: trunk/gcc/config/i386/sse.md
===================================================================
*** trunk.orig/gcc/config/i386/sse.md	2011-08-30 10:50:52.000000000 +0200
--- trunk/gcc/config/i386/sse.md	2011-08-30 10:51:30.000000000 +0200
***************
*** 1405,1418 ****
  		      (const_string "0")))
     (set_attr "mode" "<MODE>")])
  
! (define_expand "vcond<mode>"
!   [(set (match_operand:VF 0 "register_operand" "")
! 	(if_then_else:VF
  	  (match_operator 3 ""
! 	    [(match_operand:VF 4 "nonimmediate_operand" "")
! 	     (match_operand:VF 5 "nonimmediate_operand" "")])
! 	  (match_operand:VF 1 "general_operand" "")
! 	  (match_operand:VF 2 "general_operand" "")))]
    "TARGET_SSE"
  {
    bool ok = ix86_expand_fp_vcond (operands);
--- 1405,1433 ----
  		      (const_string "0")))
     (set_attr "mode" "<MODE>")])
  
! (define_expand "vcond<V_256:mode><VF_256:mode>"
!   [(set (match_operand:V_256 0 "register_operand" "")
! 	(if_then_else:V_256
  	  (match_operator 3 ""
! 	    [(match_operand:VF_256 4 "nonimmediate_operand" "")
! 	     (match_operand:VF_256 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_256 1 "general_operand" "")
! 	  (match_operand:V_256 2 "general_operand" "")))]
!   "TARGET_AVX"
! {
!   bool ok = ix86_expand_fp_vcond (operands);
!   gcc_assert (ok);
!   DONE;
! })
! 
! (define_expand "vcond<V_128:mode><VF_128:mode>"
!   [(set (match_operand:V_128 0 "register_operand" "")
! 	(if_then_else:V_128
! 	  (match_operator 3 ""
! 	    [(match_operand:VF_128 4 "nonimmediate_operand" "")
! 	     (match_operand:VF_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_128 1 "general_operand" "")
! 	  (match_operand:V_128 2 "general_operand" "")))]
    "TARGET_SSE"
  {
    bool ok = ix86_expand_fp_vcond (operands);
***************
*** 6091,6104 ****
     (set_attr "prefix" "orig,vex")
     (set_attr "mode" "TI")])
  
! (define_expand "vcond<mode>"
!   [(set (match_operand:VI124_128 0 "register_operand" "")
! 	(if_then_else:VI124_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI124_128 1 "general_operand" "")
! 	  (match_operand:VI124_128 2 "general_operand" "")))]
    "TARGET_SSE2"
  {
    bool ok = ix86_expand_int_vcond (operands);
--- 6106,6119 ----
     (set_attr "prefix" "orig,vex")
     (set_attr "mode" "TI")])
  
! (define_expand "vcond<V_128:mode><VI124_128:mode>"
!   [(set (match_operand:V_128 0 "register_operand" "")
! 	(if_then_else:V_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_128 1 "general_operand" "")
! 	  (match_operand:V_128 2 "general_operand" "")))]
    "TARGET_SSE2"
  {
    bool ok = ix86_expand_int_vcond (operands);
***************
*** 6106,6119 ****
    DONE;
  })
  
! (define_expand "vcondv2di"
!   [(set (match_operand:V2DI 0 "register_operand" "")
! 	(if_then_else:V2DI
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:V2DI 1 "general_operand" "")
! 	  (match_operand:V2DI 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
--- 6121,6134 ----
    DONE;
  })
  
! (define_expand "vcond<VI8F_128:mode>v2di"
!   [(set (match_operand:VI8F_128 0 "register_operand" "")
! 	(if_then_else:VI8F_128
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI8F_128 1 "general_operand" "")
! 	  (match_operand:VI8F_128 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
***************
*** 6121,6134 ****
    DONE;
  })
  
! (define_expand "vcondu<mode>"
!   [(set (match_operand:VI124_128 0 "register_operand" "")
! 	(if_then_else:VI124_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI124_128 1 "general_operand" "")
! 	  (match_operand:VI124_128 2 "general_operand" "")))]
    "TARGET_SSE2"
  {
    bool ok = ix86_expand_int_vcond (operands);
--- 6136,6149 ----
    DONE;
  })
  
! (define_expand "vcondu<V_128:mode><VI124_128:mode>"
!   [(set (match_operand:V_128 0 "register_operand" "")
! 	(if_then_else:V_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_128 1 "general_operand" "")
! 	  (match_operand:V_128 2 "general_operand" "")))]
    "TARGET_SSE2"
  {
    bool ok = ix86_expand_int_vcond (operands);
***************
*** 6136,6149 ****
    DONE;
  })
  
! (define_expand "vconduv2di"
!   [(set (match_operand:V2DI 0 "register_operand" "")
! 	(if_then_else:V2DI
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:V2DI 1 "general_operand" "")
! 	  (match_operand:V2DI 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
--- 6151,6164 ----
    DONE;
  })
  
! (define_expand "vcondu<VI8F_128:mode>v2di"
!   [(set (match_operand:VI8F_128 0 "register_operand" "")
! 	(if_then_else:VI8F_128
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI8F_128 1 "general_operand" "")
! 	  (match_operand:VI8F_128 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
Index: trunk/gcc/config/ia64/vect.md
===================================================================
*** trunk.orig/gcc/config/ia64/vect.md	2011-08-30 10:50:52.000000000 +0200
--- trunk/gcc/config/ia64/vect.md	2011-08-30 10:51:30.000000000 +0200
***************
*** 661,667 ****
    DONE;
  })
  
! (define_expand "vcond<mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
--- 661,667 ----
    DONE;
  })
  
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
***************
*** 675,681 ****
    DONE;
  })
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
--- 675,681 ----
    DONE;
  })
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
***************
*** 1382,1388 ****
    DONE;
  })
  
! (define_expand "vcondv2sf"
    [(set (match_operand:V2SF 0 "fr_register_operand" "")
  	(if_then_else:V2SF
  	  (match_operator 3 "" 
--- 1382,1388 ----
    DONE;
  })
  
! (define_expand "vcondv2sfv2sf"
    [(set (match_operand:V2SF 0 "fr_register_operand" "")
  	(if_then_else:V2SF
  	  (match_operator 3 "" 
Index: trunk/gcc/config/mips/mips-ps-3d.md
===================================================================
*** trunk.orig/gcc/config/mips/mips-ps-3d.md	2011-08-30 10:50:52.000000000 +0200
--- trunk/gcc/config/mips/mips-ps-3d.md	2011-08-30 10:51:30.000000000 +0200
***************
*** 597,603 ****
    [(set_attr "type" "frdiv2")
     (set_attr "mode" "<UNITMODE>")])
  
! (define_expand "vcondv2sf"
    [(set (match_operand:V2SF 0 "register_operand")
  	(if_then_else:V2SF
  	  (match_operator 3 ""
--- 597,603 ----
    [(set_attr "type" "frdiv2")
     (set_attr "mode" "<UNITMODE>")])
  
! (define_expand "vcondv2sfv2sf"
    [(set (match_operand:V2SF 0 "register_operand")
  	(if_then_else:V2SF
  	  (match_operator 3 ""
Index: trunk/gcc/config/rs6000/paired.md
===================================================================
*** trunk.orig/gcc/config/rs6000/paired.md	2011-08-30 10:50:52.000000000 +0200
--- trunk/gcc/config/rs6000/paired.md	2011-08-30 10:51:30.000000000 +0200
***************
*** 507,513 ****
    DONE;
  })
  
! (define_expand "vcondv2sf"
    [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
          (if_then_else:V2SF
           (match_operator 3 "gpc_reg_operand"
--- 507,513 ----
    DONE;
  })
  
! (define_expand "vcondv2sfv2sf"
    [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
          (if_then_else:V2SF
           (match_operator 3 "gpc_reg_operand"
Index: trunk/gcc/config/rs6000/vector.md
===================================================================
*** trunk.orig/gcc/config/rs6000/vector.md	2011-08-30 10:50:52.000000000 +0200
--- trunk/gcc/config/rs6000/vector.md	2011-08-30 10:51:30.000000000 +0200
***************
*** 370,376 ****
  
  \f
  ;; Vector comparisons
! (define_expand "vcond<mode>"
    [(set (match_operand:VEC_F 0 "vfloat_operand" "")
  	(if_then_else:VEC_F
  	 (match_operator 3 "comparison_operator"
--- 370,376 ----
  
  \f
  ;; Vector comparisons
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VEC_F 0 "vfloat_operand" "")
  	(if_then_else:VEC_F
  	 (match_operator 3 "comparison_operator"
***************
*** 388,394 ****
      FAIL;
  }")
  
! (define_expand "vcond<mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
--- 388,394 ----
      FAIL;
  }")
  
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
***************
*** 406,412 ****
      FAIL;
  }")
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
--- 406,412 ----
      FAIL;
  }")
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
Index: trunk/gcc/config/spu/spu.md
===================================================================
*** trunk.orig/gcc/config/spu/spu.md	2011-08-30 10:50:52.000000000 +0200
--- trunk/gcc/config/spu/spu.md	2011-08-30 10:51:30.000000000 +0200
*************** selb\t%0,%4,%0,%3"
*** 3874,3880 ****
  
  \f
  ;; vector conditional compare patterns
! (define_expand "vcond<mode>"
    [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
          (if_then_else:VCMP
            (match_operator 3 "comparison_operator"
--- 3874,3880 ----
  
  \f
  ;; vector conditional compare patterns
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
          (if_then_else:VCMP
            (match_operator 3 "comparison_operator"
*************** selb\t%0,%4,%0,%3"
*** 3891,3897 ****
      FAIL;
    })
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
          (if_then_else:VCMPU
            (match_operator 3 "comparison_operator"
--- 3891,3897 ----
      FAIL;
    })
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
          (if_then_else:VCMPU
            (match_operator 3 "comparison_operator"
Index: trunk/gcc/genopinit.c
===================================================================
*** trunk.orig/gcc/genopinit.c	2011-08-30 10:50:52.000000000 +0200
--- trunk/gcc/genopinit.c	2011-08-30 10:51:30.000000000 +0200
*************** static const char * const optabs[] =
*** 253,260 ****
    "set_optab_handler (vec_shl_optab, $A, CODE_FOR_$(vec_shl_$a$))",
    "set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
    "set_optab_handler (vec_realign_load_optab, $A, CODE_FOR_$(vec_realign_load_$a$))",
!   "set_direct_optab_handler (vcond_optab, $A, CODE_FOR_$(vcond$a$))",
!   "set_direct_optab_handler (vcondu_optab, $A, CODE_FOR_$(vcondu$a$))",
    "set_optab_handler (ssum_widen_optab, $A, CODE_FOR_$(widen_ssum$I$a3$))",
    "set_optab_handler (usum_widen_optab, $A, CODE_FOR_$(widen_usum$I$a3$))",
    "set_optab_handler (udot_prod_optab, $A, CODE_FOR_$(udot_prod$I$a$))",
--- 253,260 ----
    "set_optab_handler (vec_shl_optab, $A, CODE_FOR_$(vec_shl_$a$))",
    "set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
    "set_optab_handler (vec_realign_load_optab, $A, CODE_FOR_$(vec_realign_load_$a$))",
!   "set_convert_optab_handler (vcond_optab, $A, $B, CODE_FOR_$(vcond$a$b$))",
!   "set_convert_optab_handler (vcondu_optab, $A, $B, CODE_FOR_$(vcondu$a$b$))",
    "set_optab_handler (ssum_widen_optab, $A, CODE_FOR_$(widen_ssum$I$a3$))",
    "set_optab_handler (usum_widen_optab, $A, CODE_FOR_$(widen_usum$I$a3$))",
    "set_optab_handler (udot_prod_optab, $A, CODE_FOR_$(udot_prod$I$a$))",
Index: trunk/gcc/optabs.c
===================================================================
*** trunk.orig/gcc/optabs.c	2011-08-30 10:50:52.000000000 +0200
--- trunk/gcc/optabs.c	2011-08-30 10:51:30.000000000 +0200
*************** vector_compare_rtx (tree cond, bool unsi
*** 6620,6646 ****
    return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
  }
  
! /* Return insn code for TYPE, the type of a VEC_COND_EXPR.  */
  
  static inline enum insn_code
! get_vcond_icode (tree type, enum machine_mode mode)
  {
    enum insn_code icode = CODE_FOR_nothing;
! 
!   if (TYPE_UNSIGNED (type))
!     icode = direct_optab_handler (vcondu_optab, mode);
    else
!     icode = direct_optab_handler (vcond_optab, mode);
    return icode;
  }
  
  /* Return TRUE iff, appropriate vector insns are available
!    for vector cond expr with type TYPE in VMODE mode.  */
  
  bool
! expand_vec_cond_expr_p (tree type, enum machine_mode vmode)
  {
!   if (get_vcond_icode (type, vmode) == CODE_FOR_nothing)
      return false;
    return true;
  }
--- 6620,6652 ----
    return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
  }
  
! /* Return insn code for a conditional operator with a comparison in
!    mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE.  */
  
  static inline enum insn_code
! get_vcond_icode (enum machine_mode vmode, enum machine_mode cmode, bool uns)
  {
    enum insn_code icode = CODE_FOR_nothing;
!   if (uns)
!     icode = convert_optab_handler (vcondu_optab, vmode, cmode);
    else
!     icode = convert_optab_handler (vcond_optab, vmode, cmode);
    return icode;
  }
  
  /* Return TRUE iff, appropriate vector insns are available
!    for vector cond expr with vector type VALUE_TYPE and a comparison
!    with operand vector types in CMP_OP_TYPE.  */
  
  bool
! expand_vec_cond_expr_p (tree value_type, tree cmp_op_type)
  {
!   enum machine_mode value_mode = TYPE_MODE (value_type);
!   enum machine_mode cmp_op_mode = TYPE_MODE (cmp_op_type);
!   if (GET_MODE_SIZE (value_mode) != GET_MODE_SIZE (cmp_op_mode)
!       || GET_MODE_NUNITS (value_mode) != GET_MODE_NUNITS (cmp_op_mode)
!       || get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
! 			  TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing)
      return false;
    return true;
  }
*************** expand_vec_cond_expr (tree vec_cond_type
*** 6656,6664 ****
    enum insn_code icode;
    rtx comparison, rtx_op1, rtx_op2;
    enum machine_mode mode = TYPE_MODE (vec_cond_type);
!   bool unsignedp = TYPE_UNSIGNED (vec_cond_type);
  
!   icode = get_vcond_icode (vec_cond_type, mode);
    if (icode == CODE_FOR_nothing)
      return 0;
  
--- 6662,6679 ----
    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;
! 
!   gcc_assert (COMPARISON_CLASS_P (op0));
! 
!   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;
  
Index: trunk/gcc/optabs.h
===================================================================
*** trunk.orig/gcc/optabs.h	2011-08-30 10:50:52.000000000 +0200
--- trunk/gcc/optabs.h	2011-08-30 10:51:30.000000000 +0200
*************** enum convert_optab_index
*** 589,594 ****
--- 589,598 ----
    COI_vec_load_lanes,
    COI_vec_store_lanes,
  
+   /* Vector conditional operations.  */
+   COI_vcond,
+   COI_vcondu,
+ 
    COI_MAX
  };
  
*************** enum convert_optab_index
*** 611,616 ****
--- 615,622 ----
  #define satfractuns_optab (&convert_optab_table[COI_satfractuns])
  #define vec_load_lanes_optab (&convert_optab_table[COI_vec_load_lanes])
  #define vec_store_lanes_optab (&convert_optab_table[COI_vec_store_lanes])
+ #define vcond_optab (&convert_optab_table[(int) COI_vcond])
+ #define vcondu_optab (&convert_optab_table[(int) COI_vcondu])
  
  /* Contains the optab used for each rtx code.  */
  extern optab code_to_optab[NUM_RTX_CODE + 1];
*************** enum direct_optab_index
*** 632,641 ****
    DOI_reload_in,
    DOI_reload_out,
  
-   /* Vector conditional operations.  */
-   DOI_vcond,
-   DOI_vcondu,
- 
    /* Block move operation.  */
    DOI_movmem,
  
--- 638,643 ----
*************** typedef struct direct_optab_d *direct_op
*** 699,706 ****
  #endif
  #define reload_in_optab (&direct_optab_table[(int) DOI_reload_in])
  #define reload_out_optab (&direct_optab_table[(int) DOI_reload_out])
- #define vcond_optab (&direct_optab_table[(int) DOI_vcond])
- #define vcondu_optab (&direct_optab_table[(int) DOI_vcondu])
  #define movmem_optab (&direct_optab_table[(int) DOI_movmem])
  #define setmem_optab (&direct_optab_table[(int) DOI_setmem])
  #define cmpstr_optab (&direct_optab_table[(int) DOI_cmpstr])
--- 701,706 ----
*************** extern bool expand_sfix_optab (rtx, rtx,
*** 877,883 ****
  extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab);
  
  /* Return tree if target supports vector operations for COND_EXPR.  */
! bool expand_vec_cond_expr_p (tree, enum machine_mode);
  
  /* Generate code for VEC_COND_EXPR.  */
  extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
--- 877,883 ----
  extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab);
  
  /* Return tree if target supports vector operations for COND_EXPR.  */
! bool expand_vec_cond_expr_p (tree, tree);
  
  /* Generate code for VEC_COND_EXPR.  */
  extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
Index: trunk/gcc/tree-vect-stmts.c
===================================================================
*** trunk.orig/gcc/tree-vect-stmts.c	2011-08-30 10:50:52.000000000 +0200
--- trunk/gcc/tree-vect-stmts.c	2011-08-30 10:51:30.000000000 +0200
*************** vectorizable_load (gimple stmt, gimple_s
*** 4680,4694 ****
     LOOP - the loop that is being vectorized.
     COND - Condition that is checked for simple use.
  
     Returns whether a COND can be vectorized.  Checks whether
     condition operands are supportable using vec_is_simple_use.  */
  
  static bool
! vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
  {
    tree lhs, rhs;
    tree def;
    enum vect_def_type dt;
  
    if (!COMPARISON_CLASS_P (cond))
      return false;
--- 4680,4698 ----
     LOOP - the loop that is being vectorized.
     COND - Condition that is checked for simple use.
  
+    Output:
+    *COMP_VECTYPE - the vector type for the comparison.
+ 
     Returns whether a COND can be vectorized.  Checks whether
     condition operands are supportable using vec_is_simple_use.  */
  
  static bool
! vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype)
  {
    tree lhs, rhs;
    tree def;
    enum vect_def_type dt;
+   tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
  
    if (!COMPARISON_CLASS_P (cond))
      return false;
*************** vect_is_simple_cond (tree cond, loop_vec
*** 4699,4706 ****
    if (TREE_CODE (lhs) == SSA_NAME)
      {
        gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
!       if (!vect_is_simple_use (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
!                                &dt))
  	return false;
      }
    else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
--- 4703,4710 ----
    if (TREE_CODE (lhs) == SSA_NAME)
      {
        gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
!       if (!vect_is_simple_use_1 (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
! 				 &dt, &vectype1))
  	return false;
      }
    else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
*************** vect_is_simple_cond (tree cond, loop_vec
*** 4710,4723 ****
    if (TREE_CODE (rhs) == SSA_NAME)
      {
        gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
!       if (!vect_is_simple_use (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
!                                &dt))
  	return false;
      }
    else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
  	   && TREE_CODE (rhs) != FIXED_CST)
      return false;
  
    return true;
  }
  
--- 4714,4728 ----
    if (TREE_CODE (rhs) == SSA_NAME)
      {
        gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
!       if (!vect_is_simple_use_1 (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
! 				 &dt, &vectype2))
  	return false;
      }
    else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
  	   && TREE_CODE (rhs) != FIXED_CST)
      return false;
  
+   *comp_vectype = vectype1 ? vectype1 : vectype2;
    return true;
  }
  
*************** vectorizable_condition (gimple stmt, gim
*** 4744,4755 ****
    tree cond_expr, then_clause, else_clause;
    stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
    tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
    tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
    tree vec_compare, vec_cond_expr;
    tree new_temp;
    loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
-   enum machine_mode vec_mode;
    tree def;
    enum vect_def_type dt, dts[4];
    int nunits = TYPE_VECTOR_SUBPARTS (vectype);
--- 4749,4760 ----
    tree cond_expr, then_clause, else_clause;
    stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
    tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+   tree comp_vectype;
    tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
    tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
    tree vec_compare, vec_cond_expr;
    tree new_temp;
    loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
    tree def;
    enum vect_def_type dt, dts[4];
    int nunits = TYPE_VECTOR_SUBPARTS (vectype);
*************** vectorizable_condition (gimple stmt, gim
*** 4800,4812 ****
    then_clause = TREE_OPERAND (op, 1);
    else_clause = TREE_OPERAND (op, 2);
  
!   if (!vect_is_simple_cond (cond_expr, loop_vinfo))
!     return false;
! 
!   /* We do not handle two different vector types for the condition
!      and the values.  */
!   if (!types_compatible_p (TREE_TYPE (TREE_OPERAND (cond_expr, 0)),
! 			   TREE_TYPE (vectype)))
      return false;
  
    if (TREE_CODE (then_clause) == SSA_NAME)
--- 4805,4812 ----
    then_clause = TREE_OPERAND (op, 1);
    else_clause = TREE_OPERAND (op, 2);
  
!   if (!vect_is_simple_cond (cond_expr, loop_vinfo, &comp_vectype)
!       || !comp_vectype)
      return false;
  
    if (TREE_CODE (then_clause) == SSA_NAME)
*************** vectorizable_condition (gimple stmt, gim
*** 4833,4845 ****
  	   && TREE_CODE (else_clause) != FIXED_CST)
      return false;
  
- 
-   vec_mode = TYPE_MODE (vectype);
- 
    if (!vec_stmt)
      {
        STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
!       return expand_vec_cond_expr_p (TREE_TYPE (op), vec_mode);
      }
  
    /* Transform */
--- 4833,4842 ----
  	   && TREE_CODE (else_clause) != FIXED_CST)
      return false;
  
    if (!vec_stmt)
      {
        STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
!       return expand_vec_cond_expr_p (vectype, comp_vectype);
      }
  
    /* Transform */
Index: trunk/gcc/config/i386/i386.c
===================================================================
*** trunk.orig/gcc/config/i386/i386.c	2011-08-30 10:50:50.000000000 +0200
--- trunk/gcc/config/i386/i386.c	2011-08-30 10:51:30.000000000 +0200
*************** ix86_expand_sse_cmp (rtx dest, enum rtx_
*** 18412,18430 ****
  		     rtx op_true, rtx op_false)
  {
    enum machine_mode mode = GET_MODE (dest);
    rtx x;
  
!   cmp_op0 = force_reg (mode, cmp_op0);
!   if (!nonimmediate_operand (cmp_op1, mode))
!     cmp_op1 = force_reg (mode, cmp_op1);
  
    if (optimize
        || reg_overlap_mentioned_p (dest, op_true)
        || reg_overlap_mentioned_p (dest, op_false))
      dest = gen_reg_rtx (mode);
  
!   x = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
!   emit_insn (gen_rtx_SET (VOIDmode, dest, x));
  
    return dest;
  }
--- 18412,18437 ----
  		     rtx op_true, rtx op_false)
  {
    enum machine_mode mode = GET_MODE (dest);
+   enum machine_mode cmp_mode = GET_MODE (cmp_op0);
    rtx x;
  
!   cmp_op0 = force_reg (cmp_mode, cmp_op0);
!   if (!nonimmediate_operand (cmp_op1, cmp_mode))
!     cmp_op1 = force_reg (cmp_mode, cmp_op1);
  
    if (optimize
        || reg_overlap_mentioned_p (dest, op_true)
        || reg_overlap_mentioned_p (dest, op_false))
      dest = gen_reg_rtx (mode);
  
!   x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1);
!   if (cmp_mode != mode)
!     {
!       x = force_reg (cmp_mode, x);
!       convert_move (dest, x, false);
!     }
!   else
!     emit_insn (gen_rtx_SET (VOIDmode, dest, x));
  
    return dest;
  }
Index: trunk/gcc/testsuite/gcc.dg/vect/vect-cond-7.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/vect/vect-cond-7.c	2011-08-30 10:51:30.000000000 +0200
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-require-effective-target vect_condition } */
+ 
+ int vis_type[128];
+ float vs_data[128];
+ void vis_clear_data ()
+ {
+   int i;
+   for (i = 0; i < 128; i++)
+     vs_data[i] = (vis_type[i] == 1);
+ }
+ 
+ /* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
Index: trunk/gcc/doc/md.texi
===================================================================
*** trunk.orig/gcc/doc/md.texi	2011-08-30 10:50:50.000000000 +0200
--- trunk/gcc/doc/md.texi	2011-08-30 10:51:30.000000000 +0200
*************** and input vectors should have the same m
*** 4017,4022 ****
--- 4017,4033 ----
  Initialize the vector to given values.  Operand 0 is the vector to initialize
  and operand 1 is parallel containing values for individual fields.
  
+ @cindex @code{vcond@var{m}@var{n}} instruction pattern
+ @item @samp{vcond@var{m}@var{n}}
+ Output a conditional vector move.  Operand 0 is the destination to
+ receive a combination of operand 1 and operand 2, which are of mode @var{m},
+ dependent on the outcome of the predicate in operand 3 which is a
+ vector comparison with operands of mode @var{n} in operands 4 and 5.  The
+ modes @var{m} and @var{n} should have the same size.  Operand 0
+ will be set to the value @var{op1} & @var{msk} | @var{op2} & ~@var{msk}
+ where @var{msk} is computed by element-wise evaluation of the vector
+ comparison with a truth value of all-ones and a false value of all-zeros.
+ 
  @cindex @code{push@var{m}1} instruction pattern
  @item @samp{push@var{m}1}
  Output a push instruction.  Operand 0 is value to push.  Used only when

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-30 11:59                   ` Richard Guenther
@ 2011-08-30 12:11                     ` Richard Guenther
  2011-09-02  9:44                       ` Richard Guenther
  0 siblings, 1 reply; 16+ messages in thread
From: Richard Guenther @ 2011-08-30 12:11 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: Jakub Jelinek, gcc-patches, uros, rth, artyom.shinkaroff

[-- Attachment #1: Type: TEXT/PLAIN, Size: 33687 bytes --]

On Tue, 30 Aug 2011, Richard Guenther wrote:

> On Tue, 30 Aug 2011, Uros Bizjak wrote:
> 
> > On Tue, Aug 30, 2011 at 11:15 AM, Richard Guenther <rguenther@suse.de> wrote:
> > 
> > >> >> > Hmm.  But then I'd have to try emit an insn, right?  Currently
> > >> >> > the vectorizer simply looks for an optab handler ... the
> > >> >> > operands are not readily available (but their mode is known).
> > >> >> > So I'd create some fake regs, setup operands and call GEN_FCN
> > >> >> > on it?  If it succeds I'd have to delete emitted insns, etc.
> > >> >> > Or I could add a target hook ...
> > >> >>
> > >> >> Hm... indeed, too much complication...
> > >> >>
> > >> >> I'd say, let's go with modeless operands and a target hook. IMO, this
> > >> >> is much more flexible than checking optab for supported modes.
> > >> >> Existing way is appropriate for single mode patterns, but we have
> > >> >> interdependent modes here, at least on x86.
> > >> >>
> > >> >> The hook would have two input arguments, insn mode and compare mode,
> > >> >> where the hook returns suggested supported compare mode, or no mode,
> > >> >> if it really can't handle requested modes.
> > >> >
> > >> > I think a two mode vcond pattern is in fact much cleaner than
> > >> > a one mode + modeless pattern which gen* will complain about and
> > >> > a target hook.
> > >>
> > >> OK, but in this case, do not use mode iterators too much in order to
> > >> avoid invalid patterns.
> > >
> > > I don't see them as "invalid".  They will be unused (maybe combine
> > > would create them though?), but they have well-defined semantics
> > > with my proposed documentation.  And x86 can handle them just fine.
> > 
> > OK, let's go this way then... We can clean up this later if at all.
> 
> Certainly what I prefer (less work for me now) ;)  The smallest
> number of patterns would probably result from using vcond<mode><mode>
> to cover the same-mode cases and then add the 12 other patterns
> with the respective integer / float mode variant.  Thus we'd have
> 15 patterns in total (still much for my taste).
> 
> Ideally we could have a mode attribute that would map possibly
> to an iterator, thus
> 
> (define_mode_attr matching [(V4SF ["V4SF" "V4SI"]) (V8HI "V8HI") ...])
> 
> or similar.  But I don't feel like adding this sort of mode
> attr that really is a hidden iterator ... ;)
> 
> Thus, the following is the combined patch which bootstrapped and
> tested ok on x86_64-unknown-linux-gnu with {,-m32} over night,
> with the documentation for vcond added.
> 
> Ok for trunk?

I'm re-testing with the patterns having an extra condition like
   && (GET_MODE_NUNITS (<V_256:MODE>mode)
       == GET_MODE_NUNITS (<VF_256:MODE>mode))"
to have the HAVE_vcond* defines easily optimized.

Ok?

Thanks,
Richard.

2011-08-30  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/27460
	PR middle-end/29269
	* doc/md.texi (vcond): Document.
	* genopinit.c (optabs): Turn vcond{,u}_optab into a conversion
	optab with two modes.
	* optabs.h (enum convert_optab_index): Add COI_vcond, COI_vcondu.
	(enum direct_optab_index): Remove DOI_vcond, DOI_vcondu.
	(vcond_optab): Adjust.
	(vcondu_optab): Likewise.
	(expand_vec_cond_expr_p): Adjust prototype.
	* optabs.c (get_vcond_icode): Adjust.
	(expand_vec_cond_expr_p): Likewise.
	(expand_vec_cond_expr): Likewise.
	* tree-vect-stmts.c (vect_is_simple_cond): Return the comparison
	vector type.
	(vectorizable_condition): Allow differing types for comparison
	and result.

	* config/i386/i386.c (ix86_expand_sse_cmp): Use proper mode
	for the comparison.
	* config/i386/sse.md (vcond<mode>): Split to
	vcond<V_256:mode><VF_256:mode>, vcond<V_128:mode><VF_128:mode>,
	vcond<V_128:mode><VI124_128:mode> and
	vcondu<V_128:mode><VI124_128:mode>.
	(vcondv2di): Change to vcond<VI8F_128:mode>v2di.
	(vconduv2di): Likewise.
	* config/arm/neon.md (vcond<mode>): Change to vcond*<mode><mode>.
	(vcondu<mode>): Likewise.
	* config/ia64/vect.md (vcond<mode>): Likewise.
	(vcondu<mode>): Likewise.
	(vcondv2sf): Likewise.
	* config/mips/mips-ps-3d.md (vcondv2sf): Likewise.
	* config/rs6000/paired.md (vcondv2sf): Likewise.
	* config/rs6000/vector.md (vcond<mode>): Likewise.
	(vcondu<mode>): Likewise.
	* config/spu/spu.md (vcond<mode>): Likewise.
	(vcondu<mode>): Likewise.

	* gcc.dg/vect/vect-cond-7.c: New testcase.

Index: trunk/gcc/config/arm/neon.md
===================================================================
*** trunk.orig/gcc/config/arm/neon.md	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/config/arm/neon.md	2011-08-30 11:46:51.000000000 +0200
***************
*** 1600,1606 ****
  ;; where op3 is <, <=, ==, !=, >= or >.  Operations are performed
  ;; element-wise.
  
! (define_expand "vcond<mode>"
    [(set (match_operand:VDQW 0 "s_register_operand" "")
  	(if_then_else:VDQW
  	  (match_operator 3 "arm_comparison_operator"
--- 1600,1606 ----
  ;; where op3 is <, <=, ==, !=, >= or >.  Operations are performed
  ;; element-wise.
  
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VDQW 0 "s_register_operand" "")
  	(if_then_else:VDQW
  	  (match_operator 3 "arm_comparison_operator"
***************
*** 1680,1686 ****
    DONE;
  })
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VDQIW 0 "s_register_operand" "")
  	(if_then_else:VDQIW
  	  (match_operator 3 "arm_comparison_operator"
--- 1680,1686 ----
    DONE;
  })
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VDQIW 0 "s_register_operand" "")
  	(if_then_else:VDQIW
  	  (match_operator 3 "arm_comparison_operator"
Index: trunk/gcc/config/i386/sse.md
===================================================================
*** trunk.orig/gcc/config/i386/sse.md	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/config/i386/sse.md	2011-08-30 12:12:30.000000000 +0200
***************
*** 1405,1419 ****
  		      (const_string "0")))
     (set_attr "mode" "<MODE>")])
  
! (define_expand "vcond<mode>"
!   [(set (match_operand:VF 0 "register_operand" "")
! 	(if_then_else:VF
  	  (match_operator 3 ""
! 	    [(match_operand:VF 4 "nonimmediate_operand" "")
! 	     (match_operand:VF 5 "nonimmediate_operand" "")])
! 	  (match_operand:VF 1 "general_operand" "")
! 	  (match_operand:VF 2 "general_operand" "")))]
!   "TARGET_SSE"
  {
    bool ok = ix86_expand_fp_vcond (operands);
    gcc_assert (ok);
--- 1405,1438 ----
  		      (const_string "0")))
     (set_attr "mode" "<MODE>")])
  
! (define_expand "vcond<V_256:mode><VF_256:mode>"
!   [(set (match_operand:V_256 0 "register_operand" "")
! 	(if_then_else:V_256
  	  (match_operator 3 ""
! 	    [(match_operand:VF_256 4 "nonimmediate_operand" "")
! 	     (match_operand:VF_256 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_256 1 "general_operand" "")
! 	  (match_operand:V_256 2 "general_operand" "")))]
!   "TARGET_AVX
!    && (GET_MODE_NUNITS (<V_256:MODE>mode)
!        == GET_MODE_NUNITS (<VF_256:MODE>mode))"
! {
!   bool ok = ix86_expand_fp_vcond (operands);
!   gcc_assert (ok);
!   DONE;
! })
! 
! (define_expand "vcond<V_128:mode><VF_128:mode>"
!   [(set (match_operand:V_128 0 "register_operand" "")
! 	(if_then_else:V_128
! 	  (match_operator 3 ""
! 	    [(match_operand:VF_128 4 "nonimmediate_operand" "")
! 	     (match_operand:VF_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_128 1 "general_operand" "")
! 	  (match_operand:V_128 2 "general_operand" "")))]
!   "TARGET_SSE
!    && (GET_MODE_NUNITS (<V_128:MODE>mode)
!        == GET_MODE_NUNITS (<VF_128:MODE>mode))"
  {
    bool ok = ix86_expand_fp_vcond (operands);
    gcc_assert (ok);
***************
*** 6091,6119 ****
     (set_attr "prefix" "orig,vex")
     (set_attr "mode" "TI")])
  
! (define_expand "vcond<mode>"
!   [(set (match_operand:VI124_128 0 "register_operand" "")
! 	(if_then_else:VI124_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI124_128 1 "general_operand" "")
! 	  (match_operand:VI124_128 2 "general_operand" "")))]
!   "TARGET_SSE2"
  {
    bool ok = ix86_expand_int_vcond (operands);
    gcc_assert (ok);
    DONE;
  })
  
! (define_expand "vcondv2di"
!   [(set (match_operand:V2DI 0 "register_operand" "")
! 	(if_then_else:V2DI
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:V2DI 1 "general_operand" "")
! 	  (match_operand:V2DI 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
--- 6110,6140 ----
     (set_attr "prefix" "orig,vex")
     (set_attr "mode" "TI")])
  
! (define_expand "vcond<V_128:mode><VI124_128:mode>"
!   [(set (match_operand:V_128 0 "register_operand" "")
! 	(if_then_else:V_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_128 1 "general_operand" "")
! 	  (match_operand:V_128 2 "general_operand" "")))]
!   "TARGET_SSE2
!    && (GET_MODE_NUNITS (<V_128:MODE>mode)
!        == GET_MODE_NUNITS (<VI124_128:MODE>mode))"
  {
    bool ok = ix86_expand_int_vcond (operands);
    gcc_assert (ok);
    DONE;
  })
  
! (define_expand "vcond<VI8F_128:mode>v2di"
!   [(set (match_operand:VI8F_128 0 "register_operand" "")
! 	(if_then_else:VI8F_128
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI8F_128 1 "general_operand" "")
! 	  (match_operand:VI8F_128 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
***************
*** 6121,6149 ****
    DONE;
  })
  
! (define_expand "vcondu<mode>"
!   [(set (match_operand:VI124_128 0 "register_operand" "")
! 	(if_then_else:VI124_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI124_128 1 "general_operand" "")
! 	  (match_operand:VI124_128 2 "general_operand" "")))]
!   "TARGET_SSE2"
  {
    bool ok = ix86_expand_int_vcond (operands);
    gcc_assert (ok);
    DONE;
  })
  
! (define_expand "vconduv2di"
!   [(set (match_operand:V2DI 0 "register_operand" "")
! 	(if_then_else:V2DI
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:V2DI 1 "general_operand" "")
! 	  (match_operand:V2DI 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
--- 6142,6172 ----
    DONE;
  })
  
! (define_expand "vcondu<V_128:mode><VI124_128:mode>"
!   [(set (match_operand:V_128 0 "register_operand" "")
! 	(if_then_else:V_128
  	  (match_operator 3 ""
  	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
  	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
! 	  (match_operand:V_128 1 "general_operand" "")
! 	  (match_operand:V_128 2 "general_operand" "")))]
!   "TARGET_SSE2
!    && (GET_MODE_NUNITS (<V_128:MODE>mode)
!        == GET_MODE_NUNITS (<VI124_128:MODE>mode)"
  {
    bool ok = ix86_expand_int_vcond (operands);
    gcc_assert (ok);
    DONE;
  })
  
! (define_expand "vcondu<VI8F_128:mode>v2di"
!   [(set (match_operand:VI8F_128 0 "register_operand" "")
! 	(if_then_else:VI8F_128
  	  (match_operator 3 ""
  	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
  	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
! 	  (match_operand:VI8F_128 1 "general_operand" "")
! 	  (match_operand:VI8F_128 2 "general_operand" "")))]
    "TARGET_SSE4_2"
  {
    bool ok = ix86_expand_int_vcond (operands);
Index: trunk/gcc/config/ia64/vect.md
===================================================================
*** trunk.orig/gcc/config/ia64/vect.md	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/config/ia64/vect.md	2011-08-30 11:46:51.000000000 +0200
***************
*** 661,667 ****
    DONE;
  })
  
! (define_expand "vcond<mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
--- 661,667 ----
    DONE;
  })
  
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
***************
*** 675,681 ****
    DONE;
  })
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
--- 675,681 ----
    DONE;
  })
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VECINT 0 "gr_register_operand" "")
  	(if_then_else:VECINT
  	  (match_operator 3 "" 
***************
*** 1382,1388 ****
    DONE;
  })
  
! (define_expand "vcondv2sf"
    [(set (match_operand:V2SF 0 "fr_register_operand" "")
  	(if_then_else:V2SF
  	  (match_operator 3 "" 
--- 1382,1388 ----
    DONE;
  })
  
! (define_expand "vcondv2sfv2sf"
    [(set (match_operand:V2SF 0 "fr_register_operand" "")
  	(if_then_else:V2SF
  	  (match_operator 3 "" 
Index: trunk/gcc/config/mips/mips-ps-3d.md
===================================================================
*** trunk.orig/gcc/config/mips/mips-ps-3d.md	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/config/mips/mips-ps-3d.md	2011-08-30 11:46:51.000000000 +0200
***************
*** 597,603 ****
    [(set_attr "type" "frdiv2")
     (set_attr "mode" "<UNITMODE>")])
  
! (define_expand "vcondv2sf"
    [(set (match_operand:V2SF 0 "register_operand")
  	(if_then_else:V2SF
  	  (match_operator 3 ""
--- 597,603 ----
    [(set_attr "type" "frdiv2")
     (set_attr "mode" "<UNITMODE>")])
  
! (define_expand "vcondv2sfv2sf"
    [(set (match_operand:V2SF 0 "register_operand")
  	(if_then_else:V2SF
  	  (match_operator 3 ""
Index: trunk/gcc/config/rs6000/paired.md
===================================================================
*** trunk.orig/gcc/config/rs6000/paired.md	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/config/rs6000/paired.md	2011-08-30 11:46:51.000000000 +0200
***************
*** 507,513 ****
    DONE;
  })
  
! (define_expand "vcondv2sf"
    [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
          (if_then_else:V2SF
           (match_operator 3 "gpc_reg_operand"
--- 507,513 ----
    DONE;
  })
  
! (define_expand "vcondv2sfv2sf"
    [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
          (if_then_else:V2SF
           (match_operator 3 "gpc_reg_operand"
Index: trunk/gcc/config/rs6000/vector.md
===================================================================
*** trunk.orig/gcc/config/rs6000/vector.md	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/config/rs6000/vector.md	2011-08-30 11:46:51.000000000 +0200
***************
*** 370,376 ****
  
  \f
  ;; Vector comparisons
! (define_expand "vcond<mode>"
    [(set (match_operand:VEC_F 0 "vfloat_operand" "")
  	(if_then_else:VEC_F
  	 (match_operator 3 "comparison_operator"
--- 370,376 ----
  
  \f
  ;; Vector comparisons
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VEC_F 0 "vfloat_operand" "")
  	(if_then_else:VEC_F
  	 (match_operator 3 "comparison_operator"
***************
*** 388,394 ****
      FAIL;
  }")
  
! (define_expand "vcond<mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
--- 388,394 ----
      FAIL;
  }")
  
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
***************
*** 406,412 ****
      FAIL;
  }")
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
--- 406,412 ----
      FAIL;
  }")
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VEC_I 0 "vint_operand" "")
  	(if_then_else:VEC_I
  	 (match_operator 3 "comparison_operator"
Index: trunk/gcc/config/spu/spu.md
===================================================================
*** trunk.orig/gcc/config/spu/spu.md	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/config/spu/spu.md	2011-08-30 11:46:51.000000000 +0200
*************** selb\t%0,%4,%0,%3"
*** 3874,3880 ****
  
  \f
  ;; vector conditional compare patterns
! (define_expand "vcond<mode>"
    [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
          (if_then_else:VCMP
            (match_operator 3 "comparison_operator"
--- 3874,3880 ----
  
  \f
  ;; vector conditional compare patterns
! (define_expand "vcond<mode><mode>"
    [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
          (if_then_else:VCMP
            (match_operator 3 "comparison_operator"
*************** selb\t%0,%4,%0,%3"
*** 3891,3897 ****
      FAIL;
    })
  
! (define_expand "vcondu<mode>"
    [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
          (if_then_else:VCMPU
            (match_operator 3 "comparison_operator"
--- 3891,3897 ----
      FAIL;
    })
  
! (define_expand "vcondu<mode><mode>"
    [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
          (if_then_else:VCMPU
            (match_operator 3 "comparison_operator"
Index: trunk/gcc/genopinit.c
===================================================================
*** trunk.orig/gcc/genopinit.c	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/genopinit.c	2011-08-30 11:46:51.000000000 +0200
*************** static const char * const optabs[] =
*** 253,260 ****
    "set_optab_handler (vec_shl_optab, $A, CODE_FOR_$(vec_shl_$a$))",
    "set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
    "set_optab_handler (vec_realign_load_optab, $A, CODE_FOR_$(vec_realign_load_$a$))",
!   "set_direct_optab_handler (vcond_optab, $A, CODE_FOR_$(vcond$a$))",
!   "set_direct_optab_handler (vcondu_optab, $A, CODE_FOR_$(vcondu$a$))",
    "set_optab_handler (ssum_widen_optab, $A, CODE_FOR_$(widen_ssum$I$a3$))",
    "set_optab_handler (usum_widen_optab, $A, CODE_FOR_$(widen_usum$I$a3$))",
    "set_optab_handler (udot_prod_optab, $A, CODE_FOR_$(udot_prod$I$a$))",
--- 253,260 ----
    "set_optab_handler (vec_shl_optab, $A, CODE_FOR_$(vec_shl_$a$))",
    "set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
    "set_optab_handler (vec_realign_load_optab, $A, CODE_FOR_$(vec_realign_load_$a$))",
!   "set_convert_optab_handler (vcond_optab, $A, $B, CODE_FOR_$(vcond$a$b$))",
!   "set_convert_optab_handler (vcondu_optab, $A, $B, CODE_FOR_$(vcondu$a$b$))",
    "set_optab_handler (ssum_widen_optab, $A, CODE_FOR_$(widen_ssum$I$a3$))",
    "set_optab_handler (usum_widen_optab, $A, CODE_FOR_$(widen_usum$I$a3$))",
    "set_optab_handler (udot_prod_optab, $A, CODE_FOR_$(udot_prod$I$a$))",
Index: trunk/gcc/optabs.c
===================================================================
*** trunk.orig/gcc/optabs.c	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/optabs.c	2011-08-30 11:46:51.000000000 +0200
*************** vector_compare_rtx (tree cond, bool unsi
*** 6620,6646 ****
    return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
  }
  
! /* Return insn code for TYPE, the type of a VEC_COND_EXPR.  */
  
  static inline enum insn_code
! get_vcond_icode (tree type, enum machine_mode mode)
  {
    enum insn_code icode = CODE_FOR_nothing;
! 
!   if (TYPE_UNSIGNED (type))
!     icode = direct_optab_handler (vcondu_optab, mode);
    else
!     icode = direct_optab_handler (vcond_optab, mode);
    return icode;
  }
  
  /* Return TRUE iff, appropriate vector insns are available
!    for vector cond expr with type TYPE in VMODE mode.  */
  
  bool
! expand_vec_cond_expr_p (tree type, enum machine_mode vmode)
  {
!   if (get_vcond_icode (type, vmode) == CODE_FOR_nothing)
      return false;
    return true;
  }
--- 6620,6652 ----
    return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
  }
  
! /* Return insn code for a conditional operator with a comparison in
!    mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE.  */
  
  static inline enum insn_code
! get_vcond_icode (enum machine_mode vmode, enum machine_mode cmode, bool uns)
  {
    enum insn_code icode = CODE_FOR_nothing;
!   if (uns)
!     icode = convert_optab_handler (vcondu_optab, vmode, cmode);
    else
!     icode = convert_optab_handler (vcond_optab, vmode, cmode);
    return icode;
  }
  
  /* Return TRUE iff, appropriate vector insns are available
!    for vector cond expr with vector type VALUE_TYPE and a comparison
!    with operand vector types in CMP_OP_TYPE.  */
  
  bool
! expand_vec_cond_expr_p (tree value_type, tree cmp_op_type)
  {
!   enum machine_mode value_mode = TYPE_MODE (value_type);
!   enum machine_mode cmp_op_mode = TYPE_MODE (cmp_op_type);
!   if (GET_MODE_SIZE (value_mode) != GET_MODE_SIZE (cmp_op_mode)
!       || GET_MODE_NUNITS (value_mode) != GET_MODE_NUNITS (cmp_op_mode)
!       || get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
! 			  TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing)
      return false;
    return true;
  }
*************** expand_vec_cond_expr (tree vec_cond_type
*** 6656,6664 ****
    enum insn_code icode;
    rtx comparison, rtx_op1, rtx_op2;
    enum machine_mode mode = TYPE_MODE (vec_cond_type);
!   bool unsignedp = TYPE_UNSIGNED (vec_cond_type);
  
!   icode = get_vcond_icode (vec_cond_type, mode);
    if (icode == CODE_FOR_nothing)
      return 0;
  
--- 6662,6679 ----
    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;
! 
!   gcc_assert (COMPARISON_CLASS_P (op0));
! 
!   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;
  
Index: trunk/gcc/optabs.h
===================================================================
*** trunk.orig/gcc/optabs.h	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/optabs.h	2011-08-30 11:46:51.000000000 +0200
*************** enum convert_optab_index
*** 589,594 ****
--- 589,598 ----
    COI_vec_load_lanes,
    COI_vec_store_lanes,
  
+   /* Vector conditional operations.  */
+   COI_vcond,
+   COI_vcondu,
+ 
    COI_MAX
  };
  
*************** enum convert_optab_index
*** 611,616 ****
--- 615,622 ----
  #define satfractuns_optab (&convert_optab_table[COI_satfractuns])
  #define vec_load_lanes_optab (&convert_optab_table[COI_vec_load_lanes])
  #define vec_store_lanes_optab (&convert_optab_table[COI_vec_store_lanes])
+ #define vcond_optab (&convert_optab_table[(int) COI_vcond])
+ #define vcondu_optab (&convert_optab_table[(int) COI_vcondu])
  
  /* Contains the optab used for each rtx code.  */
  extern optab code_to_optab[NUM_RTX_CODE + 1];
*************** enum direct_optab_index
*** 632,641 ****
    DOI_reload_in,
    DOI_reload_out,
  
-   /* Vector conditional operations.  */
-   DOI_vcond,
-   DOI_vcondu,
- 
    /* Block move operation.  */
    DOI_movmem,
  
--- 638,643 ----
*************** typedef struct direct_optab_d *direct_op
*** 699,706 ****
  #endif
  #define reload_in_optab (&direct_optab_table[(int) DOI_reload_in])
  #define reload_out_optab (&direct_optab_table[(int) DOI_reload_out])
- #define vcond_optab (&direct_optab_table[(int) DOI_vcond])
- #define vcondu_optab (&direct_optab_table[(int) DOI_vcondu])
  #define movmem_optab (&direct_optab_table[(int) DOI_movmem])
  #define setmem_optab (&direct_optab_table[(int) DOI_setmem])
  #define cmpstr_optab (&direct_optab_table[(int) DOI_cmpstr])
--- 701,706 ----
*************** extern bool expand_sfix_optab (rtx, rtx,
*** 877,883 ****
  extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab);
  
  /* Return tree if target supports vector operations for COND_EXPR.  */
! bool expand_vec_cond_expr_p (tree, enum machine_mode);
  
  /* Generate code for VEC_COND_EXPR.  */
  extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
--- 877,883 ----
  extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab);
  
  /* Return tree if target supports vector operations for COND_EXPR.  */
! bool expand_vec_cond_expr_p (tree, tree);
  
  /* Generate code for VEC_COND_EXPR.  */
  extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
Index: trunk/gcc/tree-vect-stmts.c
===================================================================
*** trunk.orig/gcc/tree-vect-stmts.c	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/tree-vect-stmts.c	2011-08-30 11:46:51.000000000 +0200
*************** vectorizable_load (gimple stmt, gimple_s
*** 4680,4694 ****
     LOOP - the loop that is being vectorized.
     COND - Condition that is checked for simple use.
  
     Returns whether a COND can be vectorized.  Checks whether
     condition operands are supportable using vec_is_simple_use.  */
  
  static bool
! vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
  {
    tree lhs, rhs;
    tree def;
    enum vect_def_type dt;
  
    if (!COMPARISON_CLASS_P (cond))
      return false;
--- 4680,4698 ----
     LOOP - the loop that is being vectorized.
     COND - Condition that is checked for simple use.
  
+    Output:
+    *COMP_VECTYPE - the vector type for the comparison.
+ 
     Returns whether a COND can be vectorized.  Checks whether
     condition operands are supportable using vec_is_simple_use.  */
  
  static bool
! vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype)
  {
    tree lhs, rhs;
    tree def;
    enum vect_def_type dt;
+   tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
  
    if (!COMPARISON_CLASS_P (cond))
      return false;
*************** vect_is_simple_cond (tree cond, loop_vec
*** 4699,4706 ****
    if (TREE_CODE (lhs) == SSA_NAME)
      {
        gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
!       if (!vect_is_simple_use (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
!                                &dt))
  	return false;
      }
    else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
--- 4703,4710 ----
    if (TREE_CODE (lhs) == SSA_NAME)
      {
        gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
!       if (!vect_is_simple_use_1 (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
! 				 &dt, &vectype1))
  	return false;
      }
    else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
*************** vect_is_simple_cond (tree cond, loop_vec
*** 4710,4723 ****
    if (TREE_CODE (rhs) == SSA_NAME)
      {
        gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
!       if (!vect_is_simple_use (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
!                                &dt))
  	return false;
      }
    else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
  	   && TREE_CODE (rhs) != FIXED_CST)
      return false;
  
    return true;
  }
  
--- 4714,4728 ----
    if (TREE_CODE (rhs) == SSA_NAME)
      {
        gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
!       if (!vect_is_simple_use_1 (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
! 				 &dt, &vectype2))
  	return false;
      }
    else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
  	   && TREE_CODE (rhs) != FIXED_CST)
      return false;
  
+   *comp_vectype = vectype1 ? vectype1 : vectype2;
    return true;
  }
  
*************** vectorizable_condition (gimple stmt, gim
*** 4744,4755 ****
    tree cond_expr, then_clause, else_clause;
    stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
    tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
    tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
    tree vec_compare, vec_cond_expr;
    tree new_temp;
    loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
-   enum machine_mode vec_mode;
    tree def;
    enum vect_def_type dt, dts[4];
    int nunits = TYPE_VECTOR_SUBPARTS (vectype);
--- 4749,4760 ----
    tree cond_expr, then_clause, else_clause;
    stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
    tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+   tree comp_vectype;
    tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
    tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
    tree vec_compare, vec_cond_expr;
    tree new_temp;
    loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
    tree def;
    enum vect_def_type dt, dts[4];
    int nunits = TYPE_VECTOR_SUBPARTS (vectype);
*************** vectorizable_condition (gimple stmt, gim
*** 4800,4812 ****
    then_clause = TREE_OPERAND (op, 1);
    else_clause = TREE_OPERAND (op, 2);
  
!   if (!vect_is_simple_cond (cond_expr, loop_vinfo))
!     return false;
! 
!   /* We do not handle two different vector types for the condition
!      and the values.  */
!   if (!types_compatible_p (TREE_TYPE (TREE_OPERAND (cond_expr, 0)),
! 			   TREE_TYPE (vectype)))
      return false;
  
    if (TREE_CODE (then_clause) == SSA_NAME)
--- 4805,4812 ----
    then_clause = TREE_OPERAND (op, 1);
    else_clause = TREE_OPERAND (op, 2);
  
!   if (!vect_is_simple_cond (cond_expr, loop_vinfo, &comp_vectype)
!       || !comp_vectype)
      return false;
  
    if (TREE_CODE (then_clause) == SSA_NAME)
*************** vectorizable_condition (gimple stmt, gim
*** 4833,4845 ****
  	   && TREE_CODE (else_clause) != FIXED_CST)
      return false;
  
- 
-   vec_mode = TYPE_MODE (vectype);
- 
    if (!vec_stmt)
      {
        STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
!       return expand_vec_cond_expr_p (TREE_TYPE (op), vec_mode);
      }
  
    /* Transform */
--- 4833,4842 ----
  	   && TREE_CODE (else_clause) != FIXED_CST)
      return false;
  
    if (!vec_stmt)
      {
        STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
!       return expand_vec_cond_expr_p (vectype, comp_vectype);
      }
  
    /* Transform */
Index: trunk/gcc/config/i386/i386.c
===================================================================
*** trunk.orig/gcc/config/i386/i386.c	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/config/i386/i386.c	2011-08-30 11:46:51.000000000 +0200
*************** ix86_expand_sse_cmp (rtx dest, enum rtx_
*** 18412,18430 ****
  		     rtx op_true, rtx op_false)
  {
    enum machine_mode mode = GET_MODE (dest);
    rtx x;
  
!   cmp_op0 = force_reg (mode, cmp_op0);
!   if (!nonimmediate_operand (cmp_op1, mode))
!     cmp_op1 = force_reg (mode, cmp_op1);
  
    if (optimize
        || reg_overlap_mentioned_p (dest, op_true)
        || reg_overlap_mentioned_p (dest, op_false))
      dest = gen_reg_rtx (mode);
  
!   x = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
!   emit_insn (gen_rtx_SET (VOIDmode, dest, x));
  
    return dest;
  }
--- 18412,18437 ----
  		     rtx op_true, rtx op_false)
  {
    enum machine_mode mode = GET_MODE (dest);
+   enum machine_mode cmp_mode = GET_MODE (cmp_op0);
    rtx x;
  
!   cmp_op0 = force_reg (cmp_mode, cmp_op0);
!   if (!nonimmediate_operand (cmp_op1, cmp_mode))
!     cmp_op1 = force_reg (cmp_mode, cmp_op1);
  
    if (optimize
        || reg_overlap_mentioned_p (dest, op_true)
        || reg_overlap_mentioned_p (dest, op_false))
      dest = gen_reg_rtx (mode);
  
!   x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1);
!   if (cmp_mode != mode)
!     {
!       x = force_reg (cmp_mode, x);
!       convert_move (dest, x, false);
!     }
!   else
!     emit_insn (gen_rtx_SET (VOIDmode, dest, x));
  
    return dest;
  }
Index: trunk/gcc/testsuite/gcc.dg/vect/vect-cond-7.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/vect/vect-cond-7.c	2011-08-30 11:46:51.000000000 +0200
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-require-effective-target vect_condition } */
+ 
+ int vis_type[128];
+ float vs_data[128];
+ void vis_clear_data ()
+ {
+   int i;
+   for (i = 0; i < 128; i++)
+     vs_data[i] = (vis_type[i] == 1);
+ }
+ 
+ /* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
Index: trunk/gcc/doc/md.texi
===================================================================
*** trunk.orig/gcc/doc/md.texi	2011-08-30 10:53:47.000000000 +0200
--- trunk/gcc/doc/md.texi	2011-08-30 11:46:51.000000000 +0200
*************** and input vectors should have the same m
*** 4017,4022 ****
--- 4017,4033 ----
  Initialize the vector to given values.  Operand 0 is the vector to initialize
  and operand 1 is parallel containing values for individual fields.
  
+ @cindex @code{vcond@var{m}@var{n}} instruction pattern
+ @item @samp{vcond@var{m}@var{n}}
+ Output a conditional vector move.  Operand 0 is the destination to
+ receive a combination of operand 1 and operand 2, which are of mode @var{m},
+ dependent on the outcome of the predicate in operand 3 which is a
+ vector comparison with operands of mode @var{n} in operands 4 and 5.  The
+ modes @var{m} and @var{n} should have the same size.  Operand 0
+ will be set to the value @var{op1} & @var{msk} | @var{op2} & ~@var{msk}
+ where @var{msk} is computed by element-wise evaluation of the vector
+ comparison with a truth value of all-ones and a false value of all-zeros.
+ 
  @cindex @code{push@var{m}1} instruction pattern
  @item @samp{push@var{m}1}
  Output a push instruction.  Operand 0 is value to push.  Used only when

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-08-30 12:11                     ` Richard Guenther
@ 2011-09-02  9:44                       ` Richard Guenther
  2011-09-02 12:19                         ` Uros Bizjak
  0 siblings, 1 reply; 16+ messages in thread
From: Richard Guenther @ 2011-09-02  9:44 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: Jakub Jelinek, gcc-patches, uros, rth, artyom.shinkaroff

[-- Attachment #1: Type: TEXT/PLAIN, Size: 35901 bytes --]

On Tue, 30 Aug 2011, Richard Guenther wrote:

> On Tue, 30 Aug 2011, Richard Guenther wrote:
> 
> > On Tue, 30 Aug 2011, Uros Bizjak wrote:
> > 
> > > On Tue, Aug 30, 2011 at 11:15 AM, Richard Guenther <rguenther@suse.de> wrote:
> > > 
> > > >> >> > Hmm.  But then I'd have to try emit an insn, right?  Currently
> > > >> >> > the vectorizer simply looks for an optab handler ... the
> > > >> >> > operands are not readily available (but their mode is known).
> > > >> >> > So I'd create some fake regs, setup operands and call GEN_FCN
> > > >> >> > on it?  If it succeds I'd have to delete emitted insns, etc.
> > > >> >> > Or I could add a target hook ...
> > > >> >>
> > > >> >> Hm... indeed, too much complication...
> > > >> >>
> > > >> >> I'd say, let's go with modeless operands and a target hook. IMO, this
> > > >> >> is much more flexible than checking optab for supported modes.
> > > >> >> Existing way is appropriate for single mode patterns, but we have
> > > >> >> interdependent modes here, at least on x86.
> > > >> >>
> > > >> >> The hook would have two input arguments, insn mode and compare mode,
> > > >> >> where the hook returns suggested supported compare mode, or no mode,
> > > >> >> if it really can't handle requested modes.
> > > >> >
> > > >> > I think a two mode vcond pattern is in fact much cleaner than
> > > >> > a one mode + modeless pattern which gen* will complain about and
> > > >> > a target hook.
> > > >>
> > > >> OK, but in this case, do not use mode iterators too much in order to
> > > >> avoid invalid patterns.
> > > >
> > > > I don't see them as "invalid".  They will be unused (maybe combine
> > > > would create them though?), but they have well-defined semantics
> > > > with my proposed documentation.  And x86 can handle them just fine.
> > > 
> > > OK, let's go this way then... We can clean up this later if at all.
> > 
> > Certainly what I prefer (less work for me now) ;)  The smallest
> > number of patterns would probably result from using vcond<mode><mode>
> > to cover the same-mode cases and then add the 12 other patterns
> > with the respective integer / float mode variant.  Thus we'd have
> > 15 patterns in total (still much for my taste).
> > 
> > Ideally we could have a mode attribute that would map possibly
> > to an iterator, thus
> > 
> > (define_mode_attr matching [(V4SF ["V4SF" "V4SI"]) (V8HI "V8HI") ...])
> > 
> > or similar.  But I don't feel like adding this sort of mode
> > attr that really is a hidden iterator ... ;)
> > 
> > Thus, the following is the combined patch which bootstrapped and
> > tested ok on x86_64-unknown-linux-gnu with {,-m32} over night,
> > with the documentation for vcond added.
> > 
> > Ok for trunk?
> 
> I'm re-testing with the patterns having an extra condition like
>    && (GET_MODE_NUNITS (<V_256:MODE>mode)
>        == GET_MODE_NUNITS (<VF_256:MODE>mode))"
> to have the HAVE_vcond* defines easily optimized.
> 
> Ok?

Ping.  I'd like to have approval for the x86 changes.

Thanks,
Richard.

> 2011-08-30  Richard Guenther  <rguenther@suse.de>
> 
> 	PR tree-optimization/27460
> 	PR middle-end/29269
> 	* doc/md.texi (vcond): Document.
> 	* genopinit.c (optabs): Turn vcond{,u}_optab into a conversion
> 	optab with two modes.
> 	* optabs.h (enum convert_optab_index): Add COI_vcond, COI_vcondu.
> 	(enum direct_optab_index): Remove DOI_vcond, DOI_vcondu.
> 	(vcond_optab): Adjust.
> 	(vcondu_optab): Likewise.
> 	(expand_vec_cond_expr_p): Adjust prototype.
> 	* optabs.c (get_vcond_icode): Adjust.
> 	(expand_vec_cond_expr_p): Likewise.
> 	(expand_vec_cond_expr): Likewise.
> 	* tree-vect-stmts.c (vect_is_simple_cond): Return the comparison
> 	vector type.
> 	(vectorizable_condition): Allow differing types for comparison
> 	and result.
> 
> 	* config/i386/i386.c (ix86_expand_sse_cmp): Use proper mode
> 	for the comparison.
> 	* config/i386/sse.md (vcond<mode>): Split to
> 	vcond<V_256:mode><VF_256:mode>, vcond<V_128:mode><VF_128:mode>,
> 	vcond<V_128:mode><VI124_128:mode> and
> 	vcondu<V_128:mode><VI124_128:mode>.
> 	(vcondv2di): Change to vcond<VI8F_128:mode>v2di.
> 	(vconduv2di): Likewise.
> 	* config/arm/neon.md (vcond<mode>): Change to vcond*<mode><mode>.
> 	(vcondu<mode>): Likewise.
> 	* config/ia64/vect.md (vcond<mode>): Likewise.
> 	(vcondu<mode>): Likewise.
> 	(vcondv2sf): Likewise.
> 	* config/mips/mips-ps-3d.md (vcondv2sf): Likewise.
> 	* config/rs6000/paired.md (vcondv2sf): Likewise.
> 	* config/rs6000/vector.md (vcond<mode>): Likewise.
> 	(vcondu<mode>): Likewise.
> 	* config/spu/spu.md (vcond<mode>): Likewise.
> 	(vcondu<mode>): Likewise.
> 
> 	* gcc.dg/vect/vect-cond-7.c: New testcase.
> 
> Index: trunk/gcc/config/arm/neon.md
> ===================================================================
> *** trunk.orig/gcc/config/arm/neon.md	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/config/arm/neon.md	2011-08-30 11:46:51.000000000 +0200
> ***************
> *** 1600,1606 ****
>   ;; where op3 is <, <=, ==, !=, >= or >.  Operations are performed
>   ;; element-wise.
>   
> ! (define_expand "vcond<mode>"
>     [(set (match_operand:VDQW 0 "s_register_operand" "")
>   	(if_then_else:VDQW
>   	  (match_operator 3 "arm_comparison_operator"
> --- 1600,1606 ----
>   ;; where op3 is <, <=, ==, !=, >= or >.  Operations are performed
>   ;; element-wise.
>   
> ! (define_expand "vcond<mode><mode>"
>     [(set (match_operand:VDQW 0 "s_register_operand" "")
>   	(if_then_else:VDQW
>   	  (match_operator 3 "arm_comparison_operator"
> ***************
> *** 1680,1686 ****
>     DONE;
>   })
>   
> ! (define_expand "vcondu<mode>"
>     [(set (match_operand:VDQIW 0 "s_register_operand" "")
>   	(if_then_else:VDQIW
>   	  (match_operator 3 "arm_comparison_operator"
> --- 1680,1686 ----
>     DONE;
>   })
>   
> ! (define_expand "vcondu<mode><mode>"
>     [(set (match_operand:VDQIW 0 "s_register_operand" "")
>   	(if_then_else:VDQIW
>   	  (match_operator 3 "arm_comparison_operator"
> Index: trunk/gcc/config/i386/sse.md
> ===================================================================
> *** trunk.orig/gcc/config/i386/sse.md	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/config/i386/sse.md	2011-08-30 12:12:30.000000000 +0200
> ***************
> *** 1405,1419 ****
>   		      (const_string "0")))
>      (set_attr "mode" "<MODE>")])
>   
> ! (define_expand "vcond<mode>"
> !   [(set (match_operand:VF 0 "register_operand" "")
> ! 	(if_then_else:VF
>   	  (match_operator 3 ""
> ! 	    [(match_operand:VF 4 "nonimmediate_operand" "")
> ! 	     (match_operand:VF 5 "nonimmediate_operand" "")])
> ! 	  (match_operand:VF 1 "general_operand" "")
> ! 	  (match_operand:VF 2 "general_operand" "")))]
> !   "TARGET_SSE"
>   {
>     bool ok = ix86_expand_fp_vcond (operands);
>     gcc_assert (ok);
> --- 1405,1438 ----
>   		      (const_string "0")))
>      (set_attr "mode" "<MODE>")])
>   
> ! (define_expand "vcond<V_256:mode><VF_256:mode>"
> !   [(set (match_operand:V_256 0 "register_operand" "")
> ! 	(if_then_else:V_256
>   	  (match_operator 3 ""
> ! 	    [(match_operand:VF_256 4 "nonimmediate_operand" "")
> ! 	     (match_operand:VF_256 5 "nonimmediate_operand" "")])
> ! 	  (match_operand:V_256 1 "general_operand" "")
> ! 	  (match_operand:V_256 2 "general_operand" "")))]
> !   "TARGET_AVX
> !    && (GET_MODE_NUNITS (<V_256:MODE>mode)
> !        == GET_MODE_NUNITS (<VF_256:MODE>mode))"
> ! {
> !   bool ok = ix86_expand_fp_vcond (operands);
> !   gcc_assert (ok);
> !   DONE;
> ! })
> ! 
> ! (define_expand "vcond<V_128:mode><VF_128:mode>"
> !   [(set (match_operand:V_128 0 "register_operand" "")
> ! 	(if_then_else:V_128
> ! 	  (match_operator 3 ""
> ! 	    [(match_operand:VF_128 4 "nonimmediate_operand" "")
> ! 	     (match_operand:VF_128 5 "nonimmediate_operand" "")])
> ! 	  (match_operand:V_128 1 "general_operand" "")
> ! 	  (match_operand:V_128 2 "general_operand" "")))]
> !   "TARGET_SSE
> !    && (GET_MODE_NUNITS (<V_128:MODE>mode)
> !        == GET_MODE_NUNITS (<VF_128:MODE>mode))"
>   {
>     bool ok = ix86_expand_fp_vcond (operands);
>     gcc_assert (ok);
> ***************
> *** 6091,6119 ****
>      (set_attr "prefix" "orig,vex")
>      (set_attr "mode" "TI")])
>   
> ! (define_expand "vcond<mode>"
> !   [(set (match_operand:VI124_128 0 "register_operand" "")
> ! 	(if_then_else:VI124_128
>   	  (match_operator 3 ""
>   	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
>   	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
> ! 	  (match_operand:VI124_128 1 "general_operand" "")
> ! 	  (match_operand:VI124_128 2 "general_operand" "")))]
> !   "TARGET_SSE2"
>   {
>     bool ok = ix86_expand_int_vcond (operands);
>     gcc_assert (ok);
>     DONE;
>   })
>   
> ! (define_expand "vcondv2di"
> !   [(set (match_operand:V2DI 0 "register_operand" "")
> ! 	(if_then_else:V2DI
>   	  (match_operator 3 ""
>   	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
>   	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
> ! 	  (match_operand:V2DI 1 "general_operand" "")
> ! 	  (match_operand:V2DI 2 "general_operand" "")))]
>     "TARGET_SSE4_2"
>   {
>     bool ok = ix86_expand_int_vcond (operands);
> --- 6110,6140 ----
>      (set_attr "prefix" "orig,vex")
>      (set_attr "mode" "TI")])
>   
> ! (define_expand "vcond<V_128:mode><VI124_128:mode>"
> !   [(set (match_operand:V_128 0 "register_operand" "")
> ! 	(if_then_else:V_128
>   	  (match_operator 3 ""
>   	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
>   	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
> ! 	  (match_operand:V_128 1 "general_operand" "")
> ! 	  (match_operand:V_128 2 "general_operand" "")))]
> !   "TARGET_SSE2
> !    && (GET_MODE_NUNITS (<V_128:MODE>mode)
> !        == GET_MODE_NUNITS (<VI124_128:MODE>mode))"
>   {
>     bool ok = ix86_expand_int_vcond (operands);
>     gcc_assert (ok);
>     DONE;
>   })
>   
> ! (define_expand "vcond<VI8F_128:mode>v2di"
> !   [(set (match_operand:VI8F_128 0 "register_operand" "")
> ! 	(if_then_else:VI8F_128
>   	  (match_operator 3 ""
>   	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
>   	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
> ! 	  (match_operand:VI8F_128 1 "general_operand" "")
> ! 	  (match_operand:VI8F_128 2 "general_operand" "")))]
>     "TARGET_SSE4_2"
>   {
>     bool ok = ix86_expand_int_vcond (operands);
> ***************
> *** 6121,6149 ****
>     DONE;
>   })
>   
> ! (define_expand "vcondu<mode>"
> !   [(set (match_operand:VI124_128 0 "register_operand" "")
> ! 	(if_then_else:VI124_128
>   	  (match_operator 3 ""
>   	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
>   	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
> ! 	  (match_operand:VI124_128 1 "general_operand" "")
> ! 	  (match_operand:VI124_128 2 "general_operand" "")))]
> !   "TARGET_SSE2"
>   {
>     bool ok = ix86_expand_int_vcond (operands);
>     gcc_assert (ok);
>     DONE;
>   })
>   
> ! (define_expand "vconduv2di"
> !   [(set (match_operand:V2DI 0 "register_operand" "")
> ! 	(if_then_else:V2DI
>   	  (match_operator 3 ""
>   	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
>   	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
> ! 	  (match_operand:V2DI 1 "general_operand" "")
> ! 	  (match_operand:V2DI 2 "general_operand" "")))]
>     "TARGET_SSE4_2"
>   {
>     bool ok = ix86_expand_int_vcond (operands);
> --- 6142,6172 ----
>     DONE;
>   })
>   
> ! (define_expand "vcondu<V_128:mode><VI124_128:mode>"
> !   [(set (match_operand:V_128 0 "register_operand" "")
> ! 	(if_then_else:V_128
>   	  (match_operator 3 ""
>   	    [(match_operand:VI124_128 4 "nonimmediate_operand" "")
>   	     (match_operand:VI124_128 5 "nonimmediate_operand" "")])
> ! 	  (match_operand:V_128 1 "general_operand" "")
> ! 	  (match_operand:V_128 2 "general_operand" "")))]
> !   "TARGET_SSE2
> !    && (GET_MODE_NUNITS (<V_128:MODE>mode)
> !        == GET_MODE_NUNITS (<VI124_128:MODE>mode)"
>   {
>     bool ok = ix86_expand_int_vcond (operands);
>     gcc_assert (ok);
>     DONE;
>   })
>   
> ! (define_expand "vcondu<VI8F_128:mode>v2di"
> !   [(set (match_operand:VI8F_128 0 "register_operand" "")
> ! 	(if_then_else:VI8F_128
>   	  (match_operator 3 ""
>   	    [(match_operand:V2DI 4 "nonimmediate_operand" "")
>   	     (match_operand:V2DI 5 "nonimmediate_operand" "")])
> ! 	  (match_operand:VI8F_128 1 "general_operand" "")
> ! 	  (match_operand:VI8F_128 2 "general_operand" "")))]
>     "TARGET_SSE4_2"
>   {
>     bool ok = ix86_expand_int_vcond (operands);
> Index: trunk/gcc/config/ia64/vect.md
> ===================================================================
> *** trunk.orig/gcc/config/ia64/vect.md	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/config/ia64/vect.md	2011-08-30 11:46:51.000000000 +0200
> ***************
> *** 661,667 ****
>     DONE;
>   })
>   
> ! (define_expand "vcond<mode>"
>     [(set (match_operand:VECINT 0 "gr_register_operand" "")
>   	(if_then_else:VECINT
>   	  (match_operator 3 "" 
> --- 661,667 ----
>     DONE;
>   })
>   
> ! (define_expand "vcond<mode><mode>"
>     [(set (match_operand:VECINT 0 "gr_register_operand" "")
>   	(if_then_else:VECINT
>   	  (match_operator 3 "" 
> ***************
> *** 675,681 ****
>     DONE;
>   })
>   
> ! (define_expand "vcondu<mode>"
>     [(set (match_operand:VECINT 0 "gr_register_operand" "")
>   	(if_then_else:VECINT
>   	  (match_operator 3 "" 
> --- 675,681 ----
>     DONE;
>   })
>   
> ! (define_expand "vcondu<mode><mode>"
>     [(set (match_operand:VECINT 0 "gr_register_operand" "")
>   	(if_then_else:VECINT
>   	  (match_operator 3 "" 
> ***************
> *** 1382,1388 ****
>     DONE;
>   })
>   
> ! (define_expand "vcondv2sf"
>     [(set (match_operand:V2SF 0 "fr_register_operand" "")
>   	(if_then_else:V2SF
>   	  (match_operator 3 "" 
> --- 1382,1388 ----
>     DONE;
>   })
>   
> ! (define_expand "vcondv2sfv2sf"
>     [(set (match_operand:V2SF 0 "fr_register_operand" "")
>   	(if_then_else:V2SF
>   	  (match_operator 3 "" 
> Index: trunk/gcc/config/mips/mips-ps-3d.md
> ===================================================================
> *** trunk.orig/gcc/config/mips/mips-ps-3d.md	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/config/mips/mips-ps-3d.md	2011-08-30 11:46:51.000000000 +0200
> ***************
> *** 597,603 ****
>     [(set_attr "type" "frdiv2")
>      (set_attr "mode" "<UNITMODE>")])
>   
> ! (define_expand "vcondv2sf"
>     [(set (match_operand:V2SF 0 "register_operand")
>   	(if_then_else:V2SF
>   	  (match_operator 3 ""
> --- 597,603 ----
>     [(set_attr "type" "frdiv2")
>      (set_attr "mode" "<UNITMODE>")])
>   
> ! (define_expand "vcondv2sfv2sf"
>     [(set (match_operand:V2SF 0 "register_operand")
>   	(if_then_else:V2SF
>   	  (match_operator 3 ""
> Index: trunk/gcc/config/rs6000/paired.md
> ===================================================================
> *** trunk.orig/gcc/config/rs6000/paired.md	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/config/rs6000/paired.md	2011-08-30 11:46:51.000000000 +0200
> ***************
> *** 507,513 ****
>     DONE;
>   })
>   
> ! (define_expand "vcondv2sf"
>     [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
>           (if_then_else:V2SF
>            (match_operator 3 "gpc_reg_operand"
> --- 507,513 ----
>     DONE;
>   })
>   
> ! (define_expand "vcondv2sfv2sf"
>     [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
>           (if_then_else:V2SF
>            (match_operator 3 "gpc_reg_operand"
> Index: trunk/gcc/config/rs6000/vector.md
> ===================================================================
> *** trunk.orig/gcc/config/rs6000/vector.md	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/config/rs6000/vector.md	2011-08-30 11:46:51.000000000 +0200
> ***************
> *** 370,376 ****
>   
>   \f
>   ;; Vector comparisons
> ! (define_expand "vcond<mode>"
>     [(set (match_operand:VEC_F 0 "vfloat_operand" "")
>   	(if_then_else:VEC_F
>   	 (match_operator 3 "comparison_operator"
> --- 370,376 ----
>   
>   \f
>   ;; Vector comparisons
> ! (define_expand "vcond<mode><mode>"
>     [(set (match_operand:VEC_F 0 "vfloat_operand" "")
>   	(if_then_else:VEC_F
>   	 (match_operator 3 "comparison_operator"
> ***************
> *** 388,394 ****
>       FAIL;
>   }")
>   
> ! (define_expand "vcond<mode>"
>     [(set (match_operand:VEC_I 0 "vint_operand" "")
>   	(if_then_else:VEC_I
>   	 (match_operator 3 "comparison_operator"
> --- 388,394 ----
>       FAIL;
>   }")
>   
> ! (define_expand "vcond<mode><mode>"
>     [(set (match_operand:VEC_I 0 "vint_operand" "")
>   	(if_then_else:VEC_I
>   	 (match_operator 3 "comparison_operator"
> ***************
> *** 406,412 ****
>       FAIL;
>   }")
>   
> ! (define_expand "vcondu<mode>"
>     [(set (match_operand:VEC_I 0 "vint_operand" "")
>   	(if_then_else:VEC_I
>   	 (match_operator 3 "comparison_operator"
> --- 406,412 ----
>       FAIL;
>   }")
>   
> ! (define_expand "vcondu<mode><mode>"
>     [(set (match_operand:VEC_I 0 "vint_operand" "")
>   	(if_then_else:VEC_I
>   	 (match_operator 3 "comparison_operator"
> Index: trunk/gcc/config/spu/spu.md
> ===================================================================
> *** trunk.orig/gcc/config/spu/spu.md	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/config/spu/spu.md	2011-08-30 11:46:51.000000000 +0200
> *************** selb\t%0,%4,%0,%3"
> *** 3874,3880 ****
>   
>   \f
>   ;; vector conditional compare patterns
> ! (define_expand "vcond<mode>"
>     [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
>           (if_then_else:VCMP
>             (match_operator 3 "comparison_operator"
> --- 3874,3880 ----
>   
>   \f
>   ;; vector conditional compare patterns
> ! (define_expand "vcond<mode><mode>"
>     [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
>           (if_then_else:VCMP
>             (match_operator 3 "comparison_operator"
> *************** selb\t%0,%4,%0,%3"
> *** 3891,3897 ****
>       FAIL;
>     })
>   
> ! (define_expand "vcondu<mode>"
>     [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
>           (if_then_else:VCMPU
>             (match_operator 3 "comparison_operator"
> --- 3891,3897 ----
>       FAIL;
>     })
>   
> ! (define_expand "vcondu<mode><mode>"
>     [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
>           (if_then_else:VCMPU
>             (match_operator 3 "comparison_operator"
> Index: trunk/gcc/genopinit.c
> ===================================================================
> *** trunk.orig/gcc/genopinit.c	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/genopinit.c	2011-08-30 11:46:51.000000000 +0200
> *************** static const char * const optabs[] =
> *** 253,260 ****
>     "set_optab_handler (vec_shl_optab, $A, CODE_FOR_$(vec_shl_$a$))",
>     "set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
>     "set_optab_handler (vec_realign_load_optab, $A, CODE_FOR_$(vec_realign_load_$a$))",
> !   "set_direct_optab_handler (vcond_optab, $A, CODE_FOR_$(vcond$a$))",
> !   "set_direct_optab_handler (vcondu_optab, $A, CODE_FOR_$(vcondu$a$))",
>     "set_optab_handler (ssum_widen_optab, $A, CODE_FOR_$(widen_ssum$I$a3$))",
>     "set_optab_handler (usum_widen_optab, $A, CODE_FOR_$(widen_usum$I$a3$))",
>     "set_optab_handler (udot_prod_optab, $A, CODE_FOR_$(udot_prod$I$a$))",
> --- 253,260 ----
>     "set_optab_handler (vec_shl_optab, $A, CODE_FOR_$(vec_shl_$a$))",
>     "set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
>     "set_optab_handler (vec_realign_load_optab, $A, CODE_FOR_$(vec_realign_load_$a$))",
> !   "set_convert_optab_handler (vcond_optab, $A, $B, CODE_FOR_$(vcond$a$b$))",
> !   "set_convert_optab_handler (vcondu_optab, $A, $B, CODE_FOR_$(vcondu$a$b$))",
>     "set_optab_handler (ssum_widen_optab, $A, CODE_FOR_$(widen_ssum$I$a3$))",
>     "set_optab_handler (usum_widen_optab, $A, CODE_FOR_$(widen_usum$I$a3$))",
>     "set_optab_handler (udot_prod_optab, $A, CODE_FOR_$(udot_prod$I$a$))",
> Index: trunk/gcc/optabs.c
> ===================================================================
> *** trunk.orig/gcc/optabs.c	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/optabs.c	2011-08-30 11:46:51.000000000 +0200
> *************** vector_compare_rtx (tree cond, bool unsi
> *** 6620,6646 ****
>     return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
>   }
>   
> ! /* Return insn code for TYPE, the type of a VEC_COND_EXPR.  */
>   
>   static inline enum insn_code
> ! get_vcond_icode (tree type, enum machine_mode mode)
>   {
>     enum insn_code icode = CODE_FOR_nothing;
> ! 
> !   if (TYPE_UNSIGNED (type))
> !     icode = direct_optab_handler (vcondu_optab, mode);
>     else
> !     icode = direct_optab_handler (vcond_optab, mode);
>     return icode;
>   }
>   
>   /* Return TRUE iff, appropriate vector insns are available
> !    for vector cond expr with type TYPE in VMODE mode.  */
>   
>   bool
> ! expand_vec_cond_expr_p (tree type, enum machine_mode vmode)
>   {
> !   if (get_vcond_icode (type, vmode) == CODE_FOR_nothing)
>       return false;
>     return true;
>   }
> --- 6620,6652 ----
>     return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
>   }
>   
> ! /* Return insn code for a conditional operator with a comparison in
> !    mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE.  */
>   
>   static inline enum insn_code
> ! get_vcond_icode (enum machine_mode vmode, enum machine_mode cmode, bool uns)
>   {
>     enum insn_code icode = CODE_FOR_nothing;
> !   if (uns)
> !     icode = convert_optab_handler (vcondu_optab, vmode, cmode);
>     else
> !     icode = convert_optab_handler (vcond_optab, vmode, cmode);
>     return icode;
>   }
>   
>   /* Return TRUE iff, appropriate vector insns are available
> !    for vector cond expr with vector type VALUE_TYPE and a comparison
> !    with operand vector types in CMP_OP_TYPE.  */
>   
>   bool
> ! expand_vec_cond_expr_p (tree value_type, tree cmp_op_type)
>   {
> !   enum machine_mode value_mode = TYPE_MODE (value_type);
> !   enum machine_mode cmp_op_mode = TYPE_MODE (cmp_op_type);
> !   if (GET_MODE_SIZE (value_mode) != GET_MODE_SIZE (cmp_op_mode)
> !       || GET_MODE_NUNITS (value_mode) != GET_MODE_NUNITS (cmp_op_mode)
> !       || get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
> ! 			  TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing)
>       return false;
>     return true;
>   }
> *************** expand_vec_cond_expr (tree vec_cond_type
> *** 6656,6664 ****
>     enum insn_code icode;
>     rtx comparison, rtx_op1, rtx_op2;
>     enum machine_mode mode = TYPE_MODE (vec_cond_type);
> !   bool unsignedp = TYPE_UNSIGNED (vec_cond_type);
>   
> !   icode = get_vcond_icode (vec_cond_type, mode);
>     if (icode == CODE_FOR_nothing)
>       return 0;
>   
> --- 6662,6679 ----
>     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;
> ! 
> !   gcc_assert (COMPARISON_CLASS_P (op0));
> ! 
> !   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;
>   
> Index: trunk/gcc/optabs.h
> ===================================================================
> *** trunk.orig/gcc/optabs.h	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/optabs.h	2011-08-30 11:46:51.000000000 +0200
> *************** enum convert_optab_index
> *** 589,594 ****
> --- 589,598 ----
>     COI_vec_load_lanes,
>     COI_vec_store_lanes,
>   
> +   /* Vector conditional operations.  */
> +   COI_vcond,
> +   COI_vcondu,
> + 
>     COI_MAX
>   };
>   
> *************** enum convert_optab_index
> *** 611,616 ****
> --- 615,622 ----
>   #define satfractuns_optab (&convert_optab_table[COI_satfractuns])
>   #define vec_load_lanes_optab (&convert_optab_table[COI_vec_load_lanes])
>   #define vec_store_lanes_optab (&convert_optab_table[COI_vec_store_lanes])
> + #define vcond_optab (&convert_optab_table[(int) COI_vcond])
> + #define vcondu_optab (&convert_optab_table[(int) COI_vcondu])
>   
>   /* Contains the optab used for each rtx code.  */
>   extern optab code_to_optab[NUM_RTX_CODE + 1];
> *************** enum direct_optab_index
> *** 632,641 ****
>     DOI_reload_in,
>     DOI_reload_out,
>   
> -   /* Vector conditional operations.  */
> -   DOI_vcond,
> -   DOI_vcondu,
> - 
>     /* Block move operation.  */
>     DOI_movmem,
>   
> --- 638,643 ----
> *************** typedef struct direct_optab_d *direct_op
> *** 699,706 ****
>   #endif
>   #define reload_in_optab (&direct_optab_table[(int) DOI_reload_in])
>   #define reload_out_optab (&direct_optab_table[(int) DOI_reload_out])
> - #define vcond_optab (&direct_optab_table[(int) DOI_vcond])
> - #define vcondu_optab (&direct_optab_table[(int) DOI_vcondu])
>   #define movmem_optab (&direct_optab_table[(int) DOI_movmem])
>   #define setmem_optab (&direct_optab_table[(int) DOI_setmem])
>   #define cmpstr_optab (&direct_optab_table[(int) DOI_cmpstr])
> --- 701,706 ----
> *************** extern bool expand_sfix_optab (rtx, rtx,
> *** 877,883 ****
>   extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab);
>   
>   /* Return tree if target supports vector operations for COND_EXPR.  */
> ! bool expand_vec_cond_expr_p (tree, enum machine_mode);
>   
>   /* Generate code for VEC_COND_EXPR.  */
>   extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
> --- 877,883 ----
>   extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab);
>   
>   /* Return tree if target supports vector operations for COND_EXPR.  */
> ! bool expand_vec_cond_expr_p (tree, tree);
>   
>   /* Generate code for VEC_COND_EXPR.  */
>   extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
> Index: trunk/gcc/tree-vect-stmts.c
> ===================================================================
> *** trunk.orig/gcc/tree-vect-stmts.c	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/tree-vect-stmts.c	2011-08-30 11:46:51.000000000 +0200
> *************** vectorizable_load (gimple stmt, gimple_s
> *** 4680,4694 ****
>      LOOP - the loop that is being vectorized.
>      COND - Condition that is checked for simple use.
>   
>      Returns whether a COND can be vectorized.  Checks whether
>      condition operands are supportable using vec_is_simple_use.  */
>   
>   static bool
> ! vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
>   {
>     tree lhs, rhs;
>     tree def;
>     enum vect_def_type dt;
>   
>     if (!COMPARISON_CLASS_P (cond))
>       return false;
> --- 4680,4698 ----
>      LOOP - the loop that is being vectorized.
>      COND - Condition that is checked for simple use.
>   
> +    Output:
> +    *COMP_VECTYPE - the vector type for the comparison.
> + 
>      Returns whether a COND can be vectorized.  Checks whether
>      condition operands are supportable using vec_is_simple_use.  */
>   
>   static bool
> ! vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype)
>   {
>     tree lhs, rhs;
>     tree def;
>     enum vect_def_type dt;
> +   tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
>   
>     if (!COMPARISON_CLASS_P (cond))
>       return false;
> *************** vect_is_simple_cond (tree cond, loop_vec
> *** 4699,4706 ****
>     if (TREE_CODE (lhs) == SSA_NAME)
>       {
>         gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
> !       if (!vect_is_simple_use (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
> !                                &dt))
>   	return false;
>       }
>     else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
> --- 4703,4710 ----
>     if (TREE_CODE (lhs) == SSA_NAME)
>       {
>         gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
> !       if (!vect_is_simple_use_1 (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
> ! 				 &dt, &vectype1))
>   	return false;
>       }
>     else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
> *************** vect_is_simple_cond (tree cond, loop_vec
> *** 4710,4723 ****
>     if (TREE_CODE (rhs) == SSA_NAME)
>       {
>         gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
> !       if (!vect_is_simple_use (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
> !                                &dt))
>   	return false;
>       }
>     else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
>   	   && TREE_CODE (rhs) != FIXED_CST)
>       return false;
>   
>     return true;
>   }
>   
> --- 4714,4728 ----
>     if (TREE_CODE (rhs) == SSA_NAME)
>       {
>         gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
> !       if (!vect_is_simple_use_1 (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
> ! 				 &dt, &vectype2))
>   	return false;
>       }
>     else if (TREE_CODE (rhs) != INTEGER_CST  && TREE_CODE (rhs) != REAL_CST
>   	   && TREE_CODE (rhs) != FIXED_CST)
>       return false;
>   
> +   *comp_vectype = vectype1 ? vectype1 : vectype2;
>     return true;
>   }
>   
> *************** vectorizable_condition (gimple stmt, gim
> *** 4744,4755 ****
>     tree cond_expr, then_clause, else_clause;
>     stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
>     tree vectype = STMT_VINFO_VECTYPE (stmt_info);
>     tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
>     tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
>     tree vec_compare, vec_cond_expr;
>     tree new_temp;
>     loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
> -   enum machine_mode vec_mode;
>     tree def;
>     enum vect_def_type dt, dts[4];
>     int nunits = TYPE_VECTOR_SUBPARTS (vectype);
> --- 4749,4760 ----
>     tree cond_expr, then_clause, else_clause;
>     stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
>     tree vectype = STMT_VINFO_VECTYPE (stmt_info);
> +   tree comp_vectype;
>     tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
>     tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
>     tree vec_compare, vec_cond_expr;
>     tree new_temp;
>     loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
>     tree def;
>     enum vect_def_type dt, dts[4];
>     int nunits = TYPE_VECTOR_SUBPARTS (vectype);
> *************** vectorizable_condition (gimple stmt, gim
> *** 4800,4812 ****
>     then_clause = TREE_OPERAND (op, 1);
>     else_clause = TREE_OPERAND (op, 2);
>   
> !   if (!vect_is_simple_cond (cond_expr, loop_vinfo))
> !     return false;
> ! 
> !   /* We do not handle two different vector types for the condition
> !      and the values.  */
> !   if (!types_compatible_p (TREE_TYPE (TREE_OPERAND (cond_expr, 0)),
> ! 			   TREE_TYPE (vectype)))
>       return false;
>   
>     if (TREE_CODE (then_clause) == SSA_NAME)
> --- 4805,4812 ----
>     then_clause = TREE_OPERAND (op, 1);
>     else_clause = TREE_OPERAND (op, 2);
>   
> !   if (!vect_is_simple_cond (cond_expr, loop_vinfo, &comp_vectype)
> !       || !comp_vectype)
>       return false;
>   
>     if (TREE_CODE (then_clause) == SSA_NAME)
> *************** vectorizable_condition (gimple stmt, gim
> *** 4833,4845 ****
>   	   && TREE_CODE (else_clause) != FIXED_CST)
>       return false;
>   
> - 
> -   vec_mode = TYPE_MODE (vectype);
> - 
>     if (!vec_stmt)
>       {
>         STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
> !       return expand_vec_cond_expr_p (TREE_TYPE (op), vec_mode);
>       }
>   
>     /* Transform */
> --- 4833,4842 ----
>   	   && TREE_CODE (else_clause) != FIXED_CST)
>       return false;
>   
>     if (!vec_stmt)
>       {
>         STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
> !       return expand_vec_cond_expr_p (vectype, comp_vectype);
>       }
>   
>     /* Transform */
> Index: trunk/gcc/config/i386/i386.c
> ===================================================================
> *** trunk.orig/gcc/config/i386/i386.c	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/config/i386/i386.c	2011-08-30 11:46:51.000000000 +0200
> *************** ix86_expand_sse_cmp (rtx dest, enum rtx_
> *** 18412,18430 ****
>   		     rtx op_true, rtx op_false)
>   {
>     enum machine_mode mode = GET_MODE (dest);
>     rtx x;
>   
> !   cmp_op0 = force_reg (mode, cmp_op0);
> !   if (!nonimmediate_operand (cmp_op1, mode))
> !     cmp_op1 = force_reg (mode, cmp_op1);
>   
>     if (optimize
>         || reg_overlap_mentioned_p (dest, op_true)
>         || reg_overlap_mentioned_p (dest, op_false))
>       dest = gen_reg_rtx (mode);
>   
> !   x = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
> !   emit_insn (gen_rtx_SET (VOIDmode, dest, x));
>   
>     return dest;
>   }
> --- 18412,18437 ----
>   		     rtx op_true, rtx op_false)
>   {
>     enum machine_mode mode = GET_MODE (dest);
> +   enum machine_mode cmp_mode = GET_MODE (cmp_op0);
>     rtx x;
>   
> !   cmp_op0 = force_reg (cmp_mode, cmp_op0);
> !   if (!nonimmediate_operand (cmp_op1, cmp_mode))
> !     cmp_op1 = force_reg (cmp_mode, cmp_op1);
>   
>     if (optimize
>         || reg_overlap_mentioned_p (dest, op_true)
>         || reg_overlap_mentioned_p (dest, op_false))
>       dest = gen_reg_rtx (mode);
>   
> !   x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1);
> !   if (cmp_mode != mode)
> !     {
> !       x = force_reg (cmp_mode, x);
> !       convert_move (dest, x, false);
> !     }
> !   else
> !     emit_insn (gen_rtx_SET (VOIDmode, dest, x));
>   
>     return dest;
>   }
> Index: trunk/gcc/testsuite/gcc.dg/vect/vect-cond-7.c
> ===================================================================
> *** /dev/null	1970-01-01 00:00:00.000000000 +0000
> --- trunk/gcc/testsuite/gcc.dg/vect/vect-cond-7.c	2011-08-30 11:46:51.000000000 +0200
> ***************
> *** 0 ****
> --- 1,14 ----
> + /* { dg-do compile } */
> + /* { dg-require-effective-target vect_condition } */
> + 
> + int vis_type[128];
> + float vs_data[128];
> + void vis_clear_data ()
> + {
> +   int i;
> +   for (i = 0; i < 128; i++)
> +     vs_data[i] = (vis_type[i] == 1);
> + }
> + 
> + /* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
> + /* { dg-final { cleanup-tree-dump "vect" } } */
> Index: trunk/gcc/doc/md.texi
> ===================================================================
> *** trunk.orig/gcc/doc/md.texi	2011-08-30 10:53:47.000000000 +0200
> --- trunk/gcc/doc/md.texi	2011-08-30 11:46:51.000000000 +0200
> *************** and input vectors should have the same m
> *** 4017,4022 ****
> --- 4017,4033 ----
>   Initialize the vector to given values.  Operand 0 is the vector to initialize
>   and operand 1 is parallel containing values for individual fields.
>   
> + @cindex @code{vcond@var{m}@var{n}} instruction pattern
> + @item @samp{vcond@var{m}@var{n}}
> + Output a conditional vector move.  Operand 0 is the destination to
> + receive a combination of operand 1 and operand 2, which are of mode @var{m},
> + dependent on the outcome of the predicate in operand 3 which is a
> + vector comparison with operands of mode @var{n} in operands 4 and 5.  The
> + modes @var{m} and @var{n} should have the same size.  Operand 0
> + will be set to the value @var{op1} & @var{msk} | @var{op2} & ~@var{msk}
> + where @var{msk} is computed by element-wise evaluation of the vector
> + comparison with a truth value of all-ones and a false value of all-zeros.
> + 
>   @cindex @code{push@var{m}1} instruction pattern
>   @item @samp{push@var{m}1}
>   Output a push instruction.  Operand 0 is value to push.  Used only when

-- 
Richard Guenther <rguenther@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Change vcond<mode> to vcond<mode1><mode2>
  2011-09-02  9:44                       ` Richard Guenther
@ 2011-09-02 12:19                         ` Uros Bizjak
  0 siblings, 0 replies; 16+ messages in thread
From: Uros Bizjak @ 2011-09-02 12:19 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Jakub Jelinek, gcc-patches, uros, rth, artyom.shinkaroff

On Fri, Sep 2, 2011 at 11:43 AM, Richard Guenther <rguenther@suse.de> wrote:

>> > > >> >> > Hmm.  But then I'd have to try emit an insn, right?  Currently
>> > > >> >> > the vectorizer simply looks for an optab handler ... the
>> > > >> >> > operands are not readily available (but their mode is known).
>> > > >> >> > So I'd create some fake regs, setup operands and call GEN_FCN
>> > > >> >> > on it?  If it succeds I'd have to delete emitted insns, etc.
>> > > >> >> > Or I could add a target hook ...
>> > > >> >>
>> > > >> >> Hm... indeed, too much complication...
>> > > >> >>
>> > > >> >> I'd say, let's go with modeless operands and a target hook. IMO, this
>> > > >> >> is much more flexible than checking optab for supported modes.
>> > > >> >> Existing way is appropriate for single mode patterns, but we have
>> > > >> >> interdependent modes here, at least on x86.
>> > > >> >>
>> > > >> >> The hook would have two input arguments, insn mode and compare mode,
>> > > >> >> where the hook returns suggested supported compare mode, or no mode,
>> > > >> >> if it really can't handle requested modes.
>> > > >> >
>> > > >> > I think a two mode vcond pattern is in fact much cleaner than
>> > > >> > a one mode + modeless pattern which gen* will complain about and
>> > > >> > a target hook.
>> > > >>
>> > > >> OK, but in this case, do not use mode iterators too much in order to
>> > > >> avoid invalid patterns.
>> > > >
>> > > > I don't see them as "invalid".  They will be unused (maybe combine
>> > > > would create them though?), but they have well-defined semantics
>> > > > with my proposed documentation.  And x86 can handle them just fine.
>> > >
>> > > OK, let's go this way then... We can clean up this later if at all.
>> >
>> > Certainly what I prefer (less work for me now) ;)  The smallest
>> > number of patterns would probably result from using vcond<mode><mode>
>> > to cover the same-mode cases and then add the 12 other patterns
>> > with the respective integer / float mode variant.  Thus we'd have
>> > 15 patterns in total (still much for my taste).
>> >
>> > Ideally we could have a mode attribute that would map possibly
>> > to an iterator, thus
>> >
>> > (define_mode_attr matching [(V4SF ["V4SF" "V4SI"]) (V8HI "V8HI") ...])
>> >
>> > or similar.  But I don't feel like adding this sort of mode
>> > attr that really is a hidden iterator ... ;)
>> >
>> > Thus, the following is the combined patch which bootstrapped and
>> > tested ok on x86_64-unknown-linux-gnu with {,-m32} over night,
>> > with the documentation for vcond added.
>> >
>> > Ok for trunk?
>>
>> I'm re-testing with the patterns having an extra condition like
>>    && (GET_MODE_NUNITS (<V_256:MODE>mode)
>>        == GET_MODE_NUNITS (<VF_256:MODE>mode))"
>> to have the HAVE_vcond* defines easily optimized.
>>
>> Ok?
>
> Ping.  I'd like to have approval for the x86 changes.

OK.

Thanks,
Uros.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2011-09-02 12:19 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-29 15:08 [PATCH] Change vcond<mode> to vcond<mode1><mode2> Richard Guenther
2011-08-29 16:36 ` Richard Guenther
2011-08-29 20:47 ` Uros Bizjak
2011-08-29 21:05   ` Richard Guenther
2011-08-30  9:00     ` Uros Bizjak
2011-08-30  9:19       ` Richard Guenther
2011-08-30  9:24         ` Uros Bizjak
2011-08-30  9:29           ` Jakub Jelinek
2011-08-30  9:39             ` Richard Guenther
2011-08-30  9:42             ` Uros Bizjak
2011-08-30 10:17               ` Richard Guenther
2011-08-30 10:48                 ` Uros Bizjak
2011-08-30 11:59                   ` Richard Guenther
2011-08-30 12:11                     ` Richard Guenther
2011-09-02  9:44                       ` Richard Guenther
2011-09-02 12:19                         ` Uros Bizjak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).