From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8618 invoked by alias); 30 Aug 2011 10:17:50 -0000 Received: (qmail 8593 invoked by uid 22791); 30 Aug 2011 10:17:45 -0000 X-SWARE-Spam-Status: No, hits=-3.5 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,TW_TM,TW_ZJ X-Spam-Check-By: sourceware.org Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 30 Aug 2011 10:17:25 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx2.suse.de (Postfix) with ESMTP id D949A8980B; Tue, 30 Aug 2011 12:17:22 +0200 (CEST) Date: Tue, 30 Aug 2011 12:11:00 -0000 From: Richard Guenther To: Uros Bizjak Cc: Jakub Jelinek , gcc-patches@gcc.gnu.org, uros@gcc.gnu.org, rth@redhat.com, artyom.shinkaroff@gmail.com Subject: Re: [PATCH] Change vcond to vcond In-Reply-To: Message-ID: References: <20110830090713.GG2687@tyan-ft48-01.lab.bos.redhat.com> User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) MIME-Version: 1.0 Content-Type: MULTIPART/MIXED; BOUNDARY="8323584-244457163-1314699442=:2130" Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-08/txt/msg02432.txt.bz2 This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. --8323584-244457163-1314699442=:2130 Content-Type: TEXT/PLAIN; charset=ISO-8859-1 Content-Transfer-Encoding: 8BIT Content-length: 33682 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 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 > 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 (mode) == GET_MODE_NUNITS (mode))" to have the HAVE_vcond* defines easily optimized. Ok? Thanks, Richard. 2011-08-30 Richard Guenther 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): Split to vcond, vcond, vcond and vcondu. (vcondv2di): Change to vcondv2di. (vconduv2di): Likewise. * config/arm/neon.md (vcond): Change to vcond*. (vcondu): Likewise. * config/ia64/vect.md (vcond): Likewise. (vcondu): Likewise. (vcondv2sf): Likewise. * config/mips/mips-ps-3d.md (vcondv2sf): Likewise. * config/rs6000/paired.md (vcondv2sf): Likewise. * config/rs6000/vector.md (vcond): Likewise. (vcondu): Likewise. * config/spu/spu.md (vcond): Likewise. (vcondu): 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" [(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" [(set (match_operand:VDQW 0 "s_register_operand" "") (if_then_else:VDQW (match_operator 3 "arm_comparison_operator" *************** *** 1680,1686 **** DONE; }) ! (define_expand "vcondu" [(set (match_operand:VDQIW 0 "s_register_operand" "") (if_then_else:VDQIW (match_operator 3 "arm_comparison_operator" --- 1680,1686 ---- DONE; }) ! (define_expand "vcondu" [(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" "")]) ! (define_expand "vcond" ! [(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" "")]) ! (define_expand "vcond" ! [(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 (mode) ! == GET_MODE_NUNITS (mode))" ! { ! bool ok = ix86_expand_fp_vcond (operands); ! gcc_assert (ok); ! DONE; ! }) ! ! (define_expand "vcond" ! [(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 (mode) ! == GET_MODE_NUNITS (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" ! [(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" ! [(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 (mode) ! == GET_MODE_NUNITS (mode))" { bool ok = ix86_expand_int_vcond (operands); gcc_assert (ok); DONE; }) ! (define_expand "vcondv2di" ! [(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" ! [(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" ! [(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 (mode) ! == GET_MODE_NUNITS (mode)" { bool ok = ix86_expand_int_vcond (operands); gcc_assert (ok); DONE; }) ! (define_expand "vconduv2di" ! [(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" [(set (match_operand:VECINT 0 "gr_register_operand" "") (if_then_else:VECINT (match_operator 3 "" --- 661,667 ---- DONE; }) ! (define_expand "vcond" [(set (match_operand:VECINT 0 "gr_register_operand" "") (if_then_else:VECINT (match_operator 3 "" *************** *** 675,681 **** DONE; }) ! (define_expand "vcondu" [(set (match_operand:VECINT 0 "gr_register_operand" "") (if_then_else:VECINT (match_operator 3 "" --- 675,681 ---- DONE; }) ! (define_expand "vcondu" [(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" "")]) ! (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" "")]) ! (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" [(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" [(set (match_operand:VEC_F 0 "vfloat_operand" "") (if_then_else:VEC_F (match_operator 3 "comparison_operator" *************** *** 388,394 **** FAIL; }") ! (define_expand "vcond" [(set (match_operand:VEC_I 0 "vint_operand" "") (if_then_else:VEC_I (match_operator 3 "comparison_operator" --- 388,394 ---- FAIL; }") ! (define_expand "vcond" [(set (match_operand:VEC_I 0 "vint_operand" "") (if_then_else:VEC_I (match_operator 3 "comparison_operator" *************** *** 406,412 **** FAIL; }") ! (define_expand "vcondu" [(set (match_operand:VEC_I 0 "vint_operand" "") (if_then_else:VEC_I (match_operator 3 "comparison_operator" --- 406,412 ---- FAIL; }") ! (define_expand "vcondu" [(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" [(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" [(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" [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r") (if_then_else:VCMPU (match_operator 3 "comparison_operator" --- 3891,3897 ---- FAIL; }) ! (define_expand "vcondu" [(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 --8323584-244457163-1314699442=:2130--