tree lhs = gimple_assign_lhs (stmt);
wi->val_only
= (is_gimple_reg_type (TREE_TYPE (lhs)) && !is_gimple_reg (lhs))
- || !gimple_assign_single_p (stmt);
+ || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
}
for (i = 1; i < gimple_num_ops (stmt); i++)
if (wi)
{
/* If the RHS has more than 1 operand, it is not appropriate
- for the memory. */
- wi->val_only = !(is_gimple_mem_rhs (gimple_assign_rhs1 (stmt))
- || TREE_CODE (gimple_assign_rhs1 (stmt))
- == CONSTRUCTOR)
- || !gimple_assign_single_p (stmt);
+ for the memory.
+ ??? A lhs always requires an lvalue, checking the val_only flag
+ does not make any sense, so we should be able to avoid computing
+ it here. */
+ tree rhs1 = gimple_assign_rhs1 (stmt);
+ wi->val_only = !(is_gimple_mem_rhs (rhs1)
+ || TREE_CODE (rhs1) == CONSTRUCTOR)
+ || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
wi->is_lhs = true;
}
|| TREE_CODE (t) == STRING_CST);
}
-/* Return true if TYPE is a suitable type for a scalar register variable. */
-
-bool
-is_gimple_reg_type (tree type)
-{
- return !AGGREGATE_TYPE_P (type);
-}
-
/* Return true if T is a non-aggregate register variable. */
bool
}
-/* Return true if T is a GIMPLE variable whose address is not needed. */
-
-bool
-is_gimple_non_addressable (tree t)
-{
- if (TREE_CODE (t) == SSA_NAME)
- t = SSA_NAME_VAR (t);
-
- return (is_gimple_variable (t) && ! needs_to_live_in_memory (t));
-}
-
/* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant. */
bool
goto same_types;
else if (i1 == NULL_TREE || i2 == NULL_TREE)
goto different_types;
- /* If for a complete array type the possibly gimplified sizes
- are different the types are different. */
- else if (((TYPE_SIZE (i1) != NULL) ^ (TYPE_SIZE (i2) != NULL))
- || (TYPE_SIZE (i1)
- && TYPE_SIZE (i2)
- && !operand_equal_p (TYPE_SIZE (i1), TYPE_SIZE (i2), 0)))
- goto different_types;
else
{
tree min1 = TYPE_MIN_VALUE (i1);
v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
}
- /* For array types hash their domain and the string flag. */
- if (TREE_CODE (type) == ARRAY_TYPE
- && TYPE_DOMAIN (type))
+ /* For array types hash the domain and the string flag. */
+ if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
{
v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
v = visit (TYPE_DOMAIN (type), state, v,
v = iterative_hash_hashval_t (na, v);
}
- if (TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == UNION_TYPE
- || TREE_CODE (type) == QUAL_UNION_TYPE)
+ if (RECORD_OR_UNION_TYPE_P (type))
{
unsigned nf;
tree f;
v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
}
- /* For integer types hash the types min/max values and the string flag. */
+ /* For integer types hash the sizetype and the string flag. */
if (TREE_CODE (type) == INTEGER_TYPE)
{
v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
v = iterative_hash_hashval_t (TYPE_IS_SIZETYPE (type), v);
}
- /* For array types hash their domain and the string flag. */
- if (TREE_CODE (type) == ARRAY_TYPE
- && TYPE_DOMAIN (type))
+ /* For array types hash the domain bounds and the string flag. */
+ if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
{
v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
- v = iterative_hash_canonical_type (TYPE_DOMAIN (type), v);
+ /* OMP lowering can introduce error_mark_node in place of
+ random local decls in types. */
+ if (TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
+ v = iterative_hash_expr (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), v);
+ if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
+ v = iterative_hash_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), v);
}
/* Recurse for aggregates with a single element type. */
v = iterative_hash_hashval_t (na, v);
}
- if (TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == UNION_TYPE
- || TREE_CODE (type) == QUAL_UNION_TYPE)
+ if (RECORD_OR_UNION_TYPE_P (type))
{
unsigned nf;
tree f;
return true;
else if (i1 == NULL_TREE || i2 == NULL_TREE)
return false;
- /* If for a complete array type the possibly gimplified sizes
- are different the types are different. */
- else if (((TYPE_SIZE (i1) != NULL) ^ (TYPE_SIZE (i2) != NULL))
- || (TYPE_SIZE (i1)
- && TYPE_SIZE (i2)
- && !operand_equal_p (TYPE_SIZE (i1), TYPE_SIZE (i2), 0)))
- return false;
else
{
tree min1 = TYPE_MIN_VALUE (i1);
return IDENTIFIER_POINTER (DECL_NAME (decl));
}
-/* Return true when STMT is builtins call to CODE. */
+/* Return true when STMTs arguments match those of FNDECL. */
+
+static bool
+validate_call (gimple stmt, tree fndecl)
+{
+ tree arg, targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ unsigned nargs = gimple_call_num_args (stmt);
+ unsigned i;
+ for (i = 0; i < nargs; ++i)
+ {
+ /* Variadic args follow. */
+ if (!targs)
+ return true;
+ arg = gimple_call_arg (stmt, i);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (arg))
+ && INTEGRAL_TYPE_P (TREE_VALUE (targs)))
+ ;
+ else if (POINTER_TYPE_P (TREE_TYPE (arg))
+ && POINTER_TYPE_P (TREE_VALUE (targs)))
+ ;
+ else if (TREE_CODE (TREE_TYPE (arg))
+ != TREE_CODE (TREE_VALUE (targs)))
+ return false;
+ targs = TREE_CHAIN (targs);
+ }
+ if (targs && !VOID_TYPE_P (TREE_VALUE (targs)))
+ return false;
+ return true;
+}
+
+/* Return true when STMT is builtins call to CLASS. */
+
+bool
+gimple_call_builtin_class_p (gimple stmt, enum built_in_class klass)
+{
+ tree fndecl;
+ if (is_gimple_call (stmt)
+ && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
+ && DECL_BUILT_IN_CLASS (fndecl) == klass)
+ return validate_call (stmt, fndecl);
+ return false;
+}
+
+/* Return true when STMT is builtins call to CODE of CLASS. */
bool
gimple_call_builtin_p (gimple stmt, enum built_in_function code)
{
tree fndecl;
- return (is_gimple_call (stmt)
- && (fndecl = gimple_call_fndecl (stmt)) != NULL
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == code);
+ if (is_gimple_call (stmt)
+ && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
+ && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+ && DECL_FUNCTION_CODE (fndecl) == code)
+ return validate_call (stmt, fndecl);
+ return false;
}
/* Return true if STMT clobbers memory. STMT is required to be a