summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-12-03 16:41:23 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-12-03 16:41:23 +0000
commitf9b668f1f297dee9208c4f7d38b6191b3ffdf2e6 (patch)
tree101d7dce72755d652f7a8bd031b61275b10c84d4 /gcc/fold-const.c
parent88f2e16bb28fb750679c6c2b24e0ff3e0ab73f26 (diff)
downloadgcc-f9b668f1f297dee9208c4f7d38b6191b3ffdf2e6.tar.gz
* fold-const.c (fold_unary_loc): Fold VEC_UNPACK_LO_EXPR,
VEC_UNPACK_HI_EXPR, VEC_UNPACK_FLOAT_LO_EXPR and VEC_UNPACK_FLOAT_HI_EXPR with VECTOR_CST argument. (fold_binary_loc): Fold VEC_PACK_TRUNC_EXPR, VEC_PACK_FIX_TRUNC_EXPR, VEC_WIDEN_MULT_LO_EXPR and VEC_WIDEN_MULT_HI_EXPR with VECTOR_CST arguments. * gcc.dg/vect/vect-122.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181972 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 8f31a5fdb0e..a32ea9000e6 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -7651,6 +7651,8 @@ build_fold_addr_expr_loc (location_t loc, tree t)
return build_fold_addr_expr_with_type_loc (loc, t, ptrtype);
}
+static bool vec_cst_ctor_to_array (tree, tree *);
+
/* Fold a unary expression of code CODE and type TYPE with operand
OP0. Return the folded expression if folding is successful.
Otherwise, return NULL_TREE. */
@@ -8294,6 +8296,44 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
}
return NULL_TREE;
+ case VEC_UNPACK_LO_EXPR:
+ case VEC_UNPACK_HI_EXPR:
+ case VEC_UNPACK_FLOAT_LO_EXPR:
+ case VEC_UNPACK_FLOAT_HI_EXPR:
+ {
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+ tree *elts, vals = NULL_TREE;
+ enum tree_code subcode;
+
+ gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2);
+ if (TREE_CODE (arg0) != VECTOR_CST)
+ return NULL_TREE;
+
+ elts = XALLOCAVEC (tree, nelts * 2);
+ if (!vec_cst_ctor_to_array (arg0, elts))
+ return NULL_TREE;
+
+ if ((!BYTES_BIG_ENDIAN) ^ (code == VEC_UNPACK_LO_EXPR
+ || code == VEC_UNPACK_FLOAT_LO_EXPR))
+ elts += nelts;
+
+ if (code == VEC_UNPACK_LO_EXPR || code == VEC_UNPACK_HI_EXPR)
+ subcode = NOP_EXPR;
+ else
+ subcode = FLOAT_EXPR;
+
+ for (i = 0; i < nelts; i++)
+ {
+ elts[i] = fold_convert_const (subcode, TREE_TYPE (type), elts[i]);
+ if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
+ return NULL_TREE;
+ }
+
+ for (i = 0; i < nelts; i++)
+ vals = tree_cons (NULL_TREE, elts[nelts - i - 1], vals);
+ return build_vector (type, vals);
+ }
+
default:
return NULL_TREE;
} /* switch (code) */
@@ -13498,6 +13538,73 @@ fold_binary_loc (location_t loc,
}
return NULL_TREE;
+ case VEC_PACK_TRUNC_EXPR:
+ case VEC_PACK_FIX_TRUNC_EXPR:
+ {
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+ tree *elts, vals = NULL_TREE;
+
+ gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts / 2
+ && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts / 2);
+ if (TREE_CODE (arg0) != VECTOR_CST || TREE_CODE (arg1) != VECTOR_CST)
+ return NULL_TREE;
+
+ elts = XALLOCAVEC (tree, nelts);
+ if (!vec_cst_ctor_to_array (arg0, elts)
+ || !vec_cst_ctor_to_array (arg1, elts + nelts / 2))
+ return NULL_TREE;
+
+ for (i = 0; i < nelts; i++)
+ {
+ elts[i] = fold_convert_const (code == VEC_PACK_TRUNC_EXPR
+ ? NOP_EXPR : FIX_TRUNC_EXPR,
+ TREE_TYPE (type), elts[i]);
+ if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
+ return NULL_TREE;
+ }
+
+ for (i = 0; i < nelts; i++)
+ vals = tree_cons (NULL_TREE, elts[nelts - i - 1], vals);
+ return build_vector (type, vals);
+ }
+
+ case VEC_WIDEN_MULT_LO_EXPR:
+ case VEC_WIDEN_MULT_HI_EXPR:
+ {
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+ tree *elts, vals = NULL_TREE;
+
+ gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2
+ && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts * 2);
+ if (TREE_CODE (arg0) != VECTOR_CST || TREE_CODE (arg1) != VECTOR_CST)
+ return NULL_TREE;
+
+ elts = XALLOCAVEC (tree, nelts * 4);
+ if (!vec_cst_ctor_to_array (arg0, elts)
+ || !vec_cst_ctor_to_array (arg1, elts + nelts * 2))
+ return NULL_TREE;
+
+ if ((!BYTES_BIG_ENDIAN) ^ (code == VEC_WIDEN_MULT_LO_EXPR))
+ elts += nelts;
+
+ for (i = 0; i < nelts; i++)
+ {
+ elts[i] = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[i]);
+ elts[i + nelts * 2]
+ = fold_convert_const (NOP_EXPR, TREE_TYPE (type),
+ elts[i + nelts * 2]);
+ if (elts[i] == NULL_TREE || elts[i + nelts * 2] == NULL_TREE)
+ return NULL_TREE;
+ elts[i] = const_binop (MULT_EXPR, elts[i], elts[i + nelts * 2]);
+ if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
+ return NULL_TREE;
+ }
+
+ for (i = 0; i < nelts; i++)
+ vals = tree_cons (NULL_TREE, elts[nelts - i - 1], vals);
+ return build_vector (type, vals);
+ }
+
default:
return NULL_TREE;
} /* switch (code) */