-/* Given a DECL, return its AGGREGATE_VARDECL_D entry. If no entry is
- found and INSERT is TRUE, add a new entry. */
-
-static struct aggregate_vardecl_d *
-get_aggregate_vardecl (tree decl, struct dse_global_data *dse_gd, bool insert)
-{
- struct aggregate_vardecl_d av, *av_p;
- void **slot;
-
- av.decl = decl;
- slot = htab_find_slot (dse_gd->aggregate_vardecl, &av, insert ? INSERT : NO_INSERT);
-
-
- /* Not found, and we don't want to insert. */
- if (slot == NULL)
- return NULL;
-
- /* Create new entry. */
- if (*slot == NULL)
- {
- av_p = XNEW (struct aggregate_vardecl_d);
- av_p->decl = decl;
-
- /* Record how many parts the whole has. */
- if (TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE)
- av_p->nparts = 2;
- else if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
- {
- tree fields;
-
- /* Count the number of fields. */
- fields = TYPE_FIELDS (TREE_TYPE (decl));
- av_p->nparts = 0;
- while (fields)
- {
- av_p->nparts++;
- fields = TREE_CHAIN (fields);
- }
- }
- else
- abort ();
-
- av_p->ignore = true;
- av_p->parts_set = sbitmap_alloc (HOST_BITS_PER_LONG);
- sbitmap_zero (av_p->parts_set);
- *slot = av_p;
- }
- else
- av_p = (struct aggregate_vardecl_d *) *slot;
-
- return av_p;
-}
-
-
-/* If STMT is a partial store into an aggregate, record which part got set. */
-
-static void
-dse_record_partial_aggregate_store (tree stmt, struct dse_global_data *dse_gd)
-{
- tree lhs, decl;
- enum tree_code code;
- struct aggregate_vardecl_d *av_p;
- int part;
-
- gcc_assert (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT);
-
- lhs = GIMPLE_STMT_OPERAND (stmt, 0);
- code = TREE_CODE (lhs);
- if (code != IMAGPART_EXPR
- && code != REALPART_EXPR
- && code != COMPONENT_REF)
- return;
- decl = TREE_OPERAND (lhs, 0);
- /* Early bail on things like nested COMPONENT_REFs. */
- if (TREE_CODE (decl) != VAR_DECL)
- return;
- /* Early bail on unions. */
- if (code == COMPONENT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) != RECORD_TYPE)
- return;
-
- av_p = get_aggregate_vardecl (decl, dse_gd, /*insert=*/false);
- /* Run away, this isn't an aggregate we care about. */
- if (!av_p || av_p->ignore)
- return;
-
- switch (code)
- {
- case IMAGPART_EXPR:
- part = 0;
- break;
- case REALPART_EXPR:
- part = 1;
- break;
- case COMPONENT_REF:
- {
- tree orig_field, fields;
- tree record_type = TREE_TYPE (TREE_OPERAND (lhs, 0));
-
- /* Get FIELD_DECL. */
- orig_field = TREE_OPERAND (lhs, 1);
-
- /* FIXME: Eeech, do this more efficiently. Perhaps
- calculate bit/byte offsets. */
- part = -1;
- fields = TYPE_FIELDS (record_type);
- while (fields)
- {
- ++part;
- if (fields == orig_field)
- break;
- fields = TREE_CHAIN (fields);
- }
- gcc_assert (part >= 0);
- }
- break;
- default:
- return;
- }
-
- /* Record which part was set. */
- SET_BIT (av_p->parts_set, part);
-}
-
-
-/* Return TRUE if all parts in an AGGREGATE_VARDECL have been set. */
-
-static inline bool
-dse_whole_aggregate_clobbered_p (struct aggregate_vardecl_d *av_p)
-{
- unsigned int i;
- sbitmap_iterator sbi;
- int nbits_set = 0;
-
- /* Count the number of partial stores (bits set). */
- EXECUTE_IF_SET_IN_SBITMAP (av_p->parts_set, 0, i, sbi)
- nbits_set++;
- return ((unsigned) nbits_set == av_p->nparts);
-}
-
-
-/* Return TRUE if STMT is a store into a whole aggregate whose parts we
- have already seen and recorded. */
-
-static bool
-dse_partial_kill_p (tree stmt, struct dse_global_data *dse_gd)
-{
- tree decl;
- struct aggregate_vardecl_d *av_p;
-
- /* Make sure this is a store into the whole. */
- if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
- {
- enum tree_code code;
-
- decl = GIMPLE_STMT_OPERAND (stmt, 0);
- code = TREE_CODE (TREE_TYPE (decl));
-
- if (code != COMPLEX_TYPE && code != RECORD_TYPE)
- return false;
-
- if (TREE_CODE (decl) != VAR_DECL)
- return false;
- }
- else
- return false;
-
- av_p = get_aggregate_vardecl (decl, dse_gd, /*insert=*/false);
- gcc_assert (av_p != NULL);
-
- return dse_whole_aggregate_clobbered_p (av_p);
-}
-
-