aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2013-05-10 13:15:14 +0200
committerMarc Glisse <glisse@gcc.gnu.org>2013-05-10 11:15:14 +0000
commita5e0cd1d9bd6fbcff37a6545d8e60b36ff6ea7a7 (patch)
tree28b2392d93f8ced83cd8e4d51d5232f6883088da
parentcb2558bc95658155c76e1468ed4db64359452dc2 (diff)
downloadgcc-a5e0cd1d9bd6fbcff37a6545d8e60b36ff6ea7a7.zip
gcc-a5e0cd1d9bd6fbcff37a6545d8e60b36ff6ea7a7.tar.gz
gcc-a5e0cd1d9bd6fbcff37a6545d8e60b36ff6ea7a7.tar.bz2
stor-layout.c (element_precision): New function.
2013-05-10 Marc Glisse <marc.glisse@inria.fr> gcc/ * stor-layout.c (element_precision): New function. * machmode.h (element_precision): Declare it. * tree.c (build_minus_one_cst): New function. (element_precision): Likewise. * tree.h (build_minus_one_cst): Declare new function. (element_precision): Likewise. * fold-const.c (operand_equal_p): Use element_precision. (fold_binary_loc): Handle vector types. * convert.c (convert_to_integer): Use element_precision. * gimple.c (iterative_hash_canonical_type): Handle complex and vectors separately. gcc/c-family/ * c-common.c (vector_types_convertible_p): No TYPE_PRECISION for vectors. gcc/testsuite/ * gcc.dg/vector-shift.c: New testcase. From-SVN: r198772
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c-common.c2
-rw-r--r--gcc/convert.c4
-rw-r--r--gcc/fold-const.c55
-rw-r--r--gcc/gimple.c11
-rw-r--r--gcc/machmode.h4
-rw-r--r--gcc/stor-layout.c12
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/vector-shift.c13
-rw-r--r--gcc/tree.c52
-rw-r--r--gcc/tree.h2
12 files changed, 146 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3257628..bdc8bc5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2013-05-10 Marc Glisse <marc.glisse@inria.fr>
+
+ * stor-layout.c (element_precision): New function.
+ * machmode.h (element_precision): Declare it.
+ * tree.c (build_minus_one_cst): New function.
+ (element_precision): Likewise.
+ * tree.h (build_minus_one_cst): Declare new function.
+ (element_precision): Likewise.
+ * fold-const.c (operand_equal_p): Use element_precision.
+ (fold_binary_loc): Handle vector types.
+ * convert.c (convert_to_integer): Use element_precision.
+ * gimple.c (iterative_hash_canonical_type): Handle complex and vectors
+ separately.
+
2013-05-10 Richard Sandiford <rdsandiford@googlemail.com>
* config/mips/mips-protos.h (m16_uimm3_b, m16_simm4_1, m16_nsimm4_1)
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 44bad5c..62e14d0 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,8 @@
+2013-05-10 Marc Glisse <marc.glisse@inria.fr>
+
+ * c-common.c (vector_types_convertible_p): No TYPE_PRECISION for
+ vectors.
+
2013-05-07 Han Shen <shenhan@google.com>
* c-cppbuiltin.c (c_cpp_builtins): Added "__SSP_STRONG__=3".
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 8d88b26..8cc1248 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -2227,7 +2227,7 @@ vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
convertible_lax =
(tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
&& (TREE_CODE (TREE_TYPE (t1)) != REAL_TYPE ||
- TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
+ TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2))
&& (INTEGRAL_TYPE_P (TREE_TYPE (t1))
== INTEGRAL_TYPE_P (TREE_TYPE (t2))));
diff --git a/gcc/convert.c b/gcc/convert.c
index e124e7a..62ff224 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -355,8 +355,8 @@ convert_to_integer (tree type, tree expr)
{
enum tree_code ex_form = TREE_CODE (expr);
tree intype = TREE_TYPE (expr);
- unsigned int inprec = TYPE_PRECISION (intype);
- unsigned int outprec = TYPE_PRECISION (type);
+ unsigned int inprec = element_precision (intype);
+ unsigned int outprec = element_precision (type);
/* An INTEGER_TYPE cannot be incomplete, but an ENUMERAL_TYPE can
be. Consider `enum E = { a, b = (enum E) 3 };'. */
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 74b451e..bfe9e07 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -2445,7 +2445,8 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
/* If both types don't have the same precision, then it is not safe
to strip NOPs. */
- if (TYPE_PRECISION (TREE_TYPE (arg0)) != TYPE_PRECISION (TREE_TYPE (arg1)))
+ if (element_precision (TREE_TYPE (arg0))
+ != element_precision (TREE_TYPE (arg1)))
return 0;
STRIP_NOPS (arg0);
@@ -9877,6 +9878,7 @@ fold_binary_loc (location_t loc,
tree arg0, arg1, tem;
tree t1 = NULL_TREE;
bool strict_overflow_p;
+ unsigned int prec;
gcc_assert (IS_EXPR_CODE_CLASS (kind)
&& TREE_CODE_LENGTH (code) == 2
@@ -10147,7 +10149,7 @@ fold_binary_loc (location_t loc,
STRIP_NOPS (tem);
if (operand_equal_p (tem, arg1, 0))
{
- t1 = build_int_cst_type (type, -1);
+ t1 = build_minus_one_cst (type);
return omit_one_operand_loc (loc, type, t1, arg1);
}
}
@@ -10161,7 +10163,7 @@ fold_binary_loc (location_t loc,
STRIP_NOPS (tem);
if (operand_equal_p (arg0, tem, 0))
{
- t1 = build_int_cst_type (type, -1);
+ t1 = build_minus_one_cst (type);
return omit_one_operand_loc (loc, type, t1, arg0);
}
}
@@ -10387,7 +10389,8 @@ fold_binary_loc (location_t loc,
TYPE_UNSIGNED (rtype))
/* Only create rotates in complete modes. Other cases are not
expanded properly. */
- && TYPE_PRECISION (rtype) == GET_MODE_PRECISION (TYPE_MODE (rtype)))
+ && (element_precision (rtype)
+ == element_precision (TYPE_MODE (rtype))))
{
tree tree01, tree11;
enum tree_code code01, code11;
@@ -10403,7 +10406,7 @@ fold_binary_loc (location_t loc,
&& TREE_INT_CST_HIGH (tree01) == 0
&& TREE_INT_CST_HIGH (tree11) == 0
&& ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
+ == element_precision (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
{
tem = build2_loc (loc, LROTATE_EXPR,
TREE_TYPE (TREE_OPERAND (arg0, 0)),
@@ -10420,7 +10423,7 @@ fold_binary_loc (location_t loc,
STRIP_NOPS (tree111);
if (TREE_CODE (tree110) == INTEGER_CST
&& 0 == compare_tree_int (tree110,
- TYPE_PRECISION
+ element_precision
(TREE_TYPE (TREE_OPERAND
(arg0, 0))))
&& operand_equal_p (tree01, tree111, 0))
@@ -10441,7 +10444,7 @@ fold_binary_loc (location_t loc,
STRIP_NOPS (tree011);
if (TREE_CODE (tree010) == INTEGER_CST
&& 0 == compare_tree_int (tree010,
- TYPE_PRECISION
+ element_precision
(TREE_TYPE (TREE_OPERAND
(arg0, 0))))
&& operand_equal_p (tree11, tree011, 0))
@@ -11757,8 +11760,7 @@ fold_binary_loc (location_t loc,
if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
&& TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
- unsigned int prec
- = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)));
+ prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)));
if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_WIDE_INT
&& (~TREE_INT_CST_LOW (arg1)
@@ -11826,7 +11828,7 @@ fold_binary_loc (location_t loc,
&& TYPE_PRECISION (TREE_TYPE (arg0))
== GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg0))))
{
- unsigned int prec = TYPE_PRECISION (TREE_TYPE (arg0));
+ prec = TYPE_PRECISION (TREE_TYPE (arg0));
tree arg00 = TREE_OPERAND (arg0, 0);
/* See if more bits can be proven as zero because of
zero extension. */
@@ -11869,8 +11871,6 @@ fold_binary_loc (location_t loc,
newmask = mask | zerobits;
if (newmask != mask && (newmask & (newmask + 1)) == 0)
{
- unsigned int prec;
-
/* Only do the transformation if NEWMASK is some integer
mode's mask. */
for (prec = BITS_PER_UNIT;
@@ -12414,30 +12414,32 @@ fold_binary_loc (location_t loc,
if (TREE_CODE (arg1) == INTEGER_CST && tree_int_cst_sgn (arg1) < 0)
return NULL_TREE;
+ prec = element_precision (type);
+
/* Turn (a OP c1) OP c2 into a OP (c1+c2). */
if (TREE_CODE (op0) == code && host_integerp (arg1, false)
- && TREE_INT_CST_LOW (arg1) < TYPE_PRECISION (type)
+ && TREE_INT_CST_LOW (arg1) < prec
&& host_integerp (TREE_OPERAND (arg0, 1), false)
- && TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) < TYPE_PRECISION (type))
+ && TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) < prec)
{
HOST_WIDE_INT low = (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1))
+ TREE_INT_CST_LOW (arg1));
/* Deal with a OP (c1 + c2) being undefined but (a OP c1) OP c2
being well defined. */
- if (low >= TYPE_PRECISION (type))
+ if (low >= prec)
{
if (code == LROTATE_EXPR || code == RROTATE_EXPR)
- low = low % TYPE_PRECISION (type);
+ low = low % prec;
else if (TYPE_UNSIGNED (type) || code == LSHIFT_EXPR)
- return omit_one_operand_loc (loc, type, build_int_cst (type, 0),
+ return omit_one_operand_loc (loc, type, build_zero_cst (type),
TREE_OPERAND (arg0, 0));
else
- low = TYPE_PRECISION (type) - 1;
+ low = prec - 1;
}
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
- build_int_cst (type, low));
+ build_int_cst (TREE_TYPE (arg1), low));
}
/* Transform (x >> c) << c into x & (-1<<c), or transform (x << c) >> c
@@ -12446,9 +12448,9 @@ fold_binary_loc (location_t loc,
|| (TYPE_UNSIGNED (type)
&& code == RSHIFT_EXPR && TREE_CODE (arg0) == LSHIFT_EXPR))
&& host_integerp (arg1, false)
- && TREE_INT_CST_LOW (arg1) < TYPE_PRECISION (type)
+ && TREE_INT_CST_LOW (arg1) < prec
&& host_integerp (TREE_OPERAND (arg0, 1), false)
- && TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) < TYPE_PRECISION (type))
+ && TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) < prec)
{
HOST_WIDE_INT low0 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1));
HOST_WIDE_INT low1 = TREE_INT_CST_LOW (arg1);
@@ -12459,8 +12461,8 @@ fold_binary_loc (location_t loc,
{
arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
- lshift = build_int_cst (type, -1);
- lshift = int_const_binop (code, lshift, arg1);
+ lshift = build_minus_one_cst (type);
+ lshift = const_binop (code, lshift, arg1);
return fold_build2_loc (loc, BIT_AND_EXPR, type, arg00, lshift);
}
@@ -12470,8 +12472,7 @@ fold_binary_loc (location_t loc,
RROTATE_EXPR by a new constant. */
if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
{
- tree tem = build_int_cst (TREE_TYPE (arg1),
- TYPE_PRECISION (type));
+ tree tem = build_int_cst (TREE_TYPE (arg1), prec);
tem = const_binop (MINUS_EXPR, tem, arg1);
return fold_build2_loc (loc, RROTATE_EXPR, type, op0, tem);
}
@@ -12499,7 +12500,7 @@ fold_binary_loc (location_t loc,
&& TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1)) == 0
&& ((TREE_INT_CST_LOW (arg1)
+ TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)))
- == (unsigned int) TYPE_PRECISION (type)))
+ == prec))
return TREE_OPERAND (arg0, 0);
/* Fold (X & C2) << C1 into (X << C1) & (C2 << C1)
@@ -12912,8 +12913,8 @@ fold_binary_loc (location_t loc,
&& integer_zerop (arg1))
{
tree itype = TREE_TYPE (arg0);
- unsigned HOST_WIDE_INT prec = TYPE_PRECISION (itype);
tree arg001 = TREE_OPERAND (TREE_OPERAND (arg0, 0), 1);
+ prec = TYPE_PRECISION (itype);
/* Check for a valid shift count. */
if (TREE_INT_CST_HIGH (arg001) == 0
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 64f7b1a..f507419 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -3083,8 +3083,6 @@ iterative_hash_canonical_type (tree type, hashval_t val)
if (INTEGRAL_TYPE_P (type)
|| SCALAR_FLOAT_TYPE_P (type)
|| FIXED_POINT_TYPE_P (type)
- || TREE_CODE (type) == VECTOR_TYPE
- || TREE_CODE (type) == COMPLEX_TYPE
|| TREE_CODE (type) == OFFSET_TYPE
|| POINTER_TYPE_P (type))
{
@@ -3092,6 +3090,15 @@ iterative_hash_canonical_type (tree type, hashval_t val)
v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
}
+ if (VECTOR_TYPE_P (type))
+ {
+ v = iterative_hash_hashval_t (TYPE_VECTOR_SUBPARTS (type), v);
+ v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
+ }
+
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
+
/* For pointer and reference types, fold in information about the type
pointed to but do not recurse to the pointed-to type. */
if (POINTER_TYPE_P (type))
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 2efd7b5..981ee92 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -297,6 +297,10 @@ extern unsigned get_mode_alignment (enum machine_mode);
#define GET_MODE_ALIGNMENT(MODE) get_mode_alignment (MODE)
+/* Get the precision of the mode or its inner mode if it has one. */
+
+extern unsigned int element_precision (enum machine_mode);
+
/* For each class, get the narrowest mode in that class. */
extern const unsigned char class_narrowest_mode[MAX_MODE_CLASS];
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 5ad95b1..6f6b310 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -453,6 +453,18 @@ get_mode_alignment (enum machine_mode mode)
return MIN (BIGGEST_ALIGNMENT, MAX (1, mode_base_align[mode]*BITS_PER_UNIT));
}
+/* Return the precision of the mode, or for a complex or vector mode the
+ precision of the mode of its elements. */
+
+unsigned int
+element_precision (enum machine_mode mode)
+{
+ if (COMPLEX_MODE_P (mode) || VECTOR_MODE_P (mode))
+ mode = GET_MODE_INNER (mode);
+
+ return GET_MODE_PRECISION (mode);
+}
+
/* Return the natural mode of an array, given that it is SIZE bytes in
total and has elements of type ELEM_TYPE. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7f29941..d8e1354 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2013-05-10 Marc Glisse <marc.glisse@inria.fr>
+
+ * gcc.dg/vector-shift.c: New testcase.
+
2013-05-10 Jakub Jelinek <jakub@redhat.com>
* gcc.target/i386/rotate-1.c: Accept rolb or rorb instruction.
diff --git a/gcc/testsuite/gcc.dg/vector-shift.c b/gcc/testsuite/gcc.dg/vector-shift.c
new file mode 100644
index 0000000..2a4d415
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vector-shift.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-original" } */
+
+typedef unsigned vec __attribute__ ((vector_size (4 * sizeof (int))));
+
+void
+f (vec *x)
+{
+ *x = (*x << 4) << 3;
+}
+
+/* { dg-final { scan-tree-dump "<< 7" "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/tree.c b/gcc/tree.c
index 55fa99b..d93c6ae 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1643,6 +1643,45 @@ build_one_cst (tree type)
}
}
+/* Return a constant of arithmetic type TYPE which is the
+ opposite of the multiplicative identity of the set TYPE. */
+
+tree
+build_minus_one_cst (tree type)
+{
+ switch (TREE_CODE (type))
+ {
+ case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
+ case POINTER_TYPE: case REFERENCE_TYPE:
+ case OFFSET_TYPE:
+ return build_int_cst (type, -1);
+
+ case REAL_TYPE:
+ return build_real (type, dconstm1);
+
+ case FIXED_POINT_TYPE:
+ /* We can only generate 1 for accum types. */
+ gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type)));
+ return build_fixed (type, fixed_from_double_int (double_int_minus_one,
+ TYPE_MODE (type)));
+
+ case VECTOR_TYPE:
+ {
+ tree scalar = build_minus_one_cst (TREE_TYPE (type));
+
+ return build_vector_from_val (type, scalar);
+ }
+
+ case COMPLEX_TYPE:
+ return build_complex (type,
+ build_minus_one_cst (TREE_TYPE (type)),
+ build_zero_cst (TREE_TYPE (type)));
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Build 0 constant of type TYPE. This is used by constructor folding
and thus the constant should be represented in memory by
zero(es). */
@@ -6949,6 +6988,19 @@ valid_constant_size_p (const_tree size)
return true;
}
+/* Return the precision of the type, or for a complex or vector type the
+ precision of the type of its elements. */
+
+unsigned int
+element_precision (const_tree type)
+{
+ enum tree_code code = TREE_CODE (type);
+ if (code == COMPLEX_TYPE || code == VECTOR_TYPE)
+ type = TREE_TYPE (type);
+
+ return TYPE_PRECISION (type);
+}
+
/* Return true if CODE represents an associative tree code. Otherwise
return false. */
bool
diff --git a/gcc/tree.h b/gcc/tree.h
index cd1d7613..a46d276 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4767,6 +4767,7 @@ extern tree build_constructor_va (tree, int, ...);
extern tree build_real_from_int_cst (tree, const_tree);
extern tree build_complex (tree, tree, tree);
extern tree build_one_cst (tree);
+extern tree build_minus_one_cst (tree);
extern tree build_zero_cst (tree);
extern tree build_string (int, const char *);
extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
@@ -4867,6 +4868,7 @@ extern bool may_negate_without_overflow_p (const_tree);
extern tree strip_array_types (tree);
extern tree excess_precision_type (tree);
extern bool valid_constant_size_p (const_tree);
+extern unsigned int element_precision (const_tree);
/* Construct various nodes representing fract or accum data types. */