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. */
}
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) */
indirect_base0 = true;
}
offset0 = TREE_OPERAND (arg0, 1);
+ if (host_integerp (offset0, 0))
+ {
+ HOST_WIDE_INT off = size_low_cst (offset0);
+ if ((HOST_WIDE_INT) (((unsigned HOST_WIDE_INT) off)
+ * BITS_PER_UNIT)
+ / BITS_PER_UNIT == (HOST_WIDE_INT) off)
+ {
+ bitpos0 = off * BITS_PER_UNIT;
+ offset0 = NULL_TREE;
+ }
+ }
}
base1 = arg1;
indirect_base1 = true;
}
offset1 = TREE_OPERAND (arg1, 1);
+ if (host_integerp (offset1, 0))
+ {
+ HOST_WIDE_INT off = size_low_cst (offset1);
+ if ((HOST_WIDE_INT) (((unsigned HOST_WIDE_INT) off)
+ * BITS_PER_UNIT)
+ / BITS_PER_UNIT == (HOST_WIDE_INT) off)
+ {
+ bitpos1 = off * BITS_PER_UNIT;
+ offset1 = NULL_TREE;
+ }
+ }
}
/* A local variable can never be pointed to by
/* An ASSERT_EXPR should never be passed to fold_binary. */
gcc_unreachable ();
- case VEC_EXTRACT_EVEN_EXPR:
- case VEC_EXTRACT_ODD_EXPR:
- case VEC_INTERLEAVE_HIGH_EXPR:
- case VEC_INTERLEAVE_LOW_EXPR:
- if ((TREE_CODE (arg0) == VECTOR_CST
- || TREE_CODE (arg0) == CONSTRUCTOR)
- && (TREE_CODE (arg1) == VECTOR_CST
- || TREE_CODE (arg1) == CONSTRUCTOR))
- {
- unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
- unsigned char *sel = XALLOCAVEC (unsigned char, nelts);
+ case VEC_PACK_TRUNC_EXPR:
+ case VEC_PACK_FIX_TRUNC_EXPR:
+ {
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+ tree *elts, vals = NULL_TREE;
- for (i = 0; i < nelts; i++)
- switch (code)
- {
- case VEC_EXTRACT_EVEN_EXPR:
- sel[i] = i * 2;
- break;
- case VEC_EXTRACT_ODD_EXPR:
- sel[i] = i * 2 + 1;
- break;
- case VEC_INTERLEAVE_HIGH_EXPR:
- sel[i] = (i + nelts) / 2 + ((i & 1) ? nelts : 0);
- break;
- case VEC_INTERLEAVE_LOW_EXPR:
- sel[i] = i / 2 + ((i & 1) ? nelts : 0);
- break;
- default:
- gcc_unreachable ();
- }
+ 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;
- return fold_vec_perm (type, arg0, arg1, sel);
- }
- 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;
}
}
md5_process_bytes (expr, tree_size (expr), ctx);
- fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
+ if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
+ fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
if (TREE_CODE_CLASS (code) != tcc_type
&& TREE_CODE_CLASS (code) != tcc_declaration
&& code != TREE_LIST