aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const-call.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fold-const-call.c')
-rw-r--r--gcc/fold-const-call.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 004f94e..439043a 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h" /* For C[LT]Z_DEFINED_AT_ZERO. */
#include "builtins.h"
#include "gimple-expr.h"
+#include "tree-vector-builder.h"
/* Functions that test for certain constant types, abstracting away the
decision about whether to check for overflow. */
@@ -645,6 +646,40 @@ fold_const_reduction (tree type, tree arg, tree_code code)
return res;
}
+/* Fold a call to IFN_VEC_CONVERT (ARG) returning TYPE. */
+
+static tree
+fold_const_vec_convert (tree ret_type, tree arg)
+{
+ enum tree_code code = NOP_EXPR;
+ tree arg_type = TREE_TYPE (arg);
+ if (TREE_CODE (arg) != VECTOR_CST)
+ return NULL_TREE;
+
+ gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
+
+ if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
+ && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
+ code = FIX_TRUNC_EXPR;
+ else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
+ && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
+ code = FLOAT_EXPR;
+
+ tree_vector_builder elts;
+ elts.new_unary_operation (ret_type, arg, true);
+ unsigned int count = elts.encoded_nelts ();
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ tree elt = fold_unary (code, TREE_TYPE (ret_type),
+ VECTOR_CST_ELT (arg, i));
+ if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
+ return NULL_TREE;
+ elts.quick_push (elt);
+ }
+
+ return elts.build ();
+}
+
/* Try to evaluate:
*RESULT = FN (*ARG)
@@ -1232,6 +1267,9 @@ fold_const_call (combined_fn fn, tree type, tree arg)
case CFN_REDUC_XOR:
return fold_const_reduction (type, arg, BIT_XOR_EXPR);
+ case CFN_VEC_CONVERT:
+ return fold_const_vec_convert (type, arg);
+
default:
return fold_const_call_1 (fn, type, arg);
}