summaryrefslogtreecommitdiff
path: root/gcc/gimple.c
diff options
context:
space:
mode:
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>2013-10-20 23:47:35 +0000
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>2013-10-20 23:47:35 +0000
commit6b40961666f073231ed8a76e6e33deeda063cde7 (patch)
tree8247eb4232e8be98b7f61bd68bab2fd1a9f06ca3 /gcc/gimple.c
parente6b1b76450af5f98696ecedd4bd9a0ed18cdb2a6 (diff)
parentfc1ce0cf396bf638746d546a557158d87f13849b (diff)
downloadgcc-6b40961666f073231ed8a76e6e33deeda063cde7.tar.gz
Merge in trunk.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@203881 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gimple.c')
-rw-r--r--gcc/gimple.c896
1 files changed, 209 insertions, 687 deletions
diff --git a/gcc/gimple.c b/gcc/gimple.c
index b7c8281c202..f6ed803857b 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -30,18 +30,13 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "gimple.h"
#include "diagnostic.h"
-#include "tree-ssa.h"
#include "value-prof.h"
#include "flags.h"
#include "alias.h"
#include "demangle.h"
#include "langhooks.h"
+#include "bitmap.h"
-/* Global canonical type table. */
-static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node)))
- htab_t gimple_canonical_types;
-static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
- htab_t canonical_type_hash_cache;
/* All the tuples have their operand vector (if present) at the very bottom
of the structure. Therefore, the offset required to find the
@@ -54,7 +49,7 @@ EXPORTED_CONST size_t gimple_ops_offset_[] = {
};
#undef DEFGSSTRUCT
-#define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) sizeof(struct STRUCT),
+#define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) sizeof (struct STRUCT),
static const size_t gsstruct_code_size[] = {
#include "gsstruct.def"
};
@@ -157,7 +152,7 @@ gimple_set_subcode (gimple g, unsigned subcode)
/* Build a tuple with operands. CODE is the statement to build (which
- must be one of the GIMPLE_WITH_OPS tuples). SUBCODE is the sub-code
+ must be one of the GIMPLE_WITH_OPS tuples). SUBCODE is the subcode
for the new tuple. NUM_OPS is the number of operands to allocate. */
#define gimple_build_with_ops(c, s, n) \
@@ -429,7 +424,7 @@ gimple_build_assign_stat (tree lhs, tree rhs MEM_STAT_DECL)
}
-/* Build a GIMPLE_ASSIGN statement with sub-code SUBCODE and operands
+/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
OP1 and OP2. If OP2 is NULL then SUBCODE must be of class
GIMPLE_UNARY_RHS or GIMPLE_SINGLE_RHS. */
@@ -1007,6 +1002,22 @@ gimple_build_omp_master (gimple_seq body)
}
+/* Build a GIMPLE_OMP_TASKGROUP statement.
+
+ BODY is the sequence of statements to be executed by the taskgroup
+ construct. */
+
+gimple
+gimple_build_omp_taskgroup (gimple_seq body)
+{
+ gimple p = gimple_alloc (GIMPLE_OMP_TASKGROUP, 0);
+ if (body)
+ gimple_omp_set_body (p, body);
+
+ return p;
+}
+
+
/* Build a GIMPLE_OMP_CONTINUE statement.
CONTROL_DEF is the definition of the control variable.
@@ -1096,6 +1107,41 @@ gimple_build_omp_single (gimple_seq body, tree clauses)
}
+/* Build a GIMPLE_OMP_TARGET statement.
+
+ BODY is the sequence of statements that will be executed.
+ CLAUSES are any of the OMP target construct's clauses. */
+
+gimple
+gimple_build_omp_target (gimple_seq body, int kind, tree clauses)
+{
+ gimple p = gimple_alloc (GIMPLE_OMP_TARGET, 0);
+ if (body)
+ gimple_omp_set_body (p, body);
+ gimple_omp_target_set_clauses (p, clauses);
+ gimple_omp_target_set_kind (p, kind);
+
+ return p;
+}
+
+
+/* Build a GIMPLE_OMP_TEAMS statement.
+
+ BODY is the sequence of statements that will be executed.
+ CLAUSES are any of the OMP teams construct's clauses. */
+
+gimple
+gimple_build_omp_teams (gimple_seq body, tree clauses)
+{
+ gimple p = gimple_alloc (GIMPLE_OMP_TEAMS, 0);
+ if (body)
+ gimple_omp_set_body (p, body);
+ gimple_omp_teams_set_clauses (p, clauses);
+
+ return p;
+}
+
+
/* Build a GIMPLE_OMP_ATOMIC_LOAD statement. */
gimple
@@ -1154,10 +1200,10 @@ gimple_check_failed (const_gimple gs, const char *file, int line,
{
internal_error ("gimple check: expected %s(%s), have %s(%s) in %s, at %s:%d",
gimple_code_name[code],
- tree_code_name[subcode],
+ get_tree_code_name (subcode),
gimple_code_name[gimple_code (gs)],
gs->gsbase.subcode > 0
- ? tree_code_name[gs->gsbase.subcode]
+ ? get_tree_code_name ((enum tree_code) gs->gsbase.subcode)
: "",
function, trim_filename (file), line);
}
@@ -1612,6 +1658,20 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
return ret;
break;
+ case GIMPLE_OMP_TARGET:
+ ret = walk_tree (gimple_omp_target_clauses_ptr (stmt), callback_op, wi,
+ pset);
+ if (ret)
+ return ret;
+ break;
+
+ case GIMPLE_OMP_TEAMS:
+ ret = walk_tree (gimple_omp_teams_clauses_ptr (stmt), callback_op, wi,
+ pset);
+ if (ret)
+ return ret;
+ break;
+
case GIMPLE_OMP_ATOMIC_LOAD:
ret = walk_tree (gimple_omp_atomic_load_lhs_ptr (stmt), callback_op, wi,
pset);
@@ -1638,10 +1698,16 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
return ret;
break;
+ case GIMPLE_OMP_RETURN:
+ ret = walk_tree (gimple_omp_return_lhs_ptr (stmt), callback_op, wi,
+ pset);
+ if (ret)
+ return ret;
+ break;
+
/* Tuples that do not have operands. */
case GIMPLE_NOP:
case GIMPLE_RESX:
- case GIMPLE_OMP_RETURN:
case GIMPLE_PREDICT:
break;
@@ -1782,12 +1848,15 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
/* FALL THROUGH. */
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
+ case GIMPLE_OMP_TARGET:
+ case GIMPLE_OMP_TEAMS:
ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt,
callback_op, wi);
if (ret)
@@ -2153,42 +2222,9 @@ gimple_set_lhs (gimple stmt, tree lhs)
else if (code == GIMPLE_CALL)
gimple_call_set_lhs (stmt, lhs);
else
- gcc_unreachable();
+ gcc_unreachable ();
}
-/* Replace the LHS of STMT, an assignment, either a GIMPLE_ASSIGN or a
- GIMPLE_CALL, with NLHS, in preparation for modifying the RHS to an
- expression with a different value.
-
- This will update any annotations (say debug bind stmts) referring
- to the original LHS, so that they use the RHS instead. This is
- done even if NLHS and LHS are the same, for it is understood that
- the RHS will be modified afterwards, and NLHS will not be assigned
- an equivalent value.
-
- Adjusting any non-annotation uses of the LHS, if needed, is a
- responsibility of the caller.
-
- The effect of this call should be pretty much the same as that of
- inserting a copy of STMT before STMT, and then removing the
- original stmt, at which time gsi_remove() would have update
- annotations, but using this function saves all the inserting,
- copying and removing. */
-
-void
-gimple_replace_lhs (gimple stmt, tree nlhs)
-{
- if (MAY_HAVE_DEBUG_STMTS)
- {
- tree lhs = gimple_get_lhs (stmt);
-
- gcc_assert (SSA_NAME_DEF_STMT (lhs) == stmt);
-
- insert_debug_temp_for_var_def (NULL, lhs);
- }
-
- gimple_set_lhs (stmt, nlhs);
-}
/* Return a deep copy of statement STMT. All the operands from STMT
are reallocated and copied using unshare_expr. The DEF, USE, VDEF
@@ -2310,8 +2346,11 @@ gimple_copy (gimple stmt)
/* FALLTHRU */
case GIMPLE_OMP_SINGLE:
+ case GIMPLE_OMP_TARGET:
+ case GIMPLE_OMP_TEAMS:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
copy_omp_body:
new_seq = gimple_seq_copy (gimple_omp_body (stmt));
@@ -2737,6 +2776,25 @@ is_gimple_id (tree t)
|| TREE_CODE (t) == STRING_CST);
}
+/* Return true if OP, an SSA name or a DECL is a virtual operand. */
+
+bool
+virtual_operand_p (tree op)
+{
+ if (TREE_CODE (op) == SSA_NAME)
+ {
+ op = SSA_NAME_VAR (op);
+ if (!op)
+ return false;
+ }
+
+ if (TREE_CODE (op) == VAR_DECL)
+ return VAR_DECL_IS_VIRTUAL_OPERAND (op);
+
+ return false;
+}
+
+
/* Return true if T is a non-aggregate register variable. */
bool
@@ -3055,455 +3113,6 @@ gimple_compare_field_offset (tree f1, tree f2)
return false;
}
-/* Returning a hash value for gimple type TYPE combined with VAL.
-
- The hash value returned is equal for types considered compatible
- by gimple_canonical_types_compatible_p. */
-
-static hashval_t
-iterative_hash_canonical_type (tree type, hashval_t val)
-{
- hashval_t v;
- void **slot;
- struct tree_int_map *mp, m;
-
- m.base.from = type;
- if ((slot = htab_find_slot (canonical_type_hash_cache, &m, INSERT))
- && *slot)
- return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, val);
-
- /* Combine a few common features of types so that types are grouped into
- smaller sets; when searching for existing matching types to merge,
- only existing types having the same features as the new type will be
- checked. */
- v = iterative_hash_hashval_t (TREE_CODE (type), 0);
- v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v);
- v = iterative_hash_hashval_t (TYPE_ALIGN (type), v);
- v = iterative_hash_hashval_t (TYPE_MODE (type), v);
-
- /* Incorporate common features of numerical types. */
- if (INTEGRAL_TYPE_P (type)
- || SCALAR_FLOAT_TYPE_P (type)
- || FIXED_POINT_TYPE_P (type)
- || TREE_CODE (type) == OFFSET_TYPE
- || POINTER_TYPE_P (type))
- {
- v = iterative_hash_hashval_t (TYPE_PRECISION (type), v);
- 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))
- {
- v = iterative_hash_hashval_t (TYPE_REF_CAN_ALIAS_ALL (type), v);
- v = iterative_hash_hashval_t (TYPE_ADDR_SPACE (TREE_TYPE (type)), v);
- v = iterative_hash_hashval_t (TYPE_RESTRICT (type), v);
- v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
- }
-
- /* For integer types hash only the string flag. */
- if (TREE_CODE (type) == INTEGER_TYPE)
- v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
-
- /* 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);
- /* 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. */
- if (TREE_CODE (type) == ARRAY_TYPE
- || TREE_CODE (type) == COMPLEX_TYPE
- || TREE_CODE (type) == VECTOR_TYPE)
- v = iterative_hash_canonical_type (TREE_TYPE (type), v);
-
- /* Incorporate function return and argument types. */
- if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
- {
- unsigned na;
- tree p;
-
- /* For method types also incorporate their parent class. */
- if (TREE_CODE (type) == METHOD_TYPE)
- v = iterative_hash_canonical_type (TYPE_METHOD_BASETYPE (type), v);
-
- v = iterative_hash_canonical_type (TREE_TYPE (type), v);
-
- for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
- {
- v = iterative_hash_canonical_type (TREE_VALUE (p), v);
- na++;
- }
-
- v = iterative_hash_hashval_t (na, v);
- }
-
- if (RECORD_OR_UNION_TYPE_P (type))
- {
- unsigned nf;
- tree f;
-
- for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
- if (TREE_CODE (f) == FIELD_DECL)
- {
- v = iterative_hash_canonical_type (TREE_TYPE (f), v);
- nf++;
- }
-
- v = iterative_hash_hashval_t (nf, v);
- }
-
- /* Cache the just computed hash value. */
- mp = ggc_alloc_cleared_tree_int_map ();
- mp->base.from = type;
- mp->to = v;
- *slot = (void *) mp;
-
- return iterative_hash_hashval_t (v, val);
-}
-
-static hashval_t
-gimple_canonical_type_hash (const void *p)
-{
- if (canonical_type_hash_cache == NULL)
- canonical_type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
- tree_int_map_eq, NULL);
-
- return iterative_hash_canonical_type (CONST_CAST_TREE ((const_tree) p), 0);
-}
-
-
-
-
-/* The TYPE_CANONICAL merging machinery. It should closely resemble
- the middle-end types_compatible_p function. It needs to avoid
- claiming types are different for types that should be treated
- the same with respect to TBAA. Canonical types are also used
- for IL consistency checks via the useless_type_conversion_p
- predicate which does not handle all type kinds itself but falls
- back to pointer-comparison of TYPE_CANONICAL for aggregates
- for example. */
-
-/* Return true iff T1 and T2 are structurally identical for what
- TBAA is concerned. */
-
-static bool
-gimple_canonical_types_compatible_p (tree t1, tree t2)
-{
- /* Before starting to set up the SCC machinery handle simple cases. */
-
- /* Check first for the obvious case of pointer identity. */
- if (t1 == t2)
- return true;
-
- /* Check that we have two types to compare. */
- if (t1 == NULL_TREE || t2 == NULL_TREE)
- return false;
-
- /* If the types have been previously registered and found equal
- they still are. */
- if (TYPE_CANONICAL (t1)
- && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2))
- return true;
-
- /* Can't be the same type if the types don't have the same code. */
- if (TREE_CODE (t1) != TREE_CODE (t2))
- return false;
-
- if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2))
- return false;
-
- /* Qualifiers do not matter for canonical type comparison purposes. */
-
- /* Void types and nullptr types are always the same. */
- if (TREE_CODE (t1) == VOID_TYPE
- || TREE_CODE (t1) == NULLPTR_TYPE)
- return true;
-
- /* Can't be the same type if they have different alignment, or mode. */
- if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
- || TYPE_MODE (t1) != TYPE_MODE (t2))
- return false;
-
- /* Non-aggregate types can be handled cheaply. */
- if (INTEGRAL_TYPE_P (t1)
- || SCALAR_FLOAT_TYPE_P (t1)
- || FIXED_POINT_TYPE_P (t1)
- || TREE_CODE (t1) == VECTOR_TYPE
- || TREE_CODE (t1) == COMPLEX_TYPE
- || TREE_CODE (t1) == OFFSET_TYPE
- || POINTER_TYPE_P (t1))
- {
- /* Can't be the same type if they have different sign or precision. */
- if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
- || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
- return false;
-
- if (TREE_CODE (t1) == INTEGER_TYPE
- && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
- return false;
-
- /* For canonical type comparisons we do not want to build SCCs
- so we cannot compare pointed-to types. But we can, for now,
- require the same pointed-to type kind and match what
- useless_type_conversion_p would do. */
- if (POINTER_TYPE_P (t1))
- {
- /* If the two pointers have different ref-all attributes,
- they can't be the same type. */
- if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
- return false;
-
- if (TYPE_ADDR_SPACE (TREE_TYPE (t1))
- != TYPE_ADDR_SPACE (TREE_TYPE (t2)))
- return false;
-
- if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
- return false;
-
- if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2)))
- return false;
- }
-
- /* Tail-recurse to components. */
- if (TREE_CODE (t1) == VECTOR_TYPE
- || TREE_CODE (t1) == COMPLEX_TYPE)
- return gimple_canonical_types_compatible_p (TREE_TYPE (t1),
- TREE_TYPE (t2));
-
- return true;
- }
-
- /* Do type-specific comparisons. */
- switch (TREE_CODE (t1))
- {
- case ARRAY_TYPE:
- /* Array types are the same if the element types are the same and
- the number of elements are the same. */
- if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))
- || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
- || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
- return false;
- else
- {
- tree i1 = TYPE_DOMAIN (t1);
- tree i2 = TYPE_DOMAIN (t2);
-
- /* For an incomplete external array, the type domain can be
- NULL_TREE. Check this condition also. */
- if (i1 == NULL_TREE && i2 == NULL_TREE)
- return true;
- else if (i1 == NULL_TREE || i2 == NULL_TREE)
- return false;
- else
- {
- tree min1 = TYPE_MIN_VALUE (i1);
- tree min2 = TYPE_MIN_VALUE (i2);
- tree max1 = TYPE_MAX_VALUE (i1);
- tree max2 = TYPE_MAX_VALUE (i2);
-
- /* The minimum/maximum values have to be the same. */
- if ((min1 == min2
- || (min1 && min2
- && ((TREE_CODE (min1) == PLACEHOLDER_EXPR
- && TREE_CODE (min2) == PLACEHOLDER_EXPR)
- || operand_equal_p (min1, min2, 0))))
- && (max1 == max2
- || (max1 && max2
- && ((TREE_CODE (max1) == PLACEHOLDER_EXPR
- && TREE_CODE (max2) == PLACEHOLDER_EXPR)
- || operand_equal_p (max1, max2, 0)))))
- return true;
- else
- return false;
- }
- }
-
- case METHOD_TYPE:
- case FUNCTION_TYPE:
- /* Function types are the same if the return type and arguments types
- are the same. */
- if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
- return false;
-
- if (!comp_type_attributes (t1, t2))
- return false;
-
- if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
- return true;
- else
- {
- tree parms1, parms2;
-
- for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
- parms1 && parms2;
- parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
- {
- if (!gimple_canonical_types_compatible_p
- (TREE_VALUE (parms1), TREE_VALUE (parms2)))
- return false;
- }
-
- if (parms1 || parms2)
- return false;
-
- return true;
- }
-
- case RECORD_TYPE:
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- {
- tree f1, f2;
-
- /* For aggregate types, all the fields must be the same. */
- for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
- f1 || f2;
- f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
- {
- /* Skip non-fields. */
- while (f1 && TREE_CODE (f1) != FIELD_DECL)
- f1 = TREE_CHAIN (f1);
- while (f2 && TREE_CODE (f2) != FIELD_DECL)
- f2 = TREE_CHAIN (f2);
- if (!f1 || !f2)
- break;
- /* The fields must have the same name, offset and type. */
- if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
- || !gimple_compare_field_offset (f1, f2)
- || !gimple_canonical_types_compatible_p
- (TREE_TYPE (f1), TREE_TYPE (f2)))
- return false;
- }
-
- /* If one aggregate has more fields than the other, they
- are not the same. */
- if (f1 || f2)
- return false;
-
- return true;
- }
-
- default:
- gcc_unreachable ();
- }
-}
-
-
-/* Returns nonzero if P1 and P2 are equal. */
-
-static int
-gimple_canonical_type_eq (const void *p1, const void *p2)
-{
- const_tree t1 = (const_tree) p1;
- const_tree t2 = (const_tree) p2;
- return gimple_canonical_types_compatible_p (CONST_CAST_TREE (t1),
- CONST_CAST_TREE (t2));
-}
-
-/* Register type T in the global type table gimple_types.
- If another type T', compatible with T, already existed in
- gimple_types then return T', otherwise return T. This is used by
- LTO to merge identical types read from different TUs.
-
- ??? This merging does not exactly match how the tree.c middle-end
- functions will assign TYPE_CANONICAL when new types are created
- during optimization (which at least happens for pointer and array
- types). */
-
-tree
-gimple_register_canonical_type (tree t)
-{
- void **slot;
-
- gcc_assert (TYPE_P (t));
-
- if (TYPE_CANONICAL (t))
- return TYPE_CANONICAL (t);
-
- if (gimple_canonical_types == NULL)
- gimple_canonical_types = htab_create_ggc (16381, gimple_canonical_type_hash,
- gimple_canonical_type_eq, 0);
-
- slot = htab_find_slot (gimple_canonical_types, t, INSERT);
- if (*slot
- && *(tree *)slot != t)
- {
- tree new_type = (tree) *((tree *) slot);
-
- TYPE_CANONICAL (t) = new_type;
- t = new_type;
- }
- else
- {
- TYPE_CANONICAL (t) = t;
- *slot = (void *) t;
- }
-
- return t;
-}
-
-
-/* Show statistics on references to the global type table gimple_types. */
-
-void
-print_gimple_types_stats (const char *pfx)
-{
- if (gimple_canonical_types)
- fprintf (stderr, "[%s] GIMPLE canonical type table: size %ld, "
- "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx,
- (long) htab_size (gimple_canonical_types),
- (long) htab_elements (gimple_canonical_types),
- (long) gimple_canonical_types->searches,
- (long) gimple_canonical_types->collisions,
- htab_collisions (gimple_canonical_types));
- else
- fprintf (stderr, "[%s] GIMPLE canonical type table is empty\n", pfx);
- if (canonical_type_hash_cache)
- fprintf (stderr, "[%s] GIMPLE canonical type hash table: size %ld, "
- "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx,
- (long) htab_size (canonical_type_hash_cache),
- (long) htab_elements (canonical_type_hash_cache),
- (long) canonical_type_hash_cache->searches,
- (long) canonical_type_hash_cache->collisions,
- htab_collisions (canonical_type_hash_cache));
- else
- fprintf (stderr, "[%s] GIMPLE canonical type hash table is empty\n", pfx);
-}
-
-/* Free the gimple type hashtables used for LTO type merging. */
-
-void
-free_gimple_type_tables (void)
-{
- if (gimple_canonical_types)
- {
- htab_delete (gimple_canonical_types);
- gimple_canonical_types = NULL;
- }
- if (canonical_type_hash_cache)
- {
- htab_delete (canonical_type_hash_cache);
- canonical_type_hash_cache = NULL;
- }
-}
-
/* Return a type the same as TYPE except unsigned or
signed according to UNSIGNEDP. */
@@ -3739,96 +3348,6 @@ gimple_get_alias_set (tree t)
}
-/* Data structure used to count the number of dereferences to PTR
- inside an expression. */
-struct count_ptr_d
-{
- tree ptr;
- unsigned num_stores;
- unsigned num_loads;
-};
-
-/* Helper for count_uses_and_derefs. Called by walk_tree to look for
- (ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA. */
-
-static tree
-count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
-{
- struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data;
- struct count_ptr_d *count_p = (struct count_ptr_d *) wi_p->info;
-
- /* Do not walk inside ADDR_EXPR nodes. In the expression &ptr->fld,
- pointer 'ptr' is *not* dereferenced, it is simply used to compute
- the address of 'fld' as 'ptr + offsetof(fld)'. */
- if (TREE_CODE (*tp) == ADDR_EXPR)
- {
- *walk_subtrees = 0;
- return NULL_TREE;
- }
-
- if (TREE_CODE (*tp) == MEM_REF && TREE_OPERAND (*tp, 0) == count_p->ptr)
- {
- if (wi_p->is_lhs)
- count_p->num_stores++;
- else
- count_p->num_loads++;
- }
-
- return NULL_TREE;
-}
-
-/* Count the number of direct and indirect uses for pointer PTR in
- statement STMT. The number of direct uses is stored in
- *NUM_USES_P. Indirect references are counted separately depending
- on whether they are store or load operations. The counts are
- stored in *NUM_STORES_P and *NUM_LOADS_P. */
-
-void
-count_uses_and_derefs (tree ptr, gimple stmt, unsigned *num_uses_p,
- unsigned *num_loads_p, unsigned *num_stores_p)
-{
- ssa_op_iter i;
- tree use;
-
- *num_uses_p = 0;
- *num_loads_p = 0;
- *num_stores_p = 0;
-
- /* Find out the total number of uses of PTR in STMT. */
- FOR_EACH_SSA_TREE_OPERAND (use, stmt, i, SSA_OP_USE)
- if (use == ptr)
- (*num_uses_p)++;
-
- /* Now count the number of indirect references to PTR. This is
- truly awful, but we don't have much choice. There are no parent
- pointers inside INDIRECT_REFs, so an expression like
- '*x_1 = foo (x_1, *x_1)' needs to be traversed piece by piece to
- find all the indirect and direct uses of x_1 inside. The only
- shortcut we can take is the fact that GIMPLE only allows
- INDIRECT_REFs inside the expressions below. */
- if (is_gimple_assign (stmt)
- || gimple_code (stmt) == GIMPLE_RETURN
- || gimple_code (stmt) == GIMPLE_ASM
- || is_gimple_call (stmt))
- {
- struct walk_stmt_info wi;
- struct count_ptr_d count;
-
- count.ptr = ptr;
- count.num_stores = 0;
- count.num_loads = 0;
-
- memset (&wi, 0, sizeof (wi));
- wi.info = &count;
- walk_gimple_op (stmt, count_ptr_derefs, &wi);
-
- *num_stores_p = count.num_stores;
- *num_loads_p = count.num_loads;
- }
-
- gcc_assert (*num_uses_p >= *num_loads_p + *num_stores_p);
-}
-
/* From a tree operand OP return the base of a load or store operation
or NULL_TREE if OP is not a load or a store. */
@@ -4046,7 +3565,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
{
for (i = 0; i < gimple_phi_num_args (stmt); ++i)
{
- tree op = PHI_ARG_DEF (stmt, i);
+ tree op = gimple_phi_arg_def (stmt, i);
if (TREE_CODE (op) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
}
@@ -4225,106 +3744,6 @@ gimple_asm_clobbers_memory_p (const_gimple stmt)
}
-/* Create and return an unnamed temporary. MODE indicates whether
- this should be an SSA or NORMAL temporary. TYPE is the type to use
- for the new temporary. */
-
-tree
-create_gimple_tmp (tree type, enum ssa_mode mode)
-{
- return (mode == M_SSA)
- ? make_ssa_name (type, NULL)
- : create_tmp_var (type, NULL);
-}
-
-
-/* Return the expression type to use based on the CODE and type of
- the given operand OP. If the expression CODE is a comparison,
- the returned type is boolean_type_node. Otherwise, it returns
- the type of OP. */
-
-static tree
-get_expr_type (enum tree_code code, tree op)
-{
- return (TREE_CODE_CLASS (code) == tcc_comparison)
- ? boolean_type_node
- : TREE_TYPE (op);
-}
-
-
-/* Build a new gimple assignment. The LHS of the assignment is a new
- temporary whose type matches the given expression. MODE indicates
- whether the LHS should be an SSA or a normal temporary. CODE is
- the expression code for the RHS. OP1 is the first operand and VAL
- is an integer value to be used as the second operand. */
-
-gimple
-build_assign (enum tree_code code, tree op1, int val, enum ssa_mode mode)
-{
- tree op2 = build_int_cst (TREE_TYPE (op1), val);
- tree lhs = create_gimple_tmp (get_expr_type (code, op1), mode);
- return gimple_build_assign_with_ops (code, lhs, op1, op2);
-}
-
-gimple
-build_assign (enum tree_code code, gimple g, int val, enum ssa_mode mode)
-{
- return build_assign (code, gimple_assign_lhs (g), val, mode);
-}
-
-
-/* Build and return a new GIMPLE assignment. The new assignment will
- have the opcode CODE and operands OP1 and OP2. The type of the
- expression on the RHS is inferred to be the type of OP1.
-
- The LHS of the statement will be an SSA name or a GIMPLE temporary
- in normal form depending on the type of builder invoking this
- function. */
-
-gimple
-build_assign (enum tree_code code, tree op1, tree op2, enum ssa_mode mode)
-{
- tree lhs = create_gimple_tmp (get_expr_type (code, op1), mode);
- return gimple_build_assign_with_ops (code, lhs, op1, op2);
-}
-
-gimple
-build_assign (enum tree_code code, gimple op1, tree op2, enum ssa_mode mode)
-{
- return build_assign (code, gimple_assign_lhs (op1), op2, mode);
-}
-
-gimple
-build_assign (enum tree_code code, tree op1, gimple op2, enum ssa_mode mode)
-{
- return build_assign (code, op1, gimple_assign_lhs (op2), mode);
-}
-
-gimple
-build_assign (enum tree_code code, gimple op1, gimple op2, enum ssa_mode mode)
-{
- return build_assign (code, gimple_assign_lhs (op1), gimple_assign_lhs (op2),
- mode);
-}
-
-
-/* Create and return a type cast assignment. This creates a NOP_EXPR
- that converts OP to TO_TYPE. */
-
-gimple
-build_type_cast (tree to_type, tree op, enum ssa_mode mode)
-{
- tree lhs = create_gimple_tmp (to_type, mode);
- return gimple_build_assign_with_ops (NOP_EXPR, lhs, op, NULL_TREE);
-}
-
-gimple
-build_type_cast (tree to_type, gimple op, enum ssa_mode mode)
-{
- return build_type_cast (to_type, gimple_assign_lhs (op), mode);
-}
-
-
/* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
useless type conversion, otherwise return false.
@@ -4579,5 +3998,108 @@ types_compatible_p (tree type1, tree type2)
&& useless_type_conversion_p (type2, type1)));
}
+/* Dump bitmap SET (assumed to contain VAR_DECLs) to FILE. */
-#include "gt-gimple.h"
+void
+dump_decl_set (FILE *file, bitmap set)
+{
+ if (set)
+ {
+ bitmap_iterator bi;
+ unsigned i;
+
+ fprintf (file, "{ ");
+
+ EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
+ {
+ fprintf (file, "D.%u", i);
+ fprintf (file, " ");
+ }
+
+ fprintf (file, "}");
+ }
+ else
+ fprintf (file, "NIL");
+}
+
+/* Given SSA_NAMEs NAME1 and NAME2, return true if they are candidates for
+ coalescing together, false otherwise.
+
+ This must stay consistent with var_map_base_init in tree-ssa-live.c. */
+
+bool
+gimple_can_coalesce_p (tree name1, tree name2)
+{
+ /* First check the SSA_NAME's associated DECL. We only want to
+ coalesce if they have the same DECL or both have no associated DECL. */
+ tree var1 = SSA_NAME_VAR (name1);
+ tree var2 = SSA_NAME_VAR (name2);
+ var1 = (var1 && (!VAR_P (var1) || !DECL_IGNORED_P (var1))) ? var1 : NULL_TREE;
+ var2 = (var2 && (!VAR_P (var2) || !DECL_IGNORED_P (var2))) ? var2 : NULL_TREE;
+ if (var1 != var2)
+ return false;
+
+ /* Now check the types. If the types are the same, then we should
+ try to coalesce V1 and V2. */
+ tree t1 = TREE_TYPE (name1);
+ tree t2 = TREE_TYPE (name2);
+ if (t1 == t2)
+ return true;
+
+ /* If the types are not the same, check for a canonical type match. This
+ (for example) allows coalescing when the types are fundamentally the
+ same, but just have different names.
+
+ Note pointer types with different address spaces may have the same
+ canonical type. Those are rejected for coalescing by the
+ types_compatible_p check. */
+ if (TYPE_CANONICAL (t1)
+ && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2)
+ && types_compatible_p (t1, t2))
+ return true;
+
+ return false;
+}
+
+/* Return true when CALL is a call stmt that definitely doesn't
+ free any memory or makes it unavailable otherwise. */
+bool
+nonfreeing_call_p (gimple call)
+{
+ if (gimple_call_builtin_p (call, BUILT_IN_NORMAL)
+ && gimple_call_flags (call) & ECF_LEAF)
+ switch (DECL_FUNCTION_CODE (gimple_call_fndecl (call)))
+ {
+ /* Just in case these become ECF_LEAF in the future. */
+ case BUILT_IN_FREE:
+ case BUILT_IN_TM_FREE:
+ case BUILT_IN_REALLOC:
+ case BUILT_IN_STACK_RESTORE:
+ return false;
+ default:
+ return true;
+ }
+
+ return false;
+}
+
+/* Create a new VAR_DECL and copy information from VAR to it. */
+
+tree
+copy_var_decl (tree var, tree name, tree type)
+{
+ tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
+
+ TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
+ TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
+ DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
+ DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
+ DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
+ DECL_CONTEXT (copy) = DECL_CONTEXT (var);
+ TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
+ TREE_USED (copy) = 1;
+ DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
+ DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
+
+ return copy;
+}