+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.
+
2011-08-29 Jakub Jelinek <jakub@redhat.com>
PR middle-end/48722
|| 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:
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:
}
\f
/* Return a node which has the indicated constant VALUE (either 0 or
- 1), and is of the indicated TYPE. */
+ 1 for scalars or {-1,-1,..} or {0,0,...} for vectors),
+ and is of the indicated TYPE. */
tree
-constant_boolean_node (int value, tree type)
+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 build_int_cst (type, value);
+ return fold_convert (type, value ? integer_one_node : integer_zero_node);
}
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));
+ constant_boolean_node (true, type),
+ constant_boolean_node (false, type));
}
/* Handle cases of two conversions in a row. */
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))
+ && 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),
{
tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
- if (!AGGREGATE_TYPE_P (type))
+ /* 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);
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);
+ 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;
}
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. */
+ 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)
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 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);