[PATCH] Change vcond<mode> to vcond<mode1><mode2>

Richard Guenther rguenther@suse.de
Fri Sep 2 09:44:00 GMT 2011


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 ****
>   
>   

>   ;; 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 ----
>   
>   

>   ;; 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 ****
>   
>   

>   ;; 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 ----
>   
>   

>   ;; 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


More information about the Gcc-patches mailing list