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 <rguent...@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 <rguent...@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 <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer