20011-08-29  Artjoms Sinkarovs  <artyom.shinkaroff@gmail.com>
	Richard Guenther  <rguenther@suse.de>

	* tree.h (constant_boolean_node): Adjust prototype.
	* fold-const.c (fold_convert_loc): Move aggregate conversion
	leeway down.
	(constant_boolean_node): Make value parameter boolean, add
	vector type handling.
	(fold_unary_loc): Use constant_boolean_node.
	(fold_binary_loc): Preserve types properly when folding
	COMPLEX_EXPR <__real x, __imag x>.
	* gimplify.c (gimplify_expr): Handle vector comparison.
	* tree.def (EQ_EXPR, ...): Document behavior on vector typed
	comparison.
	* tree-cfg.c (verify_gimple_comparison): Verify vector typed
	comparisons.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c.orig	2011-08-29 11:48:23.000000000 +0200
--- gcc/fold-const.c	2011-08-29 12:09:51.000000000 +0200
*************** fold_convert_loc (location_t loc, tree t
*** 1867,1875 ****
        || TREE_CODE (orig) == ERROR_MARK)
      return error_mark_node;
  
-   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig))
-     return fold_build1_loc (loc, NOP_EXPR, type, arg);
- 
    switch (TREE_CODE (type))
      {
      case POINTER_TYPE:
--- 1867,1872 ----
*************** fold_convert_loc (location_t loc, tree t
*** 2017,2022 ****
--- 2014,2021 ----
        return fold_build1_loc (loc, NOP_EXPR, type, tem);
  
      default:
+       if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig))
+ 	return fold_build1_loc (loc, NOP_EXPR, type, arg);
        gcc_unreachable ();
      }
   fold_convert_exit:
*************** extract_muldiv_1 (tree t, tree c, enum t
*** 5929,5945 ****
  }
  
  /* Return a node which has the indicated constant VALUE (either 0 or
!    1), and is of the indicated TYPE.  */
  
  tree
! constant_boolean_node (int value, tree type)
  {
    if (type == integer_type_node)
      return value ? integer_one_node : integer_zero_node;
    else if (type == boolean_type_node)
      return value ? boolean_true_node : boolean_false_node;
    else
!     return build_int_cst (type, value);
  }
  
  
--- 5928,5949 ----
  }
  
  /* Return a node which has the indicated constant VALUE (either 0 or
!    1 for scalars or {-1,-1,..} or {0,0,...} for vectors),
!    and is of the indicated TYPE.  */
  
  tree
! constant_boolean_node (bool value, tree type)
  {
    if (type == integer_type_node)
      return value ? integer_one_node : integer_zero_node;
    else if (type == boolean_type_node)
      return value ? boolean_true_node : boolean_false_node;
+   else if (TREE_CODE (type) == VECTOR_TYPE)
+     return build_vector_from_val (type,
+ 				  build_int_cst (TREE_TYPE (type),
+ 						 value ? -1 : 0));
    else
!     return fold_convert (type, value ? integer_one_node : integer_zero_node);
  }
  
  
*************** fold_unary_loc (location_t loc, enum tre
*** 7668,7675 ****
  			       TREE_OPERAND (op0, 1));
  	  else if (!INTEGRAL_TYPE_P (type))
  	    return build3_loc (loc, COND_EXPR, type, op0,
! 			       fold_convert (type, boolean_true_node),
! 			       fold_convert (type, boolean_false_node));
  	}
  
        /* Handle cases of two conversions in a row.  */
--- 7672,7679 ----
  			       TREE_OPERAND (op0, 1));
  	  else if (!INTEGRAL_TYPE_P (type))
  	    return build3_loc (loc, COND_EXPR, type, op0,
! 			       constant_boolean_node (true, type),
! 			       constant_boolean_node (false, type));
  	}
  
        /* Handle cases of two conversions in a row.  */
*************** fold_binary_loc (location_t loc,
*** 13202,13209 ****
  	return build_complex (type, arg0, arg1);
        if (TREE_CODE (arg0) == REALPART_EXPR
  	  && TREE_CODE (arg1) == IMAGPART_EXPR
! 	  && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg0, 0)))
! 	      == TYPE_MAIN_VARIANT (type))
  	  && operand_equal_p (TREE_OPERAND (arg0, 0),
  			      TREE_OPERAND (arg1, 0), 0))
  	return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 0),
--- 13206,13212 ----
  	return build_complex (type, arg0, arg1);
        if (TREE_CODE (arg0) == REALPART_EXPR
  	  && TREE_CODE (arg1) == IMAGPART_EXPR
! 	  && TREE_TYPE (TREE_OPERAND (arg0, 0)) == type
  	  && operand_equal_p (TREE_OPERAND (arg0, 0),
  			      TREE_OPERAND (arg1, 0), 0))
  	return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 0),
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c.orig	2011-08-29 11:48:23.000000000 +0200
--- gcc/gimplify.c	2011-08-29 11:48:30.000000000 +0200
*************** gimplify_expr (tree *expr_p, gimple_seq
*** 7349,7355 ****
  		{
  		  tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
  
! 		  if (!AGGREGATE_TYPE_P (type))
  		    {
  		      tree org_type = TREE_TYPE (*expr_p);
  		      *expr_p = gimple_boolify (*expr_p);
--- 7349,7358 ----
  		{
  		  tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
  
! 		  /* Vector comparisons need no boolification.  */
! 		  if (TREE_CODE (type) == VECTOR_TYPE)
! 		    goto expr_2;
! 		  else if (!AGGREGATE_TYPE_P (type))
  		    {
  		      tree org_type = TREE_TYPE (*expr_p);
  		      *expr_p = gimple_boolify (*expr_p);
Index: gcc/tree.def
===================================================================
*** gcc/tree.def.orig	2011-08-29 11:48:23.000000000 +0200
--- gcc/tree.def	2011-08-29 11:48:30.000000000 +0200
*************** DEFTREECODE (TRUTH_NOT_EXPR, "truth_not_
*** 704,710 ****
     The others are allowed only for integer (or pointer or enumeral)
     or real types.
     In all cases the operands will have the same type,
!    and the value is always the type used by the language for booleans.  */
  DEFTREECODE (LT_EXPR, "lt_expr", tcc_comparison, 2)
  DEFTREECODE (LE_EXPR, "le_expr", tcc_comparison, 2)
  DEFTREECODE (GT_EXPR, "gt_expr", tcc_comparison, 2)
--- 704,713 ----
     The others are allowed only for integer (or pointer or enumeral)
     or real types.
     In all cases the operands will have the same type,
!    and the value is either the type used by the language for booleans
!    or an integer vector type of the same size and with the same number
!    of elements as the comparison operands.  True for a vector of
!    comparison results has all bits set while false is equal to zero.  */
  DEFTREECODE (LT_EXPR, "lt_expr", tcc_comparison, 2)
  DEFTREECODE (LE_EXPR, "le_expr", tcc_comparison, 2)
  DEFTREECODE (GT_EXPR, "gt_expr", tcc_comparison, 2)
Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c.orig	2011-08-29 11:48:23.000000000 +0200
--- gcc/tree-cfg.c	2011-08-29 11:48:30.000000000 +0200
*************** verify_gimple_comparison (tree type, tre
*** 3266,3290 ****
       effective type the comparison is carried out in.  Instead
       we require that either the first operand is trivially
       convertible into the second, or the other way around.
-      The resulting type of a comparison may be any integral type.
       Because we special-case pointers to void we allow
       comparisons of pointers with the same mode as well.  */
!   if ((!useless_type_conversion_p (op0_type, op1_type)
!        && !useless_type_conversion_p (op1_type, op0_type)
!        && (!POINTER_TYPE_P (op0_type)
! 	   || !POINTER_TYPE_P (op1_type)
! 	   || TYPE_MODE (op0_type) != TYPE_MODE (op1_type)))
!       || !INTEGRAL_TYPE_P (type)
!       || (TREE_CODE (type) != BOOLEAN_TYPE
! 	  && TYPE_PRECISION (type) != 1))
      {
!       error ("type mismatch in comparison expression");
!       debug_generic_expr (type);
        debug_generic_expr (op0_type);
        debug_generic_expr (op1_type);
        return true;
      }
  
    return false;
  }
  
--- 3266,3320 ----
       effective type the comparison is carried out in.  Instead
       we require that either the first operand is trivially
       convertible into the second, or the other way around.
       Because we special-case pointers to void we allow
       comparisons of pointers with the same mode as well.  */
!   if (!useless_type_conversion_p (op0_type, op1_type)
!       && !useless_type_conversion_p (op1_type, op0_type)
!       && (!POINTER_TYPE_P (op0_type)
! 	  || !POINTER_TYPE_P (op1_type)
! 	  || TYPE_MODE (op0_type) != TYPE_MODE (op1_type)))
      {
!       error ("mismatching comparison operand types");
        debug_generic_expr (op0_type);
        debug_generic_expr (op1_type);
        return true;
      }
  
+   /* The resulting type of a comparison may be an effective boolean type.  */
+   if (INTEGRAL_TYPE_P (type)
+       && (TREE_CODE (type) == BOOLEAN_TYPE
+ 	  || TYPE_PRECISION (type) == 1))
+     ;
+   /* Or an integer vector type with the same size and element count
+      as the comparison operand types.  */
+   else if (TREE_CODE (type) == VECTOR_TYPE
+ 	   && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
+     {
+       if (TREE_CODE (op0_type) != VECTOR_TYPE
+ 	  || TREE_CODE (op1_type) != VECTOR_TYPE)
+         {
+           error ("non-vector operands in vector comparison");
+           debug_generic_expr (op0_type);
+           debug_generic_expr (op1_type);
+           return true;
+         }
+ 
+       if (TYPE_VECTOR_SUBPARTS (type) != TYPE_VECTOR_SUBPARTS (op0_type)
+ 	  || (GET_MODE_SIZE (TYPE_MODE (type))
+ 	      != GET_MODE_SIZE (TYPE_MODE (op0_type))))
+         {
+           error ("invalid vector comparison resulting type");
+           debug_generic_expr (type);
+           return true;
+         }
+     }
+   else
+     {
+       error ("bogus comparison result type");
+       debug_generic_expr (type);
+       return true;
+     }
+ 
    return false;
  }
  
Index: gcc/tree.h
===================================================================
*** gcc/tree.h.orig	2011-08-29 11:48:23.000000000 +0200
--- gcc/tree.h	2011-08-29 11:48:30.000000000 +0200
*************** extern tree build_simple_mem_ref_loc (lo
*** 5274,5280 ****
  extern double_int mem_ref_offset (const_tree);
  extern tree reference_alias_ptr_type (const_tree);
  extern tree build_invariant_address (tree, tree, HOST_WIDE_INT);
! extern tree constant_boolean_node (int, tree);
  extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree);
  
  extern bool tree_swap_operands_p (const_tree, const_tree, bool);
--- 5274,5280 ----
  extern double_int mem_ref_offset (const_tree);
  extern tree reference_alias_ptr_type (const_tree);
  extern tree build_invariant_address (tree, tree, HOST_WIDE_INT);
! extern tree constant_boolean_node (bool, tree);
  extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree);
  
  extern bool tree_swap_operands_p (const_tree, const_tree, bool);
