OSDN Git Service

2011-09-02 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 2 Sep 2011 13:53:32 +0000 (13:53 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 2 Sep 2011 13:53:32 +0000 (13:53 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@178480 138bc75d-0d04-0410-961f-82ee72b054a4

15 files changed:
gcc/ChangeLog
gcc/config/arm/neon.md
gcc/config/i386/i386.c
gcc/config/i386/sse.md
gcc/config/ia64/vect.md
gcc/config/mips/mips-ps-3d.md
gcc/config/rs6000/paired.md
gcc/config/rs6000/vector.md
gcc/config/spu/spu.md
gcc/doc/md.texi
gcc/genopinit.c
gcc/optabs.c
gcc/optabs.h
gcc/testsuite/ChangeLog
gcc/tree-vect-stmts.c

index b79a964..a54f1d1 100644 (file)
@@ -1,5 +1,44 @@
 2011-09-02  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.
+
+2011-09-02  Richard Guenther  <rguenther@suse.de>
+
        * pretty-print.h (pp_unsigned_wide_integer): New.
        * tree-pretty-print.c (dump_generic_node): Print unsigned
        host-wide-int fitting INTEGER_CSTs with pp_unsigned_wide_integer.
index 24dd941..c91b0cd 100644 (file)
 ;; where op3 is <, <=, ==, !=, >= or >.  Operations are performed
 ;; element-wise.
 
-(define_expand "vcond<mode>"
+(define_expand "vcond<mode><mode>"
   [(set (match_operand:VDQW 0 "s_register_operand" "")
        (if_then_else:VDQW
          (match_operator 3 "arm_comparison_operator"
   DONE;
 })
 
-(define_expand "vcondu<mode>"
+(define_expand "vcondu<mode><mode>"
   [(set (match_operand:VDQIW 0 "s_register_operand" "")
        (if_then_else:VDQIW
          (match_operator 3 "arm_comparison_operator"
index d0e1be5..a9c0aa7 100644 (file)
@@ -18413,19 +18413,26 @@ ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1,
                     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 (mode, cmp_op0);
-  if (!nonimmediate_operand (cmp_op1, mode))
-    cmp_op1 = force_reg (mode, cmp_op1);
+  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, mode, cmp_op0, cmp_op1);
-  emit_insn (gen_rtx_SET (VOIDmode, dest, x));
+  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 3678ea8..353f4b6 100644 (file)
                      (const_string "0")))
    (set_attr "mode" "<MODE>")])
 
-(define_expand "vcond<mode>"
-  [(set (match_operand:VF 0 "register_operand" "")
-       (if_then_else:VF
+(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 4 "nonimmediate_operand" "")
-            (match_operand:VF 5 "nonimmediate_operand" "")])
-         (match_operand:VF 1 "general_operand" "")
-         (match_operand:VF 2 "general_operand" "")))]
-  "TARGET_SSE"
+           [(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);
    (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
+(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:VI124_128 1 "general_operand" "")
-         (match_operand:VI124_128 2 "general_operand" "")))]
-  "TARGET_SSE2"
+         (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 "vcondv2di"
-  [(set (match_operand:V2DI 0 "register_operand" "")
-       (if_then_else:V2DI
+(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:V2DI 1 "general_operand" "")
-         (match_operand:V2DI 2 "general_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);
   DONE;
 })
 
-(define_expand "vcondu<mode>"
-  [(set (match_operand:VI124_128 0 "register_operand" "")
-       (if_then_else:VI124_128
+(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:VI124_128 1 "general_operand" "")
-         (match_operand:VI124_128 2 "general_operand" "")))]
-  "TARGET_SSE2"
+         (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 "vconduv2di"
-  [(set (match_operand:V2DI 0 "register_operand" "")
-       (if_then_else:V2DI
+(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:V2DI 1 "general_operand" "")
-         (match_operand:V2DI 2 "general_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 1684c80..2f068eb 100644 (file)
   DONE;
 })
 
-(define_expand "vcond<mode>"
+(define_expand "vcond<mode><mode>"
   [(set (match_operand:VECINT 0 "gr_register_operand" "")
        (if_then_else:VECINT
          (match_operator 3 "" 
   DONE;
 })
 
-(define_expand "vcondu<mode>"
+(define_expand "vcondu<mode><mode>"
   [(set (match_operand:VECINT 0 "gr_register_operand" "")
        (if_then_else:VECINT
          (match_operator 3 "" 
   DONE;
 })
 
-(define_expand "vcondv2sf"
+(define_expand "vcondv2sfv2sf"
   [(set (match_operand:V2SF 0 "fr_register_operand" "")
        (if_then_else:V2SF
          (match_operator 3 "" 
index 8e94230..504f43c 100644 (file)
   [(set_attr "type" "frdiv2")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_expand "vcondv2sf"
+(define_expand "vcondv2sfv2sf"
   [(set (match_operand:V2SF 0 "register_operand")
        (if_then_else:V2SF
          (match_operator 3 ""
index d1b0e8e..f0bf7f9 100644 (file)
   DONE;
 })
 
-(define_expand "vcondv2sf"
+(define_expand "vcondv2sfv2sf"
   [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
         (if_then_else:V2SF
          (match_operator 3 "gpc_reg_operand"
index 4799ff2..0179cd9 100644 (file)
 
 \f
 ;; Vector comparisons
-(define_expand "vcond<mode>"
+(define_expand "vcond<mode><mode>"
   [(set (match_operand:VEC_F 0 "vfloat_operand" "")
        (if_then_else:VEC_F
         (match_operator 3 "comparison_operator"
     FAIL;
 }")
 
-(define_expand "vcond<mode>"
+(define_expand "vcond<mode><mode>"
   [(set (match_operand:VEC_I 0 "vint_operand" "")
        (if_then_else:VEC_I
         (match_operator 3 "comparison_operator"
     FAIL;
 }")
 
-(define_expand "vcondu<mode>"
+(define_expand "vcondu<mode><mode>"
   [(set (match_operand:VEC_I 0 "vint_operand" "")
        (if_then_else:VEC_I
         (match_operator 3 "comparison_operator"
index 5742e0d..676d54e 100644 (file)
@@ -3874,7 +3874,7 @@ selb\t%0,%4,%0,%3"
 
 \f
 ;; vector conditional compare patterns
-(define_expand "vcond<mode>"
+(define_expand "vcond<mode><mode>"
   [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
         (if_then_else:VCMP
           (match_operator 3 "comparison_operator"
@@ -3891,7 +3891,7 @@ selb\t%0,%4,%0,%3"
     FAIL;
   })
 
-(define_expand "vcondu<mode>"
+(define_expand "vcondu<mode><mode>"
   [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
         (if_then_else:VCMPU
           (match_operator 3 "comparison_operator"
index 7fc1a5e..1aa8552 100644 (file)
@@ -4017,6 +4017,17 @@ and input vectors should have the same modes (@code{N} elements). The low
 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
index 4855e5a..ec4a473 100644 (file)
@@ -253,8 +253,8 @@ static const char * const optabs[] =
   "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_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 886b259..5cdcd95 100644 (file)
@@ -6620,27 +6620,33 @@ vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
   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.  */
+/* 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 (tree type, enum machine_mode mode)
+get_vcond_icode (enum machine_mode vmode, enum machine_mode cmode, bool uns)
 {
   enum insn_code icode = CODE_FOR_nothing;
-
-  if (TYPE_UNSIGNED (type))
-    icode = direct_optab_handler (vcondu_optab, mode);
+  if (uns)
+    icode = convert_optab_handler (vcondu_optab, vmode, cmode);
   else
-    icode = direct_optab_handler (vcond_optab, mode);
+    icode = convert_optab_handler (vcond_optab, vmode, cmode);
   return icode;
 }
 
 /* Return TRUE iff, appropriate vector insns are available
-   for vector cond expr with type TYPE in VMODE mode.  */
+   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 type, enum machine_mode vmode)
-{
-  if (get_vcond_icode (type, vmode) == CODE_FOR_nothing)
+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;
 }
@@ -6656,9 +6662,18 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
   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);
+  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 (vec_cond_type, mode);
+  icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
   if (icode == CODE_FOR_nothing)
     return 0;
 
index cf5a659..56df671 100644 (file)
@@ -589,6 +589,10 @@ enum convert_optab_index
   COI_vec_load_lanes,
   COI_vec_store_lanes,
 
+  /* Vector conditional operations.  */
+  COI_vcond,
+  COI_vcondu,
+
   COI_MAX
 };
 
@@ -611,6 +615,8 @@ enum convert_optab_index
 #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];
@@ -632,10 +638,6 @@ enum direct_optab_index
   DOI_reload_in,
   DOI_reload_out,
 
-  /* Vector conditional operations.  */
-  DOI_vcond,
-  DOI_vcondu,
-
   /* Block move operation.  */
   DOI_movmem,
 
@@ -699,8 +701,6 @@ typedef struct direct_optab_d *direct_optab;
 #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])
@@ -877,7 +877,7 @@ extern bool expand_sfix_optab (rtx, rtx, convert_optab);
 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);
+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 629176d..1584cff 100644 (file)
@@ -1,3 +1,9 @@
+2011-09-02  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/27460
+       PR middle-end/29269
+       * gcc.dg/vect/vect-cond-7.c: New testcase.
+
 2011-09-02  Martin Jambor  <mjambor@suse.cz>
 
        * g++.dg/ipa/devirt-3.C: Added a distraction method.
index 2a13181..2c77091 100644 (file)
@@ -4680,15 +4680,19 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
    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)
+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;
@@ -4699,8 +4703,8 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
   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))
+      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
@@ -4710,14 +4714,15 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
   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))
+      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;
 }
 
@@ -4743,12 +4748,12 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
   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);
-  enum machine_mode vec_mode;
   tree def;
   enum vect_def_type dt, dts[4];
   int nunits = TYPE_VECTOR_SUBPARTS (vectype);
@@ -4797,13 +4802,8 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
   then_clause = gimple_assign_rhs2 (stmt);
   else_clause = gimple_assign_rhs3 (stmt);
 
-  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)))
+  if (!vect_is_simple_cond (cond_expr, loop_vinfo, &comp_vectype)
+      || !comp_vectype)
     return false;
 
   if (TREE_CODE (then_clause) == SSA_NAME)
@@ -4830,14 +4830,10 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
           && 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 (gimple_assign_lhs (stmt)),
-                                    vec_mode);
+      return expand_vec_cond_expr_p (vectype, comp_vectype);
     }
 
   /* Transform */