2004-05-13 08:41:07 +02:00
|
|
|
/* Scalar Replacement of Aggregates (SRA) converts some structure
|
|
|
|
references into scalar references, exposing them to the scalar
|
|
|
|
optimizers.
|
2009-05-29 18:47:31 +02:00
|
|
|
Copyright (C) 2008, 2009 Free Software Foundation, Inc.
|
|
|
|
Contributed by Martin Jambor <mjambor@suse.cz>
|
2004-05-13 08:41:07 +02:00
|
|
|
|
|
|
|
This file is part of GCC.
|
2004-08-19 23:34:37 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
|
|
the terms of the GNU General Public License as published by the Free
|
|
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
|
|
version.
|
2004-08-19 23:34:37 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
2004-05-13 08:41:07 +02:00
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
for more details.
|
2004-08-19 23:34:37 +02:00
|
|
|
|
2004-05-13 08:41:07 +02:00
|
|
|
You should have received a copy of the GNU General Public License
|
2007-07-26 10:37:01 +02:00
|
|
|
along with GCC; see the file COPYING3. If not see
|
|
|
|
<http://www.gnu.org/licenses/>. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* This file implements Scalar Reduction of Aggregates (SRA). SRA is run
|
|
|
|
twice, once in the early stages of compilation (early SRA) and once in the
|
|
|
|
late stages (late SRA). The aim of both is to turn references to scalar
|
|
|
|
parts of aggregates into uses of independent scalar variables.
|
|
|
|
|
|
|
|
The two passes are nearly identical, the only difference is that early SRA
|
|
|
|
does not scalarize unions which are used as the result in a GIMPLE_RETURN
|
|
|
|
statement because together with inlining this can lead to weird type
|
|
|
|
conversions.
|
|
|
|
|
|
|
|
Both passes operate in four stages:
|
|
|
|
|
|
|
|
1. The declarations that have properties which make them candidates for
|
|
|
|
scalarization are identified in function find_var_candidates(). The
|
|
|
|
candidates are stored in candidate_bitmap.
|
|
|
|
|
|
|
|
2. The function body is scanned. In the process, declarations which are
|
|
|
|
used in a manner that prevent their scalarization are removed from the
|
|
|
|
candidate bitmap. More importantly, for every access into an aggregate,
|
|
|
|
an access structure (struct access) is created by create_access() and
|
|
|
|
stored in a vector associated with the aggregate. Among other
|
|
|
|
information, the aggregate declaration, the offset and size of the access
|
|
|
|
and its type are stored in the structure.
|
|
|
|
|
|
|
|
On a related note, assign_link structures are created for every assign
|
|
|
|
statement between candidate aggregates and attached to the related
|
|
|
|
accesses.
|
|
|
|
|
|
|
|
3. The vectors of accesses are analyzed. They are first sorted according to
|
|
|
|
their offset and size and then scanned for partially overlapping accesses
|
|
|
|
(i.e. those which overlap but one is not entirely within another). Such
|
|
|
|
an access disqualifies the whole aggregate from being scalarized.
|
|
|
|
|
|
|
|
If there is no such inhibiting overlap, a representative access structure
|
|
|
|
is chosen for every unique combination of offset and size. Afterwards,
|
|
|
|
the pass builds a set of trees from these structures, in which children
|
|
|
|
of an access are within their parent (in terms of offset and size).
|
|
|
|
|
|
|
|
Then accesses are propagated whenever possible (i.e. in cases when it
|
|
|
|
does not create a partially overlapping access) across assign_links from
|
|
|
|
the right hand side to the left hand side.
|
|
|
|
|
|
|
|
Then the set of trees for each declaration is traversed again and those
|
|
|
|
accesses which should be replaced by a scalar are identified.
|
|
|
|
|
|
|
|
4. The function is traversed again, and for every reference into an
|
|
|
|
aggregate that has some component which is about to be scalarized,
|
|
|
|
statements are amended and new statements are created as necessary.
|
|
|
|
Finally, if a parameter got scalarized, the scalar replacements are
|
|
|
|
initialized with values from respective parameter aggregates. */
|
|
|
|
|
2004-05-13 08:41:07 +02:00
|
|
|
#include "config.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "coretypes.h"
|
2009-05-29 18:47:31 +02:00
|
|
|
#include "alloc-pool.h"
|
2004-05-13 08:41:07 +02:00
|
|
|
#include "tm.h"
|
|
|
|
#include "tree.h"
|
2008-07-28 16:33:56 +02:00
|
|
|
#include "gimple.h"
|
2009-09-17 13:35:38 +02:00
|
|
|
#include "cgraph.h"
|
2009-05-29 18:47:31 +02:00
|
|
|
#include "tree-flow.h"
|
2009-08-07 02:51:34 +02:00
|
|
|
#include "ipa-prop.h"
|
2009-05-29 18:47:31 +02:00
|
|
|
#include "diagnostic.h"
|
2009-06-18 17:38:36 +02:00
|
|
|
#include "statistics.h"
|
2004-05-13 08:41:07 +02:00
|
|
|
#include "tree-dump.h"
|
|
|
|
#include "timevar.h"
|
2004-10-27 23:02:16 +02:00
|
|
|
#include "params.h"
|
2009-05-29 18:47:31 +02:00
|
|
|
#include "target.h"
|
|
|
|
#include "flags.h"
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Enumeration of all aggregate reductions we can do. */
|
2009-09-17 13:35:38 +02:00
|
|
|
enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
|
|
|
|
SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
|
|
|
|
SRA_MODE_INTRA }; /* late intraprocedural SRA */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Global variable describing which aggregate reduction we are performing at
|
|
|
|
the moment. */
|
|
|
|
static enum sra_mode sra_mode;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
struct assign_link;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* ACCESS represents each access to an aggregate variable (as a whole or a
|
|
|
|
part). It can also represent a group of accesses that refer to exactly the
|
|
|
|
same fragment of an aggregate (i.e. those that have exactly the same offset
|
|
|
|
and size). Such representatives for a single aggregate, once determined,
|
|
|
|
are linked in a linked list and have the group fields set.
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
Moreover, when doing intraprocedural SRA, a tree is built from those
|
|
|
|
representatives (by the means of first_child and next_sibling pointers), in
|
|
|
|
which all items in a subtree are "within" the root, i.e. their offset is
|
|
|
|
greater or equal to offset of the root and offset+size is smaller or equal
|
|
|
|
to offset+size of the root. Children of an access are sorted by offset.
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
Note that accesses to parts of vector and complex number types always
|
|
|
|
represented by an access to the whole complex number or a vector. It is a
|
|
|
|
duty of the modifying functions to replace them appropriately. */
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access
|
|
|
|
{
|
|
|
|
/* Values returned by `get_ref_base_and_extent' for each component reference
|
|
|
|
If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
|
|
|
|
`SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
|
|
|
|
HOST_WIDE_INT offset;
|
|
|
|
HOST_WIDE_INT size;
|
|
|
|
tree base;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-11-24 11:56:14 +01:00
|
|
|
/* Expression. It is context dependent so do not use it to create new
|
|
|
|
expressions to access the original aggregate. See PR 42154 for a
|
|
|
|
testcase. */
|
2009-05-29 18:47:31 +02:00
|
|
|
tree expr;
|
|
|
|
/* Type. */
|
|
|
|
tree type;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
/* The statement this access belongs to. */
|
|
|
|
gimple stmt;
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Next group representative for this aggregate. */
|
|
|
|
struct access *next_grp;
|
|
|
|
|
|
|
|
/* Pointer to the group representative. Pointer to itself if the struct is
|
|
|
|
the representative. */
|
|
|
|
struct access *group_representative;
|
|
|
|
|
|
|
|
/* If this access has any children (in terms of the definition above), this
|
|
|
|
points to the first one. */
|
|
|
|
struct access *first_child;
|
|
|
|
|
2009-11-05 13:09:08 +01:00
|
|
|
/* In intraprocedural SRA, pointer to the next sibling in the access tree as
|
|
|
|
described above. In IPA-SRA this is a pointer to the next access
|
|
|
|
belonging to the same group (having the same representative). */
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *next_sibling;
|
|
|
|
|
|
|
|
/* Pointers to the first and last element in the linked list of assign
|
|
|
|
links. */
|
|
|
|
struct assign_link *first_link, *last_link;
|
|
|
|
|
|
|
|
/* Pointer to the next access in the work queue. */
|
|
|
|
struct access *next_queued;
|
|
|
|
|
|
|
|
/* Replacement variable for this access "region." Never to be accessed
|
|
|
|
directly, always only by the means of get_access_replacement() and only
|
|
|
|
when grp_to_be_replaced flag is set. */
|
|
|
|
tree replacement_decl;
|
|
|
|
|
|
|
|
/* Is this particular access write access? */
|
|
|
|
unsigned write : 1;
|
|
|
|
|
|
|
|
/* Is this access currently in the work queue? */
|
|
|
|
unsigned grp_queued : 1;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Does this group contain a write access? This flag is propagated down the
|
|
|
|
access tree. */
|
|
|
|
unsigned grp_write : 1;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Does this group contain a read access? This flag is propagated down the
|
|
|
|
access tree. */
|
|
|
|
unsigned grp_read : 1;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
2009-09-02 19:52:18 +02:00
|
|
|
/* Other passes of the analysis use this bit to make function
|
|
|
|
analyze_access_subtree create scalar replacements for this group if
|
|
|
|
possible. */
|
|
|
|
unsigned grp_hint : 1;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Is the subtree rooted in this access fully covered by scalar
|
|
|
|
replacements? */
|
|
|
|
unsigned grp_covered : 1;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* If set to true, this access and all below it in an access tree must not be
|
|
|
|
scalarized. */
|
|
|
|
unsigned grp_unscalarizable_region : 1;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Whether data have been written to parts of the aggregate covered by this
|
|
|
|
access which is not to be scalarized. This flag is propagated up in the
|
|
|
|
access tree. */
|
|
|
|
unsigned grp_unscalarized_data : 1;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Does this access and/or group contain a write access through a
|
|
|
|
BIT_FIELD_REF? */
|
|
|
|
unsigned grp_partial_lhs : 1;
|
|
|
|
|
2009-11-30 18:59:57 +01:00
|
|
|
/* Does this group contain accesses to different types? (I.e. through a union
|
|
|
|
or a similar mechanism). */
|
|
|
|
unsigned grp_different_types : 1;
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Set when a scalar replacement should be created for this variable. We do
|
|
|
|
the decision and creation at different places because create_tmp_var
|
|
|
|
cannot be called from within FOR_EACH_REFERENCED_VAR. */
|
|
|
|
unsigned grp_to_be_replaced : 1;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
|
|
|
/* Is it possible that the group refers to data which might be (directly or
|
|
|
|
otherwise) modified? */
|
|
|
|
unsigned grp_maybe_modified : 1;
|
|
|
|
|
|
|
|
/* Set when this is a representative of a pointer to scalar (i.e. by
|
|
|
|
reference) parameter which we consider for turning into a plain scalar
|
|
|
|
(i.e. a by value parameter). */
|
|
|
|
unsigned grp_scalar_ptr : 1;
|
|
|
|
|
|
|
|
/* Set when we discover that this pointer is not safe to dereference in the
|
|
|
|
caller. */
|
|
|
|
unsigned grp_not_necessarilly_dereferenced : 1;
|
2009-05-29 18:47:31 +02:00
|
|
|
};
|
2007-02-14 18:52:25 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
typedef struct access *access_p;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
DEF_VEC_P (access_p);
|
|
|
|
DEF_VEC_ALLOC_P (access_p, heap);
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Alloc pool for allocating access structures. */
|
|
|
|
static alloc_pool access_pool;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* A structure linking lhs and rhs accesses from an aggregate assignment. They
|
|
|
|
are used to propagate subaccesses from rhs to lhs as long as they don't
|
|
|
|
conflict with what is already there. */
|
|
|
|
struct assign_link
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *lacc, *racc;
|
|
|
|
struct assign_link *next;
|
|
|
|
};
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Alloc pool for allocating assign link structures. */
|
|
|
|
static alloc_pool link_pool;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Base (tree) -> Vector (VEC(access_p,heap) *) map. */
|
|
|
|
static struct pointer_map_t *base_access_vec;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
/* Bitmap of candidates. */
|
2009-05-29 18:47:31 +02:00
|
|
|
static bitmap candidate_bitmap;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Obstack for creation of fancy names. */
|
|
|
|
static struct obstack name_obstack;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Head of a linked list of accesses that need to have its subaccesses
|
|
|
|
propagated to their assignment counterparts. */
|
|
|
|
static struct access *work_queue_head;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
/* Number of parameters of the analyzed function when doing early ipa SRA. */
|
|
|
|
static int func_param_count;
|
|
|
|
|
|
|
|
/* scan_function sets the following to true if it encounters a call to
|
|
|
|
__builtin_apply_args. */
|
|
|
|
static bool encountered_apply_args;
|
|
|
|
|
|
|
|
/* This is a table in which for each basic block and parameter there is a
|
|
|
|
distance (offset + size) in that parameter which is dereferenced and
|
|
|
|
accessed in that BB. */
|
|
|
|
static HOST_WIDE_INT *bb_dereferences;
|
|
|
|
/* Bitmap of BBs that can cause the function to "stop" progressing by
|
|
|
|
returning, throwing externally, looping infinitely or calling a function
|
|
|
|
which might abort etc.. */
|
|
|
|
static bitmap final_bbs;
|
|
|
|
|
|
|
|
/* Representative of no accesses at all. */
|
|
|
|
static struct access no_accesses_representant;
|
|
|
|
|
|
|
|
/* Predicate to test the special value. */
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
no_accesses_p (struct access *access)
|
|
|
|
{
|
|
|
|
return access == &no_accesses_representant;
|
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
|
|
|
|
representative fields are dumped, otherwise those which only describe the
|
|
|
|
individual access are. */
|
2006-07-03 22:14:18 +02:00
|
|
|
|
2009-06-18 17:38:36 +02:00
|
|
|
static struct
|
|
|
|
{
|
2009-09-17 13:35:38 +02:00
|
|
|
/* Number of processed aggregates is readily available in
|
|
|
|
analyze_all_variable_accesses and so is not stored here. */
|
|
|
|
|
2009-06-18 17:38:36 +02:00
|
|
|
/* Number of created scalar replacements. */
|
|
|
|
int replacements;
|
|
|
|
|
|
|
|
/* Number of times sra_modify_expr or sra_modify_assign themselves changed an
|
|
|
|
expression. */
|
|
|
|
int exprs;
|
|
|
|
|
|
|
|
/* Number of statements created by generate_subtree_copies. */
|
|
|
|
int subtree_copies;
|
|
|
|
|
|
|
|
/* Number of statements created by load_assign_lhs_subreplacements. */
|
|
|
|
int subreplacements;
|
|
|
|
|
|
|
|
/* Number of times sra_modify_assign has deleted a statement. */
|
|
|
|
int deleted;
|
|
|
|
|
|
|
|
/* Number of times sra_modify_assign has to deal with subaccesses of LHS and
|
|
|
|
RHS reparately due to type conversions or nonexistent matching
|
|
|
|
references. */
|
|
|
|
int separate_lhs_rhs_handling;
|
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
/* Number of parameters that were removed because they were unused. */
|
|
|
|
int deleted_unused_parameters;
|
|
|
|
|
|
|
|
/* Number of scalars passed as parameters by reference that have been
|
|
|
|
converted to be passed by value. */
|
|
|
|
int scalar_by_ref_to_by_val;
|
|
|
|
|
|
|
|
/* Number of aggregate parameters that were replaced by one or more of their
|
|
|
|
components. */
|
|
|
|
int aggregate_params_reduced;
|
|
|
|
|
|
|
|
/* Numbber of components created when splitting aggregate parameters. */
|
|
|
|
int param_reductions_created;
|
2009-06-18 17:38:36 +02:00
|
|
|
} sra_stats;
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static void
|
|
|
|
dump_access (FILE *f, struct access *access, bool grp)
|
|
|
|
{
|
|
|
|
fprintf (f, "access { ");
|
|
|
|
fprintf (f, "base = (%d)'", DECL_UID (access->base));
|
|
|
|
print_generic_expr (f, access->base, 0);
|
|
|
|
fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
|
|
|
|
fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
|
|
|
|
fprintf (f, ", expr = ");
|
|
|
|
print_generic_expr (f, access->expr, 0);
|
|
|
|
fprintf (f, ", type = ");
|
|
|
|
print_generic_expr (f, access->type, 0);
|
|
|
|
if (grp)
|
2009-09-02 19:52:18 +02:00
|
|
|
fprintf (f, ", grp_write = %d, grp_read = %d, grp_hint = %d, "
|
|
|
|
"grp_covered = %d, grp_unscalarizable_region = %d, "
|
|
|
|
"grp_unscalarized_data = %d, grp_partial_lhs = %d, "
|
2009-11-30 18:59:57 +01:00
|
|
|
"grp_different_types = %d, grp_to_be_replaced = %d, "
|
|
|
|
"grp_maybe_modified = %d, "
|
2009-09-17 13:35:38 +02:00
|
|
|
"grp_not_necessarilly_dereferenced = %d\n",
|
2009-09-02 19:52:18 +02:00
|
|
|
access->grp_write, access->grp_read, access->grp_hint,
|
|
|
|
access->grp_covered, access->grp_unscalarizable_region,
|
|
|
|
access->grp_unscalarized_data, access->grp_partial_lhs,
|
2009-11-30 18:59:57 +01:00
|
|
|
access->grp_different_types, access->grp_to_be_replaced,
|
|
|
|
access->grp_maybe_modified,
|
2009-09-17 13:35:38 +02:00
|
|
|
access->grp_not_necessarilly_dereferenced);
|
2009-05-29 18:47:31 +02:00
|
|
|
else
|
|
|
|
fprintf (f, ", write = %d, grp_partial_lhs = %d\n", access->write,
|
|
|
|
access->grp_partial_lhs);
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
|
2004-06-10 23:41:08 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static void
|
|
|
|
dump_access_tree_1 (FILE *f, struct access *access, int level)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
int i;
|
2005-11-21 01:51:39 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
for (i = 0; i < level; i++)
|
|
|
|
fputs ("* ", dump_file);
|
2006-12-12 23:33:06 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
dump_access (f, access, true);
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (access->first_child)
|
|
|
|
dump_access_tree_1 (f, access->first_child, level + 1);
|
2004-06-10 23:41:08 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
access = access->next_sibling;
|
|
|
|
}
|
|
|
|
while (access);
|
|
|
|
}
|
2006-07-03 22:14:18 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Dump all access trees for a variable, given the pointer to the first root in
|
|
|
|
ACCESS. */
|
2006-07-03 22:14:18 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static void
|
|
|
|
dump_access_tree (FILE *f, struct access *access)
|
2006-07-03 22:14:18 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
for (; access; access = access->next_grp)
|
|
|
|
dump_access_tree_1 (f, access, 0);
|
|
|
|
}
|
2006-07-03 22:14:18 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Return true iff ACC is non-NULL and has subaccesses. */
|
2006-07-03 22:14:18 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static inline bool
|
|
|
|
access_has_children_p (struct access *acc)
|
|
|
|
{
|
|
|
|
return acc && acc->first_child;
|
|
|
|
}
|
2006-07-03 22:14:18 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Return a vector of pointers to accesses for the variable given in BASE or
|
|
|
|
NULL if there is none. */
|
2006-07-03 22:14:18 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static VEC (access_p, heap) *
|
|
|
|
get_base_access_vector (tree base)
|
|
|
|
{
|
|
|
|
void **slot;
|
|
|
|
|
|
|
|
slot = pointer_map_contains (base_access_vec, base);
|
|
|
|
if (!slot)
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
return *(VEC (access_p, heap) **) slot;
|
2006-07-03 22:14:18 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
|
|
|
|
in ACCESS. Return NULL if it cannot be found. */
|
2004-06-10 23:41:08 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static struct access *
|
|
|
|
find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
|
|
|
|
HOST_WIDE_INT size)
|
|
|
|
{
|
|
|
|
while (access && (access->offset != offset || access->size != size))
|
|
|
|
{
|
|
|
|
struct access *child = access->first_child;
|
2004-06-10 23:41:08 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
while (child && (child->offset + child->size <= offset))
|
|
|
|
child = child->next_sibling;
|
|
|
|
access = child;
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return access;
|
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Return the first group representative for DECL or NULL if none exists. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static struct access *
|
|
|
|
get_first_repr_for_decl (tree base)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
VEC (access_p, heap) *access_vec;
|
|
|
|
|
|
|
|
access_vec = get_base_access_vector (base);
|
|
|
|
if (!access_vec)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return VEC_index (access_p, access_vec, 0);
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Find an access representative for the variable BASE and given OFFSET and
|
|
|
|
SIZE. Requires that access trees have already been built. Return NULL if
|
|
|
|
it cannot be found. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static struct access *
|
|
|
|
get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
|
|
|
|
HOST_WIDE_INT size)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *access;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
access = get_first_repr_for_decl (base);
|
|
|
|
while (access && (access->offset + access->size <= offset))
|
|
|
|
access = access->next_grp;
|
|
|
|
if (!access)
|
|
|
|
return NULL;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return find_access_in_subtree (access, offset, size);
|
|
|
|
}
|
2004-06-28 14:12:51 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Add LINK to the linked list of assign links of RACC. */
|
|
|
|
static void
|
|
|
|
add_link_to_rhs (struct access *racc, struct assign_link *link)
|
2004-06-28 14:12:51 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
gcc_assert (link->racc == racc);
|
2004-06-28 14:12:51 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!racc->first_link)
|
|
|
|
{
|
|
|
|
gcc_assert (!racc->last_link);
|
|
|
|
racc->first_link = link;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
racc->last_link->next = link;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
racc->last_link = link;
|
|
|
|
link->next = NULL;
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Move all link structures in their linked list in OLD_RACC to the linked list
|
|
|
|
in NEW_RACC. */
|
|
|
|
static void
|
|
|
|
relink_to_new_repr (struct access *new_racc, struct access *old_racc)
|
|
|
|
{
|
|
|
|
if (!old_racc->first_link)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
gcc_assert (!old_racc->last_link);
|
|
|
|
return;
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (new_racc->first_link)
|
|
|
|
{
|
|
|
|
gcc_assert (!new_racc->last_link->next);
|
|
|
|
gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
new_racc->last_link->next = old_racc->first_link;
|
|
|
|
new_racc->last_link = old_racc->last_link;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gcc_assert (!new_racc->last_link);
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
new_racc->first_link = old_racc->first_link;
|
|
|
|
new_racc->last_link = old_racc->last_link;
|
|
|
|
}
|
|
|
|
old_racc->first_link = old_racc->last_link = NULL;
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Add ACCESS to the work queue (which is actually a stack). */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static void
|
|
|
|
add_access_to_work_queue (struct access *access)
|
|
|
|
{
|
|
|
|
if (!access->grp_queued)
|
|
|
|
{
|
|
|
|
gcc_assert (!access->next_queued);
|
|
|
|
access->next_queued = work_queue_head;
|
|
|
|
access->grp_queued = 1;
|
|
|
|
work_queue_head = access;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Pop an access from the work queue, and return it, assuming there is one. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static struct access *
|
|
|
|
pop_access_from_work_queue (void)
|
|
|
|
{
|
|
|
|
struct access *access = work_queue_head;
|
|
|
|
|
|
|
|
work_queue_head = access->next_queued;
|
|
|
|
access->next_queued = NULL;
|
|
|
|
access->grp_queued = 0;
|
|
|
|
return access;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Allocate necessary structures. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
sra_initialize (void)
|
|
|
|
{
|
|
|
|
candidate_bitmap = BITMAP_ALLOC (NULL);
|
|
|
|
gcc_obstack_init (&name_obstack);
|
|
|
|
access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
|
|
|
|
link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
|
|
|
|
base_access_vec = pointer_map_create ();
|
2009-06-18 17:38:36 +02:00
|
|
|
memset (&sra_stats, 0, sizeof (sra_stats));
|
2009-09-17 13:35:38 +02:00
|
|
|
encountered_apply_args = false;
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Hook fed to pointer_map_traverse, deallocate stored vectors. */
|
2008-07-06 16:51:58 +02:00
|
|
|
|
|
|
|
static bool
|
2009-05-29 18:47:31 +02:00
|
|
|
delete_base_accesses (const void *key ATTRIBUTE_UNUSED, void **value,
|
|
|
|
void *data ATTRIBUTE_UNUSED)
|
2008-07-06 16:51:58 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
VEC (access_p, heap) *access_vec;
|
|
|
|
access_vec = (VEC (access_p, heap) *) *value;
|
|
|
|
VEC_free (access_p, heap, access_vec);
|
2008-07-06 16:51:58 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return true;
|
2008-07-06 16:51:58 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Deallocate all general structures. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static void
|
|
|
|
sra_deinitialize (void)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
BITMAP_FREE (candidate_bitmap);
|
|
|
|
free_alloc_pool (access_pool);
|
|
|
|
free_alloc_pool (link_pool);
|
|
|
|
obstack_free (&name_obstack, NULL);
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
pointer_map_traverse (base_access_vec, delete_base_accesses, NULL);
|
|
|
|
pointer_map_destroy (base_access_vec);
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Remove DECL from candidates for SRA and write REASON to the dump file if
|
|
|
|
there is one. */
|
|
|
|
static void
|
|
|
|
disqualify_candidate (tree decl, const char *reason)
|
|
|
|
{
|
|
|
|
bitmap_clear_bit (candidate_bitmap, DECL_UID (decl));
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
fprintf (dump_file, "! Disqualifying ");
|
|
|
|
print_generic_expr (dump_file, decl, 0);
|
|
|
|
fprintf (dump_file, " - %s\n", reason);
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Return true iff the type contains a field or an element which does not allow
|
|
|
|
scalarization. */
|
2004-06-29 18:25:28 +02:00
|
|
|
|
|
|
|
static bool
|
2009-05-29 18:47:31 +02:00
|
|
|
type_internals_preclude_sra_p (tree type)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
tree fld;
|
|
|
|
tree et;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2004-06-29 18:25:28 +02:00
|
|
|
switch (TREE_CODE (type))
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2004-06-29 18:25:28 +02:00
|
|
|
case RECORD_TYPE:
|
2009-05-29 18:47:31 +02:00
|
|
|
case UNION_TYPE:
|
|
|
|
case QUAL_UNION_TYPE:
|
|
|
|
for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
|
|
|
|
if (TREE_CODE (fld) == FIELD_DECL)
|
|
|
|
{
|
|
|
|
tree ft = TREE_TYPE (fld);
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (TREE_THIS_VOLATILE (fld)
|
|
|
|
|| !DECL_FIELD_OFFSET (fld) || !DECL_SIZE (fld)
|
|
|
|
|| !host_integerp (DECL_FIELD_OFFSET (fld), 1)
|
|
|
|
|| !host_integerp (DECL_SIZE (fld), 1))
|
|
|
|
return true;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (AGGREGATE_TYPE_P (ft)
|
|
|
|
&& type_internals_preclude_sra_p (ft))
|
|
|
|
return true;
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return false;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2004-06-29 18:25:28 +02:00
|
|
|
case ARRAY_TYPE:
|
2009-05-29 18:47:31 +02:00
|
|
|
et = TREE_TYPE (type);
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (AGGREGATE_TYPE_P (et))
|
|
|
|
return type_internals_preclude_sra_p (et);
|
|
|
|
else
|
|
|
|
return false;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2004-06-29 18:25:28 +02:00
|
|
|
default:
|
2009-05-29 18:47:31 +02:00
|
|
|
return false;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
/* If T is an SSA_NAME, return NULL if it is not a default def or return its
|
|
|
|
base variable if it is. Return T if it is not an SSA_NAME. */
|
|
|
|
|
|
|
|
static tree
|
|
|
|
get_ssa_base_param (tree t)
|
|
|
|
{
|
|
|
|
if (TREE_CODE (t) == SSA_NAME)
|
|
|
|
{
|
|
|
|
if (SSA_NAME_IS_DEFAULT_DEF (t))
|
|
|
|
return SSA_NAME_VAR (t);
|
|
|
|
else
|
|
|
|
return NULL_TREE;
|
|
|
|
}
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Mark a dereference of BASE of distance DIST in a basic block tht STMT
|
|
|
|
belongs to, unless the BB has already been marked as a potentially
|
|
|
|
final. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
mark_parm_dereference (tree base, HOST_WIDE_INT dist, gimple stmt)
|
|
|
|
{
|
|
|
|
basic_block bb = gimple_bb (stmt);
|
|
|
|
int idx, parm_index = 0;
|
|
|
|
tree parm;
|
|
|
|
|
|
|
|
if (bitmap_bit_p (final_bbs, bb->index))
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (parm = DECL_ARGUMENTS (current_function_decl);
|
|
|
|
parm && parm != base;
|
|
|
|
parm = TREE_CHAIN (parm))
|
|
|
|
parm_index++;
|
|
|
|
|
|
|
|
gcc_assert (parm_index < func_param_count);
|
|
|
|
|
|
|
|
idx = bb->index * func_param_count + parm_index;
|
|
|
|
if (bb_dereferences[idx] < dist)
|
|
|
|
bb_dereferences[idx] = dist;
|
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Create and insert access for EXPR. Return created access, or NULL if it is
|
|
|
|
not possible. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static struct access *
|
2009-09-17 13:35:38 +02:00
|
|
|
create_access (tree expr, gimple stmt, bool write)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *access;
|
|
|
|
void **slot;
|
|
|
|
VEC (access_p,heap) *vec;
|
|
|
|
HOST_WIDE_INT offset, size, max_size;
|
|
|
|
tree base = expr;
|
2009-09-17 13:35:38 +02:00
|
|
|
bool ptr, unscalarizable_region = false;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
if (sra_mode == SRA_MODE_EARLY_IPA && INDIRECT_REF_P (base))
|
|
|
|
{
|
|
|
|
base = get_ssa_base_param (TREE_OPERAND (base, 0));
|
|
|
|
if (!base)
|
|
|
|
return NULL;
|
|
|
|
ptr = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ptr = false;
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
|
|
|
|
return NULL;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
if (sra_mode == SRA_MODE_EARLY_IPA)
|
2009-05-29 18:47:31 +02:00
|
|
|
{
|
2009-09-17 13:35:38 +02:00
|
|
|
if (size < 0 || size != max_size)
|
|
|
|
{
|
|
|
|
disqualify_candidate (base, "Encountered a variable sized access.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if ((offset % BITS_PER_UNIT) != 0 || (size % BITS_PER_UNIT) != 0)
|
|
|
|
{
|
|
|
|
disqualify_candidate (base,
|
|
|
|
"Encountered an acces not aligned to a byte.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-07-11 19:41:52 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
if (ptr)
|
|
|
|
mark_parm_dereference (base, offset + size, stmt);
|
|
|
|
}
|
|
|
|
else
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-09-17 13:35:38 +02:00
|
|
|
if (size != max_size)
|
|
|
|
{
|
|
|
|
size = max_size;
|
|
|
|
unscalarizable_region = true;
|
|
|
|
}
|
|
|
|
if (size < 0)
|
|
|
|
{
|
|
|
|
disqualify_candidate (base, "Encountered an unconstrained access.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
}
|
2004-07-11 19:41:52 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
access = (struct access *) pool_alloc (access_pool);
|
|
|
|
memset (access, 0, sizeof (struct access));
|
2004-07-11 19:41:52 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
access->base = base;
|
|
|
|
access->offset = offset;
|
|
|
|
access->size = size;
|
|
|
|
access->expr = expr;
|
|
|
|
access->type = TREE_TYPE (expr);
|
|
|
|
access->write = write;
|
|
|
|
access->grp_unscalarizable_region = unscalarizable_region;
|
2009-09-17 13:35:38 +02:00
|
|
|
access->stmt = stmt;
|
2006-07-03 22:14:18 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
slot = pointer_map_contains (base_access_vec, base);
|
|
|
|
if (slot)
|
|
|
|
vec = (VEC (access_p, heap) *) *slot;
|
|
|
|
else
|
|
|
|
vec = VEC_alloc (access_p, heap, 32);
|
2004-07-11 19:41:52 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
VEC_safe_push (access_p, heap, vec, access);
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
*((struct VEC (access_p,heap) **)
|
|
|
|
pointer_map_insert (base_access_vec, base)) = vec;
|
2004-07-11 19:41:52 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return access;
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Search the given tree for a declaration by skipping handled components and
|
|
|
|
exclude it from the candidates. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
disqualify_base_of_expr (tree t, const char *reason)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
while (handled_component_p (t))
|
|
|
|
t = TREE_OPERAND (t, 0);
|
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
if (sra_mode == SRA_MODE_EARLY_IPA)
|
|
|
|
{
|
|
|
|
if (INDIRECT_REF_P (t))
|
|
|
|
t = TREE_OPERAND (t, 0);
|
|
|
|
t = get_ssa_base_param (t);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t && DECL_P (t))
|
2009-05-29 18:47:31 +02:00
|
|
|
disqualify_candidate (t, reason);
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-08-19 23:34:37 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Scan expression EXPR and create access structures for all accesses to
|
|
|
|
candidates for scalarization. Return the created access or NULL if none is
|
|
|
|
created. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static struct access *
|
2009-09-17 13:35:38 +02:00
|
|
|
build_access_from_expr_1 (tree *expr_ptr, gimple stmt, bool write)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *ret = NULL;
|
|
|
|
tree expr = *expr_ptr;
|
|
|
|
bool partial_ref;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (TREE_CODE (expr) == BIT_FIELD_REF
|
|
|
|
|| TREE_CODE (expr) == IMAGPART_EXPR
|
|
|
|
|| TREE_CODE (expr) == REALPART_EXPR)
|
|
|
|
{
|
|
|
|
expr = TREE_OPERAND (expr, 0);
|
|
|
|
partial_ref = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
partial_ref = false;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* We need to dive through V_C_Es in order to get the size of its parameter
|
|
|
|
and not the result type. Ada produces such statements. We are also
|
|
|
|
capable of handling the topmost V_C_E but not any of those buried in other
|
|
|
|
handled components. */
|
|
|
|
if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
|
|
|
|
expr = TREE_OPERAND (expr, 0);
|
|
|
|
|
|
|
|
if (contains_view_convert_expr_p (expr))
|
|
|
|
{
|
|
|
|
disqualify_base_of_expr (expr, "V_C_E under a different handled "
|
|
|
|
"component.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-07-11 19:41:52 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
switch (TREE_CODE (expr))
|
2004-07-11 19:41:52 +02:00
|
|
|
{
|
2009-09-17 13:35:38 +02:00
|
|
|
case INDIRECT_REF:
|
|
|
|
if (sra_mode != SRA_MODE_EARLY_IPA)
|
|
|
|
return NULL;
|
|
|
|
/* fall through */
|
2004-07-11 19:41:52 +02:00
|
|
|
case VAR_DECL:
|
|
|
|
case PARM_DECL:
|
|
|
|
case RESULT_DECL:
|
2009-05-29 18:47:31 +02:00
|
|
|
case COMPONENT_REF:
|
|
|
|
case ARRAY_REF:
|
|
|
|
case ARRAY_RANGE_REF:
|
2009-09-17 13:35:38 +02:00
|
|
|
ret = create_access (expr, stmt, write);
|
2009-05-29 18:47:31 +02:00
|
|
|
break;
|
2004-07-11 19:41:52 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2004-07-11 19:41:52 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (write && partial_ref && ret)
|
|
|
|
ret->grp_partial_lhs = 1;
|
2006-07-03 22:14:18 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return ret;
|
|
|
|
}
|
2004-07-11 19:41:52 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Callback of scan_function. Scan expression EXPR and create access
|
|
|
|
structures for all accesses to candidates for scalarization. Return true if
|
|
|
|
any access has been inserted. */
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static bool
|
|
|
|
build_access_from_expr (tree *expr_ptr,
|
|
|
|
gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, bool write,
|
|
|
|
void *data ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2009-09-17 13:35:38 +02:00
|
|
|
return build_access_from_expr_1 (expr_ptr, gsi_stmt (*gsi), write) != NULL;
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Disqualify LHS and RHS for scalarization if STMT must end its basic block in
|
|
|
|
modes in which it matters, return true iff they have been disqualified. RHS
|
|
|
|
may be NULL, in that case ignore it. If we scalarize an aggregate in
|
|
|
|
intra-SRA we may need to add statements after each statement. This is not
|
|
|
|
possible if a statement unconditionally has to end the basic block. */
|
|
|
|
static bool
|
|
|
|
disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-09-17 13:35:38 +02:00
|
|
|
if ((sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
|
|
|
|
&& (stmt_can_throw_internal (stmt) || stmt_ends_bb_p (stmt)))
|
2009-05-29 18:47:31 +02:00
|
|
|
{
|
|
|
|
disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
|
|
|
|
if (rhs)
|
|
|
|
disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Result code for scan_assign callback for scan_function. */
|
|
|
|
enum scan_assign_result { SRA_SA_NONE, /* nothing done for the stmt */
|
|
|
|
SRA_SA_PROCESSED, /* stmt analyzed/changed */
|
|
|
|
SRA_SA_REMOVED }; /* stmt redundant and eliminated */
|
2004-06-29 18:25:28 +02:00
|
|
|
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Callback of scan_function. Scan expressions occuring in the statement
|
|
|
|
pointed to by STMT_EXPR, create access structures for all accesses to
|
|
|
|
candidates for scalarization and remove those candidates which occur in
|
|
|
|
statements or expressions that prevent them from being split apart. Return
|
|
|
|
true if any access has been inserted. */
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static enum scan_assign_result
|
|
|
|
build_accesses_from_assign (gimple *stmt_ptr,
|
|
|
|
gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
|
|
|
|
void *data ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
gimple stmt = *stmt_ptr;
|
|
|
|
tree *lhs_ptr, *rhs_ptr;
|
|
|
|
struct access *lacc, *racc;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!gimple_assign_single_p (stmt))
|
|
|
|
return SRA_SA_NONE;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
lhs_ptr = gimple_assign_lhs_ptr (stmt);
|
|
|
|
rhs_ptr = gimple_assign_rhs1_ptr (stmt);
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (disqualify_ops_if_throwing_stmt (stmt, *lhs_ptr, *rhs_ptr))
|
|
|
|
return SRA_SA_NONE;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
racc = build_access_from_expr_1 (rhs_ptr, stmt, false);
|
|
|
|
lacc = build_access_from_expr_1 (lhs_ptr, stmt, true);
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (lacc && racc
|
2009-09-17 13:35:38 +02:00
|
|
|
&& (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
|
2009-05-29 18:47:31 +02:00
|
|
|
&& !lacc->grp_unscalarizable_region
|
|
|
|
&& !racc->grp_unscalarizable_region
|
|
|
|
&& AGGREGATE_TYPE_P (TREE_TYPE (*lhs_ptr))
|
|
|
|
/* FIXME: Turn the following line into an assert after PR 40058 is
|
|
|
|
fixed. */
|
|
|
|
&& lacc->size == racc->size
|
|
|
|
&& useless_type_conversion_p (lacc->type, racc->type))
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct assign_link *link;
|
2006-07-03 22:14:18 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
link = (struct assign_link *) pool_alloc (link_pool);
|
|
|
|
memset (link, 0, sizeof (struct assign_link));
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
link->lacc = lacc;
|
|
|
|
link->racc = racc;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
add_link_to_rhs (racc, link);
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return (lacc || racc) ? SRA_SA_PROCESSED : SRA_SA_NONE;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
|
|
|
|
GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static bool
|
|
|
|
asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
|
|
|
|
void *data ATTRIBUTE_UNUSED)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
if (DECL_P (op))
|
|
|
|
disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return false;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Scan function and look for interesting statements. Return true if any has
|
|
|
|
been found or processed, as indicated by callbacks. SCAN_EXPR is a callback
|
|
|
|
called on all expressions within statements except assign statements and
|
|
|
|
those deemed entirely unsuitable for some reason (all operands in such
|
|
|
|
statements and expression are removed from candidate_bitmap). SCAN_ASSIGN
|
|
|
|
is a callback called on all assign statements, HANDLE_SSA_DEFS is a callback
|
2009-09-17 13:35:38 +02:00
|
|
|
called on assign statements and those call statements which have a lhs, it
|
|
|
|
can be NULL. ANALYSIS_STAGE is true when running in the analysis stage of a
|
|
|
|
pass and thus no statement is being modified. DATA is a pointer passed to
|
|
|
|
all callbacks. If any single callback returns true, this function also
|
|
|
|
returns true, otherwise it returns false. */
|
2004-11-24 21:21:29 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static bool
|
|
|
|
scan_function (bool (*scan_expr) (tree *, gimple_stmt_iterator *, bool, void *),
|
|
|
|
enum scan_assign_result (*scan_assign) (gimple *,
|
|
|
|
gimple_stmt_iterator *,
|
|
|
|
void *),
|
|
|
|
bool (*handle_ssa_defs)(gimple, void *),
|
|
|
|
bool analysis_stage, void *data)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
gimple_stmt_iterator gsi;
|
2004-06-29 18:25:28 +02:00
|
|
|
basic_block bb;
|
2009-05-29 18:47:31 +02:00
|
|
|
unsigned i;
|
|
|
|
tree *t;
|
|
|
|
bool ret = false;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
|
|
|
FOR_EACH_BB (bb)
|
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
bool bb_changed = false;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
if (handle_ssa_defs)
|
|
|
|
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
|
|
|
ret |= handle_ssa_defs (gsi_stmt (gsi), data);
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
gsi = gsi_start_bb (bb);
|
|
|
|
while (!gsi_end_p (gsi))
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
gimple stmt = gsi_stmt (gsi);
|
|
|
|
enum scan_assign_result assign_result;
|
|
|
|
bool any = false, deleted = false;
|
2009-05-20 12:18:10 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
if (analysis_stage && final_bbs && stmt_can_throw_external (stmt))
|
|
|
|
bitmap_set_bit (final_bbs, bb->index);
|
2009-05-29 18:47:31 +02:00
|
|
|
switch (gimple_code (stmt))
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
case GIMPLE_RETURN:
|
|
|
|
t = gimple_return_retval_ptr (stmt);
|
|
|
|
if (*t != NULL_TREE)
|
|
|
|
any |= scan_expr (t, &gsi, false, data);
|
2009-09-17 13:35:38 +02:00
|
|
|
if (analysis_stage && final_bbs)
|
|
|
|
bitmap_set_bit (final_bbs, bb->index);
|
2009-05-29 18:47:31 +02:00
|
|
|
break;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
case GIMPLE_ASSIGN:
|
|
|
|
assign_result = scan_assign (&stmt, &gsi, data);
|
|
|
|
any |= assign_result == SRA_SA_PROCESSED;
|
|
|
|
deleted = assign_result == SRA_SA_REMOVED;
|
|
|
|
if (handle_ssa_defs && assign_result != SRA_SA_REMOVED)
|
|
|
|
any |= handle_ssa_defs (stmt, data);
|
|
|
|
break;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
case GIMPLE_CALL:
|
|
|
|
/* Operands must be processed before the lhs. */
|
|
|
|
for (i = 0; i < gimple_call_num_args (stmt); i++)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
tree *argp = gimple_call_arg_ptr (stmt, i);
|
|
|
|
any |= scan_expr (argp, &gsi, false, data);
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
if (analysis_stage)
|
|
|
|
{
|
|
|
|
tree dest = gimple_call_fndecl (stmt);
|
|
|
|
int flags = gimple_call_flags (stmt);
|
|
|
|
|
|
|
|
if (dest
|
|
|
|
&& DECL_BUILT_IN_CLASS (dest) == BUILT_IN_NORMAL
|
|
|
|
&& DECL_FUNCTION_CODE (dest) == BUILT_IN_APPLY_ARGS)
|
|
|
|
encountered_apply_args = true;
|
|
|
|
|
|
|
|
if (final_bbs
|
|
|
|
&& (flags & (ECF_CONST | ECF_PURE)) == 0)
|
|
|
|
bitmap_set_bit (final_bbs, bb->index);
|
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (gimple_call_lhs (stmt))
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
tree *lhs_ptr = gimple_call_lhs_ptr (stmt);
|
|
|
|
if (!analysis_stage
|
|
|
|
|| !disqualify_ops_if_throwing_stmt (stmt,
|
|
|
|
*lhs_ptr, NULL))
|
|
|
|
{
|
|
|
|
any |= scan_expr (lhs_ptr, &gsi, true, data);
|
|
|
|
if (handle_ssa_defs)
|
|
|
|
any |= handle_ssa_defs (stmt, data);
|
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
break;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
case GIMPLE_ASM:
|
|
|
|
if (analysis_stage)
|
2009-09-17 13:35:38 +02:00
|
|
|
{
|
|
|
|
walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
|
|
|
|
asm_visit_addr);
|
|
|
|
if (final_bbs)
|
|
|
|
bitmap_set_bit (final_bbs, bb->index);
|
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
for (i = 0; i < gimple_asm_ninputs (stmt); i++)
|
|
|
|
{
|
|
|
|
tree *op = &TREE_VALUE (gimple_asm_input_op (stmt, i));
|
|
|
|
any |= scan_expr (op, &gsi, false, data);
|
|
|
|
}
|
|
|
|
for (i = 0; i < gimple_asm_noutputs (stmt); i++)
|
|
|
|
{
|
|
|
|
tree *op = &TREE_VALUE (gimple_asm_output_op (stmt, i));
|
|
|
|
any |= scan_expr (op, &gsi, true, data);
|
|
|
|
}
|
2009-09-17 13:35:38 +02:00
|
|
|
break;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (any)
|
|
|
|
{
|
|
|
|
ret = true;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!analysis_stage)
|
|
|
|
{
|
2009-09-17 13:35:38 +02:00
|
|
|
bb_changed = true;
|
2009-05-29 18:47:31 +02:00
|
|
|
update_stmt (stmt);
|
2009-09-14 21:18:58 +02:00
|
|
|
maybe_clean_eh_stmt (stmt);
|
2009-05-29 18:47:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (deleted)
|
|
|
|
bb_changed = true;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gsi_next (&gsi);
|
|
|
|
ret = true;
|
|
|
|
}
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2009-09-17 13:35:38 +02:00
|
|
|
if (!analysis_stage && bb_changed && sra_mode == SRA_MODE_EARLY_IPA)
|
2009-05-29 18:47:31 +02:00
|
|
|
gimple_purge_dead_eh_edges (bb);
|
bitmap.h (EXECUTE_IF_SET_IN_BITMAP, [...]): Changed to iterator style.
* bitmap.h (EXECUTE_IF_SET_IN_BITMAP, EXECUTE_IF_AND_COMPL_IN_BITMAP,
EXECUTE_IF_AND_IN_BITMAP): Changed to iterator style.
(bitmap_iterator): New type.
(bmp_iter_common_next_1, bmp_iter_single_next_1, bmp_iter_single_init,
bmp_iter_end_p, bmp_iter_single_next, bmp_iter_and_not_next_1,
bmp_iter_and_not_init, bmp_iter_and_not_next, bmp_iter_and_next_1,
bmp_iter_and_init, bmp_iter_and_next): New functions.
* basic-block.h (EXECUTE_IF_SET_IN_REG_SET,
EXECUTE_IF_AND_COMPL_IN_REG_SET, EXECUTE_IF_AND_IN_REG_SET): Changed to
use iterator-style EXECUTE_IF_IN_BITMAP macros.
* bitmap.c (bitmap_print): Ditto.
* bt-load.c (clear_btr_from_live_range, add_btr_to_live_range,
btr_def_live_range): Ditto.
* cfganal.c (compute_dominance_frontiers_1) Ditto.
* cgraphunit.c (convert_UIDs_in_bitmap, cgraph_characterize_statics):
Ditto.
* ddg.c (build_inter_loop_deps): Ditto.
* df.c (FOR_EACH_BB_IN_BITMAP, df_bb_reg_info_compute, df_refs_update):
Ditto.
* except.c (remove_eh_handler): Ditto.
* flow.c (reg_set_to_hard_reg_set): Ditto.
* gcse.c (clear_modify_mem_tables): Ditto.
* global.c (build_insn_chain): Ditto.
* ifcvt.c (dead_or_predicable): Ditto.
* loop-invariant.c (get_inv_cost, set_move_mark, move_invariant_reg):
Ditto.
* ra-build.c (livethrough_conflicts_bb, conflicts_between_webs): Ditto.
* ra-rewrite.c (reloads_to_loads, rewrite_program2,
detect_web_parts_to_rebuild, delete_useless_defs, actual_spill): Ditto.
* tree-cfg.c (allocate_ssa_names, tree_duplicate_sese_region,
tree_purge_all_dead_eh_edges): Ditto.
* tree-into-ssa.c (compute_global_livein, insert_phi_nodes,
insert_phi_nodes_for, debug_def_blocks_r, invalidate_name_tags,
rewrite_ssa_into_ssa): Ditto.
* tree-outof-ssa.c (find_replaceable_exprs): Ditto.
* tree-sra.c (scan_function, decide_instantiations, scalarize_parms):
Ditto.
* tree-ssa-alias.c (init_alias_info, compute_points_to_and_addr_escape,
compute_flow_sensitive_aliasing, maybe_create_global_var,
dump_points_to_info_for): Ditto.
* tree-ssa-dce.c (EXECUTE_IF_CONTROL_DEPENDENT): Ditto.
* tree-ssa-dse.c (dse_finalize_block): Ditto.
* tree-ssa-live.c (live_worklist, calculate_live_on_entry,
calculate_live_on_exit, build_tree_conflict_graph, dump_live_info):
Ditto.
* tree-ssa-loop-ivopts.c (find_induction_variables,
find_interesting_uses, add_old_ivs_candidates, alloc_use_cost_map,
determine_use_iv_costs, determine_set_costs, find_best_candidate,
set_cost_up_to, create_new_ivs, remove_unused_ivs, free_loop_data):
Ditto.
* tree-ssa-loop-manip.c (add_exit_phis_var, add_exit_phis): Ditto.
* tree-ssa-operands.c (get_asm_expr_operands, add_call_clobber_ops,
add_call_read_ops): Ditto.
* tree-ssa-pre.c (bitmap_print_value_set, insert_aux): Ditto.
From-SVN: r88145
2004-09-26 21:53:13 +02:00
|
|
|
}
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return ret;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Helper of QSORT function. There are pointers to accesses in the array. An
|
|
|
|
access is considered smaller than another if it has smaller offset or if the
|
|
|
|
offsets are the same but is size is bigger. */
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static int
|
|
|
|
compare_access_positions (const void *a, const void *b)
|
|
|
|
{
|
|
|
|
const access_p *fp1 = (const access_p *) a;
|
|
|
|
const access_p *fp2 = (const access_p *) b;
|
|
|
|
const access_p f1 = *fp1;
|
|
|
|
const access_p f2 = *fp2;
|
|
|
|
|
|
|
|
if (f1->offset != f2->offset)
|
|
|
|
return f1->offset < f2->offset ? -1 : 1;
|
|
|
|
|
|
|
|
if (f1->size == f2->size)
|
|
|
|
{
|
|
|
|
/* Put any non-aggregate type before any aggregate type. */
|
|
|
|
if (!is_gimple_reg_type (f1->type)
|
2009-11-30 18:59:57 +01:00
|
|
|
&& is_gimple_reg_type (f2->type))
|
2009-05-29 18:47:31 +02:00
|
|
|
return 1;
|
|
|
|
else if (is_gimple_reg_type (f1->type)
|
|
|
|
&& !is_gimple_reg_type (f2->type))
|
|
|
|
return -1;
|
2009-11-30 18:59:57 +01:00
|
|
|
/* Put any complex or vector type before any other scalar type. */
|
|
|
|
else if (TREE_CODE (f1->type) != COMPLEX_TYPE
|
|
|
|
&& TREE_CODE (f1->type) != VECTOR_TYPE
|
|
|
|
&& (TREE_CODE (f2->type) == COMPLEX_TYPE
|
|
|
|
|| TREE_CODE (f2->type) == VECTOR_TYPE))
|
|
|
|
return 1;
|
|
|
|
else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
|
|
|
|
|| TREE_CODE (f1->type) == VECTOR_TYPE)
|
|
|
|
&& TREE_CODE (f2->type) != COMPLEX_TYPE
|
|
|
|
&& TREE_CODE (f2->type) != VECTOR_TYPE)
|
|
|
|
return -1;
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Put the integral type with the bigger precision first. */
|
|
|
|
else if (INTEGRAL_TYPE_P (f1->type)
|
2009-11-30 18:59:57 +01:00
|
|
|
&& INTEGRAL_TYPE_P (f2->type))
|
2009-05-29 18:47:31 +02:00
|
|
|
return TYPE_PRECISION (f1->type) > TYPE_PRECISION (f2->type) ? -1 : 1;
|
|
|
|
/* Put any integral type with non-full precision last. */
|
|
|
|
else if (INTEGRAL_TYPE_P (f1->type)
|
|
|
|
&& (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
|
|
|
|
!= TYPE_PRECISION (f1->type)))
|
|
|
|
return 1;
|
|
|
|
else if (INTEGRAL_TYPE_P (f2->type)
|
|
|
|
&& (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
|
|
|
|
!= TYPE_PRECISION (f2->type)))
|
|
|
|
return -1;
|
|
|
|
/* Stabilize the sort. */
|
|
|
|
return TYPE_UID (f1->type) - TYPE_UID (f2->type);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We want the bigger accesses first, thus the opposite operator in the next
|
|
|
|
line: */
|
|
|
|
return f1->size > f2->size ? -1 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Append a name of the declaration to the name obstack. A helper function for
|
|
|
|
make_fancy_name. */
|
backport: copy-prop, incremental SSA updating of FUD chains and newly exposed symbols.
Merge from tree-cleanup-branch: VRP, store CCP, store
copy-prop, incremental SSA updating of FUD chains and
newly exposed symbols.
* Makefile.in (tree-ssa-copy.o): Depend on tree-ssa-propagate.h.
(OBJS-common): Add tree-vrp.o.
(tree-vrp.o): New rule.
* basic-block.h (nearest_common_dominator_for_set): Declare.
* common.opt (ftree-store-ccp): New flag.
(ftree-copy-prop): New flag.
(ftree-vrp): New flag.
(ftree-store-copy-prop): New flag.
* dominance.c (nearest_common_dominator_for_set): New.
* domwalk.c (walk_dominator_tree): Only traverse
statements in blocks marked in walk_data->interesting_blocks.
* domwalk.h (struct dom_walk_data): Add field interesting_blocks.
* fold-const.c (fold): Handle ASSERT_EXPR.
* opts.c (decode_options): Set flag_tree_copy_prop at -O1.
Set flag_tree_store_ccp, flag_tree_store_copy_prop and
flag_tree_vrp at -O2.
* timevar.def (TV_TREE_VRP): Define.
(TV_TREE_COPY_PROP): Define.
(TV_TREE_STORE_COPY_PROP): Define.
(TV_TREE_SSA_INCREMENTAL): Define.
(TV_TREE_STORE_CCP): Define.
* tree-cfg.c (tree_can_merge_blocks_p): Remove reference
to kill_redundant_phi_nodes from comment.
(verify_expr): Handle ASSERT_EXPR.
* tree-dfa.c (mark_new_vars_to_rename): Remove second
argument. Update all users.
(mark_call_clobbered_vars_to_rename): Remove. Update all
users.
* tree-flow-inline.h (unmodifiable_var_p): New.
* tree-flow.h (enum value_range_type): Declare.
(struct value_range_def): Declare.
(value_range): Declare.
(remove_all_phi_nodes_for): Remove. Update all users.
(find_phi_node_for): Declare.
(add_type_alias): Declare.
(count_uses_and_derefs): Declare.
(kill_redundant_phi_nodes): Remove.
(rewrite_into_ssa): Remove.
(rewrite_def_def_chains): Remove.
(update_ssa, register_new_name_mapping, create_new_def_for,
need_ssa_update_p, name_registered_for_update_p,
release_ssa_name_after_update_ssa, dump_repl_tbl,
debug_repl_tbl, dump_names_replaced_by,
debug_names_replaced_by, mark_sym_for_renaming,
mark_set_for_renaming, get_current_def, set_current_def,
get_value_range, dump_value_range, debug_value_range,
dump_all_value_ranges, debug_all_value_ranges,
expr_computes_nonzero, loop_depth_of_name,
unmodifiable_var_p): Declare.
* tree-gimple.c (is_gimple_formal_tmp_rhs): Handle
ASSERT_EXPR.
* tree-into-ssa.c (block_defs_stack): Update comment.
(old_ssa_names, new_ssa_names, old_virtual_ssa_names,
syms_to_rename, names_to_release, repl_tbl,
need_to_initialize_update_ssa_p, need_to_update_vops_p,
need_to_replace_names_p): New locals.
(NAME_SETS_GROWTH_FACTOR): Define.
(struct repl_map_d): Declare.
(struct mark_def_sites_global_data): Add field
interesting_blocks.
(enum rewrite_mode): Declare.
(REGISTER_DEFS_IN_THIS_STMT): Define.
(compute_global_livein): Use last_basic_block instead of
n_basic_blocks.
(set_def_block): Remove last argument. Update all callers.
(prepare_use_operand_for_rename): Remove. Update all callers.
(prepare_def_operand_for_rename): Remove. Update all callers.
(symbol_marked_for_renaming): New.
(is_old_name): New.
(is_new_name): New.
(repl_map_hash): New.
(repl_map_eq): New.
(repl_map_free): New.
(names_replaced_by): New.
(add_to_repl_tbl): New.
(add_new_name_mapping): New.
(mark_def_sites): Assume that all the operands in the
statement are in normal form.
(find_idf): Assert that the block in the stack is valid.
(get_default_def_for): New.
(insert_phi_nodes_for): Add new argument 'update_p'.
Add documentation.
If update_p is true, add a new mapping between the LHS of
each new PHI and the name that it replaces.
(insert_phi_nodes_1): Only call find_idf if needed.
(get_reaching_def): Call get_default_def_for.
(rewrite_operand): Remove.
(rewrite_stmt): Do nothing if REGISTER_DEFS_IN_THIS_STMT
and REWRITE_THIS_STMT are false.
Assume that all the operands in the statement are in
normal form.
(rewrite_add_phi_arguments): Don't use PHI_REWRITTEN.
(rewrite_virtual_phi_arguments): Remove.
(invalidate_name_tags): Remove.
(register_new_update_single, register_new_update_set,
rewrite_update_init_block, replace_use,
rewrite_update_fini_block, rewrite_update_stmt,
rewrite_update_phi_arguments): New.
rewrite_blocks): Remove argument 'fix_virtual_phis'.
Add arguments 'entry', 'what' and 'blocks'.
Initialize the dominator walker according to 'what' and
'blocks'.
Start the dominator walk at 'entry'.
(mark_def_site_blocks): Add argument 'interesting_blocks'.
Use it to configure the dominator walker.
(rewrite_into_ssa): Remove argument 'all'.
Make internal.
(rewrite_all_into_ssa): Remove.
(rewrite_def_def_chains): Remove.
(mark_def_interesting, mark_use_interesting,
prepare_phi_args_for_update, prepare_block_for_update,
prepare_def_site_for, prepare_def_sites,
dump_names_replaced_by, debug_names_replaced_by,
dump_repl_tbl, debug_repl_tbl, init_update_ssa,
delete_update_ssa, create_new_def_for,
register_new_name_mapping, mark_sym_for_renaming,
mark_set_for_renaming, need_ssa_update_p,
name_registered_for_update_p, ssa_names_to_replace,
release_ssa_name_after_update_ssa,
insert_updated_phi_nodes_for, update_ssa): New.
* tree-loop-linear.c (linear_transform_loops): Call
update_ssa instead of rewrite_into_ssa.
* tree-optimize.c (vars_to_rename): Remove.
Update all users.
(init_tree_optimization_passes): Replace
pass_redundant_phi with pass_copy_prop.
Add pass_vrp.
Replace pass_ccp with pass_store_ccp.
Add pass_store_copy_prop after pass_store_ccp.
(execute_todo): If the TODO_ flags don't include updating
the SSA form, assert that it does not need to be updated.
Call update_ssa instead of rewrite_into_ssa and
rewrite_def_def_chains.
If TODO_verify_loops is set, call verify_loop_closed_ssa.
(tree_rest_of_compilation):
* tree-pass.h (TODO_dump_func, TODO_ggc_collect,
TODO_verify_ssa, TODO_verify_flow, TODO_verify_stmts,
TODO_cleanup_cfg): Renumber.
(TODO_verify_loops, TODO_update_ssa,
TODO_update_ssa_no_phi, TODO_update_ssa_full_phi,
TODO_update_ssa_only_virtuals): Define.
(pass_copy_prop, pass_store_ccp, pass_store_copy_prop, pass_vrp):
Declare.
* tree-phinodes.c (make_phi_node): Update documentation.
(remove_all_phi_nodes_for): Remove.
(find_phi_node_for): New.
* tree-pretty-print.c (dump_generic_node): Handle ASSERT_EXPR.
* tree-scalar-evolution.c (follow_ssa_edge_in_rhs): Likewise.
(interpret_rhs_modify_expr): Likewise.
* tree-sra.c (decide_instantiations): Mark all symbols in
SRA_CANDIDATES for renaming.
(mark_all_v_defs_1): Rename from mark_all_v_defs.
(mark_all_v_defs): New function. Update all users to call it
with the whole list of scalarized statements, not just the
first one.
* tree-ssa-alias.c (count_ptr_derefs): Make extern.
(compute_flow_insensitive_aliasing): If the tag is
unmodifiable and the variable isn't or vice-versa, don't
make them alias of each other.
(setup_pointers_and_addressables): If the type tag for
VAR is about to change, mark the old one for renaming.
(add_type_alias): New.
* tree-ssa-ccp.c: Document SSA-CCP and STORE-CCP.
(ccp_lattice_t): Rename from latticevalue.
(value): Remove. Update all users.
(const_val): New local variable.
(do_store_ccp): New local variable.
(dump_lattice_value): Handle UNINITIALIZED.
(debug_lattice_value): New.
(get_default_value): Re-write.
(set_lattice_value): Re-write.
(def_to_varying): Remove. Update all users.
(likely_value): Return VARYING for statements that make
stores when STORE_CCP is false.
Return VARYING for any statement other than MODIFY_EXPR,
COND_EXPR and SWITCH_EXPR.
(ccp_initialize): Re-write.
(replace_uses_in, replace_vuse_in, substitute_and_fold):
Move to tree-ssa-propagate.c.
(ccp_lattice_meet): Handle memory stores when
DO_STORE_CCP is true.
(ccp_visit_phi_node): Likewise.
(ccp_fold): Likewise.
(evaluate_stmt): Likewise.
(visit_assignment): Likewise.
(ccp_visit_stmt): Likewise.
(execute_ssa_ccp): Add argument 'store_ccp'. Copy it
into DO_STORE_CCP.
(do_ssa_ccp): New.
(pass_ccp): Use it.
(do_ssa_store_ccp): New.
(gate_store_ccp): New.
(pass_store_ccp): Declare.
* tree-ssa-copy.c: Include tree-ssa-propagate.h.
(may_propagate_copy): Reformat.
Don't abort if ORIG is a virtual and DEST isn't.
If NEW does not have alias information but DEST does,
copy it.
(copy_of, cached_last_copy_of, do_store_copy_prop, enum
copy_prop_kind, which_copy_prop): Declare.
(stmt_may_generate_copy, get_copy_of_val,
get_last_copy_of, set_copy_of_val, dump_copy_of,
copy_prop_visit_assignment, copy_prop_visit_cond_stmt,
copy_prop_visit_stmt, copy_prop_visit_phi_node,
init_copy_prop, fini_copy_prop, execute_copy_prop,
gate_copy_prop, do_copy_prop, gate_store_copy_prop,
store_copy_prop): New.
(pass_copy_prop, pass_store_copy_prop): Declare.
* tree-ssa-dom.c (struct opt_stats_d): Add fields
'num_const_prop' and 'num_copy_prop'.
(cprop_operand): Update them.
(dump_dominator_optimization_stats): Dump them.
(tree_ssa_dominator_optimize): Call update_ssa instead of
rewrite_into_ssa.
(loop_depth_of_name): Declare extern.
(simplify_cond_and_lookup_avail_expr): Guard against NULL
values for LOW or HIGH.
(cprop_into_successor_phis): Only propagate if NEW != ORIG.
(record_equivalences_from_stmt): Call expr_computes_nonzero.
(cprop_operand): Only propagate if VAL != OP.
* tree-ssa-dse.c (dse_optimize_stmt): Mark symbols in removed
statement for renaming.
* tree-ssa-loop-im.c (move_computations): Call update_ssa.
* tree-ssa-loop-ivopts.c (rewrite_address_base): Call
add_type_alias if necessary.
Call mark_new_vars_to_rename.
(tree_ssa_iv_optimize): If new symbols need to be renamed,
mark every statement updated, call update_ssa and
rewrite_into_loop_closed_ssa.
* tree-ssa-loop-manip.c (add_exit_phis): Do not remove DEF_BB
from LIVEIN if VAR is a virtual.
* tree-ssa-loop.c (tree_loop_optimizer_init): Call update_ssa.
* tree-ssa-operands.c (get_expr_operands): Handle ASSERT_EXPR.
(get_call_expr_operands): Reformat statement.
(add_stmt_operand): Don't create V_MAY_DEFs for read-only
symbols.
* tree-ssa-propagate.c (ssa_prop_init): Initialize
SSA_NAME_VALUE for every name.
(first_vdef, stmt_makes_single_load, stmt_makes_single_store,
get_value_loaded_by): New.
(replace_uses_in, replace_vuses_in, replace_phi_args_in,
substitute_and_fold): Move from tree-ssa-ccp.c.
* tree-ssa-propagate.h (struct prop_value_d, prop_value_t,
first_vdef, stmt_makes_single_load, stmt_makes_single_store,
get_value_loaded_by, replace_uses_in, substitute_and_fold):
Declare.
* tree-ssa.c (verify_use): Fix error message.
(propagate_into_addr, replace_immediate_uses, get_eq_name,
check_phi_redundancy, kill_redundant_phi_nodes,
pass_redundant_phi): Remove. Update all users.
* tree-vect-transform.c (vect_create_data_ref_ptr): Call
add_type_alias, if necessary.
* tree-vectorizer.h (struct _stmt_vect_info): Update
documentation for field 'memtag'.
* tree-vrp.c: New file.
* tree.def (ASSERT_EXPR): Define.
* tree.h (ASSERT_EXPR_VAR): Define.
(ASSERT_EXPR_COND): Define.
(SSA_NAME_VALUE_RANGE): Define.
(struct tree_ssa_name): Add field 'value_range'.
(PHI_REWRITTEN): Remove.
(struct tree_phi_node): Remove field 'rewritten'.
* doc/invoke.texi (-fdump-tree-storeccp, -ftree-copy-prop,
-ftree-store-copy-prop): Document.
* doc/tree-ssa.texi: Remove broken link to McCAT's compiler.
Document usage of update_ssa.
testsuite/ChangeLog
* g++.dg/tree-ssa/pr18178.C: New test.
* gcc.c-torture/execute/20030216-1.x: Ignore at -O1.
* gcc.c-torture/execute/20041019-1.c: New test.
* gcc.dg/tree-ssa/20041008-1.c: New test.
* gcc.dg/tree-ssa/ssa-ccp-12.c: New test.
* gcc.dg/tree-ssa/20030731-2.c: Update to use -fdump-tree-store_ccp.
* gcc.dg/tree-ssa/20030917-1.c: Likewise.
* gcc.dg/tree-ssa/20030917-3.c: Likewise.
* gcc.dg/tree-ssa/20040721-1.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-1.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-2.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-3.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-7.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-9.c: Likewise.
From-SVN: r97884
2005-04-09 03:37:54 +02:00
|
|
|
|
|
|
|
static void
|
2009-05-29 18:47:31 +02:00
|
|
|
make_fancy_decl_name (tree decl)
|
backport: copy-prop, incremental SSA updating of FUD chains and newly exposed symbols.
Merge from tree-cleanup-branch: VRP, store CCP, store
copy-prop, incremental SSA updating of FUD chains and
newly exposed symbols.
* Makefile.in (tree-ssa-copy.o): Depend on tree-ssa-propagate.h.
(OBJS-common): Add tree-vrp.o.
(tree-vrp.o): New rule.
* basic-block.h (nearest_common_dominator_for_set): Declare.
* common.opt (ftree-store-ccp): New flag.
(ftree-copy-prop): New flag.
(ftree-vrp): New flag.
(ftree-store-copy-prop): New flag.
* dominance.c (nearest_common_dominator_for_set): New.
* domwalk.c (walk_dominator_tree): Only traverse
statements in blocks marked in walk_data->interesting_blocks.
* domwalk.h (struct dom_walk_data): Add field interesting_blocks.
* fold-const.c (fold): Handle ASSERT_EXPR.
* opts.c (decode_options): Set flag_tree_copy_prop at -O1.
Set flag_tree_store_ccp, flag_tree_store_copy_prop and
flag_tree_vrp at -O2.
* timevar.def (TV_TREE_VRP): Define.
(TV_TREE_COPY_PROP): Define.
(TV_TREE_STORE_COPY_PROP): Define.
(TV_TREE_SSA_INCREMENTAL): Define.
(TV_TREE_STORE_CCP): Define.
* tree-cfg.c (tree_can_merge_blocks_p): Remove reference
to kill_redundant_phi_nodes from comment.
(verify_expr): Handle ASSERT_EXPR.
* tree-dfa.c (mark_new_vars_to_rename): Remove second
argument. Update all users.
(mark_call_clobbered_vars_to_rename): Remove. Update all
users.
* tree-flow-inline.h (unmodifiable_var_p): New.
* tree-flow.h (enum value_range_type): Declare.
(struct value_range_def): Declare.
(value_range): Declare.
(remove_all_phi_nodes_for): Remove. Update all users.
(find_phi_node_for): Declare.
(add_type_alias): Declare.
(count_uses_and_derefs): Declare.
(kill_redundant_phi_nodes): Remove.
(rewrite_into_ssa): Remove.
(rewrite_def_def_chains): Remove.
(update_ssa, register_new_name_mapping, create_new_def_for,
need_ssa_update_p, name_registered_for_update_p,
release_ssa_name_after_update_ssa, dump_repl_tbl,
debug_repl_tbl, dump_names_replaced_by,
debug_names_replaced_by, mark_sym_for_renaming,
mark_set_for_renaming, get_current_def, set_current_def,
get_value_range, dump_value_range, debug_value_range,
dump_all_value_ranges, debug_all_value_ranges,
expr_computes_nonzero, loop_depth_of_name,
unmodifiable_var_p): Declare.
* tree-gimple.c (is_gimple_formal_tmp_rhs): Handle
ASSERT_EXPR.
* tree-into-ssa.c (block_defs_stack): Update comment.
(old_ssa_names, new_ssa_names, old_virtual_ssa_names,
syms_to_rename, names_to_release, repl_tbl,
need_to_initialize_update_ssa_p, need_to_update_vops_p,
need_to_replace_names_p): New locals.
(NAME_SETS_GROWTH_FACTOR): Define.
(struct repl_map_d): Declare.
(struct mark_def_sites_global_data): Add field
interesting_blocks.
(enum rewrite_mode): Declare.
(REGISTER_DEFS_IN_THIS_STMT): Define.
(compute_global_livein): Use last_basic_block instead of
n_basic_blocks.
(set_def_block): Remove last argument. Update all callers.
(prepare_use_operand_for_rename): Remove. Update all callers.
(prepare_def_operand_for_rename): Remove. Update all callers.
(symbol_marked_for_renaming): New.
(is_old_name): New.
(is_new_name): New.
(repl_map_hash): New.
(repl_map_eq): New.
(repl_map_free): New.
(names_replaced_by): New.
(add_to_repl_tbl): New.
(add_new_name_mapping): New.
(mark_def_sites): Assume that all the operands in the
statement are in normal form.
(find_idf): Assert that the block in the stack is valid.
(get_default_def_for): New.
(insert_phi_nodes_for): Add new argument 'update_p'.
Add documentation.
If update_p is true, add a new mapping between the LHS of
each new PHI and the name that it replaces.
(insert_phi_nodes_1): Only call find_idf if needed.
(get_reaching_def): Call get_default_def_for.
(rewrite_operand): Remove.
(rewrite_stmt): Do nothing if REGISTER_DEFS_IN_THIS_STMT
and REWRITE_THIS_STMT are false.
Assume that all the operands in the statement are in
normal form.
(rewrite_add_phi_arguments): Don't use PHI_REWRITTEN.
(rewrite_virtual_phi_arguments): Remove.
(invalidate_name_tags): Remove.
(register_new_update_single, register_new_update_set,
rewrite_update_init_block, replace_use,
rewrite_update_fini_block, rewrite_update_stmt,
rewrite_update_phi_arguments): New.
rewrite_blocks): Remove argument 'fix_virtual_phis'.
Add arguments 'entry', 'what' and 'blocks'.
Initialize the dominator walker according to 'what' and
'blocks'.
Start the dominator walk at 'entry'.
(mark_def_site_blocks): Add argument 'interesting_blocks'.
Use it to configure the dominator walker.
(rewrite_into_ssa): Remove argument 'all'.
Make internal.
(rewrite_all_into_ssa): Remove.
(rewrite_def_def_chains): Remove.
(mark_def_interesting, mark_use_interesting,
prepare_phi_args_for_update, prepare_block_for_update,
prepare_def_site_for, prepare_def_sites,
dump_names_replaced_by, debug_names_replaced_by,
dump_repl_tbl, debug_repl_tbl, init_update_ssa,
delete_update_ssa, create_new_def_for,
register_new_name_mapping, mark_sym_for_renaming,
mark_set_for_renaming, need_ssa_update_p,
name_registered_for_update_p, ssa_names_to_replace,
release_ssa_name_after_update_ssa,
insert_updated_phi_nodes_for, update_ssa): New.
* tree-loop-linear.c (linear_transform_loops): Call
update_ssa instead of rewrite_into_ssa.
* tree-optimize.c (vars_to_rename): Remove.
Update all users.
(init_tree_optimization_passes): Replace
pass_redundant_phi with pass_copy_prop.
Add pass_vrp.
Replace pass_ccp with pass_store_ccp.
Add pass_store_copy_prop after pass_store_ccp.
(execute_todo): If the TODO_ flags don't include updating
the SSA form, assert that it does not need to be updated.
Call update_ssa instead of rewrite_into_ssa and
rewrite_def_def_chains.
If TODO_verify_loops is set, call verify_loop_closed_ssa.
(tree_rest_of_compilation):
* tree-pass.h (TODO_dump_func, TODO_ggc_collect,
TODO_verify_ssa, TODO_verify_flow, TODO_verify_stmts,
TODO_cleanup_cfg): Renumber.
(TODO_verify_loops, TODO_update_ssa,
TODO_update_ssa_no_phi, TODO_update_ssa_full_phi,
TODO_update_ssa_only_virtuals): Define.
(pass_copy_prop, pass_store_ccp, pass_store_copy_prop, pass_vrp):
Declare.
* tree-phinodes.c (make_phi_node): Update documentation.
(remove_all_phi_nodes_for): Remove.
(find_phi_node_for): New.
* tree-pretty-print.c (dump_generic_node): Handle ASSERT_EXPR.
* tree-scalar-evolution.c (follow_ssa_edge_in_rhs): Likewise.
(interpret_rhs_modify_expr): Likewise.
* tree-sra.c (decide_instantiations): Mark all symbols in
SRA_CANDIDATES for renaming.
(mark_all_v_defs_1): Rename from mark_all_v_defs.
(mark_all_v_defs): New function. Update all users to call it
with the whole list of scalarized statements, not just the
first one.
* tree-ssa-alias.c (count_ptr_derefs): Make extern.
(compute_flow_insensitive_aliasing): If the tag is
unmodifiable and the variable isn't or vice-versa, don't
make them alias of each other.
(setup_pointers_and_addressables): If the type tag for
VAR is about to change, mark the old one for renaming.
(add_type_alias): New.
* tree-ssa-ccp.c: Document SSA-CCP and STORE-CCP.
(ccp_lattice_t): Rename from latticevalue.
(value): Remove. Update all users.
(const_val): New local variable.
(do_store_ccp): New local variable.
(dump_lattice_value): Handle UNINITIALIZED.
(debug_lattice_value): New.
(get_default_value): Re-write.
(set_lattice_value): Re-write.
(def_to_varying): Remove. Update all users.
(likely_value): Return VARYING for statements that make
stores when STORE_CCP is false.
Return VARYING for any statement other than MODIFY_EXPR,
COND_EXPR and SWITCH_EXPR.
(ccp_initialize): Re-write.
(replace_uses_in, replace_vuse_in, substitute_and_fold):
Move to tree-ssa-propagate.c.
(ccp_lattice_meet): Handle memory stores when
DO_STORE_CCP is true.
(ccp_visit_phi_node): Likewise.
(ccp_fold): Likewise.
(evaluate_stmt): Likewise.
(visit_assignment): Likewise.
(ccp_visit_stmt): Likewise.
(execute_ssa_ccp): Add argument 'store_ccp'. Copy it
into DO_STORE_CCP.
(do_ssa_ccp): New.
(pass_ccp): Use it.
(do_ssa_store_ccp): New.
(gate_store_ccp): New.
(pass_store_ccp): Declare.
* tree-ssa-copy.c: Include tree-ssa-propagate.h.
(may_propagate_copy): Reformat.
Don't abort if ORIG is a virtual and DEST isn't.
If NEW does not have alias information but DEST does,
copy it.
(copy_of, cached_last_copy_of, do_store_copy_prop, enum
copy_prop_kind, which_copy_prop): Declare.
(stmt_may_generate_copy, get_copy_of_val,
get_last_copy_of, set_copy_of_val, dump_copy_of,
copy_prop_visit_assignment, copy_prop_visit_cond_stmt,
copy_prop_visit_stmt, copy_prop_visit_phi_node,
init_copy_prop, fini_copy_prop, execute_copy_prop,
gate_copy_prop, do_copy_prop, gate_store_copy_prop,
store_copy_prop): New.
(pass_copy_prop, pass_store_copy_prop): Declare.
* tree-ssa-dom.c (struct opt_stats_d): Add fields
'num_const_prop' and 'num_copy_prop'.
(cprop_operand): Update them.
(dump_dominator_optimization_stats): Dump them.
(tree_ssa_dominator_optimize): Call update_ssa instead of
rewrite_into_ssa.
(loop_depth_of_name): Declare extern.
(simplify_cond_and_lookup_avail_expr): Guard against NULL
values for LOW or HIGH.
(cprop_into_successor_phis): Only propagate if NEW != ORIG.
(record_equivalences_from_stmt): Call expr_computes_nonzero.
(cprop_operand): Only propagate if VAL != OP.
* tree-ssa-dse.c (dse_optimize_stmt): Mark symbols in removed
statement for renaming.
* tree-ssa-loop-im.c (move_computations): Call update_ssa.
* tree-ssa-loop-ivopts.c (rewrite_address_base): Call
add_type_alias if necessary.
Call mark_new_vars_to_rename.
(tree_ssa_iv_optimize): If new symbols need to be renamed,
mark every statement updated, call update_ssa and
rewrite_into_loop_closed_ssa.
* tree-ssa-loop-manip.c (add_exit_phis): Do not remove DEF_BB
from LIVEIN if VAR is a virtual.
* tree-ssa-loop.c (tree_loop_optimizer_init): Call update_ssa.
* tree-ssa-operands.c (get_expr_operands): Handle ASSERT_EXPR.
(get_call_expr_operands): Reformat statement.
(add_stmt_operand): Don't create V_MAY_DEFs for read-only
symbols.
* tree-ssa-propagate.c (ssa_prop_init): Initialize
SSA_NAME_VALUE for every name.
(first_vdef, stmt_makes_single_load, stmt_makes_single_store,
get_value_loaded_by): New.
(replace_uses_in, replace_vuses_in, replace_phi_args_in,
substitute_and_fold): Move from tree-ssa-ccp.c.
* tree-ssa-propagate.h (struct prop_value_d, prop_value_t,
first_vdef, stmt_makes_single_load, stmt_makes_single_store,
get_value_loaded_by, replace_uses_in, substitute_and_fold):
Declare.
* tree-ssa.c (verify_use): Fix error message.
(propagate_into_addr, replace_immediate_uses, get_eq_name,
check_phi_redundancy, kill_redundant_phi_nodes,
pass_redundant_phi): Remove. Update all users.
* tree-vect-transform.c (vect_create_data_ref_ptr): Call
add_type_alias, if necessary.
* tree-vectorizer.h (struct _stmt_vect_info): Update
documentation for field 'memtag'.
* tree-vrp.c: New file.
* tree.def (ASSERT_EXPR): Define.
* tree.h (ASSERT_EXPR_VAR): Define.
(ASSERT_EXPR_COND): Define.
(SSA_NAME_VALUE_RANGE): Define.
(struct tree_ssa_name): Add field 'value_range'.
(PHI_REWRITTEN): Remove.
(struct tree_phi_node): Remove field 'rewritten'.
* doc/invoke.texi (-fdump-tree-storeccp, -ftree-copy-prop,
-ftree-store-copy-prop): Document.
* doc/tree-ssa.texi: Remove broken link to McCAT's compiler.
Document usage of update_ssa.
testsuite/ChangeLog
* g++.dg/tree-ssa/pr18178.C: New test.
* gcc.c-torture/execute/20030216-1.x: Ignore at -O1.
* gcc.c-torture/execute/20041019-1.c: New test.
* gcc.dg/tree-ssa/20041008-1.c: New test.
* gcc.dg/tree-ssa/ssa-ccp-12.c: New test.
* gcc.dg/tree-ssa/20030731-2.c: Update to use -fdump-tree-store_ccp.
* gcc.dg/tree-ssa/20030917-1.c: Likewise.
* gcc.dg/tree-ssa/20030917-3.c: Likewise.
* gcc.dg/tree-ssa/20040721-1.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-1.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-2.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-3.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-7.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-9.c: Likewise.
From-SVN: r97884
2005-04-09 03:37:54 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
char buffer[32];
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
tree name = DECL_NAME (decl);
|
|
|
|
if (name)
|
|
|
|
obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
|
|
|
|
IDENTIFIER_LENGTH (name));
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf (buffer, "D%u", DECL_UID (decl));
|
|
|
|
obstack_grow (&name_obstack, buffer, strlen (buffer));
|
|
|
|
}
|
2008-07-28 16:33:56 +02:00
|
|
|
}
|
[multiple changes]
2006-12-11 Diego Novillo <dnovillo@redhat.com>
* doc/tree-ssa.texi: Update documentation for virtual operands
and the use of push_stmt_changes/pop_stmt_changes.
* doc/invoke.texi: Remove documentation for params
global-var-threshold.
Update documentation on max-aliased-vops.
* tree-into-ssa.c: Cleanup comments, variables and
spacing in various functions.
(regs_to_rename): Declare.
(mem_syms_to_rename): Declare.
(dump_update_ssa): Declare.
(debug_update_ssa): Declare.
(dump_names_replaced_by): Declare.
(debug_names_replaced_by): Declare.
(dump_def_blocks): Declare.
(debug_def_blocks): Declare.
(dump_defs_stack): Declare.
(debug_defs_stack): Declare.
(dump_currdefs): Declare.
(debug_currdefs): Declare.
(mark_def_sites): Do not handle virtual operands.
(compute_idf): Rename from find_idf. Update users.
(register_new_def): Make local. Convert second argument
to 'tree'.
Use BLOCK_DEFS_STACK directly.
If pushing a non-register, also push the underlying
symbol.
(rewrite_stmt): Do not handle virtual operands.
(dump_tree_ssa): Call dump_def_blocks, dump_defs_stack,
dump_currdefs and dump_tree_ssa_stats.
(dump_tree_ssa_stats): Also dump REPL_TBL.
(replace_use): Remove. Update all users to call SET_USE
instead.
(rewrite_blocks): Move code to free memory to
fini_ssa_renamer.
(mark_def_site_blocks): Move initialization code to
init_ssa_renamer.
(init_ssa_renamer): New.
(fini_ssa_renamer): New.
(rewrite_into_ssa): Call them.
(prepare_block_for_update): Process SSA_OP_ALL_USES first
and SSA_OP_ALL_DEFS later. Do not process virtual
operands separately.
(dump_update_ssa): Call dump_decl_set.
(init_update_ssa): Initialize regs_to_rename and
mem_syms_to_rename.
Call init_ssa_renamer.
(delete_update_ssa): Call fini_ssa_renamer.
Free blocks_with_phis_to_rewrite.
(mark_sym_for_renaming): If the variable has
sub-variables, also mark them.
If the variable belongs to a partition, also mark it.
(mark_set_for_renaming): Call mark_sym_for_renaming on
every symbol in the set.
(switch_virtuals_to_full_rewrite): Call
mark_set_for_renaming.
(update_ssa): Separate syms_to_rename into regs_to_rename
and mem_syms_to_rename.
* tree-dump.c (dump_options): Add TDF_MEMSYMS.
* tree-pretty-print.c (debug_generic_expr): Add TDF_MEMSYMS.
(debug_generic_stmt): Likewise.
(debug_tree_chain): Likewise.
(dump_symbols): New.
(dump_generic_node): Check for TDF_MEMSYMS.
Handle MEMORY_PARTITION_TAG.
If the statement references memory and TDF_MEMSYMS is
given, call dump_symbols.
Indicate default names with (D).
(dump_vops): Update for new virtual operator format.
* tree.c (init_ttree): Add MEMORY_PARTITION_TAG to
tree_contains_struct.
(tree_code_size): Handle MEMORY_PARTITION_TAG.
(tree_node_structure): Likewise.
(needs_to_live_in_memory): Handle SSA names.
* tree.h (MTAG_P): Likewise.
(struct tree_memory_partition_tag): Declare.
(MPT_SYMBOLS): Define.
(union tree_node): Add field 'mpt'.
* treestruct.def (TS_MEMORY_PARTITION_TAG): Define.
* tree.def (MEMORY_PARTITION_TAG): Define.
* tree-pass.h (TDF_MEMSYMS): Define.
* params.h (GLOBAL_VAR_THRESHOLD): Remove.
* tree-ssa-alias.c: Include pointer-set.h
(struct alias_map_d): Remove fields total_alias_vops,
grouped_p and may_aliases. Update all users.
(struct mp_info_def): Declare.
(mp_info_t): New type.
(get_smt_for): Rename from get_tmt_for. Update all
users.
(add_may_alias): Add argument ALREADY_ADDED. If given,
use it to avoid adding duplicate entries to alias sets.
(replace_may_alias): Remove. Update all users.
(total_alias_vops_cmp): Remove. Update all users.
(group_aliases_into): Remove. Update all users.
(tree_pointer_compare): Remove. Update all users.
(compact_name_tags): Remove. Update all users.
(group_aliases): Remove. Update all users.
(mark_non_addressable): Move from tree-flow-inline.h.
Remove the symbol from the partition holding it, if
needed.
(dump_mp_info): New.
(debug_mp_info): New.
(sort_mp_info): New.
(create_partition_for): New.
(rewrite_alias_set_for): New.
(compute_memory_partitions): New.
(compute_may_aliases): Call it.
(init_alias_info): If computing aliases for the first
time, mark every memory symbol for renaming.
(have_common_aliases_p): New.
(compute_flow_insensitive_aliasing): Call it.
(setup_pointers_and_addressables): Do not cache
num_referenced_vars.
For register promoted symbols, mark their former
partition for renaming.
(maybe_create_global_var): Only create .GLOBAL_VAR if
there are no call-clobbered variables and a mix of pure
and non-pure functions were found.
(may_alias_p): Tidy comments.
(create_tag_raw): Remove unused variable new_type.
(dump_alias_info): call dump_memory_partitions.
(dump_points_to_info_for): Call dump_decl_set.
(may_be_aliased): Tidy comments and formatting.
* timevar.def (TV_MEMORY_PARTITIONING): Define.
* tree-vectorizer.c (vect_memsyms_to_rename): Rename from
vect_vnames_to_rename. Set DECL_UIDs instead of SSA name
versions in it.
(slpeel_update_phi_nodes_for_guard1): Ignore memory PHIs.
* tree-vect-transform.c (vect_transform_loop): Call
mark_set_for_renaming with vect_memsyms_to_rename.
* tree-flow-inline.h (zero_imm_uses_p): New.
(memory_partition): New.
(set_memory_partition): New.
(factoring_name_p): New.
(symbol_mem_tag): New. Update every function that used
to access the annotation directly.
(set_symbol_mem_tag): Likewise.
* tree-ssa-copy.c (may_propagate_copy): Allow copies
between a partition and a symbol as long as the symbol
belongs to the partition.
(merge_alias_info): Ignore merge requests when memory
partitions are involved.
* tree-ssa.c (verify_ssa_name): Check that default
definitions have empty defining statements.
(verify_use): Remove argument IS_VIRTUAL.
Don't call verify_ssa_name.
(verify_phi_args): Call verify_ssa_name.
(verify_flow_insensitive_alias_info): Handle MPTs.
(verify_flow_sensitive_alias_info): Likewise.
(verify_name_tags): Likewise.
(verify_call_clobbering): Likewise.
(verify_ssa): Check for VOPs only after aliasing
information is available.
Check virtuals and real operands separately.
Call verify_ssa_name on every operand.
(stmt_references_memory_p): Move to tree-ssa-operands.c.
(walk_use_def_chains_1): Guard against NULL PHI
arguments.
* tree-ssa-operands.c (stmt_references_memory_p): Move from
tree-ssa.c.
(get_mpt_for): New.
(dump_memory_partitions): New.
(debug_memory_partitions): New.
* tree-flow.h (struct var_ann_d): Add field mpt.
(struct stmt_ann_d): Add bitfield references_memory.
* Makefile.in (tree-ssa-structalias.o): Include
pointer-set.h
(tree-ssa-alias.o): Likewise.
* tree-ssa-structalias.c: (update_alias_info): Use
STORED_SYMS to determine which variables are being
written to by the store operation.
* tree-ssa-structalias.h (struct alias_info)
<total_alias_vops>: Remove. Update all users.
<written_vars>: Change to a pointer set. Update all
users.
<dereferenced_ptrs_store>: Likewise.
<dereferenced_ptrs_load>: Likewise.
(NUM_REFERENCES): Remove. Update all users.
(NUM_REFERENCES_CLEAR): Remove. Update all users.
(NUM_REFERENCES_INC): Remove. Update all users.
(NUM_REFERENCES_SET): Remove. Update all users.
* params.def (PARAM_GLOBAL_VAR_THRESHOLD): Remove.
Update all users.
(PARAM_MAX_ALIASED_VOPS): Set to 10.
* tree-ssanames.c (make_ssa_name): Initialize
SSA_NAME_IS_DEFAULT_DEF to 0.
2006-12-11 Aldy Hernandez <aldyh@redhat.com>
* tree-ssa-dse.c (aggregate_vardecl_d): New.
(dse_global_data): Add aggregate_vardecl field.
(dse_possible_dead_store_p): New.
Add prev_defvar variable.
Allow immediate uses and previous immediate uses to differ
if they are setting different parts of the whole.
(get_aggregate_vardecl): New.
(dse_record_partial_aggregate_store): New.
(dse_whole_aggregate_clobbered_p): New.
(dse_partial_kill_p): New.
(dse_optimize_stmt): Abstract code checking a possible dead store
into new function dse_possible_dead_store_p().
Call dse_maybe_record_aggregate_store().
When checking whether a STMT and its USE_STMT refer to the
same memory address, check also for partial kills that clobber
the whole.
Move some variable definitions to the block where they are used.
(aggregate_vardecl_hash): New.
(aggregate_vardecl_eq): New.
(aggregate_vardecl_free): New.
(aggregate_whole_store_p): New.
(tree_ssa_dse): Initialize and free aggregate_vardecl.
Mark which aggregate stores we care about.
2006-12-11 Andrew Macleod <amacleod@redhat.com>
* tree-ssa-operands.h (struct vuse_element_d): Declare.
(vuse_element_t): Declare.
(struct vuse_vec_d): Declare.
(vuse_vec_p): Declare.
(VUSE_VECT_NUM_ELEM): Define.
(VUSE_VECT_ELEMENT_NC): Define.
(VUSE_ELEMENT_PTR_NC): Define.
(VUSE_ELEMENT_VAR_NC): Define.
(VUSE_VECT_ELEMENT): Define.
(VUSE_ELEMENT_PTR): Define.
(VUSE_ELEMENT_VAR): Define.
(struct maydef_optype_d) <use_var>: Remove.
<use_ptr>: Remove.
<usev>: Add.
(struct vuse_optype_d) <kill_var>: Remove.
<use_ptr>: Remove.
<usev>: Add.
(struct mustdef_optype_d) <kill_var>: Remove.
<use_ptr>: Remove.
<usev>: Add.
(VUSE_OP_PTR): Add argument. Use VUSE_ELEMENT_PTR.
(VUSE_OP): Add argument. Use VUSE_ELEMENT_PTR.
(VUSE_NUM): Define.
(VUSE_VECT): Define.
(MAYDEF_OP_PTR): Add argument. Use VUSE_OP_PTR.
(MAYDEF_OP): Add argument. Use VUSE_OP.
(MAYDEF_NUM): Define.
(MAYDEF_VECT): Define.
(MUSTDEF_KILL_PTR): Use VUSE_OP_PTR.
(MUSTDEF_KILL): Use VUSE_OP.
(MUSTDEF_NUM): Define.
(MUSTDEF_VECT): Define.
(realloc_maydef): Declare.
(realloc_vuse): Declare.
(struct ssa_operand_iterator_d) <vuse_index>: Add.
<mayuse_index>: Add.
(LOADED_SYMS): Define.
(STORED_SYMS): Define.
(FOR_EACH_SSA_MUSTDEF_OPERAND): Call op_iter_next_mustdef.
* tree-into-ssa.c: Adapt for multi-operand V_MAY_DEF and VUSE
operators.
* tree-pretty-print.c: Likewise.
* tree-ssa-dse.c: Likewise.
* tree-flow-inline.h: Likewise.
(op_iter_next_mustdef): New.
* tree-ssa-operands.c: Likewise.
(ALLOC_OPTYPE): Remove.
Update all users.
(alloc_def): New.
(alloc_use): New.
(alloc_maydef): New.
(alloc_vuse): New.
(alloc_mustdef): New.
(realloc_maydef): New.
(realloc_vuse): New.
2006-12-11 Aldy Hernandez <aldyh@redhat.com>
* tree-ssa-operands.c: Remove build_v_must_defs.
(init_ssa_operands): Delete build_v_must_defs.
(finalize_ssa_v_must_def_ops): Remove.
(finalize_ssa_v_must_defs): Remove.
(finalize_ssa_stmt_operands): Do not call
finalize_ssa_v_must_defs.
(start_ssa_stmt_operands): Do not check build_v_must_defs.
(append_v_must_def): Delete.
(copy_virtual_operands): Do not copy V_MUST_DEFs.
(get_modify_expr_operands): Remove reference to V_MUST_DEF from
comment. Remove opf_kill_def.
(build_ssa_operands): Remove references to v_must_defs.
(copy_virtual_operands): Same.
(copy_virtual_operands): Same.
(fini_ssa_operands): Same.
(free_ssa_operands): Same.
(add_mustdef_op): Remove.
Remove mustdef_optype_p.
(alloc_mustdef): Remove.
Remove references to V_MUST_DEFs in comment at top of file.
(get_expr_operands): Remove opf_kill_def.
(opf_kill_def): Remove.
(add_virtual_operand): Remove opf_kill_def.
(get_indirect_ref_operands): Same.
(get_tmr_operands): Same.
* tree-vectorizer.c (rename_variables_in_bb): Remove
SSA_OP_ALL_KILLS.
* tree-ssa-loop-manip.c (find_uses_to_rename_stmt): Remove
SSA_OP_ALL_KILLS.
(check_loop_closed_ssa_stmt): Same.
* tree-ssa.c (verify_def): Remove V_MUST_DEF from comment.
(verify_use): Same.
(verify_ssa): Remove V_MUST_DEFs traces.
(verify_ssa): Remove SSA_OP_ALL_KILLS.
* tree-into-ssa.c (mark_def_sites): Change SSA_OP_VMUSTDEF to
SSA_OP_VMAYDEF.
(rewrite_update_stmt): Remove SSA_OP_VIRTUAL_KILLS.
(rewrite_stmt): Remove SSA_OP_ALL_KILLS.
* tree-ssa-operands.h (struct stmt_operands_d): Remove V_MUST_DEF
references.
(MUSTDEF_OPS): Remove.
(SSA_OP_VMUSTDEF): Remove.
(FOR_EACH_SSA_MUSTDEF_OPERAND): Remove.
(struct mustdef_optype_d): Remove.
Remove mustdef_optype_p.
(struct stmt_operands_d): Remove mustdef_ops.
(ssa_operand_iterator_d): Remove mustdefs and mustkills.
(SSA_OP_VIRTUAL_DEFS): Remove SSA_OP_VMUSTDEF.
(MUSTDEF_RESULT_PTR): Remove.
(MUSTDEF_RESULT): Remove.
(MUSTDEF_KILL_PTR): Remove.
(MUSTDEF_KILL): Remove.
(MUSTDEF_NUM): Remove.
(MUSTDEF_VECT): Remove.
(SSA_OP_VIRTUAL_KILLS): Remove.
(SSA_OP_ALL_VIRTUALS): Remove SSA_OP_VIRTUAL_KILLS.
(SSA_OP_VMUSTKILL): Remove.
(SSA_OP_ALL_KILLS): Remove.
(SSA_OP_ALL_OPERANDS): Remove SSA_OP_ALL_KILLS.
* tree-flow-inline.h (op_iter_init_def): Remove
SSA_OP_VIRTUAL_KILLS.
(delink_stmt_imm_use): Remove SSA_OP_ALL_KILLS.
* tree-ssa-pre.c (compute_rvuse_and_antic_safe): Remove
SSA_OP_VIRTUAL_KILLS.
* tree-ssa-loop-im.c (determine_max_movement): Remove
SSA_OP_VIRTUAL_KILLS.
(gather_mem_refs_stmt): Same.
(gather_mem_refs_stmt): Same.
* tree-ssa-dce.c (mark_really_necessary_kill_operand_phis): Delete.
(perform_tree_ssa_dce): Remove call to
mark_really_necessary_kill_operand_phis.
* tree-flow-inline.h (op_iter_init): Remove setting of mustdefs
and mustkills.
(op_iter_next_use): Do not check mustkills.
(op_iter_next_def): Do not check mustdefs.
(op_iter_next_tree): Do not check mustkills or mustdefs.
(clear_and_done_ssa_iter): Do not set mustdefs or mustkills.
(op_iter_next_maymustdef): Do not check mustkills.
(op_iter_init_must_and_may_def): Remove SSA_OP_VMUSTKILL.
(op_iter_init_mustdef): Remove.
* tree-ssa-live.c (create_ssa_var_map): Change SSA_OP_VMUSTDEF to
SSA_OP_VMAYDEF.
* tree-ssa-dse.c (dse_optimize_stmt): Remove SSA_OP_VMUSTDEF.
* tree-ssa-ccp.c: Remove V_MUST_DEF traces from comments.
(visit_assignment): Same.
* tree-ssa-copy.c (copy_prop_visit_assignment): Same.
* tree-sra.c (mark_all_v_defs_1): Remove V_MUST_DEF from comment.
* tree-outof-ssa.c (check_replaceable): Remove SSA_OP_VMUSTDEF.
* tree-pretty-print.c (dump_vops): Remove printing of V_MUST_DEF.
Remove kill_p variable.
* tree-dfa.c (struct dfa_stats_d): Remove num_v_must_defs.
(dump_dfa_stats): Remove code related to V_MUST_DEFs.
(collect_dfa_stats_r): Do not set num_v_must_defs.
(mark_new_vars_to_rename): Remove v_must_defs_{before,after}
code.
* tree-into-ssa.c (mark_def_sites): Change SSA_OP_VMUSTKILL to
SSA_OP_VMAYUSE.
* tree-ssa-pre.c (compute_rvuse_and_antic_safe): Remove
SSA_OP_VMUSTDEF and SSA_OP_VMUSTKILL.
* tree-ssa-propagate.c (stmt_makes_single_store): Remove
SSA_OP_VMUSTDEF.
From-SVN: r119760
2006-12-12 02:48:51 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Helper for make_fancy_name. */
|
2005-11-21 01:51:39 +01:00
|
|
|
|
|
|
|
static void
|
2009-05-29 18:47:31 +02:00
|
|
|
make_fancy_name_1 (tree expr)
|
2005-11-21 01:51:39 +01:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
char buffer[32];
|
|
|
|
tree index;
|
|
|
|
|
|
|
|
if (DECL_P (expr))
|
2005-11-21 01:51:39 +01:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
make_fancy_decl_name (expr);
|
|
|
|
return;
|
2005-11-21 01:51:39 +01:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
switch (TREE_CODE (expr))
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
case COMPONENT_REF:
|
|
|
|
make_fancy_name_1 (TREE_OPERAND (expr, 0));
|
|
|
|
obstack_1grow (&name_obstack, '$');
|
|
|
|
make_fancy_decl_name (TREE_OPERAND (expr, 1));
|
|
|
|
break;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
case ARRAY_REF:
|
|
|
|
make_fancy_name_1 (TREE_OPERAND (expr, 0));
|
|
|
|
obstack_1grow (&name_obstack, '$');
|
|
|
|
/* Arrays with only one element may not have a constant as their
|
|
|
|
index. */
|
|
|
|
index = TREE_OPERAND (expr, 1);
|
|
|
|
if (TREE_CODE (index) != INTEGER_CST)
|
|
|
|
break;
|
|
|
|
sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
|
|
|
|
obstack_grow (&name_obstack, buffer, strlen (buffer));
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
break;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
case BIT_FIELD_REF:
|
|
|
|
case REALPART_EXPR:
|
|
|
|
case IMAGPART_EXPR:
|
|
|
|
gcc_unreachable (); /* we treat these as scalars. */
|
|
|
|
break;
|
2004-06-29 18:25:28 +02:00
|
|
|
default:
|
2009-05-29 18:47:31 +02:00
|
|
|
break;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Create a human readable name for replacement variable of ACCESS. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static char *
|
|
|
|
make_fancy_name (tree expr)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
make_fancy_name_1 (expr);
|
|
|
|
obstack_1grow (&name_obstack, '\0');
|
|
|
|
return XOBFINISH (&name_obstack, char *);
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Helper function for build_ref_for_offset. */
|
2007-10-01 18:35:55 +02:00
|
|
|
|
|
|
|
static bool
|
2009-05-29 18:47:31 +02:00
|
|
|
build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset,
|
|
|
|
tree exp_type)
|
2007-02-15 05:24:50 +01:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
while (1)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
tree fld;
|
2009-09-04 13:08:12 +02:00
|
|
|
tree tr_size, index, minidx;
|
2009-05-29 18:47:31 +02:00
|
|
|
HOST_WIDE_INT el_size;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (offset == 0 && exp_type
|
2009-06-30 12:10:29 +02:00
|
|
|
&& types_compatible_p (exp_type, type))
|
2009-05-29 18:47:31 +02:00
|
|
|
return true;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
switch (TREE_CODE (type))
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
case UNION_TYPE:
|
|
|
|
case QUAL_UNION_TYPE:
|
|
|
|
case RECORD_TYPE:
|
|
|
|
for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
|
|
|
|
{
|
|
|
|
HOST_WIDE_INT pos, size;
|
|
|
|
tree expr, *expr_ptr;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (TREE_CODE (fld) != FIELD_DECL)
|
|
|
|
continue;
|
2008-07-08 18:34:37 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
pos = int_bit_position (fld);
|
|
|
|
gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
|
2009-10-20 11:19:17 +02:00
|
|
|
tr_size = DECL_SIZE (fld);
|
|
|
|
if (!tr_size || !host_integerp (tr_size, 1))
|
|
|
|
continue;
|
|
|
|
size = tree_low_cst (tr_size, 1);
|
2009-05-29 18:47:31 +02:00
|
|
|
if (pos > offset || (pos + size) <= offset)
|
|
|
|
continue;
|
2008-03-01 01:27:26 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (res)
|
|
|
|
{
|
|
|
|
expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
|
|
|
|
NULL_TREE);
|
|
|
|
expr_ptr = &expr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
expr_ptr = NULL;
|
|
|
|
if (build_ref_for_offset_1 (expr_ptr, TREE_TYPE (fld),
|
|
|
|
offset - pos, exp_type))
|
|
|
|
{
|
|
|
|
if (res)
|
|
|
|
*res = expr;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2008-12-03 13:27:48 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
case ARRAY_TYPE:
|
|
|
|
tr_size = TYPE_SIZE (TREE_TYPE (type));
|
|
|
|
if (!tr_size || !host_integerp (tr_size, 1))
|
|
|
|
return false;
|
|
|
|
el_size = tree_low_cst (tr_size, 1);
|
2008-12-03 13:27:48 +01:00
|
|
|
|
2009-09-04 13:08:12 +02:00
|
|
|
minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
|
|
|
|
if (TREE_CODE (minidx) != INTEGER_CST)
|
|
|
|
return false;
|
2009-05-29 18:47:31 +02:00
|
|
|
if (res)
|
|
|
|
{
|
|
|
|
index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
|
2009-09-04 13:08:12 +02:00
|
|
|
if (!integer_zerop (minidx))
|
|
|
|
index = int_const_binop (PLUS_EXPR, index, minidx, 0);
|
2009-05-29 18:47:31 +02:00
|
|
|
*res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
|
|
|
|
NULL_TREE, NULL_TREE);
|
|
|
|
}
|
|
|
|
offset = offset % el_size;
|
|
|
|
type = TREE_TYPE (type);
|
|
|
|
break;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
default:
|
|
|
|
if (offset != 0)
|
|
|
|
return false;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (exp_type)
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
return true;
|
|
|
|
}
|
2008-09-16 14:34:01 +02:00
|
|
|
}
|
2007-02-15 05:24:50 +01:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Construct an expression that would reference a part of aggregate *EXPR of
|
|
|
|
type TYPE at the given OFFSET of the type EXP_TYPE. If EXPR is NULL, the
|
|
|
|
function only determines whether it can build such a reference without
|
2009-10-29 13:40:48 +01:00
|
|
|
actually doing it, otherwise, the tree it points to is unshared first and
|
|
|
|
then used as a base for furhter sub-references.
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
FIXME: Eventually this should be replaced with
|
|
|
|
maybe_fold_offset_to_reference() from tree-ssa-ccp.c but that requires a
|
|
|
|
minor rewrite of fold_stmt.
|
|
|
|
*/
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-08-07 02:51:34 +02:00
|
|
|
bool
|
2009-05-29 18:47:31 +02:00
|
|
|
build_ref_for_offset (tree *expr, tree type, HOST_WIDE_INT offset,
|
|
|
|
tree exp_type, bool allow_ptr)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
re PR c/40435 (Revision 148442 caused many regressions on trunk)
2009-07-17 Aldy Hernandez <aldyh@redhat.com>
Manuel López-Ibáñez <manu@gcc.gnu.org>
PR 40435
* tree-complex.c, tree-loop-distribution.c,
tree.c, tree.h, builtins.c, fold-const.c, omp-low.c,
cgraphunit.c, tree-ssa-ccp.c, tree-ssa-dom.c,
gimple-low.c, expr.c, tree-ssa-ifcombine.c, c-decl.c,
stor-layout.c, tree-if-conv.c, c-typeck.c,
gimplify.c, calls.c, tree-sra.c, tree-mudflap.c,
tree-ssa-copy.c, tree-ssa-forwprop.c, c-convert.c, c-omp.c,
varasm.c, tree-inline.c, c-common.c,
c-common.h, gimple.c, tree-switch-conversion.c, gimple.h,
tree-cfg.c, c-parser.c, convert.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
objc/
* objc-act.c: Add location argument to all calls to
build_fold_addr_expr.
testsuite/
* gcc.dg/pr36902.c: Add column info.
* g++.dg/gcov/gcov-2.C: Change count for definition.
cp/
* typeck.c, init.c, class.c, method.c, rtti.c, except.c, error.c,
tree.c, cp-gimplify.c, cxx-pretty-print.c, pt.c, semantics.c,
call.c, cvt.c, mangle.c: Add location argument to
fold_{unary,binary,ternary}, fold_build[123], build_call_expr,
build_size_arg, build_fold_addr_expr, build_call_array,
non_lvalue, size_diffop, fold_build1_initializer,
fold_build2_initializer, fold_build3_initializer,
fold_build_call_array, fold_build_call_array_initializer,
fold_single_bit_test, omit_one_operand, omit_two_operands,
invert_truthvalue, fold_truth_not_expr, build_fold_indirect_ref,
fold_indirect_ref, combine_comparisons, fold_builtin_*,
fold_call_expr, build_range_check, maybe_fold_offset_to_address,
round_up, round_down.
fortran/
* trans-expr.c, trans-array.c, trans-openmp.c, trans-stmt.c,
trans.c, trans-io.c, trans-decl.c, trans-intrinsic.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
Co-Authored-By: Manuel López-Ibáñez <manu@gcc.gnu.org>
From-SVN: r149722
2009-07-17 00:29:52 +02:00
|
|
|
location_t loc = expr ? EXPR_LOCATION (*expr) : UNKNOWN_LOCATION;
|
|
|
|
|
2009-10-29 13:40:48 +01:00
|
|
|
if (expr)
|
|
|
|
*expr = unshare_expr (*expr);
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (allow_ptr && POINTER_TYPE_P (type))
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
type = TREE_TYPE (type);
|
|
|
|
if (expr)
|
re PR c/40435 (Revision 148442 caused many regressions on trunk)
2009-07-17 Aldy Hernandez <aldyh@redhat.com>
Manuel López-Ibáñez <manu@gcc.gnu.org>
PR 40435
* tree-complex.c, tree-loop-distribution.c,
tree.c, tree.h, builtins.c, fold-const.c, omp-low.c,
cgraphunit.c, tree-ssa-ccp.c, tree-ssa-dom.c,
gimple-low.c, expr.c, tree-ssa-ifcombine.c, c-decl.c,
stor-layout.c, tree-if-conv.c, c-typeck.c,
gimplify.c, calls.c, tree-sra.c, tree-mudflap.c,
tree-ssa-copy.c, tree-ssa-forwprop.c, c-convert.c, c-omp.c,
varasm.c, tree-inline.c, c-common.c,
c-common.h, gimple.c, tree-switch-conversion.c, gimple.h,
tree-cfg.c, c-parser.c, convert.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
objc/
* objc-act.c: Add location argument to all calls to
build_fold_addr_expr.
testsuite/
* gcc.dg/pr36902.c: Add column info.
* g++.dg/gcov/gcov-2.C: Change count for definition.
cp/
* typeck.c, init.c, class.c, method.c, rtti.c, except.c, error.c,
tree.c, cp-gimplify.c, cxx-pretty-print.c, pt.c, semantics.c,
call.c, cvt.c, mangle.c: Add location argument to
fold_{unary,binary,ternary}, fold_build[123], build_call_expr,
build_size_arg, build_fold_addr_expr, build_call_array,
non_lvalue, size_diffop, fold_build1_initializer,
fold_build2_initializer, fold_build3_initializer,
fold_build_call_array, fold_build_call_array_initializer,
fold_single_bit_test, omit_one_operand, omit_two_operands,
invert_truthvalue, fold_truth_not_expr, build_fold_indirect_ref,
fold_indirect_ref, combine_comparisons, fold_builtin_*,
fold_call_expr, build_range_check, maybe_fold_offset_to_address,
round_up, round_down.
fortran/
* trans-expr.c, trans-array.c, trans-openmp.c, trans-stmt.c,
trans.c, trans-io.c, trans-decl.c, trans-intrinsic.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
Co-Authored-By: Manuel López-Ibáñez <manu@gcc.gnu.org>
From-SVN: r149722
2009-07-17 00:29:52 +02:00
|
|
|
*expr = fold_build1_loc (loc, INDIRECT_REF, type, *expr);
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return build_ref_for_offset_1 (expr, type, offset, exp_type);
|
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-10-01 13:30:12 +02:00
|
|
|
/* Return true iff TYPE is stdarg va_list type. */
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
is_va_list_type (tree type)
|
|
|
|
{
|
|
|
|
return TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node);
|
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
|
|
|
|
those with type which is suitable for scalarization. */
|
2008-12-10 18:20:50 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static bool
|
|
|
|
find_var_candidates (void)
|
|
|
|
{
|
|
|
|
tree var, type;
|
|
|
|
referenced_var_iterator rvi;
|
|
|
|
bool ret = false;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
FOR_EACH_REFERENCED_VAR (var, rvi)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
if (TREE_CODE (var) != VAR_DECL && TREE_CODE (var) != PARM_DECL)
|
|
|
|
continue;
|
|
|
|
type = TREE_TYPE (var);
|
|
|
|
|
|
|
|
if (!AGGREGATE_TYPE_P (type)
|
|
|
|
|| needs_to_live_in_memory (var)
|
|
|
|
|| TREE_THIS_VOLATILE (var)
|
|
|
|
|| !COMPLETE_TYPE_P (type)
|
|
|
|
|| !host_integerp (TYPE_SIZE (type), 1)
|
|
|
|
|| tree_low_cst (TYPE_SIZE (type), 1) == 0
|
2009-09-09 18:50:15 +02:00
|
|
|
|| type_internals_preclude_sra_p (type)
|
|
|
|
/* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
|
|
|
|
we also want to schedule it rather late. Thus we ignore it in
|
|
|
|
the early pass. */
|
|
|
|
|| (sra_mode == SRA_MODE_EARLY_INTRA
|
2009-10-01 13:30:12 +02:00
|
|
|
&& is_va_list_type (type)))
|
2009-05-29 18:47:31 +02:00
|
|
|
continue;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
bitmap_set_bit (candidate_bitmap, DECL_UID (var));
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
|
|
|
|
print_generic_expr (dump_file, var, 0);
|
|
|
|
fprintf (dump_file, "\n");
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
ret = true;
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return ret;
|
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Sort all accesses for the given variable, check for partial overlaps and
|
|
|
|
return NULL if there are any. If there are none, pick a representative for
|
|
|
|
each combination of offset and size and create a linked list out of them.
|
|
|
|
Return the pointer to the first representative and make sure it is the first
|
|
|
|
one in the vector of accesses. */
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static struct access *
|
|
|
|
sort_and_splice_var_accesses (tree var)
|
|
|
|
{
|
|
|
|
int i, j, access_count;
|
|
|
|
struct access *res, **prev_acc_ptr = &res;
|
|
|
|
VEC (access_p, heap) *access_vec;
|
|
|
|
bool first = true;
|
|
|
|
HOST_WIDE_INT low = -1, high = 0;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
access_vec = get_base_access_vector (var);
|
|
|
|
if (!access_vec)
|
|
|
|
return NULL;
|
|
|
|
access_count = VEC_length (access_p, access_vec);
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Sort by <OFFSET, SIZE>. */
|
|
|
|
qsort (VEC_address (access_p, access_vec), access_count, sizeof (access_p),
|
|
|
|
compare_access_positions);
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
i = 0;
|
|
|
|
while (i < access_count)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *access = VEC_index (access_p, access_vec, i);
|
2009-09-02 19:52:18 +02:00
|
|
|
bool grp_write = access->write;
|
2009-05-29 18:47:31 +02:00
|
|
|
bool grp_read = !access->write;
|
2009-09-02 19:52:18 +02:00
|
|
|
bool multiple_reads = false;
|
2009-05-29 18:47:31 +02:00
|
|
|
bool grp_partial_lhs = access->grp_partial_lhs;
|
2009-11-30 18:59:57 +01:00
|
|
|
bool grp_different_types = false;
|
2009-05-29 18:47:31 +02:00
|
|
|
bool first_scalar = is_gimple_reg_type (access->type);
|
|
|
|
bool unscalarizable_region = access->grp_unscalarizable_region;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (first || access->offset >= high)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
first = false;
|
|
|
|
low = access->offset;
|
|
|
|
high = access->offset + access->size;
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
else if (access->offset > low && access->offset + access->size > high)
|
|
|
|
return NULL;
|
2007-10-01 18:35:55 +02:00
|
|
|
else
|
2009-05-29 18:47:31 +02:00
|
|
|
gcc_assert (access->offset >= low
|
|
|
|
&& access->offset + access->size <= high);
|
|
|
|
|
|
|
|
j = i + 1;
|
|
|
|
while (j < access_count)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *ac2 = VEC_index (access_p, access_vec, j);
|
|
|
|
if (ac2->offset != access->offset || ac2->size != access->size)
|
|
|
|
break;
|
2009-09-02 19:52:18 +02:00
|
|
|
if (ac2->write)
|
|
|
|
grp_write = true;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (grp_read)
|
|
|
|
multiple_reads = true;
|
|
|
|
else
|
|
|
|
grp_read = true;
|
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
grp_partial_lhs |= ac2->grp_partial_lhs;
|
2009-11-30 18:59:57 +01:00
|
|
|
grp_different_types |= !types_compatible_p (access->type, ac2->type);
|
2009-05-29 18:47:31 +02:00
|
|
|
unscalarizable_region |= ac2->grp_unscalarizable_region;
|
|
|
|
relink_to_new_repr (access, ac2);
|
|
|
|
|
|
|
|
/* If there are both aggregate-type and scalar-type accesses with
|
|
|
|
this combination of size and offset, the comparison function
|
|
|
|
should have put the scalars first. */
|
|
|
|
gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
|
|
|
|
ac2->group_representative = access;
|
|
|
|
j++;
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
i = j;
|
|
|
|
|
|
|
|
access->group_representative = access;
|
2009-09-02 19:52:18 +02:00
|
|
|
access->grp_write = grp_write;
|
2009-05-29 18:47:31 +02:00
|
|
|
access->grp_read = grp_read;
|
2009-09-02 19:52:18 +02:00
|
|
|
access->grp_hint = multiple_reads;
|
2009-05-29 18:47:31 +02:00
|
|
|
access->grp_partial_lhs = grp_partial_lhs;
|
2009-11-30 18:59:57 +01:00
|
|
|
access->grp_different_types = grp_different_types;
|
2009-05-29 18:47:31 +02:00
|
|
|
access->grp_unscalarizable_region = unscalarizable_region;
|
|
|
|
if (access->first_link)
|
|
|
|
add_access_to_work_queue (access);
|
|
|
|
|
|
|
|
*prev_acc_ptr = access;
|
|
|
|
prev_acc_ptr = &access->next_grp;
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
gcc_assert (res == VEC_index (access_p, access_vec, 0));
|
|
|
|
return res;
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Create a variable for the given ACCESS which determines the type, name and a
|
|
|
|
few other properties. Return the variable declaration and store it also to
|
|
|
|
ACCESS->replacement. */
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static tree
|
|
|
|
create_access_replacement (struct access *access)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
tree repl;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
repl = create_tmp_var (access->type, "SR");
|
|
|
|
get_var_ann (repl);
|
|
|
|
add_referenced_var (repl);
|
|
|
|
mark_sym_for_renaming (repl);
|
2005-06-18 10:51:44 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!access->grp_partial_lhs
|
|
|
|
&& (TREE_CODE (access->type) == COMPLEX_TYPE
|
|
|
|
|| TREE_CODE (access->type) == VECTOR_TYPE))
|
|
|
|
DECL_GIMPLE_REG_P (repl) = 1;
|
2005-06-18 10:51:44 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
|
|
|
|
DECL_ARTIFICIAL (repl) = 1;
|
|
|
|
|
|
|
|
if (DECL_NAME (access->base)
|
|
|
|
&& !DECL_IGNORED_P (access->base)
|
|
|
|
&& !DECL_ARTIFICIAL (access->base))
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
char *pretty_name = make_fancy_name (access->expr);
|
|
|
|
|
|
|
|
DECL_NAME (repl) = get_identifier (pretty_name);
|
|
|
|
obstack_free (&name_obstack, pretty_name);
|
|
|
|
|
|
|
|
SET_DECL_DEBUG_EXPR (repl, access->expr);
|
|
|
|
DECL_DEBUG_EXPR_IS_FROM (repl) = 1;
|
|
|
|
DECL_IGNORED_P (repl) = 0;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
|
|
|
|
DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
|
|
|
|
TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
|
|
|
|
|
|
|
|
if (dump_file)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
fprintf (dump_file, "Created a replacement for ");
|
|
|
|
print_generic_expr (dump_file, access->base, 0);
|
|
|
|
fprintf (dump_file, " offset: %u, size: %u: ",
|
|
|
|
(unsigned) access->offset, (unsigned) access->size);
|
|
|
|
print_generic_expr (dump_file, repl, 0);
|
|
|
|
fprintf (dump_file, "\n");
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2009-06-18 17:38:36 +02:00
|
|
|
sra_stats.replacements++;
|
2009-05-29 18:47:31 +02:00
|
|
|
|
|
|
|
return repl;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Return ACCESS scalar replacement, create it if it does not exist yet. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static inline tree
|
|
|
|
get_access_replacement (struct access *access)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
gcc_assert (access->grp_to_be_replaced);
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-06-18 17:38:36 +02:00
|
|
|
if (!access->replacement_decl)
|
|
|
|
access->replacement_decl = create_access_replacement (access);
|
2009-05-29 18:47:31 +02:00
|
|
|
return access->replacement_decl;
|
|
|
|
}
|
2008-02-12 19:35:05 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
|
|
|
|
linked list along the way. Stop when *ACCESS is NULL or the access pointed
|
|
|
|
to it is not "within" the root. */
|
2008-02-12 19:35:05 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static void
|
|
|
|
build_access_subtree (struct access **access)
|
|
|
|
{
|
|
|
|
struct access *root = *access, *last_child = NULL;
|
|
|
|
HOST_WIDE_INT limit = root->offset + root->size;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
*access = (*access)->next_grp;
|
|
|
|
while (*access && (*access)->offset + (*access)->size <= limit)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!last_child)
|
|
|
|
root->first_child = *access;
|
|
|
|
else
|
|
|
|
last_child->next_sibling = *access;
|
|
|
|
last_child = *access;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
build_access_subtree (access);
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Build a tree of access representatives, ACCESS is the pointer to the first
|
|
|
|
one, others are linked in a list by the next_grp field. Decide about scalar
|
|
|
|
replacements on the way, return true iff any are to be created. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2004-06-29 18:25:28 +02:00
|
|
|
static void
|
2009-05-29 18:47:31 +02:00
|
|
|
build_access_trees (struct access *access)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
while (access)
|
2004-07-07 01:02:22 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *root = access;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
build_access_subtree (&access);
|
|
|
|
root->next_grp = access;
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-09-04 13:08:12 +02:00
|
|
|
/* Return true if expr contains some ARRAY_REFs into a variable bounded
|
|
|
|
array. */
|
|
|
|
|
|
|
|
static bool
|
|
|
|
expr_with_var_bounded_array_refs_p (tree expr)
|
|
|
|
{
|
|
|
|
while (handled_component_p (expr))
|
|
|
|
{
|
|
|
|
if (TREE_CODE (expr) == ARRAY_REF
|
|
|
|
&& !host_integerp (array_ref_low_bound (expr), 0))
|
|
|
|
return true;
|
|
|
|
expr = TREE_OPERAND (expr, 0);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
|
|
|
|
both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set
|
|
|
|
all sorts of access flags appropriately along the way, notably always ser
|
|
|
|
grp_read when MARK_READ is true and grp_write when MARK_WRITE is true. */
|
2004-07-11 19:33:02 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static bool
|
|
|
|
analyze_access_subtree (struct access *root, bool allow_replacements,
|
|
|
|
bool mark_read, bool mark_write)
|
2004-07-11 19:33:02 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *child;
|
|
|
|
HOST_WIDE_INT limit = root->offset + root->size;
|
|
|
|
HOST_WIDE_INT covered_to = root->offset;
|
|
|
|
bool scalar = is_gimple_reg_type (root->type);
|
|
|
|
bool hole = false, sth_created = false;
|
2009-09-02 19:52:18 +02:00
|
|
|
bool direct_read = root->grp_read;
|
2004-07-11 19:33:02 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (mark_read)
|
|
|
|
root->grp_read = true;
|
|
|
|
else if (root->grp_read)
|
|
|
|
mark_read = true;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (mark_write)
|
|
|
|
root->grp_write = true;
|
|
|
|
else if (root->grp_write)
|
|
|
|
mark_write = true;
|
|
|
|
|
|
|
|
if (root->grp_unscalarizable_region)
|
|
|
|
allow_replacements = false;
|
|
|
|
|
2009-09-04 13:08:12 +02:00
|
|
|
if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
|
|
|
|
allow_replacements = false;
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
for (child = root->first_child; child; child = child->next_sibling)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!hole && child->offset < covered_to)
|
|
|
|
hole = true;
|
|
|
|
else
|
|
|
|
covered_to += child->size;
|
|
|
|
|
|
|
|
sth_created |= analyze_access_subtree (child, allow_replacements,
|
|
|
|
mark_read, mark_write);
|
|
|
|
|
|
|
|
root->grp_unscalarized_data |= child->grp_unscalarized_data;
|
|
|
|
hole |= !child->grp_covered;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-09-02 19:52:18 +02:00
|
|
|
if (allow_replacements && scalar && !root->first_child
|
|
|
|
&& (root->grp_hint
|
|
|
|
|| (direct_read && root->grp_write)))
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
fprintf (dump_file, "Marking ");
|
|
|
|
print_generic_expr (dump_file, root->base, 0);
|
|
|
|
fprintf (dump_file, " offset: %u, size: %u: ",
|
|
|
|
(unsigned) root->offset, (unsigned) root->size);
|
|
|
|
fprintf (dump_file, " to be replaced.\n");
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
root->grp_to_be_replaced = 1;
|
|
|
|
sth_created = true;
|
|
|
|
hole = false;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
else if (covered_to < limit)
|
|
|
|
hole = true;
|
2004-07-05 18:14:51 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (sth_created && !hole)
|
|
|
|
{
|
|
|
|
root->grp_covered = 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (root->grp_write || TREE_CODE (root->base) == PARM_DECL)
|
|
|
|
root->grp_unscalarized_data = 1; /* not covered and written to */
|
|
|
|
if (sth_created)
|
|
|
|
return true;
|
|
|
|
return false;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Analyze all access trees linked by next_grp by the means of
|
|
|
|
analyze_access_subtree. */
|
2005-01-05 00:54:26 +01:00
|
|
|
static bool
|
2009-05-29 18:47:31 +02:00
|
|
|
analyze_access_trees (struct access *access)
|
2005-01-05 00:54:26 +01:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
bool ret = false;
|
2005-01-05 00:54:26 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
while (access)
|
2005-01-05 00:54:26 +01:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
if (analyze_access_subtree (access, true, false, false))
|
|
|
|
ret = true;
|
|
|
|
access = access->next_grp;
|
2005-01-05 00:54:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Return true iff a potential new child of LACC at offset OFFSET and with size
|
|
|
|
SIZE would conflict with an already existing one. If exactly such a child
|
|
|
|
already exists in LACC, store a pointer to it in EXACT_MATCH. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static bool
|
|
|
|
child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
|
|
|
|
HOST_WIDE_INT size, struct access **exact_match)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *child;
|
|
|
|
|
|
|
|
for (child = lacc->first_child; child; child = child->next_sibling)
|
|
|
|
{
|
|
|
|
if (child->offset == norm_offset && child->size == size)
|
|
|
|
{
|
|
|
|
*exact_match = child;
|
|
|
|
return true;
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (child->offset < norm_offset + size
|
|
|
|
&& child->offset + child->size > norm_offset)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Create a new child access of PARENT, with all properties just like MODEL
|
|
|
|
except for its offset and with its grp_write false and grp_read true.
|
2009-09-07 19:08:12 +02:00
|
|
|
Return the new access or NULL if it cannot be created. Note that this access
|
|
|
|
is created long after all splicing and sorting, it's not located in any
|
|
|
|
access vector and is automatically a representative of its group. */
|
2009-05-29 18:47:31 +02:00
|
|
|
|
|
|
|
static struct access *
|
|
|
|
create_artificial_child_access (struct access *parent, struct access *model,
|
|
|
|
HOST_WIDE_INT new_offset)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *access;
|
|
|
|
struct access **child;
|
2009-09-07 19:08:12 +02:00
|
|
|
tree expr = parent->base;;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
gcc_assert (!model->grp_unscalarizable_region);
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-09-07 19:08:12 +02:00
|
|
|
if (!build_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
|
|
|
|
model->type, false))
|
|
|
|
return NULL;
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
access = (struct access *) pool_alloc (access_pool);
|
|
|
|
memset (access, 0, sizeof (struct access));
|
|
|
|
access->base = parent->base;
|
2009-09-07 19:08:12 +02:00
|
|
|
access->expr = expr;
|
2009-05-29 18:47:31 +02:00
|
|
|
access->offset = new_offset;
|
|
|
|
access->size = model->size;
|
|
|
|
access->type = model->type;
|
|
|
|
access->grp_write = true;
|
|
|
|
access->grp_read = false;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
child = &parent->first_child;
|
|
|
|
while (*child && (*child)->offset < new_offset)
|
|
|
|
child = &(*child)->next_sibling;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
access->next_sibling = *child;
|
|
|
|
*child = access;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
return access;
|
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
|
|
|
|
/* Propagate all subaccesses of RACC across an assignment link to LACC. Return
|
|
|
|
true if any new subaccess was created. Additionally, if RACC is a scalar
|
2009-09-07 19:08:12 +02:00
|
|
|
access but LACC is not, change the type of the latter, if possible. */
|
2007-10-01 18:35:55 +02:00
|
|
|
|
|
|
|
static bool
|
2009-10-29 13:40:48 +01:00
|
|
|
propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *rchild;
|
|
|
|
HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
|
|
|
|
bool ret = false;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (is_gimple_reg_type (lacc->type)
|
|
|
|
|| lacc->grp_unscalarizable_region
|
|
|
|
|| racc->grp_unscalarizable_region)
|
|
|
|
return false;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!lacc->first_child && !racc->first_child
|
|
|
|
&& is_gimple_reg_type (racc->type))
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-09-07 19:08:12 +02:00
|
|
|
tree t = lacc->base;
|
2009-09-03 23:25:00 +02:00
|
|
|
|
2009-09-07 19:08:12 +02:00
|
|
|
if (build_ref_for_offset (&t, TREE_TYPE (t), lacc->offset, racc->type,
|
|
|
|
false))
|
|
|
|
{
|
|
|
|
lacc->expr = t;
|
|
|
|
lacc->type = racc->type;
|
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
return false;
|
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
|
|
|
|
{
|
|
|
|
struct access *new_acc = NULL;
|
|
|
|
HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (rchild->grp_unscalarizable_region)
|
|
|
|
continue;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
|
|
|
|
&new_acc))
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-09-02 19:52:18 +02:00
|
|
|
if (new_acc)
|
|
|
|
{
|
|
|
|
rchild->grp_hint = 1;
|
|
|
|
new_acc->grp_hint |= new_acc->grp_read;
|
|
|
|
if (rchild->first_child)
|
2009-10-29 13:40:48 +01:00
|
|
|
ret |= propagate_subaccesses_across_link (new_acc, rchild);
|
2009-09-02 19:52:18 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
continue;
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
|
2009-06-16 12:11:55 +02:00
|
|
|
/* If a (part of) a union field is on the RHS of an assignment, it can
|
2009-06-09 18:52:57 +02:00
|
|
|
have sub-accesses which do not make sense on the LHS (PR 40351).
|
|
|
|
Check that this is not the case. */
|
|
|
|
if (!build_ref_for_offset (NULL, TREE_TYPE (lacc->base), norm_offset,
|
|
|
|
rchild->type, false))
|
|
|
|
continue;
|
|
|
|
|
2009-09-02 19:52:18 +02:00
|
|
|
rchild->grp_hint = 1;
|
2009-05-29 18:47:31 +02:00
|
|
|
new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
|
2009-09-07 19:08:12 +02:00
|
|
|
if (new_acc)
|
|
|
|
{
|
|
|
|
ret = true;
|
|
|
|
if (racc->first_child)
|
2009-10-29 13:40:48 +01:00
|
|
|
propagate_subaccesses_across_link (new_acc, rchild);
|
2009-09-07 19:08:12 +02:00
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Propagate all subaccesses across assignment links. */
|
2007-10-01 18:35:55 +02:00
|
|
|
|
|
|
|
static void
|
2009-05-29 18:47:31 +02:00
|
|
|
propagate_all_subaccesses (void)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
while (work_queue_head)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *racc = pop_access_from_work_queue ();
|
|
|
|
struct assign_link *link;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
gcc_assert (racc->first_link);
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
for (link = racc->first_link; link; link = link->next)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *lacc = link->lacc;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
|
|
|
|
continue;
|
|
|
|
lacc = lacc->group_representative;
|
2009-10-29 13:40:48 +01:00
|
|
|
if (propagate_subaccesses_across_link (lacc, racc)
|
2009-05-29 18:47:31 +02:00
|
|
|
&& lacc->first_link)
|
|
|
|
add_access_to_work_queue (lacc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Go through all accesses collected throughout the (intraprocedural) analysis
|
|
|
|
stage, exclude overlapping ones, identify representatives and build trees
|
|
|
|
out of them, making decisions about scalarization on the way. Return true
|
|
|
|
iff there are any to-be-scalarized variables after this stage. */
|
2007-10-09 06:45:22 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static bool
|
|
|
|
analyze_all_variable_accesses (void)
|
|
|
|
{
|
|
|
|
tree var;
|
|
|
|
referenced_var_iterator rvi;
|
2009-06-18 17:38:36 +02:00
|
|
|
int res = 0;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
FOR_EACH_REFERENCED_VAR (var, rvi)
|
|
|
|
if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
|
|
|
|
{
|
|
|
|
struct access *access;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
access = sort_and_splice_var_accesses (var);
|
|
|
|
if (access)
|
|
|
|
build_access_trees (access);
|
|
|
|
else
|
|
|
|
disqualify_candidate (var,
|
|
|
|
"No or inhibitingly overlapping accesses.");
|
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
propagate_all_subaccesses ();
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
FOR_EACH_REFERENCED_VAR (var, rvi)
|
|
|
|
if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
|
|
|
|
{
|
|
|
|
struct access *access = get_first_repr_for_decl (var);
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (analyze_access_trees (access))
|
|
|
|
{
|
2009-06-18 17:38:36 +02:00
|
|
|
res++;
|
2009-05-29 18:47:31 +02:00
|
|
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
|
|
|
{
|
|
|
|
fprintf (dump_file, "\nAccess trees for ");
|
|
|
|
print_generic_expr (dump_file, var, 0);
|
|
|
|
fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
|
|
|
|
dump_access_tree (dump_file, access);
|
|
|
|
fprintf (dump_file, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
disqualify_candidate (var, "No scalar replacements to be created.");
|
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-06-18 17:38:36 +02:00
|
|
|
if (res)
|
|
|
|
{
|
|
|
|
statistics_counter_event (cfun, "Scalarized aggregates", res);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Return true iff a reference statement into aggregate AGG can be built for
|
|
|
|
every single to-be-replaced accesses that is a child of ACCESS, its sibling
|
|
|
|
or a child of its sibling. TOP_OFFSET is the offset from the processed
|
|
|
|
access subtree that has to be subtracted from offset of each access. */
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static bool
|
|
|
|
ref_expr_for_all_replacements_p (struct access *access, tree agg,
|
|
|
|
HOST_WIDE_INT top_offset)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
do
|
|
|
|
{
|
|
|
|
if (access->grp_to_be_replaced
|
|
|
|
&& !build_ref_for_offset (NULL, TREE_TYPE (agg),
|
|
|
|
access->offset - top_offset,
|
|
|
|
access->type, false))
|
|
|
|
return false;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (access->first_child
|
|
|
|
&& !ref_expr_for_all_replacements_p (access->first_child, agg,
|
|
|
|
top_offset))
|
|
|
|
return false;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
access = access->next_sibling;
|
|
|
|
}
|
|
|
|
while (access);
|
|
|
|
|
|
|
|
return true;
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Generate statements copying scalar replacements of accesses within a subtree
|
|
|
|
into or out of AGG. ACCESS is the first child of the root of the subtree to
|
|
|
|
be processed. AGG is an aggregate type expression (can be a declaration but
|
|
|
|
does not have to be, it can for example also be an indirect_ref).
|
|
|
|
TOP_OFFSET is the offset of the processed subtree which has to be subtracted
|
|
|
|
from offsets of individual accesses to get corresponding offsets for AGG.
|
|
|
|
If CHUNK_SIZE is non-null, copy only replacements in the interval
|
|
|
|
<start_offset, start_offset + chunk_size>, otherwise copy all. GSI is a
|
|
|
|
statement iterator used to place the new statements. WRITE should be true
|
|
|
|
when the statements should write from AGG to the replacement and false if
|
|
|
|
vice versa. if INSERT_AFTER is true, new statements will be added after the
|
|
|
|
current statement in GSI, they will be added before the statement
|
|
|
|
otherwise. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
|
|
|
static void
|
2009-05-29 18:47:31 +02:00
|
|
|
generate_subtree_copies (struct access *access, tree agg,
|
|
|
|
HOST_WIDE_INT top_offset,
|
|
|
|
HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
|
|
|
|
gimple_stmt_iterator *gsi, bool write,
|
|
|
|
bool insert_after)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
do
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-10-29 13:40:48 +01:00
|
|
|
tree expr = agg;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (chunk_size && access->offset >= start_offset + chunk_size)
|
|
|
|
return;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (access->grp_to_be_replaced
|
|
|
|
&& (chunk_size == 0
|
|
|
|
|| access->offset + access->size > start_offset))
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
tree repl = get_access_replacement (access);
|
|
|
|
bool ref_found;
|
|
|
|
gimple stmt;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
ref_found = build_ref_for_offset (&expr, TREE_TYPE (agg),
|
|
|
|
access->offset - top_offset,
|
|
|
|
access->type, false);
|
|
|
|
gcc_assert (ref_found);
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (write)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
if (access->grp_partial_lhs)
|
|
|
|
expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
|
|
|
|
!insert_after,
|
|
|
|
insert_after ? GSI_NEW_STMT
|
|
|
|
: GSI_SAME_STMT);
|
|
|
|
stmt = gimple_build_assign (repl, expr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TREE_NO_WARNING (repl) = 1;
|
|
|
|
if (access->grp_partial_lhs)
|
|
|
|
repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
|
|
|
|
!insert_after,
|
|
|
|
insert_after ? GSI_NEW_STMT
|
|
|
|
: GSI_SAME_STMT);
|
|
|
|
stmt = gimple_build_assign (expr, repl);
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (insert_after)
|
|
|
|
gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
|
2007-11-25 15:45:53 +01:00
|
|
|
else
|
2009-05-29 18:47:31 +02:00
|
|
|
gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
|
|
|
|
update_stmt (stmt);
|
2009-06-30 12:10:29 +02:00
|
|
|
sra_stats.subtree_copies++;
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (access->first_child)
|
|
|
|
generate_subtree_copies (access->first_child, agg, top_offset,
|
|
|
|
start_offset, chunk_size, gsi,
|
|
|
|
write, insert_after);
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
access = access->next_sibling;
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
while (access);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Assign zero to all scalar replacements in an access subtree. ACCESS is the
|
|
|
|
the root of the subtree to be processed. GSI is the statement iterator used
|
|
|
|
for inserting statements which are added after the current statement if
|
|
|
|
INSERT_AFTER is true or before it otherwise. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
|
|
|
|
bool insert_after)
|
|
|
|
|
|
|
|
{
|
|
|
|
struct access *child;
|
|
|
|
|
|
|
|
if (access->grp_to_be_replaced)
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
gimple stmt;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
stmt = gimple_build_assign (get_access_replacement (access),
|
|
|
|
fold_convert (access->type,
|
|
|
|
integer_zero_node));
|
|
|
|
if (insert_after)
|
|
|
|
gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
|
|
|
|
else
|
|
|
|
gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
|
|
|
|
update_stmt (stmt);
|
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
for (child = access->first_child; child; child = child->next_sibling)
|
|
|
|
init_subtree_with_zero (child, gsi, insert_after);
|
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Search for an access representative for the given expression EXPR and
|
|
|
|
return it or NULL if it cannot be found. */
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static struct access *
|
|
|
|
get_access_for_expr (tree expr)
|
|
|
|
{
|
|
|
|
HOST_WIDE_INT offset, size, max_size;
|
|
|
|
tree base;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
|
|
|
|
a different size than the size of its argument and we need the latter
|
|
|
|
one. */
|
|
|
|
if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
|
|
|
|
expr = TREE_OPERAND (expr, 0);
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
|
|
|
|
if (max_size == -1 || !DECL_P (base))
|
|
|
|
return NULL;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return get_var_base_offset_size_access (base, offset, max_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Callback for scan_function. Replace the expression EXPR with a scalar
|
|
|
|
replacement if there is one and generate other statements to do type
|
|
|
|
conversion or subtree copying if necessary. GSI is used to place newly
|
|
|
|
created statements, WRITE is true if the expression is being written to (it
|
|
|
|
is on a LHS of a statement or output in an assembly statement). */
|
|
|
|
|
|
|
|
static bool
|
|
|
|
sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write,
|
|
|
|
void *data ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
struct access *access;
|
|
|
|
tree type, bfr;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (TREE_CODE (*expr) == BIT_FIELD_REF)
|
|
|
|
{
|
|
|
|
bfr = *expr;
|
|
|
|
expr = &TREE_OPERAND (*expr, 0);
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
2004-06-29 18:25:28 +02:00
|
|
|
else
|
2009-05-29 18:47:31 +02:00
|
|
|
bfr = NULL_TREE;
|
|
|
|
|
|
|
|
if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
|
|
|
|
expr = &TREE_OPERAND (*expr, 0);
|
|
|
|
access = get_access_for_expr (*expr);
|
|
|
|
if (!access)
|
|
|
|
return false;
|
|
|
|
type = TREE_TYPE (*expr);
|
|
|
|
|
|
|
|
if (access->grp_to_be_replaced)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
tree repl = get_access_replacement (access);
|
|
|
|
/* If we replace a non-register typed access simply use the original
|
|
|
|
access expression to extract the scalar component afterwards.
|
|
|
|
This happens if scalarizing a function return value or parameter
|
|
|
|
like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
|
2009-11-30 18:59:57 +01:00
|
|
|
gcc.c-torture/compile/20011217-1.c.
|
|
|
|
|
|
|
|
We also want to use this when accessing a complex or vector which can
|
|
|
|
be accessed as a different type too, potentially creating a need for
|
|
|
|
type conversion (see PR42196). */
|
|
|
|
if (!is_gimple_reg_type (type)
|
|
|
|
|| (access->grp_different_types
|
|
|
|
&& (TREE_CODE (type) == COMPLEX_TYPE
|
|
|
|
|| TREE_CODE (type) == VECTOR_TYPE)))
|
2009-05-29 18:47:31 +02:00
|
|
|
{
|
2009-11-24 11:56:14 +01:00
|
|
|
tree ref = access->base;
|
|
|
|
bool ok;
|
|
|
|
|
|
|
|
ok = build_ref_for_offset (&ref, TREE_TYPE (ref),
|
|
|
|
access->offset, access->type, false);
|
|
|
|
gcc_assert (ok);
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (write)
|
|
|
|
{
|
2009-11-24 11:56:14 +01:00
|
|
|
gimple stmt;
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (access->grp_partial_lhs)
|
|
|
|
ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
|
|
|
|
false, GSI_NEW_STMT);
|
|
|
|
stmt = gimple_build_assign (repl, ref);
|
|
|
|
gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-11-24 11:56:14 +01:00
|
|
|
gimple stmt;
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (access->grp_partial_lhs)
|
|
|
|
repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
|
|
|
|
true, GSI_SAME_STMT);
|
2009-11-24 11:56:14 +01:00
|
|
|
stmt = gimple_build_assign (ref, repl);
|
2009-05-29 18:47:31 +02:00
|
|
|
gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
|
|
|
|
}
|
|
|
|
}
|
2007-04-30 19:41:11 +02:00
|
|
|
else
|
2007-04-05 20:50:34 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
gcc_assert (useless_type_conversion_p (type, access->type));
|
|
|
|
*expr = repl;
|
|
|
|
}
|
2009-06-18 17:38:36 +02:00
|
|
|
sra_stats.exprs++;
|
2009-05-29 18:47:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (access->first_child)
|
|
|
|
{
|
|
|
|
HOST_WIDE_INT start_offset, chunk_size;
|
|
|
|
if (bfr
|
|
|
|
&& host_integerp (TREE_OPERAND (bfr, 1), 1)
|
|
|
|
&& host_integerp (TREE_OPERAND (bfr, 2), 1))
|
|
|
|
{
|
2009-06-25 12:38:13 +02:00
|
|
|
chunk_size = tree_low_cst (TREE_OPERAND (bfr, 1), 1);
|
2009-06-30 12:03:26 +02:00
|
|
|
start_offset = access->offset
|
|
|
|
+ tree_low_cst (TREE_OPERAND (bfr, 2), 1);
|
2005-11-21 01:51:39 +01:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
else
|
|
|
|
start_offset = chunk_size = 0;
|
|
|
|
|
|
|
|
generate_subtree_copies (access->first_child, access->base, 0,
|
|
|
|
start_offset, chunk_size, gsi, write, write);
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
return true;
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
|
|
|
|
2009-06-25 12:38:13 +02:00
|
|
|
/* Where scalar replacements of the RHS have been written to when a replacement
|
|
|
|
of a LHS of an assigments cannot be direclty loaded from a replacement of
|
|
|
|
the RHS. */
|
|
|
|
enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
|
|
|
|
SRA_UDH_RIGHT, /* Data flushed to the RHS. */
|
|
|
|
SRA_UDH_LEFT }; /* Data flushed to the LHS. */
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Store all replacements in the access tree rooted in TOP_RACC either to their
|
|
|
|
base aggregate if there are unscalarized data or directly to LHS
|
|
|
|
otherwise. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-06-25 12:38:13 +02:00
|
|
|
static enum unscalarized_data_handling
|
2009-05-29 18:47:31 +02:00
|
|
|
handle_unscalarized_data_in_subtree (struct access *top_racc, tree lhs,
|
|
|
|
gimple_stmt_iterator *gsi)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
if (top_racc->grp_unscalarized_data)
|
2009-06-25 12:38:13 +02:00
|
|
|
{
|
|
|
|
generate_subtree_copies (top_racc->first_child, top_racc->base, 0, 0, 0,
|
|
|
|
gsi, false, false);
|
|
|
|
return SRA_UDH_RIGHT;
|
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
else
|
2009-06-25 12:38:13 +02:00
|
|
|
{
|
|
|
|
generate_subtree_copies (top_racc->first_child, lhs, top_racc->offset,
|
|
|
|
0, 0, gsi, false, false);
|
|
|
|
return SRA_UDH_LEFT;
|
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Try to generate statements to load all sub-replacements in an access
|
|
|
|
(sub)tree (LACC is the first child) from scalar replacements in the TOP_RACC
|
|
|
|
(sub)tree. If that is not possible, refresh the TOP_RACC base aggregate and
|
|
|
|
load the accesses from it. LEFT_OFFSET is the offset of the left whole
|
|
|
|
subtree being copied, RIGHT_OFFSET is the same thing for the right subtree.
|
|
|
|
GSI is stmt iterator used for statement insertions. *REFRESHED is true iff
|
|
|
|
the rhs top aggregate has already been refreshed by contents of its scalar
|
|
|
|
reductions and is set to true if this function has to do it. */
|
2008-07-28 16:33:56 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static void
|
|
|
|
load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
|
|
|
|
HOST_WIDE_INT left_offset,
|
|
|
|
HOST_WIDE_INT right_offset,
|
|
|
|
gimple_stmt_iterator *old_gsi,
|
|
|
|
gimple_stmt_iterator *new_gsi,
|
2009-06-25 12:38:13 +02:00
|
|
|
enum unscalarized_data_handling *refreshed,
|
|
|
|
tree lhs)
|
2009-05-29 18:47:31 +02:00
|
|
|
{
|
re PR c/40435 (Revision 148442 caused many regressions on trunk)
2009-07-17 Aldy Hernandez <aldyh@redhat.com>
Manuel López-Ibáñez <manu@gcc.gnu.org>
PR 40435
* tree-complex.c, tree-loop-distribution.c,
tree.c, tree.h, builtins.c, fold-const.c, omp-low.c,
cgraphunit.c, tree-ssa-ccp.c, tree-ssa-dom.c,
gimple-low.c, expr.c, tree-ssa-ifcombine.c, c-decl.c,
stor-layout.c, tree-if-conv.c, c-typeck.c,
gimplify.c, calls.c, tree-sra.c, tree-mudflap.c,
tree-ssa-copy.c, tree-ssa-forwprop.c, c-convert.c, c-omp.c,
varasm.c, tree-inline.c, c-common.c,
c-common.h, gimple.c, tree-switch-conversion.c, gimple.h,
tree-cfg.c, c-parser.c, convert.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
objc/
* objc-act.c: Add location argument to all calls to
build_fold_addr_expr.
testsuite/
* gcc.dg/pr36902.c: Add column info.
* g++.dg/gcov/gcov-2.C: Change count for definition.
cp/
* typeck.c, init.c, class.c, method.c, rtti.c, except.c, error.c,
tree.c, cp-gimplify.c, cxx-pretty-print.c, pt.c, semantics.c,
call.c, cvt.c, mangle.c: Add location argument to
fold_{unary,binary,ternary}, fold_build[123], build_call_expr,
build_size_arg, build_fold_addr_expr, build_call_array,
non_lvalue, size_diffop, fold_build1_initializer,
fold_build2_initializer, fold_build3_initializer,
fold_build_call_array, fold_build_call_array_initializer,
fold_single_bit_test, omit_one_operand, omit_two_operands,
invert_truthvalue, fold_truth_not_expr, build_fold_indirect_ref,
fold_indirect_ref, combine_comparisons, fold_builtin_*,
fold_call_expr, build_range_check, maybe_fold_offset_to_address,
round_up, round_down.
fortran/
* trans-expr.c, trans-array.c, trans-openmp.c, trans-stmt.c,
trans.c, trans-io.c, trans-decl.c, trans-intrinsic.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
Co-Authored-By: Manuel López-Ibáñez <manu@gcc.gnu.org>
From-SVN: r149722
2009-07-17 00:29:52 +02:00
|
|
|
location_t loc = EXPR_LOCATION (lacc->expr);
|
2009-05-29 18:47:31 +02:00
|
|
|
do
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
if (lacc->grp_to_be_replaced)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *racc;
|
|
|
|
HOST_WIDE_INT offset = lacc->offset - left_offset + right_offset;
|
|
|
|
gimple stmt;
|
|
|
|
tree rhs;
|
|
|
|
|
|
|
|
racc = find_access_in_subtree (top_racc, offset, lacc->size);
|
|
|
|
if (racc && racc->grp_to_be_replaced)
|
|
|
|
{
|
|
|
|
rhs = get_access_replacement (racc);
|
|
|
|
if (!useless_type_conversion_p (lacc->type, racc->type))
|
re PR c/40435 (Revision 148442 caused many regressions on trunk)
2009-07-17 Aldy Hernandez <aldyh@redhat.com>
Manuel López-Ibáñez <manu@gcc.gnu.org>
PR 40435
* tree-complex.c, tree-loop-distribution.c,
tree.c, tree.h, builtins.c, fold-const.c, omp-low.c,
cgraphunit.c, tree-ssa-ccp.c, tree-ssa-dom.c,
gimple-low.c, expr.c, tree-ssa-ifcombine.c, c-decl.c,
stor-layout.c, tree-if-conv.c, c-typeck.c,
gimplify.c, calls.c, tree-sra.c, tree-mudflap.c,
tree-ssa-copy.c, tree-ssa-forwprop.c, c-convert.c, c-omp.c,
varasm.c, tree-inline.c, c-common.c,
c-common.h, gimple.c, tree-switch-conversion.c, gimple.h,
tree-cfg.c, c-parser.c, convert.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
objc/
* objc-act.c: Add location argument to all calls to
build_fold_addr_expr.
testsuite/
* gcc.dg/pr36902.c: Add column info.
* g++.dg/gcov/gcov-2.C: Change count for definition.
cp/
* typeck.c, init.c, class.c, method.c, rtti.c, except.c, error.c,
tree.c, cp-gimplify.c, cxx-pretty-print.c, pt.c, semantics.c,
call.c, cvt.c, mangle.c: Add location argument to
fold_{unary,binary,ternary}, fold_build[123], build_call_expr,
build_size_arg, build_fold_addr_expr, build_call_array,
non_lvalue, size_diffop, fold_build1_initializer,
fold_build2_initializer, fold_build3_initializer,
fold_build_call_array, fold_build_call_array_initializer,
fold_single_bit_test, omit_one_operand, omit_two_operands,
invert_truthvalue, fold_truth_not_expr, build_fold_indirect_ref,
fold_indirect_ref, combine_comparisons, fold_builtin_*,
fold_call_expr, build_range_check, maybe_fold_offset_to_address,
round_up, round_down.
fortran/
* trans-expr.c, trans-array.c, trans-openmp.c, trans-stmt.c,
trans.c, trans-io.c, trans-decl.c, trans-intrinsic.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
Co-Authored-By: Manuel López-Ibáñez <manu@gcc.gnu.org>
From-SVN: r149722
2009-07-17 00:29:52 +02:00
|
|
|
rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, lacc->type, rhs);
|
2009-05-29 18:47:31 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* No suitable access on the right hand side, need to load from
|
|
|
|
the aggregate. See if we have to update it first... */
|
2009-06-25 12:38:13 +02:00
|
|
|
if (*refreshed == SRA_UDH_NONE)
|
|
|
|
*refreshed = handle_unscalarized_data_in_subtree (top_racc,
|
|
|
|
lhs, old_gsi);
|
|
|
|
|
|
|
|
if (*refreshed == SRA_UDH_LEFT)
|
2009-11-24 11:56:14 +01:00
|
|
|
{
|
|
|
|
bool repl_found;
|
|
|
|
|
|
|
|
rhs = lacc->base;
|
|
|
|
repl_found = build_ref_for_offset (&rhs, TREE_TYPE (rhs),
|
|
|
|
lacc->offset, lacc->type,
|
|
|
|
false);
|
|
|
|
gcc_assert (repl_found);
|
|
|
|
}
|
2009-06-25 12:38:13 +02:00
|
|
|
else
|
2009-05-29 18:47:31 +02:00
|
|
|
{
|
2009-11-24 11:56:14 +01:00
|
|
|
bool repl_found;
|
|
|
|
|
2009-10-29 13:40:48 +01:00
|
|
|
rhs = top_racc->base;
|
2009-06-25 12:38:13 +02:00
|
|
|
repl_found = build_ref_for_offset (&rhs,
|
|
|
|
TREE_TYPE (top_racc->base),
|
|
|
|
offset, lacc->type, false);
|
|
|
|
gcc_assert (repl_found);
|
2009-05-29 18:47:31 +02:00
|
|
|
}
|
|
|
|
}
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
|
|
|
|
gsi_insert_after (new_gsi, stmt, GSI_NEW_STMT);
|
|
|
|
update_stmt (stmt);
|
2009-06-18 17:38:36 +02:00
|
|
|
sra_stats.subreplacements++;
|
2009-05-29 18:47:31 +02:00
|
|
|
}
|
2009-06-25 12:38:13 +02:00
|
|
|
else if (*refreshed == SRA_UDH_NONE
|
|
|
|
&& lacc->grp_read && !lacc->grp_covered)
|
|
|
|
*refreshed = handle_unscalarized_data_in_subtree (top_racc, lhs,
|
|
|
|
old_gsi);
|
2009-05-29 18:47:31 +02:00
|
|
|
|
|
|
|
if (lacc->first_child)
|
|
|
|
load_assign_lhs_subreplacements (lacc->first_child, top_racc,
|
|
|
|
left_offset, right_offset,
|
|
|
|
old_gsi, new_gsi, refreshed, lhs);
|
|
|
|
lacc = lacc->next_sibling;
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
while (lacc);
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
|
|
|
|
to the assignment and GSI is the statement iterator pointing at it. Returns
|
|
|
|
the same values as sra_modify_assign. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
static enum scan_assign_result
|
|
|
|
sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
tree lhs = gimple_assign_lhs (*stmt);
|
|
|
|
struct access *acc;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
acc = get_access_for_expr (lhs);
|
|
|
|
if (!acc)
|
|
|
|
return SRA_SA_NONE;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (VEC_length (constructor_elt,
|
|
|
|
CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
|
2008-08-18 10:40:32 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
/* I have never seen this code path trigger but if it can happen the
|
|
|
|
following should handle it gracefully. */
|
|
|
|
if (access_has_children_p (acc))
|
|
|
|
generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
|
|
|
|
true, true);
|
|
|
|
return SRA_SA_PROCESSED;
|
2008-08-18 10:40:32 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (acc->grp_covered)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
init_subtree_with_zero (acc, gsi, false);
|
|
|
|
unlink_stmt_vdef (*stmt);
|
|
|
|
gsi_remove (gsi, true);
|
|
|
|
return SRA_SA_REMOVED;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
init_subtree_with_zero (acc, gsi, true);
|
|
|
|
return SRA_SA_PROCESSED;
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Callback of scan_function to process assign statements. It examines both
|
|
|
|
sides of the statement, replaces them with a scalare replacement if there is
|
|
|
|
one and generating copying of replacements if scalarized aggregates have been
|
|
|
|
used in the assignment. STMT is a pointer to the assign statement, GSI is
|
|
|
|
used to hold generated statements for type conversions and subtree
|
|
|
|
copying. */
|
|
|
|
|
|
|
|
static enum scan_assign_result
|
|
|
|
sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
|
|
|
|
void *data ATTRIBUTE_UNUSED)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
struct access *lacc, *racc;
|
|
|
|
tree lhs, rhs;
|
|
|
|
bool modify_this_stmt = false;
|
|
|
|
bool force_gimple_rhs = false;
|
re PR c/40435 (Revision 148442 caused many regressions on trunk)
2009-07-17 Aldy Hernandez <aldyh@redhat.com>
Manuel López-Ibáñez <manu@gcc.gnu.org>
PR 40435
* tree-complex.c, tree-loop-distribution.c,
tree.c, tree.h, builtins.c, fold-const.c, omp-low.c,
cgraphunit.c, tree-ssa-ccp.c, tree-ssa-dom.c,
gimple-low.c, expr.c, tree-ssa-ifcombine.c, c-decl.c,
stor-layout.c, tree-if-conv.c, c-typeck.c,
gimplify.c, calls.c, tree-sra.c, tree-mudflap.c,
tree-ssa-copy.c, tree-ssa-forwprop.c, c-convert.c, c-omp.c,
varasm.c, tree-inline.c, c-common.c,
c-common.h, gimple.c, tree-switch-conversion.c, gimple.h,
tree-cfg.c, c-parser.c, convert.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
objc/
* objc-act.c: Add location argument to all calls to
build_fold_addr_expr.
testsuite/
* gcc.dg/pr36902.c: Add column info.
* g++.dg/gcov/gcov-2.C: Change count for definition.
cp/
* typeck.c, init.c, class.c, method.c, rtti.c, except.c, error.c,
tree.c, cp-gimplify.c, cxx-pretty-print.c, pt.c, semantics.c,
call.c, cvt.c, mangle.c: Add location argument to
fold_{unary,binary,ternary}, fold_build[123], build_call_expr,
build_size_arg, build_fold_addr_expr, build_call_array,
non_lvalue, size_diffop, fold_build1_initializer,
fold_build2_initializer, fold_build3_initializer,
fold_build_call_array, fold_build_call_array_initializer,
fold_single_bit_test, omit_one_operand, omit_two_operands,
invert_truthvalue, fold_truth_not_expr, build_fold_indirect_ref,
fold_indirect_ref, combine_comparisons, fold_builtin_*,
fold_call_expr, build_range_check, maybe_fold_offset_to_address,
round_up, round_down.
fortran/
* trans-expr.c, trans-array.c, trans-openmp.c, trans-stmt.c,
trans.c, trans-io.c, trans-decl.c, trans-intrinsic.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
Co-Authored-By: Manuel López-Ibáñez <manu@gcc.gnu.org>
From-SVN: r149722
2009-07-17 00:29:52 +02:00
|
|
|
location_t loc = gimple_location (*stmt);
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!gimple_assign_single_p (*stmt))
|
|
|
|
return SRA_SA_NONE;
|
|
|
|
lhs = gimple_assign_lhs (*stmt);
|
|
|
|
rhs = gimple_assign_rhs1 (*stmt);
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (TREE_CODE (rhs) == CONSTRUCTOR)
|
|
|
|
return sra_modify_constructor_assign (stmt, gsi);
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
|
|
|
|
|| TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
|
|
|
|
|| TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
|
|
|
|
{
|
|
|
|
modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
|
|
|
|
gsi, false, data);
|
|
|
|
modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
|
|
|
|
gsi, true, data);
|
|
|
|
return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
lacc = get_access_for_expr (lhs);
|
|
|
|
racc = get_access_for_expr (rhs);
|
|
|
|
if (!lacc && !racc)
|
|
|
|
return SRA_SA_NONE;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (lacc && lacc->grp_to_be_replaced)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
lhs = get_access_replacement (lacc);
|
|
|
|
gimple_assign_set_lhs (*stmt, lhs);
|
|
|
|
modify_this_stmt = true;
|
|
|
|
if (lacc->grp_partial_lhs)
|
|
|
|
force_gimple_rhs = true;
|
2009-06-18 17:38:36 +02:00
|
|
|
sra_stats.exprs++;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (racc && racc->grp_to_be_replaced)
|
|
|
|
{
|
|
|
|
rhs = get_access_replacement (racc);
|
|
|
|
modify_this_stmt = true;
|
|
|
|
if (racc->grp_partial_lhs)
|
|
|
|
force_gimple_rhs = true;
|
2009-06-18 17:38:36 +02:00
|
|
|
sra_stats.exprs++;
|
2009-05-29 18:47:31 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (modify_this_stmt)
|
|
|
|
{
|
|
|
|
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
/* If we can avoid creating a VIEW_CONVERT_EXPR do so.
|
|
|
|
??? This should move to fold_stmt which we simply should
|
|
|
|
call after building a VIEW_CONVERT_EXPR here. */
|
|
|
|
if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
|
|
|
|
&& !access_has_children_p (lacc))
|
|
|
|
{
|
2009-10-29 13:40:48 +01:00
|
|
|
tree expr = lhs;
|
2009-06-22 12:54:16 +02:00
|
|
|
if (build_ref_for_offset (&expr, TREE_TYPE (lhs), 0,
|
2009-05-29 18:47:31 +02:00
|
|
|
TREE_TYPE (rhs), false))
|
|
|
|
{
|
|
|
|
lhs = expr;
|
|
|
|
gimple_assign_set_lhs (*stmt, expr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
|
|
|
|
&& !access_has_children_p (racc))
|
2007-10-01 18:35:55 +02:00
|
|
|
{
|
2009-10-29 13:40:48 +01:00
|
|
|
tree expr = rhs;
|
2009-06-22 12:54:16 +02:00
|
|
|
if (build_ref_for_offset (&expr, TREE_TYPE (rhs), 0,
|
2009-05-29 18:47:31 +02:00
|
|
|
TREE_TYPE (lhs), false))
|
|
|
|
rhs = expr;
|
2007-10-01 18:35:55 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
|
2009-06-16 12:16:40 +02:00
|
|
|
{
|
re PR c/40435 (Revision 148442 caused many regressions on trunk)
2009-07-17 Aldy Hernandez <aldyh@redhat.com>
Manuel López-Ibáñez <manu@gcc.gnu.org>
PR 40435
* tree-complex.c, tree-loop-distribution.c,
tree.c, tree.h, builtins.c, fold-const.c, omp-low.c,
cgraphunit.c, tree-ssa-ccp.c, tree-ssa-dom.c,
gimple-low.c, expr.c, tree-ssa-ifcombine.c, c-decl.c,
stor-layout.c, tree-if-conv.c, c-typeck.c,
gimplify.c, calls.c, tree-sra.c, tree-mudflap.c,
tree-ssa-copy.c, tree-ssa-forwprop.c, c-convert.c, c-omp.c,
varasm.c, tree-inline.c, c-common.c,
c-common.h, gimple.c, tree-switch-conversion.c, gimple.h,
tree-cfg.c, c-parser.c, convert.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
objc/
* objc-act.c: Add location argument to all calls to
build_fold_addr_expr.
testsuite/
* gcc.dg/pr36902.c: Add column info.
* g++.dg/gcov/gcov-2.C: Change count for definition.
cp/
* typeck.c, init.c, class.c, method.c, rtti.c, except.c, error.c,
tree.c, cp-gimplify.c, cxx-pretty-print.c, pt.c, semantics.c,
call.c, cvt.c, mangle.c: Add location argument to
fold_{unary,binary,ternary}, fold_build[123], build_call_expr,
build_size_arg, build_fold_addr_expr, build_call_array,
non_lvalue, size_diffop, fold_build1_initializer,
fold_build2_initializer, fold_build3_initializer,
fold_build_call_array, fold_build_call_array_initializer,
fold_single_bit_test, omit_one_operand, omit_two_operands,
invert_truthvalue, fold_truth_not_expr, build_fold_indirect_ref,
fold_indirect_ref, combine_comparisons, fold_builtin_*,
fold_call_expr, build_range_check, maybe_fold_offset_to_address,
round_up, round_down.
fortran/
* trans-expr.c, trans-array.c, trans-openmp.c, trans-stmt.c,
trans.c, trans-io.c, trans-decl.c, trans-intrinsic.c: Add location
argument to fold_{unary,binary,ternary}, fold_build[123],
build_call_expr, build_size_arg, build_fold_addr_expr,
build_call_array, non_lvalue, size_diffop,
fold_build1_initializer, fold_build2_initializer,
fold_build3_initializer, fold_build_call_array,
fold_build_call_array_initializer, fold_single_bit_test,
omit_one_operand, omit_two_operands, invert_truthvalue,
fold_truth_not_expr, build_fold_indirect_ref, fold_indirect_ref,
combine_comparisons, fold_builtin_*, fold_call_expr,
build_range_check, maybe_fold_offset_to_address, round_up,
round_down.
Co-Authored-By: Manuel López-Ibáñez <manu@gcc.gnu.org>
From-SVN: r149722
2009-07-17 00:29:52 +02:00
|
|
|
rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
|
2009-12-13 18:36:20 +01:00
|
|
|
if (is_gimple_reg_type (TREE_TYPE (lhs))
|
|
|
|
&& TREE_CODE (lhs) != SSA_NAME)
|
2009-06-16 12:16:40 +02:00
|
|
|
force_gimple_rhs = true;
|
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
}
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (force_gimple_rhs)
|
|
|
|
rhs = force_gimple_operand_gsi (gsi, rhs, true, NULL_TREE,
|
|
|
|
true, GSI_SAME_STMT);
|
|
|
|
if (gimple_assign_rhs1 (*stmt) != rhs)
|
|
|
|
{
|
|
|
|
gimple_assign_set_rhs_from_tree (gsi, rhs);
|
|
|
|
gcc_assert (*stmt == gsi_stmt (*gsi));
|
|
|
|
}
|
|
|
|
}
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* From this point on, the function deals with assignments in between
|
|
|
|
aggregates when at least one has scalar reductions of some of its
|
|
|
|
components. There are three possible scenarios: Both the LHS and RHS have
|
|
|
|
to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
|
|
|
|
|
|
|
|
In the first case, we would like to load the LHS components from RHS
|
|
|
|
components whenever possible. If that is not possible, we would like to
|
|
|
|
read it directly from the RHS (after updating it by storing in it its own
|
|
|
|
components). If there are some necessary unscalarized data in the LHS,
|
|
|
|
those will be loaded by the original assignment too. If neither of these
|
|
|
|
cases happen, the original statement can be removed. Most of this is done
|
|
|
|
by load_assign_lhs_subreplacements.
|
|
|
|
|
|
|
|
In the second case, we would like to store all RHS scalarized components
|
|
|
|
directly into LHS and if they cover the aggregate completely, remove the
|
|
|
|
statement too. In the third case, we want the LHS components to be loaded
|
|
|
|
directly from the RHS (DSE will remove the original statement if it
|
|
|
|
becomes redundant).
|
|
|
|
|
|
|
|
This is a bit complex but manageable when types match and when unions do
|
|
|
|
not cause confusion in a way that we cannot really load a component of LHS
|
|
|
|
from the RHS or vice versa (the access representing this level can have
|
|
|
|
subaccesses that are accessible only through a different union field at a
|
|
|
|
higher level - different from the one used in the examined expression).
|
|
|
|
Unions are fun.
|
|
|
|
|
|
|
|
Therefore, I specially handle a fourth case, happening when there is a
|
|
|
|
specific type cast or it is impossible to locate a scalarized subaccess on
|
|
|
|
the other side of the expression. If that happens, I simply "refresh" the
|
|
|
|
RHS by storing in it is scalarized components leave the original statement
|
|
|
|
there to do the copying and then load the scalar replacements of the LHS.
|
|
|
|
This is what the first branch does. */
|
|
|
|
|
|
|
|
if (contains_view_convert_expr_p (rhs) || contains_view_convert_expr_p (lhs)
|
|
|
|
|| (access_has_children_p (racc)
|
|
|
|
&& !ref_expr_for_all_replacements_p (racc, lhs, racc->offset))
|
|
|
|
|| (access_has_children_p (lacc)
|
|
|
|
&& !ref_expr_for_all_replacements_p (lacc, rhs, lacc->offset)))
|
|
|
|
{
|
|
|
|
if (access_has_children_p (racc))
|
|
|
|
generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
|
|
|
|
gsi, false, false);
|
|
|
|
if (access_has_children_p (lacc))
|
|
|
|
generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
|
|
|
|
gsi, true, true);
|
2009-06-18 17:38:36 +02:00
|
|
|
sra_stats.separate_lhs_rhs_handling++;
|
2009-05-29 18:47:31 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (access_has_children_p (lacc) && access_has_children_p (racc))
|
|
|
|
{
|
|
|
|
gimple_stmt_iterator orig_gsi = *gsi;
|
2009-06-25 12:38:13 +02:00
|
|
|
enum unscalarized_data_handling refreshed;
|
2007-10-01 18:35:55 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (lacc->grp_read && !lacc->grp_covered)
|
2009-06-25 12:38:13 +02:00
|
|
|
refreshed = handle_unscalarized_data_in_subtree (racc, lhs, gsi);
|
2009-05-29 18:47:31 +02:00
|
|
|
else
|
2009-06-25 12:38:13 +02:00
|
|
|
refreshed = SRA_UDH_NONE;
|
2004-08-19 23:34:37 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
load_assign_lhs_subreplacements (lacc->first_child, racc,
|
|
|
|
lacc->offset, racc->offset,
|
|
|
|
&orig_gsi, gsi, &refreshed, lhs);
|
2009-06-25 12:38:13 +02:00
|
|
|
if (refreshed != SRA_UDH_RIGHT)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
if (*stmt == gsi_stmt (*gsi))
|
|
|
|
gsi_next (gsi);
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
unlink_stmt_vdef (*stmt);
|
|
|
|
gsi_remove (&orig_gsi, true);
|
2009-06-18 17:38:36 +02:00
|
|
|
sra_stats.deleted++;
|
2009-05-29 18:47:31 +02:00
|
|
|
return SRA_SA_REMOVED;
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
2004-06-29 18:25:28 +02:00
|
|
|
else
|
2009-05-29 18:47:31 +02:00
|
|
|
{
|
|
|
|
if (access_has_children_p (racc))
|
|
|
|
{
|
|
|
|
if (!racc->grp_unscalarized_data)
|
|
|
|
{
|
|
|
|
generate_subtree_copies (racc->first_child, lhs,
|
|
|
|
racc->offset, 0, 0, gsi,
|
|
|
|
false, false);
|
|
|
|
gcc_assert (*stmt == gsi_stmt (*gsi));
|
|
|
|
unlink_stmt_vdef (*stmt);
|
|
|
|
gsi_remove (gsi, true);
|
2009-06-18 17:38:36 +02:00
|
|
|
sra_stats.deleted++;
|
2009-05-29 18:47:31 +02:00
|
|
|
return SRA_SA_REMOVED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
generate_subtree_copies (racc->first_child, lhs,
|
|
|
|
racc->offset, 0, 0, gsi, false, true);
|
|
|
|
}
|
|
|
|
else if (access_has_children_p (lacc))
|
|
|
|
generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
|
|
|
|
0, 0, gsi, true, true);
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
2009-05-29 18:47:31 +02:00
|
|
|
return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Generate statements initializing scalar replacements of parts of function
|
|
|
|
parameters. */
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2004-06-29 18:25:28 +02:00
|
|
|
static void
|
2009-05-29 18:47:31 +02:00
|
|
|
initialize_parameter_reductions (void)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
gimple_stmt_iterator gsi;
|
2008-07-28 16:33:56 +02:00
|
|
|
gimple_seq seq = NULL;
|
2009-05-29 18:47:31 +02:00
|
|
|
tree parm;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
for (parm = DECL_ARGUMENTS (current_function_decl);
|
|
|
|
parm;
|
|
|
|
parm = TREE_CHAIN (parm))
|
backport: copy-prop, incremental SSA updating of FUD chains and newly exposed symbols.
Merge from tree-cleanup-branch: VRP, store CCP, store
copy-prop, incremental SSA updating of FUD chains and
newly exposed symbols.
* Makefile.in (tree-ssa-copy.o): Depend on tree-ssa-propagate.h.
(OBJS-common): Add tree-vrp.o.
(tree-vrp.o): New rule.
* basic-block.h (nearest_common_dominator_for_set): Declare.
* common.opt (ftree-store-ccp): New flag.
(ftree-copy-prop): New flag.
(ftree-vrp): New flag.
(ftree-store-copy-prop): New flag.
* dominance.c (nearest_common_dominator_for_set): New.
* domwalk.c (walk_dominator_tree): Only traverse
statements in blocks marked in walk_data->interesting_blocks.
* domwalk.h (struct dom_walk_data): Add field interesting_blocks.
* fold-const.c (fold): Handle ASSERT_EXPR.
* opts.c (decode_options): Set flag_tree_copy_prop at -O1.
Set flag_tree_store_ccp, flag_tree_store_copy_prop and
flag_tree_vrp at -O2.
* timevar.def (TV_TREE_VRP): Define.
(TV_TREE_COPY_PROP): Define.
(TV_TREE_STORE_COPY_PROP): Define.
(TV_TREE_SSA_INCREMENTAL): Define.
(TV_TREE_STORE_CCP): Define.
* tree-cfg.c (tree_can_merge_blocks_p): Remove reference
to kill_redundant_phi_nodes from comment.
(verify_expr): Handle ASSERT_EXPR.
* tree-dfa.c (mark_new_vars_to_rename): Remove second
argument. Update all users.
(mark_call_clobbered_vars_to_rename): Remove. Update all
users.
* tree-flow-inline.h (unmodifiable_var_p): New.
* tree-flow.h (enum value_range_type): Declare.
(struct value_range_def): Declare.
(value_range): Declare.
(remove_all_phi_nodes_for): Remove. Update all users.
(find_phi_node_for): Declare.
(add_type_alias): Declare.
(count_uses_and_derefs): Declare.
(kill_redundant_phi_nodes): Remove.
(rewrite_into_ssa): Remove.
(rewrite_def_def_chains): Remove.
(update_ssa, register_new_name_mapping, create_new_def_for,
need_ssa_update_p, name_registered_for_update_p,
release_ssa_name_after_update_ssa, dump_repl_tbl,
debug_repl_tbl, dump_names_replaced_by,
debug_names_replaced_by, mark_sym_for_renaming,
mark_set_for_renaming, get_current_def, set_current_def,
get_value_range, dump_value_range, debug_value_range,
dump_all_value_ranges, debug_all_value_ranges,
expr_computes_nonzero, loop_depth_of_name,
unmodifiable_var_p): Declare.
* tree-gimple.c (is_gimple_formal_tmp_rhs): Handle
ASSERT_EXPR.
* tree-into-ssa.c (block_defs_stack): Update comment.
(old_ssa_names, new_ssa_names, old_virtual_ssa_names,
syms_to_rename, names_to_release, repl_tbl,
need_to_initialize_update_ssa_p, need_to_update_vops_p,
need_to_replace_names_p): New locals.
(NAME_SETS_GROWTH_FACTOR): Define.
(struct repl_map_d): Declare.
(struct mark_def_sites_global_data): Add field
interesting_blocks.
(enum rewrite_mode): Declare.
(REGISTER_DEFS_IN_THIS_STMT): Define.
(compute_global_livein): Use last_basic_block instead of
n_basic_blocks.
(set_def_block): Remove last argument. Update all callers.
(prepare_use_operand_for_rename): Remove. Update all callers.
(prepare_def_operand_for_rename): Remove. Update all callers.
(symbol_marked_for_renaming): New.
(is_old_name): New.
(is_new_name): New.
(repl_map_hash): New.
(repl_map_eq): New.
(repl_map_free): New.
(names_replaced_by): New.
(add_to_repl_tbl): New.
(add_new_name_mapping): New.
(mark_def_sites): Assume that all the operands in the
statement are in normal form.
(find_idf): Assert that the block in the stack is valid.
(get_default_def_for): New.
(insert_phi_nodes_for): Add new argument 'update_p'.
Add documentation.
If update_p is true, add a new mapping between the LHS of
each new PHI and the name that it replaces.
(insert_phi_nodes_1): Only call find_idf if needed.
(get_reaching_def): Call get_default_def_for.
(rewrite_operand): Remove.
(rewrite_stmt): Do nothing if REGISTER_DEFS_IN_THIS_STMT
and REWRITE_THIS_STMT are false.
Assume that all the operands in the statement are in
normal form.
(rewrite_add_phi_arguments): Don't use PHI_REWRITTEN.
(rewrite_virtual_phi_arguments): Remove.
(invalidate_name_tags): Remove.
(register_new_update_single, register_new_update_set,
rewrite_update_init_block, replace_use,
rewrite_update_fini_block, rewrite_update_stmt,
rewrite_update_phi_arguments): New.
rewrite_blocks): Remove argument 'fix_virtual_phis'.
Add arguments 'entry', 'what' and 'blocks'.
Initialize the dominator walker according to 'what' and
'blocks'.
Start the dominator walk at 'entry'.
(mark_def_site_blocks): Add argument 'interesting_blocks'.
Use it to configure the dominator walker.
(rewrite_into_ssa): Remove argument 'all'.
Make internal.
(rewrite_all_into_ssa): Remove.
(rewrite_def_def_chains): Remove.
(mark_def_interesting, mark_use_interesting,
prepare_phi_args_for_update, prepare_block_for_update,
prepare_def_site_for, prepare_def_sites,
dump_names_replaced_by, debug_names_replaced_by,
dump_repl_tbl, debug_repl_tbl, init_update_ssa,
delete_update_ssa, create_new_def_for,
register_new_name_mapping, mark_sym_for_renaming,
mark_set_for_renaming, need_ssa_update_p,
name_registered_for_update_p, ssa_names_to_replace,
release_ssa_name_after_update_ssa,
insert_updated_phi_nodes_for, update_ssa): New.
* tree-loop-linear.c (linear_transform_loops): Call
update_ssa instead of rewrite_into_ssa.
* tree-optimize.c (vars_to_rename): Remove.
Update all users.
(init_tree_optimization_passes): Replace
pass_redundant_phi with pass_copy_prop.
Add pass_vrp.
Replace pass_ccp with pass_store_ccp.
Add pass_store_copy_prop after pass_store_ccp.
(execute_todo): If the TODO_ flags don't include updating
the SSA form, assert that it does not need to be updated.
Call update_ssa instead of rewrite_into_ssa and
rewrite_def_def_chains.
If TODO_verify_loops is set, call verify_loop_closed_ssa.
(tree_rest_of_compilation):
* tree-pass.h (TODO_dump_func, TODO_ggc_collect,
TODO_verify_ssa, TODO_verify_flow, TODO_verify_stmts,
TODO_cleanup_cfg): Renumber.
(TODO_verify_loops, TODO_update_ssa,
TODO_update_ssa_no_phi, TODO_update_ssa_full_phi,
TODO_update_ssa_only_virtuals): Define.
(pass_copy_prop, pass_store_ccp, pass_store_copy_prop, pass_vrp):
Declare.
* tree-phinodes.c (make_phi_node): Update documentation.
(remove_all_phi_nodes_for): Remove.
(find_phi_node_for): New.
* tree-pretty-print.c (dump_generic_node): Handle ASSERT_EXPR.
* tree-scalar-evolution.c (follow_ssa_edge_in_rhs): Likewise.
(interpret_rhs_modify_expr): Likewise.
* tree-sra.c (decide_instantiations): Mark all symbols in
SRA_CANDIDATES for renaming.
(mark_all_v_defs_1): Rename from mark_all_v_defs.
(mark_all_v_defs): New function. Update all users to call it
with the whole list of scalarized statements, not just the
first one.
* tree-ssa-alias.c (count_ptr_derefs): Make extern.
(compute_flow_insensitive_aliasing): If the tag is
unmodifiable and the variable isn't or vice-versa, don't
make them alias of each other.
(setup_pointers_and_addressables): If the type tag for
VAR is about to change, mark the old one for renaming.
(add_type_alias): New.
* tree-ssa-ccp.c: Document SSA-CCP and STORE-CCP.
(ccp_lattice_t): Rename from latticevalue.
(value): Remove. Update all users.
(const_val): New local variable.
(do_store_ccp): New local variable.
(dump_lattice_value): Handle UNINITIALIZED.
(debug_lattice_value): New.
(get_default_value): Re-write.
(set_lattice_value): Re-write.
(def_to_varying): Remove. Update all users.
(likely_value): Return VARYING for statements that make
stores when STORE_CCP is false.
Return VARYING for any statement other than MODIFY_EXPR,
COND_EXPR and SWITCH_EXPR.
(ccp_initialize): Re-write.
(replace_uses_in, replace_vuse_in, substitute_and_fold):
Move to tree-ssa-propagate.c.
(ccp_lattice_meet): Handle memory stores when
DO_STORE_CCP is true.
(ccp_visit_phi_node): Likewise.
(ccp_fold): Likewise.
(evaluate_stmt): Likewise.
(visit_assignment): Likewise.
(ccp_visit_stmt): Likewise.
(execute_ssa_ccp): Add argument 'store_ccp'. Copy it
into DO_STORE_CCP.
(do_ssa_ccp): New.
(pass_ccp): Use it.
(do_ssa_store_ccp): New.
(gate_store_ccp): New.
(pass_store_ccp): Declare.
* tree-ssa-copy.c: Include tree-ssa-propagate.h.
(may_propagate_copy): Reformat.
Don't abort if ORIG is a virtual and DEST isn't.
If NEW does not have alias information but DEST does,
copy it.
(copy_of, cached_last_copy_of, do_store_copy_prop, enum
copy_prop_kind, which_copy_prop): Declare.
(stmt_may_generate_copy, get_copy_of_val,
get_last_copy_of, set_copy_of_val, dump_copy_of,
copy_prop_visit_assignment, copy_prop_visit_cond_stmt,
copy_prop_visit_stmt, copy_prop_visit_phi_node,
init_copy_prop, fini_copy_prop, execute_copy_prop,
gate_copy_prop, do_copy_prop, gate_store_copy_prop,
store_copy_prop): New.
(pass_copy_prop, pass_store_copy_prop): Declare.
* tree-ssa-dom.c (struct opt_stats_d): Add fields
'num_const_prop' and 'num_copy_prop'.
(cprop_operand): Update them.
(dump_dominator_optimization_stats): Dump them.
(tree_ssa_dominator_optimize): Call update_ssa instead of
rewrite_into_ssa.
(loop_depth_of_name): Declare extern.
(simplify_cond_and_lookup_avail_expr): Guard against NULL
values for LOW or HIGH.
(cprop_into_successor_phis): Only propagate if NEW != ORIG.
(record_equivalences_from_stmt): Call expr_computes_nonzero.
(cprop_operand): Only propagate if VAL != OP.
* tree-ssa-dse.c (dse_optimize_stmt): Mark symbols in removed
statement for renaming.
* tree-ssa-loop-im.c (move_computations): Call update_ssa.
* tree-ssa-loop-ivopts.c (rewrite_address_base): Call
add_type_alias if necessary.
Call mark_new_vars_to_rename.
(tree_ssa_iv_optimize): If new symbols need to be renamed,
mark every statement updated, call update_ssa and
rewrite_into_loop_closed_ssa.
* tree-ssa-loop-manip.c (add_exit_phis): Do not remove DEF_BB
from LIVEIN if VAR is a virtual.
* tree-ssa-loop.c (tree_loop_optimizer_init): Call update_ssa.
* tree-ssa-operands.c (get_expr_operands): Handle ASSERT_EXPR.
(get_call_expr_operands): Reformat statement.
(add_stmt_operand): Don't create V_MAY_DEFs for read-only
symbols.
* tree-ssa-propagate.c (ssa_prop_init): Initialize
SSA_NAME_VALUE for every name.
(first_vdef, stmt_makes_single_load, stmt_makes_single_store,
get_value_loaded_by): New.
(replace_uses_in, replace_vuses_in, replace_phi_args_in,
substitute_and_fold): Move from tree-ssa-ccp.c.
* tree-ssa-propagate.h (struct prop_value_d, prop_value_t,
first_vdef, stmt_makes_single_load, stmt_makes_single_store,
get_value_loaded_by, replace_uses_in, substitute_and_fold):
Declare.
* tree-ssa.c (verify_use): Fix error message.
(propagate_into_addr, replace_immediate_uses, get_eq_name,
check_phi_redundancy, kill_redundant_phi_nodes,
pass_redundant_phi): Remove. Update all users.
* tree-vect-transform.c (vect_create_data_ref_ptr): Call
add_type_alias, if necessary.
* tree-vectorizer.h (struct _stmt_vect_info): Update
documentation for field 'memtag'.
* tree-vrp.c: New file.
* tree.def (ASSERT_EXPR): Define.
* tree.h (ASSERT_EXPR_VAR): Define.
(ASSERT_EXPR_COND): Define.
(SSA_NAME_VALUE_RANGE): Define.
(struct tree_ssa_name): Add field 'value_range'.
(PHI_REWRITTEN): Remove.
(struct tree_phi_node): Remove field 'rewritten'.
* doc/invoke.texi (-fdump-tree-storeccp, -ftree-copy-prop,
-ftree-store-copy-prop): Document.
* doc/tree-ssa.texi: Remove broken link to McCAT's compiler.
Document usage of update_ssa.
testsuite/ChangeLog
* g++.dg/tree-ssa/pr18178.C: New test.
* gcc.c-torture/execute/20030216-1.x: Ignore at -O1.
* gcc.c-torture/execute/20041019-1.c: New test.
* gcc.dg/tree-ssa/20041008-1.c: New test.
* gcc.dg/tree-ssa/ssa-ccp-12.c: New test.
* gcc.dg/tree-ssa/20030731-2.c: Update to use -fdump-tree-store_ccp.
* gcc.dg/tree-ssa/20030917-1.c: Likewise.
* gcc.dg/tree-ssa/20030917-3.c: Likewise.
* gcc.dg/tree-ssa/20040721-1.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-1.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-2.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-3.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-7.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-9.c: Likewise.
From-SVN: r97884
2005-04-09 03:37:54 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
VEC (access_p, heap) *access_vec;
|
|
|
|
struct access *access;
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
|
|
|
|
continue;
|
|
|
|
access_vec = get_base_access_vector (parm);
|
|
|
|
if (!access_vec)
|
|
|
|
continue;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!seq)
|
2004-06-29 18:25:28 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
seq = gimple_seq_alloc ();
|
|
|
|
gsi = gsi_start (seq);
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
for (access = VEC_index (access_p, access_vec, 0);
|
|
|
|
access;
|
|
|
|
access = access->next_grp)
|
|
|
|
generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true);
|
|
|
|
}
|
2004-06-29 18:25:28 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (seq)
|
|
|
|
gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR), seq);
|
2004-06-29 18:25:28 +02:00
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* The "main" function of intraprocedural SRA passes. Runs the analysis and if
|
|
|
|
it reveals there are components of some aggregates to be scalarized, it runs
|
|
|
|
the required transformations. */
|
|
|
|
static unsigned int
|
|
|
|
perform_intra_sra (void)
|
Makefile.in: Added rules for ipa-pure-const.c...
2005-07-16 Danny Berlin <dberlin@dberlin.org>
Kenneth Zadeck <zadeck@naturalbridge.com>
* Makefile.in: Added rules for ipa-pure-const.c, ipa-reference.c,
ipa-reference.h, ipa-utils.c, ipa-utils.h, ipa-type-escape.c,
ipa-type-escape.h, tree-promote-statics.c
* ipa-pure-const.c, ipa-reference.c, ipa-reference.h, ipa-utils.c,
ipa-utils.h, ipa-type-escape.c, ipa-type-escape.h,
tree-promote-statics.c: new files.
* alias.c: (nonlocal_mentioned_p_1, nonlocal_mentioned_p,
nonlocal_referenced_p_1, nonlocal_referenced_p, nonlocal_set_p_1,
int nonlocal_set_p, mark_constant_function): Deleted.
(rest_of_handle_cfg): Removed call to mark_constant_function.
(nonoverlapping_component_refs_p): Added calls to support
type based aliasing.
* tree-ssa-alias.c (may_alias_p,
compute_flow_insensitive_aliasing): Ditto.
* calls.c (flags_from_decl_or_type): Removed reference to
cgraph_rtl_info.
(flags_from_decl_or_type): Support ECF_POINTER_NO_CAPTURE attribute.
* c-common.c (handle_pointer_no_capture_attribute): New function
and added pointer_no_capture attribute.
* c-typeck.c (convert_arguments): Make builtins tolerant of having
too many arguments. This is necessary for Spec 2000.
* cgraph.h (const_function, pure_function): Removed.
* common.opt: Added "fipa-pure-const", "fipa-reference",
"fipa-type-escape", and "ftree-promote-static".
* opts.c: Ditto.
* passes.c: Added ipa and tree-promote-statics passes.
* timevar.def: Added TV_IPA_PURE_CONST, TV_IPA_REFERENCE,
TV_IPA_TYPE_ESCAPE, and TV_PROMOTE_STATICS.
* tree.h: Support ECF_POINTER_NO_CAPTURE attribute.
* tree-dfa.c (referenced_var_lookup_if_exists): New function.
* tree-flow.h: Added exposed sra calls and addition of
reference_vars_info field for FUNCTION_DECLS.
* tree-pass.h: Added passes.
* tree-sra.c: (sra_init_cache): New function.
(sra_insert_before, sra_insert_after) Made public.
(type_can_be_decomposed_p): Renamed from type_can_be_decomposed_p
and made public.
* tree-ssa-alias.c (dump_alias_stats): Added stats for type based
aliasing. (may_alias_p): Added code to use type escape analysis to
improve alias sets.
* tree-ssa-operands.c (add_call_clobber_ops): Added parameter and
code to prune clobbers of static variables based on information
produced in ipa-reference pass. Changed call clobbering so that
statics are not marked as clobbered if the call does not clobber
them.
2005-07-16 Danny Berlin <dberlin@dberlin.org>
Kenneth Zadeck <zadeck@naturalbridge.com>
* gcc.dg/tree-ssa/ssa-dce-2.c: Changed dg-options to run at -O2
since pure const detection cannot run at -O1 in c compiler.
* gcc.dg/tree-ssa/20030714-1.c Changed scanning patterns because we
can now optimize this case properly.
* gcc.dg/tree-ssa/sra-2.c: Changed to -O3 and removed xfail
because we now pass.
* gcc.dg/vect/vect-92.c: Removed out of bounds array access.
Co-Authored-By: Kenneth Zadeck <zadeck@naturalbridge.com>
From-SVN: r102098
2005-07-16 20:56:53 +02:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
int ret = 0;
|
|
|
|
sra_initialize ();
|
Makefile.in: Added rules for ipa-pure-const.c...
2005-07-16 Danny Berlin <dberlin@dberlin.org>
Kenneth Zadeck <zadeck@naturalbridge.com>
* Makefile.in: Added rules for ipa-pure-const.c, ipa-reference.c,
ipa-reference.h, ipa-utils.c, ipa-utils.h, ipa-type-escape.c,
ipa-type-escape.h, tree-promote-statics.c
* ipa-pure-const.c, ipa-reference.c, ipa-reference.h, ipa-utils.c,
ipa-utils.h, ipa-type-escape.c, ipa-type-escape.h,
tree-promote-statics.c: new files.
* alias.c: (nonlocal_mentioned_p_1, nonlocal_mentioned_p,
nonlocal_referenced_p_1, nonlocal_referenced_p, nonlocal_set_p_1,
int nonlocal_set_p, mark_constant_function): Deleted.
(rest_of_handle_cfg): Removed call to mark_constant_function.
(nonoverlapping_component_refs_p): Added calls to support
type based aliasing.
* tree-ssa-alias.c (may_alias_p,
compute_flow_insensitive_aliasing): Ditto.
* calls.c (flags_from_decl_or_type): Removed reference to
cgraph_rtl_info.
(flags_from_decl_or_type): Support ECF_POINTER_NO_CAPTURE attribute.
* c-common.c (handle_pointer_no_capture_attribute): New function
and added pointer_no_capture attribute.
* c-typeck.c (convert_arguments): Make builtins tolerant of having
too many arguments. This is necessary for Spec 2000.
* cgraph.h (const_function, pure_function): Removed.
* common.opt: Added "fipa-pure-const", "fipa-reference",
"fipa-type-escape", and "ftree-promote-static".
* opts.c: Ditto.
* passes.c: Added ipa and tree-promote-statics passes.
* timevar.def: Added TV_IPA_PURE_CONST, TV_IPA_REFERENCE,
TV_IPA_TYPE_ESCAPE, and TV_PROMOTE_STATICS.
* tree.h: Support ECF_POINTER_NO_CAPTURE attribute.
* tree-dfa.c (referenced_var_lookup_if_exists): New function.
* tree-flow.h: Added exposed sra calls and addition of
reference_vars_info field for FUNCTION_DECLS.
* tree-pass.h: Added passes.
* tree-sra.c: (sra_init_cache): New function.
(sra_insert_before, sra_insert_after) Made public.
(type_can_be_decomposed_p): Renamed from type_can_be_decomposed_p
and made public.
* tree-ssa-alias.c (dump_alias_stats): Added stats for type based
aliasing. (may_alias_p): Added code to use type escape analysis to
improve alias sets.
* tree-ssa-operands.c (add_call_clobber_ops): Added parameter and
code to prune clobbers of static variables based on information
produced in ipa-reference pass. Changed call clobbering so that
statics are not marked as clobbered if the call does not clobber
them.
2005-07-16 Danny Berlin <dberlin@dberlin.org>
Kenneth Zadeck <zadeck@naturalbridge.com>
* gcc.dg/tree-ssa/ssa-dce-2.c: Changed dg-options to run at -O2
since pure const detection cannot run at -O1 in c compiler.
* gcc.dg/tree-ssa/20030714-1.c Changed scanning patterns because we
can now optimize this case properly.
* gcc.dg/tree-ssa/sra-2.c: Changed to -O3 and removed xfail
because we now pass.
* gcc.dg/vect/vect-92.c: Removed out of bounds array access.
Co-Authored-By: Kenneth Zadeck <zadeck@naturalbridge.com>
From-SVN: r102098
2005-07-16 20:56:53 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!find_var_candidates ())
|
|
|
|
goto out;
|
Makefile.in: Added rules for ipa-pure-const.c...
2005-07-16 Danny Berlin <dberlin@dberlin.org>
Kenneth Zadeck <zadeck@naturalbridge.com>
* Makefile.in: Added rules for ipa-pure-const.c, ipa-reference.c,
ipa-reference.h, ipa-utils.c, ipa-utils.h, ipa-type-escape.c,
ipa-type-escape.h, tree-promote-statics.c
* ipa-pure-const.c, ipa-reference.c, ipa-reference.h, ipa-utils.c,
ipa-utils.h, ipa-type-escape.c, ipa-type-escape.h,
tree-promote-statics.c: new files.
* alias.c: (nonlocal_mentioned_p_1, nonlocal_mentioned_p,
nonlocal_referenced_p_1, nonlocal_referenced_p, nonlocal_set_p_1,
int nonlocal_set_p, mark_constant_function): Deleted.
(rest_of_handle_cfg): Removed call to mark_constant_function.
(nonoverlapping_component_refs_p): Added calls to support
type based aliasing.
* tree-ssa-alias.c (may_alias_p,
compute_flow_insensitive_aliasing): Ditto.
* calls.c (flags_from_decl_or_type): Removed reference to
cgraph_rtl_info.
(flags_from_decl_or_type): Support ECF_POINTER_NO_CAPTURE attribute.
* c-common.c (handle_pointer_no_capture_attribute): New function
and added pointer_no_capture attribute.
* c-typeck.c (convert_arguments): Make builtins tolerant of having
too many arguments. This is necessary for Spec 2000.
* cgraph.h (const_function, pure_function): Removed.
* common.opt: Added "fipa-pure-const", "fipa-reference",
"fipa-type-escape", and "ftree-promote-static".
* opts.c: Ditto.
* passes.c: Added ipa and tree-promote-statics passes.
* timevar.def: Added TV_IPA_PURE_CONST, TV_IPA_REFERENCE,
TV_IPA_TYPE_ESCAPE, and TV_PROMOTE_STATICS.
* tree.h: Support ECF_POINTER_NO_CAPTURE attribute.
* tree-dfa.c (referenced_var_lookup_if_exists): New function.
* tree-flow.h: Added exposed sra calls and addition of
reference_vars_info field for FUNCTION_DECLS.
* tree-pass.h: Added passes.
* tree-sra.c: (sra_init_cache): New function.
(sra_insert_before, sra_insert_after) Made public.
(type_can_be_decomposed_p): Renamed from type_can_be_decomposed_p
and made public.
* tree-ssa-alias.c (dump_alias_stats): Added stats for type based
aliasing. (may_alias_p): Added code to use type escape analysis to
improve alias sets.
* tree-ssa-operands.c (add_call_clobber_ops): Added parameter and
code to prune clobbers of static variables based on information
produced in ipa-reference pass. Changed call clobbering so that
statics are not marked as clobbered if the call does not clobber
them.
2005-07-16 Danny Berlin <dberlin@dberlin.org>
Kenneth Zadeck <zadeck@naturalbridge.com>
* gcc.dg/tree-ssa/ssa-dce-2.c: Changed dg-options to run at -O2
since pure const detection cannot run at -O1 in c compiler.
* gcc.dg/tree-ssa/20030714-1.c Changed scanning patterns because we
can now optimize this case properly.
* gcc.dg/tree-ssa/sra-2.c: Changed to -O3 and removed xfail
because we now pass.
* gcc.dg/vect/vect-92.c: Removed out of bounds array access.
Co-Authored-By: Kenneth Zadeck <zadeck@naturalbridge.com>
From-SVN: r102098
2005-07-16 20:56:53 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!scan_function (build_access_from_expr, build_accesses_from_assign, NULL,
|
|
|
|
true, NULL))
|
|
|
|
goto out;
|
2008-07-28 16:33:56 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
if (!analyze_all_variable_accesses ())
|
|
|
|
goto out;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
scan_function (sra_modify_expr, sra_modify_assign, NULL, false, NULL);
|
2009-05-29 18:47:31 +02:00
|
|
|
initialize_parameter_reductions ();
|
2009-06-18 17:38:36 +02:00
|
|
|
|
|
|
|
statistics_counter_event (cfun, "Scalar replacements created",
|
|
|
|
sra_stats.replacements);
|
|
|
|
statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
|
|
|
|
statistics_counter_event (cfun, "Subtree copy stmts",
|
|
|
|
sra_stats.subtree_copies);
|
|
|
|
statistics_counter_event (cfun, "Subreplacement stmts",
|
|
|
|
sra_stats.subreplacements);
|
|
|
|
statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
|
|
|
|
statistics_counter_event (cfun, "Separate LHS and RHS handling",
|
|
|
|
sra_stats.separate_lhs_rhs_handling);
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
ret = TODO_update_ssa;
|
2004-05-13 08:41:07 +02:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
out:
|
|
|
|
sra_deinitialize ();
|
|
|
|
return ret;
|
2004-05-13 08:41:07 +02:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Perform early intraprocedural SRA. */
|
2007-02-14 18:52:25 +01:00
|
|
|
static unsigned int
|
2009-05-29 18:47:31 +02:00
|
|
|
early_intra_sra (void)
|
2007-02-14 18:52:25 +01:00
|
|
|
{
|
2009-05-29 18:47:31 +02:00
|
|
|
sra_mode = SRA_MODE_EARLY_INTRA;
|
|
|
|
return perform_intra_sra ();
|
|
|
|
}
|
2007-02-14 18:52:25 +01:00
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
/* Perform "late" intraprocedural SRA. */
|
|
|
|
static unsigned int
|
|
|
|
late_intra_sra (void)
|
|
|
|
{
|
|
|
|
sra_mode = SRA_MODE_INTRA;
|
|
|
|
return perform_intra_sra ();
|
2007-02-14 18:52:25 +01:00
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
|
2004-05-13 08:41:07 +02:00
|
|
|
static bool
|
2009-05-29 18:47:31 +02:00
|
|
|
gate_intra_sra (void)
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
|
|
|
return flag_tree_sra != 0;
|
|
|
|
}
|
|
|
|
|
2009-05-29 18:47:31 +02:00
|
|
|
|
re PR other/35094 (RTL dump file letters hosed and partly undocumented)
* gcc.dg/20050811-2.c: Update dumping flags.
* gcc.dg/sms-2.c: Update dumping flags.
* gcc.dg/var-expand1.c: Update dumping flags.
* gcc.dg/var-expand3.c: Update dumping flags.
* gcc.dg/pr30957-1.c: Update dumping flags.
* gcc.dg/20050811-1.c: Update dumping flags.
* gcc.dg/cpp/cmdlne-dI-M.C: Do not xfail.
* gcc.dg/cpp/cmdlne-dM-M.C: Do not xfail.
PR other/35094
* toplev.c (decode_d_option): Handle all CPP flags.
* tree-vrp.c: Update tree_pass descriptors.
* regrename.c: Update tree_pass descriptors.
* fwprop.c: Update tree_pass descriptors.
* doc/invoke.texi: Remove documentation of dropped -d? flags.
* tree-into-ssa.c: Update tree_pass descriptors.
* tree-dump.c: Update tree_pass descriptors.
* tree-complex.c: Update tree_pass descriptors.
* tree-dump.h: Update tree_pass descriptors.
* see.c: Update tree_pass descriptors.
* cgraphbuild.c: Update tree_pass descriptors.
* tracer.c: Update tree_pass descriptors.
* tree-loop-distribution.c: Update tree_pass descriptors.
* cgraph.c: Update tree_pass descriptors.
* postreload-gcse.c: Update tree_pass descriptors.
* postreload.c: Update tree_pass descriptors.
* tree-ssa-loop-ch.c: Update tree_pass descriptors.
* tree-tailcall.c: Update tree_pass descriptors.
* tree-pass.h (tree_opt_pass): Rename to ...
(opt_pass) ... this one; add "type" field and remove letter field.
(gimple_opt_pass, rtl_opt_pass, simple_ipa_opt_pass): New.
(execute_pass_list, execute_ipa_pass_list, all_passes, all_ipa_passes,
all_lowering_passes): Update declaration.
* ipa-cp.c: Update tree_pass descriptors.
* final.c: Update tree_pass descriptors.
* omp-low.c: Update tree_pass descriptors.
* tree-ssa-dse.c: Update tree_pass descriptors.
* ipa-reference.c: Update tree_pass descriptors.
* tree-ssa-uncprop.c: Update tree_pass descriptors.
* auto-inc-dec.c: Update tree_pass descriptors.
* reorg.c: Update tree_pass descriptors.
* cgraphunit.c: Update tree_pass descriptors.
* tree-ssa-copyrename.c: Update tree_pass descriptors.
* tree-ssa-ccp.c: Update tree_pass descriptors.
* df-core.c: Update tree_pass descriptors.
* mode-switching.c: Update tree_pass descriptors.
* tree-nomudflap.c: Update tree_pass descriptors.
* modulo-sched.c: Update tree_pass descriptors.
* ipa-pure-const.c: Update tree_pass descriptors.
* cse.c: Update tree_pass descriptors.
* web.c: Update tree_pass descriptors.
* tree-stdarg.c: Update tree_pass descriptors.
* tree-ssa-math-opts.c: Update tree_pass descriptors.
* tree-ssa-dom.c: Update tree_pass descriptors.
* tree-nrv.c: Update tree_pass descriptors.
* tree-ssa-alias.c: Update tree_pass descriptors.
* loop-init.c: Update tree_pass descriptors.
* gimple-low.c: Update tree_pass descriptors.
* ipa-inline.c: Update tree_pass descriptors.
* tree-ssa-sink.c: Update tree_pass descriptors.
* global.c: Update tree_pass descriptors.
* ifcvt.c: Update tree_pass descriptors.
* jump.c: Update tree_pass descriptors.
* predict.c: Update tree_pass descriptors.
* tree-ssa-loop.c: Update tree_pass descriptors.
* recog.c: Update tree_pass descriptors.
* dse.c: Update tree_pass descriptors.
* tree-ssa-ifcombine.c: Update tree_pass descriptors.
* tree-eh.c: Update tree_pass descriptors.
* regmove.c: Update tree_pass descriptors.
* local-alloc.c
* function.c: Update tree_pass descriptors.
* tree-vectorizer.c: Update tree_pass descriptors.
* gcse.c: Update tree_pass descriptors.
* ipa-type-escape.c: Update tree_pass descriptors.
* tree-if-conv.c: Update tree_pass descriptors.
* init-regs.c: Update tree_pass descriptors.
* ipa.c: Update tree_pass descriptors.
* tree-ssa-phiopt.c: Update tree_pass descriptors.
* rtl-factoring.c: Update tree_pass descriptors.
* lower-subreg.c: Update tree_pass descriptors.
* bt-load.c: Update tree_pass descriptors.
* tree-dfa.c: Update tree_pass descriptors.
* except.c: Update tree_pass descriptors.
* emit-rtl.c: Update tree_pass descriptors.
* cfgexpand.c: Update tree_pass descriptors.
* tree-cfgcleanup.c: Update tree_pass descriptors.
* cfgcleanup.c: Update tree_pass descriptors.
* tree-ssa-pre.c: Update tree_pass descriptors.
* tree-sra.c: Update tree_pass descriptors.
* tree-mudflap.c: Update tree_pass descriptors.
* tree-ssa-copy.c: Update tree_pass descriptors.
* cfglayout.c: Update tree_pass descriptors.
* tree-ssa-forwprop.c: Update tree_pass descriptors.
* tree-ssa-dce.c: Update tree_pass descriptors.
* tree-ssa.c: Update tree_pass descriptors.
* regclass.c: Update tree_pass descriptors.
* integrate.c: Update tree_pass descriptors.
* tree-optimize.c: Update tree_pass descriptors.
* tree-ssa-phiprop.c: Update tree_pass descriptors.
* tree-object-size.c: Update tree_pass descriptors.
* combine.c: Update tree_pass descriptors.
* tree-outof-ssa.c: Update tree_pass descriptors.
* bb-reorder.c: Update tree_pass descriptors.
* stack-ptr-mod.c: Update tree_pass descriptors.
* var-tracking.c: Update tree_pass descriptors.
* tree-profile.c: Update tree_pass descriptors.
* tree-vect-generic.c: Update tree_pass descriptors.
* reg-stack.c: Update tree_pass descriptors.
* sched-rgn.c: Update tree_pass descriptors.
* tree-ssa-structalias.c: Update tree_pass descriptors.
* tree-cfg.c: Update tree_pass descriptors.
* passes.c (current_pass): Update declaration.
(finish_optimization_passes): Update.
(all_passes, all_ipa_passes, all_lowering_passes): Update declaration.
(register_one_dump_file, register_dump_files_1, next_pass_1):
Update arguments.
(init_optimization_passes): Update handling of new types.
(execute_one_pass, execute_pass_list, execute_ipa_pass_list): Update.
* ipa-struct-reorg.c: Update tree_pass descriptors.
* tree-ssa-reassoc.c: Update tree_pass descriptors.
* combine-stack-adj.c: Update tree_pass descriptors.
* cfgrtl.c: Update tree_pass descriptors.
* dce.c: Update tree_pass descriptors.
* tree-ssanames.c: Update tree_pass descriptors.
From-SVN: r133342
2008-03-19 12:22:40 +01:00
|
|
|
struct gimple_opt_pass pass_sra_early =
|
2007-02-14 18:52:25 +01:00
|
|
|
{
|
re PR other/35094 (RTL dump file letters hosed and partly undocumented)
* gcc.dg/20050811-2.c: Update dumping flags.
* gcc.dg/sms-2.c: Update dumping flags.
* gcc.dg/var-expand1.c: Update dumping flags.
* gcc.dg/var-expand3.c: Update dumping flags.
* gcc.dg/pr30957-1.c: Update dumping flags.
* gcc.dg/20050811-1.c: Update dumping flags.
* gcc.dg/cpp/cmdlne-dI-M.C: Do not xfail.
* gcc.dg/cpp/cmdlne-dM-M.C: Do not xfail.
PR other/35094
* toplev.c (decode_d_option): Handle all CPP flags.
* tree-vrp.c: Update tree_pass descriptors.
* regrename.c: Update tree_pass descriptors.
* fwprop.c: Update tree_pass descriptors.
* doc/invoke.texi: Remove documentation of dropped -d? flags.
* tree-into-ssa.c: Update tree_pass descriptors.
* tree-dump.c: Update tree_pass descriptors.
* tree-complex.c: Update tree_pass descriptors.
* tree-dump.h: Update tree_pass descriptors.
* see.c: Update tree_pass descriptors.
* cgraphbuild.c: Update tree_pass descriptors.
* tracer.c: Update tree_pass descriptors.
* tree-loop-distribution.c: Update tree_pass descriptors.
* cgraph.c: Update tree_pass descriptors.
* postreload-gcse.c: Update tree_pass descriptors.
* postreload.c: Update tree_pass descriptors.
* tree-ssa-loop-ch.c: Update tree_pass descriptors.
* tree-tailcall.c: Update tree_pass descriptors.
* tree-pass.h (tree_opt_pass): Rename to ...
(opt_pass) ... this one; add "type" field and remove letter field.
(gimple_opt_pass, rtl_opt_pass, simple_ipa_opt_pass): New.
(execute_pass_list, execute_ipa_pass_list, all_passes, all_ipa_passes,
all_lowering_passes): Update declaration.
* ipa-cp.c: Update tree_pass descriptors.
* final.c: Update tree_pass descriptors.
* omp-low.c: Update tree_pass descriptors.
* tree-ssa-dse.c: Update tree_pass descriptors.
* ipa-reference.c: Update tree_pass descriptors.
* tree-ssa-uncprop.c: Update tree_pass descriptors.
* auto-inc-dec.c: Update tree_pass descriptors.
* reorg.c: Update tree_pass descriptors.
* cgraphunit.c: Update tree_pass descriptors.
* tree-ssa-copyrename.c: Update tree_pass descriptors.
* tree-ssa-ccp.c: Update tree_pass descriptors.
* df-core.c: Update tree_pass descriptors.
* mode-switching.c: Update tree_pass descriptors.
* tree-nomudflap.c: Update tree_pass descriptors.
* modulo-sched.c: Update tree_pass descriptors.
* ipa-pure-const.c: Update tree_pass descriptors.
* cse.c: Update tree_pass descriptors.
* web.c: Update tree_pass descriptors.
* tree-stdarg.c: Update tree_pass descriptors.
* tree-ssa-math-opts.c: Update tree_pass descriptors.
* tree-ssa-dom.c: Update tree_pass descriptors.
* tree-nrv.c: Update tree_pass descriptors.
* tree-ssa-alias.c: Update tree_pass descriptors.
* loop-init.c: Update tree_pass descriptors.
* gimple-low.c: Update tree_pass descriptors.
* ipa-inline.c: Update tree_pass descriptors.
* tree-ssa-sink.c: Update tree_pass descriptors.
* global.c: Update tree_pass descriptors.
* ifcvt.c: Update tree_pass descriptors.
* jump.c: Update tree_pass descriptors.
* predict.c: Update tree_pass descriptors.
* tree-ssa-loop.c: Update tree_pass descriptors.
* recog.c: Update tree_pass descriptors.
* dse.c: Update tree_pass descriptors.
* tree-ssa-ifcombine.c: Update tree_pass descriptors.
* tree-eh.c: Update tree_pass descriptors.
* regmove.c: Update tree_pass descriptors.
* local-alloc.c
* function.c: Update tree_pass descriptors.
* tree-vectorizer.c: Update tree_pass descriptors.
* gcse.c: Update tree_pass descriptors.
* ipa-type-escape.c: Update tree_pass descriptors.
* tree-if-conv.c: Update tree_pass descriptors.
* init-regs.c: Update tree_pass descriptors.
* ipa.c: Update tree_pass descriptors.
* tree-ssa-phiopt.c: Update tree_pass descriptors.
* rtl-factoring.c: Update tree_pass descriptors.
* lower-subreg.c: Update tree_pass descriptors.
* bt-load.c: Update tree_pass descriptors.
* tree-dfa.c: Update tree_pass descriptors.
* except.c: Update tree_pass descriptors.
* emit-rtl.c: Update tree_pass descriptors.
* cfgexpand.c: Update tree_pass descriptors.
* tree-cfgcleanup.c: Update tree_pass descriptors.
* cfgcleanup.c: Update tree_pass descriptors.
* tree-ssa-pre.c: Update tree_pass descriptors.
* tree-sra.c: Update tree_pass descriptors.
* tree-mudflap.c: Update tree_pass descriptors.
* tree-ssa-copy.c: Update tree_pass descriptors.
* cfglayout.c: Update tree_pass descriptors.
* tree-ssa-forwprop.c: Update tree_pass descriptors.
* tree-ssa-dce.c: Update tree_pass descriptors.
* tree-ssa.c: Update tree_pass descriptors.
* regclass.c: Update tree_pass descriptors.
* integrate.c: Update tree_pass descriptors.
* tree-optimize.c: Update tree_pass descriptors.
* tree-ssa-phiprop.c: Update tree_pass descriptors.
* tree-object-size.c: Update tree_pass descriptors.
* combine.c: Update tree_pass descriptors.
* tree-outof-ssa.c: Update tree_pass descriptors.
* bb-reorder.c: Update tree_pass descriptors.
* stack-ptr-mod.c: Update tree_pass descriptors.
* var-tracking.c: Update tree_pass descriptors.
* tree-profile.c: Update tree_pass descriptors.
* tree-vect-generic.c: Update tree_pass descriptors.
* reg-stack.c: Update tree_pass descriptors.
* sched-rgn.c: Update tree_pass descriptors.
* tree-ssa-structalias.c: Update tree_pass descriptors.
* tree-cfg.c: Update tree_pass descriptors.
* passes.c (current_pass): Update declaration.
(finish_optimization_passes): Update.
(all_passes, all_ipa_passes, all_lowering_passes): Update declaration.
(register_one_dump_file, register_dump_files_1, next_pass_1):
Update arguments.
(init_optimization_passes): Update handling of new types.
(execute_one_pass, execute_pass_list, execute_ipa_pass_list): Update.
* ipa-struct-reorg.c: Update tree_pass descriptors.
* tree-ssa-reassoc.c: Update tree_pass descriptors.
* combine-stack-adj.c: Update tree_pass descriptors.
* cfgrtl.c: Update tree_pass descriptors.
* dce.c: Update tree_pass descriptors.
* tree-ssanames.c: Update tree_pass descriptors.
From-SVN: r133342
2008-03-19 12:22:40 +01:00
|
|
|
{
|
|
|
|
GIMPLE_PASS,
|
2009-05-29 18:47:31 +02:00
|
|
|
"esra", /* name */
|
|
|
|
gate_intra_sra, /* gate */
|
|
|
|
early_intra_sra, /* execute */
|
2007-02-14 18:52:25 +01:00
|
|
|
NULL, /* sub */
|
|
|
|
NULL, /* next */
|
|
|
|
0, /* static_pass_number */
|
|
|
|
TV_TREE_SRA, /* tv_id */
|
2009-05-29 18:47:31 +02:00
|
|
|
PROP_cfg | PROP_ssa, /* properties_required */
|
2007-02-14 18:52:25 +01:00
|
|
|
0, /* properties_provided */
|
2009-05-29 18:47:31 +02:00
|
|
|
0, /* properties_destroyed */
|
2007-02-14 18:52:25 +01:00
|
|
|
0, /* todo_flags_start */
|
|
|
|
TODO_dump_func
|
|
|
|
| TODO_update_ssa
|
|
|
|
| TODO_ggc_collect
|
re PR other/35094 (RTL dump file letters hosed and partly undocumented)
* gcc.dg/20050811-2.c: Update dumping flags.
* gcc.dg/sms-2.c: Update dumping flags.
* gcc.dg/var-expand1.c: Update dumping flags.
* gcc.dg/var-expand3.c: Update dumping flags.
* gcc.dg/pr30957-1.c: Update dumping flags.
* gcc.dg/20050811-1.c: Update dumping flags.
* gcc.dg/cpp/cmdlne-dI-M.C: Do not xfail.
* gcc.dg/cpp/cmdlne-dM-M.C: Do not xfail.
PR other/35094
* toplev.c (decode_d_option): Handle all CPP flags.
* tree-vrp.c: Update tree_pass descriptors.
* regrename.c: Update tree_pass descriptors.
* fwprop.c: Update tree_pass descriptors.
* doc/invoke.texi: Remove documentation of dropped -d? flags.
* tree-into-ssa.c: Update tree_pass descriptors.
* tree-dump.c: Update tree_pass descriptors.
* tree-complex.c: Update tree_pass descriptors.
* tree-dump.h: Update tree_pass descriptors.
* see.c: Update tree_pass descriptors.
* cgraphbuild.c: Update tree_pass descriptors.
* tracer.c: Update tree_pass descriptors.
* tree-loop-distribution.c: Update tree_pass descriptors.
* cgraph.c: Update tree_pass descriptors.
* postreload-gcse.c: Update tree_pass descriptors.
* postreload.c: Update tree_pass descriptors.
* tree-ssa-loop-ch.c: Update tree_pass descriptors.
* tree-tailcall.c: Update tree_pass descriptors.
* tree-pass.h (tree_opt_pass): Rename to ...
(opt_pass) ... this one; add "type" field and remove letter field.
(gimple_opt_pass, rtl_opt_pass, simple_ipa_opt_pass): New.
(execute_pass_list, execute_ipa_pass_list, all_passes, all_ipa_passes,
all_lowering_passes): Update declaration.
* ipa-cp.c: Update tree_pass descriptors.
* final.c: Update tree_pass descriptors.
* omp-low.c: Update tree_pass descriptors.
* tree-ssa-dse.c: Update tree_pass descriptors.
* ipa-reference.c: Update tree_pass descriptors.
* tree-ssa-uncprop.c: Update tree_pass descriptors.
* auto-inc-dec.c: Update tree_pass descriptors.
* reorg.c: Update tree_pass descriptors.
* cgraphunit.c: Update tree_pass descriptors.
* tree-ssa-copyrename.c: Update tree_pass descriptors.
* tree-ssa-ccp.c: Update tree_pass descriptors.
* df-core.c: Update tree_pass descriptors.
* mode-switching.c: Update tree_pass descriptors.
* tree-nomudflap.c: Update tree_pass descriptors.
* modulo-sched.c: Update tree_pass descriptors.
* ipa-pure-const.c: Update tree_pass descriptors.
* cse.c: Update tree_pass descriptors.
* web.c: Update tree_pass descriptors.
* tree-stdarg.c: Update tree_pass descriptors.
* tree-ssa-math-opts.c: Update tree_pass descriptors.
* tree-ssa-dom.c: Update tree_pass descriptors.
* tree-nrv.c: Update tree_pass descriptors.
* tree-ssa-alias.c: Update tree_pass descriptors.
* loop-init.c: Update tree_pass descriptors.
* gimple-low.c: Update tree_pass descriptors.
* ipa-inline.c: Update tree_pass descriptors.
* tree-ssa-sink.c: Update tree_pass descriptors.
* global.c: Update tree_pass descriptors.
* ifcvt.c: Update tree_pass descriptors.
* jump.c: Update tree_pass descriptors.
* predict.c: Update tree_pass descriptors.
* tree-ssa-loop.c: Update tree_pass descriptors.
* recog.c: Update tree_pass descriptors.
* dse.c: Update tree_pass descriptors.
* tree-ssa-ifcombine.c: Update tree_pass descriptors.
* tree-eh.c: Update tree_pass descriptors.
* regmove.c: Update tree_pass descriptors.
* local-alloc.c
* function.c: Update tree_pass descriptors.
* tree-vectorizer.c: Update tree_pass descriptors.
* gcse.c: Update tree_pass descriptors.
* ipa-type-escape.c: Update tree_pass descriptors.
* tree-if-conv.c: Update tree_pass descriptors.
* init-regs.c: Update tree_pass descriptors.
* ipa.c: Update tree_pass descriptors.
* tree-ssa-phiopt.c: Update tree_pass descriptors.
* rtl-factoring.c: Update tree_pass descriptors.
* lower-subreg.c: Update tree_pass descriptors.
* bt-load.c: Update tree_pass descriptors.
* tree-dfa.c: Update tree_pass descriptors.
* except.c: Update tree_pass descriptors.
* emit-rtl.c: Update tree_pass descriptors.
* cfgexpand.c: Update tree_pass descriptors.
* tree-cfgcleanup.c: Update tree_pass descriptors.
* cfgcleanup.c: Update tree_pass descriptors.
* tree-ssa-pre.c: Update tree_pass descriptors.
* tree-sra.c: Update tree_pass descriptors.
* tree-mudflap.c: Update tree_pass descriptors.
* tree-ssa-copy.c: Update tree_pass descriptors.
* cfglayout.c: Update tree_pass descriptors.
* tree-ssa-forwprop.c: Update tree_pass descriptors.
* tree-ssa-dce.c: Update tree_pass descriptors.
* tree-ssa.c: Update tree_pass descriptors.
* regclass.c: Update tree_pass descriptors.
* integrate.c: Update tree_pass descriptors.
* tree-optimize.c: Update tree_pass descriptors.
* tree-ssa-phiprop.c: Update tree_pass descriptors.
* tree-object-size.c: Update tree_pass descriptors.
* combine.c: Update tree_pass descriptors.
* tree-outof-ssa.c: Update tree_pass descriptors.
* bb-reorder.c: Update tree_pass descriptors.
* stack-ptr-mod.c: Update tree_pass descriptors.
* var-tracking.c: Update tree_pass descriptors.
* tree-profile.c: Update tree_pass descriptors.
* tree-vect-generic.c: Update tree_pass descriptors.
* reg-stack.c: Update tree_pass descriptors.
* sched-rgn.c: Update tree_pass descriptors.
* tree-ssa-structalias.c: Update tree_pass descriptors.
* tree-cfg.c: Update tree_pass descriptors.
* passes.c (current_pass): Update declaration.
(finish_optimization_passes): Update.
(all_passes, all_ipa_passes, all_lowering_passes): Update declaration.
(register_one_dump_file, register_dump_files_1, next_pass_1):
Update arguments.
(init_optimization_passes): Update handling of new types.
(execute_one_pass, execute_pass_list, execute_ipa_pass_list): Update.
* ipa-struct-reorg.c: Update tree_pass descriptors.
* tree-ssa-reassoc.c: Update tree_pass descriptors.
* combine-stack-adj.c: Update tree_pass descriptors.
* cfgrtl.c: Update tree_pass descriptors.
* dce.c: Update tree_pass descriptors.
* tree-ssanames.c: Update tree_pass descriptors.
From-SVN: r133342
2008-03-19 12:22:40 +01:00
|
|
|
| TODO_verify_ssa /* todo_flags_finish */
|
|
|
|
}
|
2007-02-14 18:52:25 +01:00
|
|
|
};
|
|
|
|
|
re PR other/35094 (RTL dump file letters hosed and partly undocumented)
* gcc.dg/20050811-2.c: Update dumping flags.
* gcc.dg/sms-2.c: Update dumping flags.
* gcc.dg/var-expand1.c: Update dumping flags.
* gcc.dg/var-expand3.c: Update dumping flags.
* gcc.dg/pr30957-1.c: Update dumping flags.
* gcc.dg/20050811-1.c: Update dumping flags.
* gcc.dg/cpp/cmdlne-dI-M.C: Do not xfail.
* gcc.dg/cpp/cmdlne-dM-M.C: Do not xfail.
PR other/35094
* toplev.c (decode_d_option): Handle all CPP flags.
* tree-vrp.c: Update tree_pass descriptors.
* regrename.c: Update tree_pass descriptors.
* fwprop.c: Update tree_pass descriptors.
* doc/invoke.texi: Remove documentation of dropped -d? flags.
* tree-into-ssa.c: Update tree_pass descriptors.
* tree-dump.c: Update tree_pass descriptors.
* tree-complex.c: Update tree_pass descriptors.
* tree-dump.h: Update tree_pass descriptors.
* see.c: Update tree_pass descriptors.
* cgraphbuild.c: Update tree_pass descriptors.
* tracer.c: Update tree_pass descriptors.
* tree-loop-distribution.c: Update tree_pass descriptors.
* cgraph.c: Update tree_pass descriptors.
* postreload-gcse.c: Update tree_pass descriptors.
* postreload.c: Update tree_pass descriptors.
* tree-ssa-loop-ch.c: Update tree_pass descriptors.
* tree-tailcall.c: Update tree_pass descriptors.
* tree-pass.h (tree_opt_pass): Rename to ...
(opt_pass) ... this one; add "type" field and remove letter field.
(gimple_opt_pass, rtl_opt_pass, simple_ipa_opt_pass): New.
(execute_pass_list, execute_ipa_pass_list, all_passes, all_ipa_passes,
all_lowering_passes): Update declaration.
* ipa-cp.c: Update tree_pass descriptors.
* final.c: Update tree_pass descriptors.
* omp-low.c: Update tree_pass descriptors.
* tree-ssa-dse.c: Update tree_pass descriptors.
* ipa-reference.c: Update tree_pass descriptors.
* tree-ssa-uncprop.c: Update tree_pass descriptors.
* auto-inc-dec.c: Update tree_pass descriptors.
* reorg.c: Update tree_pass descriptors.
* cgraphunit.c: Update tree_pass descriptors.
* tree-ssa-copyrename.c: Update tree_pass descriptors.
* tree-ssa-ccp.c: Update tree_pass descriptors.
* df-core.c: Update tree_pass descriptors.
* mode-switching.c: Update tree_pass descriptors.
* tree-nomudflap.c: Update tree_pass descriptors.
* modulo-sched.c: Update tree_pass descriptors.
* ipa-pure-const.c: Update tree_pass descriptors.
* cse.c: Update tree_pass descriptors.
* web.c: Update tree_pass descriptors.
* tree-stdarg.c: Update tree_pass descriptors.
* tree-ssa-math-opts.c: Update tree_pass descriptors.
* tree-ssa-dom.c: Update tree_pass descriptors.
* tree-nrv.c: Update tree_pass descriptors.
* tree-ssa-alias.c: Update tree_pass descriptors.
* loop-init.c: Update tree_pass descriptors.
* gimple-low.c: Update tree_pass descriptors.
* ipa-inline.c: Update tree_pass descriptors.
* tree-ssa-sink.c: Update tree_pass descriptors.
* global.c: Update tree_pass descriptors.
* ifcvt.c: Update tree_pass descriptors.
* jump.c: Update tree_pass descriptors.
* predict.c: Update tree_pass descriptors.
* tree-ssa-loop.c: Update tree_pass descriptors.
* recog.c: Update tree_pass descriptors.
* dse.c: Update tree_pass descriptors.
* tree-ssa-ifcombine.c: Update tree_pass descriptors.
* tree-eh.c: Update tree_pass descriptors.
* regmove.c: Update tree_pass descriptors.
* local-alloc.c
* function.c: Update tree_pass descriptors.
* tree-vectorizer.c: Update tree_pass descriptors.
* gcse.c: Update tree_pass descriptors.
* ipa-type-escape.c: Update tree_pass descriptors.
* tree-if-conv.c: Update tree_pass descriptors.
* init-regs.c: Update tree_pass descriptors.
* ipa.c: Update tree_pass descriptors.
* tree-ssa-phiopt.c: Update tree_pass descriptors.
* rtl-factoring.c: Update tree_pass descriptors.
* lower-subreg.c: Update tree_pass descriptors.
* bt-load.c: Update tree_pass descriptors.
* tree-dfa.c: Update tree_pass descriptors.
* except.c: Update tree_pass descriptors.
* emit-rtl.c: Update tree_pass descriptors.
* cfgexpand.c: Update tree_pass descriptors.
* tree-cfgcleanup.c: Update tree_pass descriptors.
* cfgcleanup.c: Update tree_pass descriptors.
* tree-ssa-pre.c: Update tree_pass descriptors.
* tree-sra.c: Update tree_pass descriptors.
* tree-mudflap.c: Update tree_pass descriptors.
* tree-ssa-copy.c: Update tree_pass descriptors.
* cfglayout.c: Update tree_pass descriptors.
* tree-ssa-forwprop.c: Update tree_pass descriptors.
* tree-ssa-dce.c: Update tree_pass descriptors.
* tree-ssa.c: Update tree_pass descriptors.
* regclass.c: Update tree_pass descriptors.
* integrate.c: Update tree_pass descriptors.
* tree-optimize.c: Update tree_pass descriptors.
* tree-ssa-phiprop.c: Update tree_pass descriptors.
* tree-object-size.c: Update tree_pass descriptors.
* combine.c: Update tree_pass descriptors.
* tree-outof-ssa.c: Update tree_pass descriptors.
* bb-reorder.c: Update tree_pass descriptors.
* stack-ptr-mod.c: Update tree_pass descriptors.
* var-tracking.c: Update tree_pass descriptors.
* tree-profile.c: Update tree_pass descriptors.
* tree-vect-generic.c: Update tree_pass descriptors.
* reg-stack.c: Update tree_pass descriptors.
* sched-rgn.c: Update tree_pass descriptors.
* tree-ssa-structalias.c: Update tree_pass descriptors.
* tree-cfg.c: Update tree_pass descriptors.
* passes.c (current_pass): Update declaration.
(finish_optimization_passes): Update.
(all_passes, all_ipa_passes, all_lowering_passes): Update declaration.
(register_one_dump_file, register_dump_files_1, next_pass_1):
Update arguments.
(init_optimization_passes): Update handling of new types.
(execute_one_pass, execute_pass_list, execute_ipa_pass_list): Update.
* ipa-struct-reorg.c: Update tree_pass descriptors.
* tree-ssa-reassoc.c: Update tree_pass descriptors.
* combine-stack-adj.c: Update tree_pass descriptors.
* cfgrtl.c: Update tree_pass descriptors.
* dce.c: Update tree_pass descriptors.
* tree-ssanames.c: Update tree_pass descriptors.
From-SVN: r133342
2008-03-19 12:22:40 +01:00
|
|
|
struct gimple_opt_pass pass_sra =
|
2004-05-13 08:41:07 +02:00
|
|
|
{
|
re PR other/35094 (RTL dump file letters hosed and partly undocumented)
* gcc.dg/20050811-2.c: Update dumping flags.
* gcc.dg/sms-2.c: Update dumping flags.
* gcc.dg/var-expand1.c: Update dumping flags.
* gcc.dg/var-expand3.c: Update dumping flags.
* gcc.dg/pr30957-1.c: Update dumping flags.
* gcc.dg/20050811-1.c: Update dumping flags.
* gcc.dg/cpp/cmdlne-dI-M.C: Do not xfail.
* gcc.dg/cpp/cmdlne-dM-M.C: Do not xfail.
PR other/35094
* toplev.c (decode_d_option): Handle all CPP flags.
* tree-vrp.c: Update tree_pass descriptors.
* regrename.c: Update tree_pass descriptors.
* fwprop.c: Update tree_pass descriptors.
* doc/invoke.texi: Remove documentation of dropped -d? flags.
* tree-into-ssa.c: Update tree_pass descriptors.
* tree-dump.c: Update tree_pass descriptors.
* tree-complex.c: Update tree_pass descriptors.
* tree-dump.h: Update tree_pass descriptors.
* see.c: Update tree_pass descriptors.
* cgraphbuild.c: Update tree_pass descriptors.
* tracer.c: Update tree_pass descriptors.
* tree-loop-distribution.c: Update tree_pass descriptors.
* cgraph.c: Update tree_pass descriptors.
* postreload-gcse.c: Update tree_pass descriptors.
* postreload.c: Update tree_pass descriptors.
* tree-ssa-loop-ch.c: Update tree_pass descriptors.
* tree-tailcall.c: Update tree_pass descriptors.
* tree-pass.h (tree_opt_pass): Rename to ...
(opt_pass) ... this one; add "type" field and remove letter field.
(gimple_opt_pass, rtl_opt_pass, simple_ipa_opt_pass): New.
(execute_pass_list, execute_ipa_pass_list, all_passes, all_ipa_passes,
all_lowering_passes): Update declaration.
* ipa-cp.c: Update tree_pass descriptors.
* final.c: Update tree_pass descriptors.
* omp-low.c: Update tree_pass descriptors.
* tree-ssa-dse.c: Update tree_pass descriptors.
* ipa-reference.c: Update tree_pass descriptors.
* tree-ssa-uncprop.c: Update tree_pass descriptors.
* auto-inc-dec.c: Update tree_pass descriptors.
* reorg.c: Update tree_pass descriptors.
* cgraphunit.c: Update tree_pass descriptors.
* tree-ssa-copyrename.c: Update tree_pass descriptors.
* tree-ssa-ccp.c: Update tree_pass descriptors.
* df-core.c: Update tree_pass descriptors.
* mode-switching.c: Update tree_pass descriptors.
* tree-nomudflap.c: Update tree_pass descriptors.
* modulo-sched.c: Update tree_pass descriptors.
* ipa-pure-const.c: Update tree_pass descriptors.
* cse.c: Update tree_pass descriptors.
* web.c: Update tree_pass descriptors.
* tree-stdarg.c: Update tree_pass descriptors.
* tree-ssa-math-opts.c: Update tree_pass descriptors.
* tree-ssa-dom.c: Update tree_pass descriptors.
* tree-nrv.c: Update tree_pass descriptors.
* tree-ssa-alias.c: Update tree_pass descriptors.
* loop-init.c: Update tree_pass descriptors.
* gimple-low.c: Update tree_pass descriptors.
* ipa-inline.c: Update tree_pass descriptors.
* tree-ssa-sink.c: Update tree_pass descriptors.
* global.c: Update tree_pass descriptors.
* ifcvt.c: Update tree_pass descriptors.
* jump.c: Update tree_pass descriptors.
* predict.c: Update tree_pass descriptors.
* tree-ssa-loop.c: Update tree_pass descriptors.
* recog.c: Update tree_pass descriptors.
* dse.c: Update tree_pass descriptors.
* tree-ssa-ifcombine.c: Update tree_pass descriptors.
* tree-eh.c: Update tree_pass descriptors.
* regmove.c: Update tree_pass descriptors.
* local-alloc.c
* function.c: Update tree_pass descriptors.
* tree-vectorizer.c: Update tree_pass descriptors.
* gcse.c: Update tree_pass descriptors.
* ipa-type-escape.c: Update tree_pass descriptors.
* tree-if-conv.c: Update tree_pass descriptors.
* init-regs.c: Update tree_pass descriptors.
* ipa.c: Update tree_pass descriptors.
* tree-ssa-phiopt.c: Update tree_pass descriptors.
* rtl-factoring.c: Update tree_pass descriptors.
* lower-subreg.c: Update tree_pass descriptors.
* bt-load.c: Update tree_pass descriptors.
* tree-dfa.c: Update tree_pass descriptors.
* except.c: Update tree_pass descriptors.
* emit-rtl.c: Update tree_pass descriptors.
* cfgexpand.c: Update tree_pass descriptors.
* tree-cfgcleanup.c: Update tree_pass descriptors.
* cfgcleanup.c: Update tree_pass descriptors.
* tree-ssa-pre.c: Update tree_pass descriptors.
* tree-sra.c: Update tree_pass descriptors.
* tree-mudflap.c: Update tree_pass descriptors.
* tree-ssa-copy.c: Update tree_pass descriptors.
* cfglayout.c: Update tree_pass descriptors.
* tree-ssa-forwprop.c: Update tree_pass descriptors.
* tree-ssa-dce.c: Update tree_pass descriptors.
* tree-ssa.c: Update tree_pass descriptors.
* regclass.c: Update tree_pass descriptors.
* integrate.c: Update tree_pass descriptors.
* tree-optimize.c: Update tree_pass descriptors.
* tree-ssa-phiprop.c: Update tree_pass descriptors.
* tree-object-size.c: Update tree_pass descriptors.
* combine.c: Update tree_pass descriptors.
* tree-outof-ssa.c: Update tree_pass descriptors.
* bb-reorder.c: Update tree_pass descriptors.
* stack-ptr-mod.c: Update tree_pass descriptors.
* var-tracking.c: Update tree_pass descriptors.
* tree-profile.c: Update tree_pass descriptors.
* tree-vect-generic.c: Update tree_pass descriptors.
* reg-stack.c: Update tree_pass descriptors.
* sched-rgn.c: Update tree_pass descriptors.
* tree-ssa-structalias.c: Update tree_pass descriptors.
* tree-cfg.c: Update tree_pass descriptors.
* passes.c (current_pass): Update declaration.
(finish_optimization_passes): Update.
(all_passes, all_ipa_passes, all_lowering_passes): Update declaration.
(register_one_dump_file, register_dump_files_1, next_pass_1):
Update arguments.
(init_optimization_passes): Update handling of new types.
(execute_one_pass, execute_pass_list, execute_ipa_pass_list): Update.
* ipa-struct-reorg.c: Update tree_pass descriptors.
* tree-ssa-reassoc.c: Update tree_pass descriptors.
* combine-stack-adj.c: Update tree_pass descriptors.
* cfgrtl.c: Update tree_pass descriptors.
* dce.c: Update tree_pass descriptors.
* tree-ssanames.c: Update tree_pass descriptors.
From-SVN: r133342
2008-03-19 12:22:40 +01:00
|
|
|
{
|
|
|
|
GIMPLE_PASS,
|
2009-05-29 18:47:31 +02:00
|
|
|
"sra", /* name */
|
|
|
|
gate_intra_sra, /* gate */
|
|
|
|
late_intra_sra, /* execute */
|
2004-05-13 08:41:07 +02:00
|
|
|
NULL, /* sub */
|
|
|
|
NULL, /* next */
|
|
|
|
0, /* static_pass_number */
|
|
|
|
TV_TREE_SRA, /* tv_id */
|
2009-05-29 18:47:31 +02:00
|
|
|
PROP_cfg | PROP_ssa, /* properties_required */
|
2004-05-13 08:41:07 +02:00
|
|
|
0, /* properties_provided */
|
2009-05-29 18:47:31 +02:00
|
|
|
0, /* properties_destroyed */
|
re PR middle-end/13146 (inheritance for nonoverlapping_component_refs_p)
2009-04-03 Richard Guenther <rguenther@suse.de>
PR middle-end/13146
PR tree-optimization/23940
PR tree-optimization/33237
PR middle-end/33974
PR middle-end/34093
PR tree-optimization/36201
PR tree-optimization/36230
PR tree-optimization/38049
PR tree-optimization/38207
PR tree-optimization/38230
PR tree-optimization/38301
PR tree-optimization/38585
PR middle-end/38895
PR tree-optimization/38985
PR tree-optimization/39299
* tree-ssa-structalias.h: Remove.
* tree-ssa-operands.h (NULL_USE_OPERAND_P): Make of type use_operand_p.
(NULL_DEF_OPERAND_P): Make of type def_operand_p.
(struct vuse_element_d): Remove.
(struct vuse_vec_d): Likewise.
(VUSE_VECT_NUM_ELEM, VUSE_VECT_ELEMENT_NC, VUSE_ELEMENT_PTR_NC,
VUSE_ELEMENT_VAR_NC, VUSE_VECT_ELEMENT, VUSE_ELEMENT_PTR,
SET_VUSE_VECT_ELEMENT, SET_VUSE_ELEMENT_VAR, SET_VUSE_ELEMENT_PTR,
VUSE_ELEMENT_VAR): Likewise.
(struct voptype_d): Likewise.
(NUM_VOP_FREE_BUCKETS): Likewise.
(struct ssa_operands): Remove vop_free_buckets and mpt_table fields.
(struct stmt_operands_d): Remove.
(VUSE_OP_PTR, VUSE_OP, SET_VUSE_OP, VUSE_NUM, VUSE_VECT,
VDEF_RESULT_PTR, VDEF_RESULT, VDEF_OP_PTR, VDEF_OP, SET_VDEF_OP,
VDEF_NUM, VDEF_VECT): Likewise.
(copy_virtual_operands): Remove.
(operand_build_cmp): Likewise.
(create_ssa_artificial_load_stmt): Likewise.
(enum ssa_op_iter_type): Remove ssa_op_iter_vdef.
(struct ssa_operand_iterator_d): Remove vuses, vdefs, mayusesm
vuse_index and mayuse_index members. Pack and move done and iter_type
members to the front.
(SSA_OP_VMAYUSE): Remove.
(SSA_OP_VIRTUAL_USES): Adjust.
(FOR_EACH_SSA_VDEF_OPERAND): Remove.
(unlink_stmt_vdef): Declare.
(add_to_addressable_set): Remove.
* tree-vrp.c (stmt_interesting_for_vrp): Adjust.
(vrp_visit_stmt): Likewise.
* doc/tree-ssa.texi (Alias analysis): Update.
* doc/invoke.texi (max-aliased-vops): Remove docs.
(avg-aliased-vops): Likewise.
* tree-into-ssa.c (syms_to_rename): Remove.
(need_to_update_vops_p): Likewise.
(need_to_initialize_update_ssa_p): Rename to ...
(update_ssa_initialized_fn): ... this. Track function we are
initialized for.
(symbol_marked_for_renaming): Simplify.
(add_new_name_mapping): Do not set need_to_update_vops_p.
(dump_currdefs): Use SYMS_TO_RENAME.
(rewrite_update_stmt): Always walk all uses/defs.
(dump_update_ssa): Adjust.
(init_update_ssa): Take function argument. Track what we are
initialized for.
(delete_update_ssa): Reset SYMS_TO_RENAME and update_ssa_initialized_fn.
(create_new_def_for): Initialize for cfun, assert we are initialized
for cfun.
(mark_sym_for_renaming): Simplify.
(mark_set_for_renaming): Do not initialize update-ssa.
(need_ssa_update_p): Simplify. Take function argument.
(name_mappings_registered_p): Assert we ask for the correct function.
(name_registered_for_update_p): Likewise.
(ssa_names_to_replace): Likewise.
(release_ssa_name_after_update_ssa): Likewise.
(update_ssa): Likewise. Use SYMS_TO_RENAME.
(dump_decl_set): Do not print a newline.
(debug_decl_set): Do it here.
(dump_update_ssa): And here.
* tree-ssa-loop-im.c (move_computations): Adjust.
(movement_possibility): Likewise.
(determine_max_movement): Likewise.
(gather_mem_refs_stmt): Likewise.
* tree-dump.c (dequeue_and_dump): Do not handle SYMBOL_MEMORY_TAG
or NAME_MEMORY_TAG.
* tree-complex.c (update_all_vops): Remove.
(expand_complex_move): Adjust.
* tree-ssa-loop-niter.c (chain_of_csts_start): Use NULL_TREE.
Simplify test for memory referencing statement. Exclude
non-invariant ADDR_EXPRs.
* tree-pretty-print.c (dump_generic_node): Do not handle memory tags.
* tree-loop-distribution.c (generate_memset_zero): Adjust.
(rdg_flag_uses): Likewise.
* tree-tailcall.c (suitable_for_tail_opt_p): Remove memory-tag
related code.
(tree_optimize_tail_calls_1): Also split the
edge from the entry block if we have degenerate PHI nodes in
the first basic block.
* tree.c (init_ttree): Remove memory-tag related code.
(tree_code_size): Likewise.
(tree_node_structure): Likewise.
(build7_stat): Re-write to be build6_stat.
* tree.h (MTAG_P, TREE_MEMORY_TAG_CHECK, TMR_TAG): Remove.
(SSA_VAR_P): Adjust.
(struct tree_memory_tag): Remove.
(struct tree_memory_partition_tag): Likewise.
(union tree_node): Adjust.
(build7): Re-write to be build6.
* tree-pass.h (pass_reset_cc_flags): Remove.
(TODO_update_address_taken): New flag.
(pass_simple_dse): Remove.
* ipa-cp.c (ipcp_update_callgraph): Update SSA form.
* params.h (MAX_ALIASED_VOPS): Remove.
(AVG_ALIASED_VOPS): Likewise.
* omp-low.c (expand_omp_taskreg): Update SSA form.
* tree-ssa-dse.c (dse_optimize_stmt): Properly query if the rhs
aliases the lhs in a copy stmt.
* tree-ssa-dse.c (struct address_walk_data): Remove.
(memory_ssa_name_same): Likewise.
(memory_address_same): Likewise.
(get_kill_of_stmt_lhs): Likewise.
(dse_possible_dead_store_p): Simplify, use the oracle. Handle
unused stores. Look through PHI nodes into post-dominated regions.
(dse_optimize_stmt): Simplify. Properly remove stores.
(tree_ssa_dse): Compute dominators.
(execute_simple_dse): Remove.
(pass_simple_dse): Likewise.
* ipa-reference.c (scan_stmt_for_static_refs): Open-code
gimple_loaded_syms and gimple_stored_syms computation.
* toplev.c (dump_memory_report): Dump alias and pta stats.
* tree-ssa-sccvn.c (vn_reference_compute_hash): Simplify.
(vn_reference_eq): Likewise.
(vuses_to_vec, copy_vuses_from_stmt, vdefs_to_vec,
copy_vdefs_from_stmt, shared_lookup_vops, shared_vuses_from_stmt,
valueize_vuses): Remove.
(get_def_ref_stmt_vuses): Simplify. Rename to ...
(get_def_ref_stmt_vuse): ... this.
(vn_reference_lookup_2): New function.
(vn_reference_lookup_pieces): Use walk_non_aliased_vuses for
walking equivalent vuses. Simplify.
(vn_reference_lookup): Likewise.
(vn_reference_insert): Likewise.
(vn_reference_insert_pieces): Likewise.
(visit_reference_op_call): Simplify.
(visit_reference_op_load): Likewise.
(visit_reference_op_store): Likewise.
(init_scc_vn): Remove shared_lookup_vuses initialization.
(free_scc_vn): Remove shared_lookup_vuses freeing.
(sort_vuses, sort_vuses_heap): Remove.
(get_ref_from_reference_ops): Export.
* tree-ssa-sccvn.h (struct vn_reference_s): Replace vuses
vector with single vuse pointer.
(vn_reference_lookup_pieces, vn_reference_lookup,
vn_reference_insert, vn_reference_insert_pieces): Adjust prototypes.
(shared_vuses_from_stmt): Remove.
(get_ref_from_reference_ops): Declare.
* tree-ssa-loop-manip.c (slpeel_can_duplicate_loop_p): Adjust.
* tree-ssa-copyrename.c (copy_rename_partition_coalesce): Remove
memory-tag related code.
* tree-ssa-ccp.c (get_symbol_constant_value): Remove memory-tag code.
(likely_value): Add comment, skip static-chain of call statements.
(surely_varying_stmt_p): Adjust.
(gimplify_and_update_call_from_tree): Likewise.
(execute_fold_all_builtins): Do not rebuild alias info.
(gimplify_and_update_call_from_tree): Properly update VOPs.
* tree-ssa-loop-ivopts.c (get_ref_tag): Remove.
(copy_ref_info): Remove memory-tag related code.
* tree-call-cdce.c (tree_call_cdce): Rename the VOP.
* ipa-pure-const.c (check_decl): Remove memory-tag related code.
(check_stmt): Open-code gimple_loaded_syms and gimple_stored_syms
computation.
* tree-ssa-dom.c (gimple_p): Remove typedef.
(eliminate_redundant_computations): Adjust.
(record_equivalences_from_stmt): Likewise.
(avail_expr_hash): Likewise.
(avail_expr_eq): Likewise.
* tree-ssa-propagate.c (update_call_from_tree): Properly
update VOPs.
(stmt_makes_single_load): Likewise.
(stmt_makes_single_store): Likewise.
* tree-ssa-alias.c: Rewrite completely.
(debug_memory_partitions, dump_mem_ref_stats, debug_mem_ref_stats,
debug_mem_sym_stats, dump_mem_sym_stats_for_var,
debug_all_mem_sym_stats, debug_mp_info, update_mem_sym_stats_from_stmt,
delete_mem_ref_stats, create_tag_raw, dump_points_to_info,
dump_may_aliases_for, debug_may_aliases_for, new_type_alias):
Remove public functions.
(pass_reset_cc_flags): Remove.
(pass_build_alias): Move ...
* tree-ssa-structalias.c (pass_build_alias): ... here.
* tree-ssa-alias.c (may_be_aliased): Move ...
* tree-flow-inline.h (may_be_aliased): ... here.
tree-ssa-alias.c (struct count_ptr_d, count_ptr_derefs,
count_uses_and_derefs): Move ...
* gimple.c: ... here.
* gimple.h (count_uses_and_derefs): Declare.
* tree-ssa-alias.c (dump_alias_stats, ptr_deref_may_alias_global_p,
ptr_deref_may_alias_decl_p, ptr_derefs_may_alias_p,
same_type_for_tbaa, nonaliasing_component_refs_p, decl_refs_may_alias_p,
indirect_ref_may_alias_decl_p, indirect_refs_may_alias_p,
ref_maybe_used_by_call_p, ref_maybe_used_by_stmt_p,
call_may_clobber_ref_p, stmt_may_clobber_ref_p, maybe_skip_until,
get_continuation_for_phi, walk_non_aliased_vuses, walk_aliased_vdefs):
New functions.
* tree-dfa.c (refs_may_alias_p): Move ...
* tree-ssa-alias.c (refs_may_alias_p): ... here. Extend.
* tree-ssa-alias.h: New file.
* tree-ssa-sink.c (is_hidden_global_store): Adjust.
(statement_sink_location): Likewise.
* opts.c (decode_options): Do not adjust max-aliased-vops or
avg-aliased-vops values.
* timevar.def (TV_TREE_MAY_ALIAS): Remove.
(TV_CALL_CLOBBER): Likewise.
(TV_FLOW_SENSITIVE): Likewise.
(TV_FLOW_INSENSITIVE): Likewise.
(TV_MEMORY_PARTITIONING): Likewise.
(TV_ALIAS_STMT_WALK): New timevar.
* tree-ssa-loop-ivcanon.c (empty_loop_p): Adjust.
* tree-ssa-address.c (create_mem_ref_raw): Use build6.
(get_address_description): Remove memory-tag related code.
* tree-ssa-ifcombine.c (bb_no_side_effects_p): Adjust.
* treestruct.def (TS_MEMORY_TAG, TS_MEMORY_PARTITION_TAG): Remove.
* tree-eh.c (cleanup_empty_eh): Do not leave stale SSA_NAMEs
and immediate uses in statements. Document.
* gimple-pretty-print.c (dump_gimple_mem_ops): Adjust.
(dump_symbols): Remove.
(dump_gimple_mem_ops): Do not dump loaded or stored syms.
* alias.c (get_deref_alias_set): New function split out from ...
(get_alias_set): ... here.
* alias.h (get_deref_alias_set): Declare.
* tree-vect-data-refs.c (vect_create_data_ref_ptr): Remove unused
type parameter. Remove restrict pointer handling. Create a
ref-all pointer in case type-based alias sets do not conflict.
(vect_analyze_data_refs): Remove SMT related code.
* tree-vect-stmts.c (vectorizable_store): Re-instantiate TBAA assert.
(vectorizable_load): Likewise.
* tree-data-ref.h (struct dr_alias): Remove symbol_tag field.
(DR_SYMBOL_TAG, DR_VOPS): Remove.
* tree-data-ref.c (dr_may_alias_p): Use the alias-oracle.
Ignore vops and SMTs.
(dr_analyze_alias): Likewise..
(free_data_ref): Likewise.
(create_data_ref): Likewise.
(analyze_all_data_dependences): Likewise.
(get_references_in_stmt): Adjust.
* tree-flow-inline.h (gimple_aliases_computed_p,
gimple_addressable_vars, gimple_call_clobbered_vars,
gimple_call_used_vars, gimple_global_var, may_aliases, memory_partition,
factoring_name_p, mark_call_clobbered, clear_call_clobbered,
compare_ssa_operands_equal, symbol_mem_tag, set_symbol_mem_tag,
gimple_mem_ref_stats): Remove.
(gimple_vop): New function.
(op_iter_next_use): Remove vuses and mayuses cases.
(op_iter_next_def): Remove vdefs case.
(op_iter_next_tree): Remove vuses, mayuses and vdefs cases.
(clear_and_done_ssa_iter): Do not set removed fields.
(op_iter_init): Likewise. Skip vuse and/or vdef if requested.
Assert we are not iterating over vuses or vdefs if not also
iterating over uses or defs.
(op_iter_init_use): Likewise.
(op_iter_init_def): Likewise.
(op_iter_next_vdef): Remove.
(op_iter_next_mustdef): Likewise.
(op_iter_init_vdef): Likewise.
(compare_ssa_operands_equal): Likewise.
(link_use_stmts_after): Handle vuse operand.
(is_call_used): Use is_call_clobbered.
(is_call_clobbered): Global variables are always call clobbered,
query the call-clobbers bitmap.
(mark_call_clobbered): Ignore global variables.
(clear_call_clobbered): Likewise.
* tree-ssa-coalesce.c (create_outofssa_var_map): Adjust
virtual operands sanity check.
* tree.def (NAME_MEMORY_TAG, SYMBOL_MEMORY_TAG, MEMORY_PARTITION_TAG):
Remove.
(TARGET_MEM_REF): Remove TMR_TAG operand.
* tree-dfa.c (add_referenced_var): Initialize call-clobber state.
Remove call-clobber related code.
(remove_referenced_var): Likewise. Do not clear mpt or symbol_mem_tag.
(dump_variable): Do not dump SMTs, memory stats, may-aliases or
partitions or escape reason.
(get_single_def_stmt, get_single_def_stmt_from_phi,
get_single_def_stmt_with_phi): Remove.
(dump_referenced_vars): Tidy.
(get_ref_base_and_extent): Allow bare decls.
(collect_dfa_stats): Adjust.
* graphite.c (rename_variables_in_stmt): Adjust.
(graphite_copy_stmts_from_block): Likewise.
(translate_clast): Likewise.
* tree-ssa-pre.c (struct bb_bitmap_sets): Add expr_dies bitmap.
(EXPR_DIES): New.
(translate_vuse_through_block): Use the oracle.
(phi_translate_1): Adjust.
(value_dies_in_block_x): Use the oracle. Cache the outcome
in EXPR_DIES.
(valid_in_sets): Check if the VUSE for
a REFERENCE is available.
(eliminate): Do not remove stmts during elimination,
instead queue and remove them afterwards.
(do_pre): Do not rebuild alias info.
(pass_pre): Run TODO_rebuild_alias before PRE.
* tree-ssa-live.c (remove_unused_locals): Remove memory-tag code.
* tree-sra.c (sra_walk_function): Use gimple_references_memory_p.
(mark_all_v_defs_stmt): Remove.
(mark_all_v_defs_seq): Adjust.
(sra_replace): Likewise.
(scalarize_use): Likewise.
(scalarize_copy): Likewise.
(scalarize_init): Likewise.
(scalarize_ldst): Likewise.
(todoflags): Remove.
(tree_sra): Do not rebuild alias info.
(tree_sra_early): Adjust.
(pass_sra): Run TODO_update_address_taken before SRA.
* tree-predcom.c (set_alias_info): Remove.
(prepare_initializers_chain): Do not call it.
(mark_virtual_ops_for_renaming): Adjust.
(mark_virtual_ops_for_renaming_list): Remove.
(initialize_root_vars): Adjust.
(initialize_root_vars_lm): Likewise.
(prepare_initializers_chain): Likewise.
* tree-ssa-copy.c (may_propagate_copy): Remove memory-tag related code.
(may_propagate_copy_into_stmt): Likewise.
(merge_alias_info): Do nothing for now.
(propagate_tree_value_into_stmt): Adjust.
(stmt_may_generate_copy): Likewise.
* tree-ssa-forwprop.c (tidy_after_forward_propagate_addr): Do
not mark symbols for renaming.
(forward_propagate_addr_expr): Match up push/pop_stmt_changes
with the same statement, make sure to update the new pointed-to one.
* tree-ssa-dce.c (eliminate_unnecessary_stmts): Do not copy
call statements, do not mark symbols for renaming.
(mark_operand_necessary): Dump something.
(ref_may_be_aliased): New function.
(mark_aliased_reaching_defs_necessary_1): New helper function.
(mark_aliased_reaching_defs_necessary): Likewise.
(mark_all_reaching_defs_necessary_1): Likewise.
(mark_all_reaching_defs_necessary): Likewise.
(propagate_necessity): Do not process virtual PHIs. For
non-aliased loads mark all reaching definitions as necessary.
For aliased loads and stores mark the immediate dominating
aliased clobbers as necessary.
(visited): New global static.
(perform_tree_ssa_dce): Free visited bitmap after propagating
necessity.
(remove_dead_phis): Perform simple dead virtual PHI removal.
(remove_dead_stmt): Properly unlink virtual operands when
removing stores.
(eliminate_unnecessary_stmts): Schedule PHI removal after
stmt removal.
* tree-ssa-ter.c (is_replaceable_p): Adjust.
(process_replaceable): Likewise.
(find_replaceable_in_bb): Likewise.
* tree-ssa.c (verify_ssa_name): Verify all VOPs are
based on the single gimple vop.
(verify_flow_insensitive_alias_info): Remove.
(verify_flow_sensitive_alias_info): Likewise.
(verify_call_clobbering): Likewise.
(verify_memory_partitions): Likewise.
(verify_alias_info): Likewise.
(verify_ssa): Adjust..
(execute_update_addresses_taken): Export. Update SSA
manually. Optimize only when optimizing. Use a local bitmap.
(pass_update_address_taken): Remove TODO_update_ssa, add
TODO_dump_func.
(pass_update_address_taken): Just use TODO_update_address_taken.
(init_tree_ssa): Do not initialize addressable_vars.
(verify_ssa): Verify new VUSE / VDEF properties.
Verify that all stmts definitions have the stmt as SSA_NAME_DEF_STMT.
Do not call verify_alias_info.
(delete_tree_ssa): Clear the VUSE, VDEF operands.
Do not free the loaded and stored syms bitmaps. Reset the escaped
and callused solutions. Do not free addressable_vars.
Remove memory-tag related code.
(warn_uninitialized_var): Aliases are always available.
* tree-ssa-loop-prefetch.c (gather_memory_references): Adjust.
* lambda-code.c (can_put_in_inner_loop): Adjust.
(can_put_after_inner_loop): Likewise.
(perfect_nestify): Likewise.
* tree-vect-stmts.c (vect_stmt_relevant_p): Adjust.
(vect_gen_widened_results_half): Remove CALL_EXPR handling.
(vectorizable_conversion): Do not mark symbols for renaming.
* tree-inline.c (remap_gimple_stmt): Clear VUSE/VDEF.
(expand_call_inline): Unlink the calls virtual operands before
replacing it.
(tree_function_versioning): Do not call update_ssa if we are not
updating clones. Simplify.
* tree-ssa-phiprop.c (phivn_valid_p): Adjust.
(propagate_with_phi): Likewise..
* tree-outof-ssa.c (create_temp): Remove memory tag and call
clobber code. Assert we are not aliased or global.
* tree-flow.h: Include tree-ssa-alias.h
(enum escape_type): Remove.
(struct mem_sym_stats_d): Likewise.
(struct mem_ref_stats_d): Likewise.
(struct gimple_df): Add vop member. Remove global_var,
call_clobbered_vars, call_used_vars, addressable_vars,
aliases_compted_p and mem_ref_stats members. Add syms_to_rename,
escaped and callused members.
(struct ptr_info_def): Remove all members, add points-to solution
member pt.
(struct var_ann_d): Remove in_vuse_list, in_vdef_list,
call_clobbered, escape_mask, mpt and symbol_mem_tag members.
* Makefile.in (TREE_FLOW_H): Add tree-ssa-alias.h.
(tree-ssa-structalias.o): Remove tree-ssa-structalias.h.
(tree-ssa-alias.o): Likewise.
(toplev.o): Add tree-ssa-alias.h
(GTFILES): Remove tree-ssa-structalias.h, add tree-ssa-alias.h.
* gimple.c (gimple_set_bb): Fix off-by-one error.
(is_gimple_reg): Do not handle memory tags.
(gimple_copy): Also copy virtual operands.
Delay updating the statement. Do not reset loaded and stored syms.
(gimple_set_stored_syms): Remove.
(gimple_set_loaded_syms): Likewise.
(gimple_call_copy_skip_args): Copy the virtual operands
and mark the new statement modified.
* tree-ssa-structalias.c (may_alias_p): Remove.
(set_uids_in_ptset): Take the alias set to prune with as
parameter. Fold in the alias test of may_alias_p.
(compute_points_to_sets): Compute whether a ptr is dereferenced
in a local sbitmap.
(process_constraint): Deal with &ANYTHING on the lhs, reject all
other ADDRESSOF constraints on the lhs.
(get_constraint_for_component_ref): Assert that we don't get
ADDRESSOF constraints from the base of the reference.
Properly generate UNKNOWN_OFFSET for DEREF if needed.
(struct variable_info): Remove collapsed_to member.
(get_varinfo_fc): Remove.
(new_var_info): Do not set collapsed_to.
(dump_constraint): Do not follow cycles.
(dump_constraint_graph): Likewise.
(build_pred_graph): Likewise.
(build_succ_graph): Likewise.
(rewrite_constraints): Likewise.
(do_simple_structure_copy): Remove.
(do_rhs_deref_structure_copy): Remove.
(do_lhs_deref_structure_copy): Remove.
(collapse_rest_of_var): Remove.
(do_structure_copy): Re-implement.
(pta_stats): New global variable.
(dump_pta_stats): New function.
(struct constraint_expr): Make offset signed.
(UNKNOWN_OFFSET): Define special value.
(dump_constraint): Dump UNKNOWN_OFFSET as UNKNOWN.
(solution_set_expand): New helper function split out from ...
(do_sd_constraint): ... here.
(solution_set_add): Handle UNKNOWN_OFFSET. Handle negative offsets.
(do_ds_constraint): Likewise.
(do_sd_constraint): Likewise. Do not special-case ESCAPED = *ESCAPED
and CALLUSED = *CALLUSED.
(set_union_with_increment): Make inc argument signed.
(type_safe): Remove.
(get_constraint_for_ptr_offset): Handle unknown and negative
constant offsets.
(first_vi_for_offset): Handle offsets before start. Bail
out early for offsets beyond the variable extent.
(first_or_preceding_vi_for_offset): New function.
(init_base_vars): Add ESCAPED = ESCAPED + UNKNOWN_OFFSET constraint.
Together with ESCAPED = *ESCAPED this properly computes reachability.
(find_what_var_points_to): New function.
(find_what_p_points_to): Implement in terms of find_what_var_points_to.
(pt_solution_reset, pt_solution_empty_p, pt_solution_includes_global,
pt_solution_includes_1, pt_solution_includes, pt_solutions_intersect_1,
pt_solutions_intersect): New functions.
(compute_call_used_vars): Remove.
(compute_may_aliases): New main entry into PTA computation.
* gimple.h (gimple_p): New typedef.
(struct gimple_statement_base): Remove references_memory_p.
(struct gimple_statement_with_memory_ops_base): Remove
vdef_ops, vuse_ops, stores and loads members. Add vdef and vuse
members.
(gimple_vuse_ops, gimple_set_vuse_ops, gimple_vdef_ops,
gimple_set_vdef_ops, gimple_loaded_syms, gimple_stored_syms,
gimple_set_references_memory): Remove.
(gimple_vuse_op, gimple_vdef_op, gimple_vuse, gimple_vdef,
gimple_vuse_ptr, gimple_vdef_ptri, gimple_set_vuse, gimple_set_vdef):
New functions.
* tree-cfg.c (move_block_to_fn): Fix off-by-one error.
(verify_expr): Allow RESULT_DECL.
(gimple_duplicate_bb): Do not copy virtual operands.
(gimple_duplicate_sese_region): Adjust.
(gimple_duplicate_sese_tail): Likewise.
(mark_virtual_ops_in_region): Remove.
(move_sese_region_to_fn): Do not call it.
* passes.c (init_optimization_passes): Remove pass_reset_cc_flags
and pass_simple_dse.
(execute_function_todo): Handle TODO_update_address_taken,
call execute_update_addresses_taken for TODO_rebuild_alias.
(execute_todo): Adjust.
(execute_one_pass): Init dump files early.
* ipa-struct-reorg.c (finalize_var_creation): Do not mark vars
call-clobbered.
(create_general_new_stmt): Clear vops.
* tree-ssa-reassoc.c (get_rank): Adjust.
* tree-vect-slp.c (vect_create_mask_and_perm): Do not mark
symbols for renaming.
* params.def (PARAM_MAX_ALIASED_VOPS): Remove.
(PARAM_AVG_ALIASED_VOPS): Likewise.
* tree-ssanames.c (init_ssanames): Allocate SYMS_TO_RENAME.
(duplicate_ssa_name_ptr_info): No need to copy the shared bitmaps.
* tree-ssa-operands.c: Simplify for new virtual operand
representation.
(operand_build_cmp, copy_virtual_operands,
create_ssa_artificial_load_stmt, add_to_addressable_set,
gimple_add_to_addresses_taken): Remove public functions.
(unlink_stmt_vdef): New function.
* gcc.dg/pr19633-1.c: Adjust.
* gcc.dg/torture/pta-callused-1.c: Likewise.
* gcc.dg/torture/pr39074-2.c: Likewise.
* gcc.dg/torture/pr39074.c: Likewise.
* gcc.dg/torture/pta-ptrarith-3.c: New testcase.
* gcc.dg/torture/pr30375.c: Adjust.
* gcc.dg/torture/pr33563.c: Likewise.
* gcc.dg/torture/pr33870.c: Likewise.
* gcc.dg/torture/pr33560.c: Likewise.
* gcc.dg/torture/pta-structcopy-1.c: New testcase.
* gcc.dg/torture/ssa-pta-fn-1.c: Likewise.
* gcc.dg/tree-ssa/alias-15.c: Remove.
* gcc.dg/tree-ssa/ssa-dce-4.c: New testcase.
* gcc.dg/tree-ssa/pr26421.c: Adjust.
* gcc.dg/tree-ssa/ssa-fre-10.c: XFAIL.
* gcc.dg/tree-ssa/ssa-dce-5.c: New testcase.
* gcc.dg/tree-ssa/pr23382.c: Adjust.
* gcc.dg/tree-ssa/ssa-fre-20.c: New testcase.
* gcc.dg/tree-ssa/alias-16.c: Adjust.
* gcc.dg/tree-ssa/ssa-fre-13.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-14.c: Likewise.
* gcc.dg/tree-ssa/alias-18.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-15.c: Likewise.
* gcc.dg/tree-ssa/ssa-lim-3.c: Likewise.
* gcc.dg/tree-ssa/alias-19.c: Likewise.
* gcc.dg/tree-ssa/pta-ptrarith-1.c: New testcase.
* gcc.dg/tree-ssa/pr13146.c: Likewise.
* gcc.dg/tree-ssa/ssa-pre-23.c: Likewise.
* gcc.dg/tree-ssa/pta-ptrarith-2.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-18.c: Likewise.
* gcc.dg/tree-ssa/ssa-pre-24.c: New XFAILed testcase.
* gcc.dg/tree-ssa/ssa-fre-19.c: New testcase.
* gcc.dg/tree-ssa/alias-20.c: Likewise.
* gcc.dg/tree-ssa/ssa-dse-12.c: Likewise.
* gcc.dg/tree-ssa/pr38895.c: Likewise.
* gcc.dg/uninit-B.c: XFAIL.
* gcc.dg/vect/no-vfa-vect-43.c: Adjust.
* gcc.dg/uninit-pr19430.c: XFAIL.
* g++.dg/tree-ssa/pr13146.C: New testcase.
* g++.dg/opt/pr36187.C: Adjust.
* g++.dg/torture/20090329-1.C: New testcase.
From-SVN: r145494
2009-04-03 12:24:28 +02:00
|
|
|
TODO_update_address_taken, /* todo_flags_start */
|
[multiple changes]
2006-12-11 Diego Novillo <dnovillo@redhat.com>
* doc/tree-ssa.texi: Update documentation for virtual operands
and the use of push_stmt_changes/pop_stmt_changes.
* doc/invoke.texi: Remove documentation for params
global-var-threshold.
Update documentation on max-aliased-vops.
* tree-into-ssa.c: Cleanup comments, variables and
spacing in various functions.
(regs_to_rename): Declare.
(mem_syms_to_rename): Declare.
(dump_update_ssa): Declare.
(debug_update_ssa): Declare.
(dump_names_replaced_by): Declare.
(debug_names_replaced_by): Declare.
(dump_def_blocks): Declare.
(debug_def_blocks): Declare.
(dump_defs_stack): Declare.
(debug_defs_stack): Declare.
(dump_currdefs): Declare.
(debug_currdefs): Declare.
(mark_def_sites): Do not handle virtual operands.
(compute_idf): Rename from find_idf. Update users.
(register_new_def): Make local. Convert second argument
to 'tree'.
Use BLOCK_DEFS_STACK directly.
If pushing a non-register, also push the underlying
symbol.
(rewrite_stmt): Do not handle virtual operands.
(dump_tree_ssa): Call dump_def_blocks, dump_defs_stack,
dump_currdefs and dump_tree_ssa_stats.
(dump_tree_ssa_stats): Also dump REPL_TBL.
(replace_use): Remove. Update all users to call SET_USE
instead.
(rewrite_blocks): Move code to free memory to
fini_ssa_renamer.
(mark_def_site_blocks): Move initialization code to
init_ssa_renamer.
(init_ssa_renamer): New.
(fini_ssa_renamer): New.
(rewrite_into_ssa): Call them.
(prepare_block_for_update): Process SSA_OP_ALL_USES first
and SSA_OP_ALL_DEFS later. Do not process virtual
operands separately.
(dump_update_ssa): Call dump_decl_set.
(init_update_ssa): Initialize regs_to_rename and
mem_syms_to_rename.
Call init_ssa_renamer.
(delete_update_ssa): Call fini_ssa_renamer.
Free blocks_with_phis_to_rewrite.
(mark_sym_for_renaming): If the variable has
sub-variables, also mark them.
If the variable belongs to a partition, also mark it.
(mark_set_for_renaming): Call mark_sym_for_renaming on
every symbol in the set.
(switch_virtuals_to_full_rewrite): Call
mark_set_for_renaming.
(update_ssa): Separate syms_to_rename into regs_to_rename
and mem_syms_to_rename.
* tree-dump.c (dump_options): Add TDF_MEMSYMS.
* tree-pretty-print.c (debug_generic_expr): Add TDF_MEMSYMS.
(debug_generic_stmt): Likewise.
(debug_tree_chain): Likewise.
(dump_symbols): New.
(dump_generic_node): Check for TDF_MEMSYMS.
Handle MEMORY_PARTITION_TAG.
If the statement references memory and TDF_MEMSYMS is
given, call dump_symbols.
Indicate default names with (D).
(dump_vops): Update for new virtual operator format.
* tree.c (init_ttree): Add MEMORY_PARTITION_TAG to
tree_contains_struct.
(tree_code_size): Handle MEMORY_PARTITION_TAG.
(tree_node_structure): Likewise.
(needs_to_live_in_memory): Handle SSA names.
* tree.h (MTAG_P): Likewise.
(struct tree_memory_partition_tag): Declare.
(MPT_SYMBOLS): Define.
(union tree_node): Add field 'mpt'.
* treestruct.def (TS_MEMORY_PARTITION_TAG): Define.
* tree.def (MEMORY_PARTITION_TAG): Define.
* tree-pass.h (TDF_MEMSYMS): Define.
* params.h (GLOBAL_VAR_THRESHOLD): Remove.
* tree-ssa-alias.c: Include pointer-set.h
(struct alias_map_d): Remove fields total_alias_vops,
grouped_p and may_aliases. Update all users.
(struct mp_info_def): Declare.
(mp_info_t): New type.
(get_smt_for): Rename from get_tmt_for. Update all
users.
(add_may_alias): Add argument ALREADY_ADDED. If given,
use it to avoid adding duplicate entries to alias sets.
(replace_may_alias): Remove. Update all users.
(total_alias_vops_cmp): Remove. Update all users.
(group_aliases_into): Remove. Update all users.
(tree_pointer_compare): Remove. Update all users.
(compact_name_tags): Remove. Update all users.
(group_aliases): Remove. Update all users.
(mark_non_addressable): Move from tree-flow-inline.h.
Remove the symbol from the partition holding it, if
needed.
(dump_mp_info): New.
(debug_mp_info): New.
(sort_mp_info): New.
(create_partition_for): New.
(rewrite_alias_set_for): New.
(compute_memory_partitions): New.
(compute_may_aliases): Call it.
(init_alias_info): If computing aliases for the first
time, mark every memory symbol for renaming.
(have_common_aliases_p): New.
(compute_flow_insensitive_aliasing): Call it.
(setup_pointers_and_addressables): Do not cache
num_referenced_vars.
For register promoted symbols, mark their former
partition for renaming.
(maybe_create_global_var): Only create .GLOBAL_VAR if
there are no call-clobbered variables and a mix of pure
and non-pure functions were found.
(may_alias_p): Tidy comments.
(create_tag_raw): Remove unused variable new_type.
(dump_alias_info): call dump_memory_partitions.
(dump_points_to_info_for): Call dump_decl_set.
(may_be_aliased): Tidy comments and formatting.
* timevar.def (TV_MEMORY_PARTITIONING): Define.
* tree-vectorizer.c (vect_memsyms_to_rename): Rename from
vect_vnames_to_rename. Set DECL_UIDs instead of SSA name
versions in it.
(slpeel_update_phi_nodes_for_guard1): Ignore memory PHIs.
* tree-vect-transform.c (vect_transform_loop): Call
mark_set_for_renaming with vect_memsyms_to_rename.
* tree-flow-inline.h (zero_imm_uses_p): New.
(memory_partition): New.
(set_memory_partition): New.
(factoring_name_p): New.
(symbol_mem_tag): New. Update every function that used
to access the annotation directly.
(set_symbol_mem_tag): Likewise.
* tree-ssa-copy.c (may_propagate_copy): Allow copies
between a partition and a symbol as long as the symbol
belongs to the partition.
(merge_alias_info): Ignore merge requests when memory
partitions are involved.
* tree-ssa.c (verify_ssa_name): Check that default
definitions have empty defining statements.
(verify_use): Remove argument IS_VIRTUAL.
Don't call verify_ssa_name.
(verify_phi_args): Call verify_ssa_name.
(verify_flow_insensitive_alias_info): Handle MPTs.
(verify_flow_sensitive_alias_info): Likewise.
(verify_name_tags): Likewise.
(verify_call_clobbering): Likewise.
(verify_ssa): Check for VOPs only after aliasing
information is available.
Check virtuals and real operands separately.
Call verify_ssa_name on every operand.
(stmt_references_memory_p): Move to tree-ssa-operands.c.
(walk_use_def_chains_1): Guard against NULL PHI
arguments.
* tree-ssa-operands.c (stmt_references_memory_p): Move from
tree-ssa.c.
(get_mpt_for): New.
(dump_memory_partitions): New.
(debug_memory_partitions): New.
* tree-flow.h (struct var_ann_d): Add field mpt.
(struct stmt_ann_d): Add bitfield references_memory.
* Makefile.in (tree-ssa-structalias.o): Include
pointer-set.h
(tree-ssa-alias.o): Likewise.
* tree-ssa-structalias.c: (update_alias_info): Use
STORED_SYMS to determine which variables are being
written to by the store operation.
* tree-ssa-structalias.h (struct alias_info)
<total_alias_vops>: Remove. Update all users.
<written_vars>: Change to a pointer set. Update all
users.
<dereferenced_ptrs_store>: Likewise.
<dereferenced_ptrs_load>: Likewise.
(NUM_REFERENCES): Remove. Update all users.
(NUM_REFERENCES_CLEAR): Remove. Update all users.
(NUM_REFERENCES_INC): Remove. Update all users.
(NUM_REFERENCES_SET): Remove. Update all users.
* params.def (PARAM_GLOBAL_VAR_THRESHOLD): Remove.
Update all users.
(PARAM_MAX_ALIASED_VOPS): Set to 10.
* tree-ssanames.c (make_ssa_name): Initialize
SSA_NAME_IS_DEFAULT_DEF to 0.
2006-12-11 Aldy Hernandez <aldyh@redhat.com>
* tree-ssa-dse.c (aggregate_vardecl_d): New.
(dse_global_data): Add aggregate_vardecl field.
(dse_possible_dead_store_p): New.
Add prev_defvar variable.
Allow immediate uses and previous immediate uses to differ
if they are setting different parts of the whole.
(get_aggregate_vardecl): New.
(dse_record_partial_aggregate_store): New.
(dse_whole_aggregate_clobbered_p): New.
(dse_partial_kill_p): New.
(dse_optimize_stmt): Abstract code checking a possible dead store
into new function dse_possible_dead_store_p().
Call dse_maybe_record_aggregate_store().
When checking whether a STMT and its USE_STMT refer to the
same memory address, check also for partial kills that clobber
the whole.
Move some variable definitions to the block where they are used.
(aggregate_vardecl_hash): New.
(aggregate_vardecl_eq): New.
(aggregate_vardecl_free): New.
(aggregate_whole_store_p): New.
(tree_ssa_dse): Initialize and free aggregate_vardecl.
Mark which aggregate stores we care about.
2006-12-11 Andrew Macleod <amacleod@redhat.com>
* tree-ssa-operands.h (struct vuse_element_d): Declare.
(vuse_element_t): Declare.
(struct vuse_vec_d): Declare.
(vuse_vec_p): Declare.
(VUSE_VECT_NUM_ELEM): Define.
(VUSE_VECT_ELEMENT_NC): Define.
(VUSE_ELEMENT_PTR_NC): Define.
(VUSE_ELEMENT_VAR_NC): Define.
(VUSE_VECT_ELEMENT): Define.
(VUSE_ELEMENT_PTR): Define.
(VUSE_ELEMENT_VAR): Define.
(struct maydef_optype_d) <use_var>: Remove.
<use_ptr>: Remove.
<usev>: Add.
(struct vuse_optype_d) <kill_var>: Remove.
<use_ptr>: Remove.
<usev>: Add.
(struct mustdef_optype_d) <kill_var>: Remove.
<use_ptr>: Remove.
<usev>: Add.
(VUSE_OP_PTR): Add argument. Use VUSE_ELEMENT_PTR.
(VUSE_OP): Add argument. Use VUSE_ELEMENT_PTR.
(VUSE_NUM): Define.
(VUSE_VECT): Define.
(MAYDEF_OP_PTR): Add argument. Use VUSE_OP_PTR.
(MAYDEF_OP): Add argument. Use VUSE_OP.
(MAYDEF_NUM): Define.
(MAYDEF_VECT): Define.
(MUSTDEF_KILL_PTR): Use VUSE_OP_PTR.
(MUSTDEF_KILL): Use VUSE_OP.
(MUSTDEF_NUM): Define.
(MUSTDEF_VECT): Define.
(realloc_maydef): Declare.
(realloc_vuse): Declare.
(struct ssa_operand_iterator_d) <vuse_index>: Add.
<mayuse_index>: Add.
(LOADED_SYMS): Define.
(STORED_SYMS): Define.
(FOR_EACH_SSA_MUSTDEF_OPERAND): Call op_iter_next_mustdef.
* tree-into-ssa.c: Adapt for multi-operand V_MAY_DEF and VUSE
operators.
* tree-pretty-print.c: Likewise.
* tree-ssa-dse.c: Likewise.
* tree-flow-inline.h: Likewise.
(op_iter_next_mustdef): New.
* tree-ssa-operands.c: Likewise.
(ALLOC_OPTYPE): Remove.
Update all users.
(alloc_def): New.
(alloc_use): New.
(alloc_maydef): New.
(alloc_vuse): New.
(alloc_mustdef): New.
(realloc_maydef): New.
(realloc_vuse): New.
2006-12-11 Aldy Hernandez <aldyh@redhat.com>
* tree-ssa-operands.c: Remove build_v_must_defs.
(init_ssa_operands): Delete build_v_must_defs.
(finalize_ssa_v_must_def_ops): Remove.
(finalize_ssa_v_must_defs): Remove.
(finalize_ssa_stmt_operands): Do not call
finalize_ssa_v_must_defs.
(start_ssa_stmt_operands): Do not check build_v_must_defs.
(append_v_must_def): Delete.
(copy_virtual_operands): Do not copy V_MUST_DEFs.
(get_modify_expr_operands): Remove reference to V_MUST_DEF from
comment. Remove opf_kill_def.
(build_ssa_operands): Remove references to v_must_defs.
(copy_virtual_operands): Same.
(copy_virtual_operands): Same.
(fini_ssa_operands): Same.
(free_ssa_operands): Same.
(add_mustdef_op): Remove.
Remove mustdef_optype_p.
(alloc_mustdef): Remove.
Remove references to V_MUST_DEFs in comment at top of file.
(get_expr_operands): Remove opf_kill_def.
(opf_kill_def): Remove.
(add_virtual_operand): Remove opf_kill_def.
(get_indirect_ref_operands): Same.
(get_tmr_operands): Same.
* tree-vectorizer.c (rename_variables_in_bb): Remove
SSA_OP_ALL_KILLS.
* tree-ssa-loop-manip.c (find_uses_to_rename_stmt): Remove
SSA_OP_ALL_KILLS.
(check_loop_closed_ssa_stmt): Same.
* tree-ssa.c (verify_def): Remove V_MUST_DEF from comment.
(verify_use): Same.
(verify_ssa): Remove V_MUST_DEFs traces.
(verify_ssa): Remove SSA_OP_ALL_KILLS.
* tree-into-ssa.c (mark_def_sites): Change SSA_OP_VMUSTDEF to
SSA_OP_VMAYDEF.
(rewrite_update_stmt): Remove SSA_OP_VIRTUAL_KILLS.
(rewrite_stmt): Remove SSA_OP_ALL_KILLS.
* tree-ssa-operands.h (struct stmt_operands_d): Remove V_MUST_DEF
references.
(MUSTDEF_OPS): Remove.
(SSA_OP_VMUSTDEF): Remove.
(FOR_EACH_SSA_MUSTDEF_OPERAND): Remove.
(struct mustdef_optype_d): Remove.
Remove mustdef_optype_p.
(struct stmt_operands_d): Remove mustdef_ops.
(ssa_operand_iterator_d): Remove mustdefs and mustkills.
(SSA_OP_VIRTUAL_DEFS): Remove SSA_OP_VMUSTDEF.
(MUSTDEF_RESULT_PTR): Remove.
(MUSTDEF_RESULT): Remove.
(MUSTDEF_KILL_PTR): Remove.
(MUSTDEF_KILL): Remove.
(MUSTDEF_NUM): Remove.
(MUSTDEF_VECT): Remove.
(SSA_OP_VIRTUAL_KILLS): Remove.
(SSA_OP_ALL_VIRTUALS): Remove SSA_OP_VIRTUAL_KILLS.
(SSA_OP_VMUSTKILL): Remove.
(SSA_OP_ALL_KILLS): Remove.
(SSA_OP_ALL_OPERANDS): Remove SSA_OP_ALL_KILLS.
* tree-flow-inline.h (op_iter_init_def): Remove
SSA_OP_VIRTUAL_KILLS.
(delink_stmt_imm_use): Remove SSA_OP_ALL_KILLS.
* tree-ssa-pre.c (compute_rvuse_and_antic_safe): Remove
SSA_OP_VIRTUAL_KILLS.
* tree-ssa-loop-im.c (determine_max_movement): Remove
SSA_OP_VIRTUAL_KILLS.
(gather_mem_refs_stmt): Same.
(gather_mem_refs_stmt): Same.
* tree-ssa-dce.c (mark_really_necessary_kill_operand_phis): Delete.
(perform_tree_ssa_dce): Remove call to
mark_really_necessary_kill_operand_phis.
* tree-flow-inline.h (op_iter_init): Remove setting of mustdefs
and mustkills.
(op_iter_next_use): Do not check mustkills.
(op_iter_next_def): Do not check mustdefs.
(op_iter_next_tree): Do not check mustkills or mustdefs.
(clear_and_done_ssa_iter): Do not set mustdefs or mustkills.
(op_iter_next_maymustdef): Do not check mustkills.
(op_iter_init_must_and_may_def): Remove SSA_OP_VMUSTKILL.
(op_iter_init_mustdef): Remove.
* tree-ssa-live.c (create_ssa_var_map): Change SSA_OP_VMUSTDEF to
SSA_OP_VMAYDEF.
* tree-ssa-dse.c (dse_optimize_stmt): Remove SSA_OP_VMUSTDEF.
* tree-ssa-ccp.c: Remove V_MUST_DEF traces from comments.
(visit_assignment): Same.
* tree-ssa-copy.c (copy_prop_visit_assignment): Same.
* tree-sra.c (mark_all_v_defs_1): Remove V_MUST_DEF from comment.
* tree-outof-ssa.c (check_replaceable): Remove SSA_OP_VMUSTDEF.
* tree-pretty-print.c (dump_vops): Remove printing of V_MUST_DEF.
Remove kill_p variable.
* tree-dfa.c (struct dfa_stats_d): Remove num_v_must_defs.
(dump_dfa_stats): Remove code related to V_MUST_DEFs.
(collect_dfa_stats_r): Do not set num_v_must_defs.
(mark_new_vars_to_rename): Remove v_must_defs_{before,after}
code.
* tree-into-ssa.c (mark_def_sites): Change SSA_OP_VMUSTKILL to
SSA_OP_VMAYUSE.
* tree-ssa-pre.c (compute_rvuse_and_antic_safe): Remove
SSA_OP_VMUSTDEF and SSA_OP_VMUSTKILL.
* tree-ssa-propagate.c (stmt_makes_single_store): Remove
SSA_OP_VMUSTDEF.
From-SVN: r119760
2006-12-12 02:48:51 +01:00
|
|
|
TODO_dump_func
|
2006-02-20 14:38:01 +01:00
|
|
|
| TODO_update_ssa
|
[multiple changes]
2006-12-11 Diego Novillo <dnovillo@redhat.com>
* doc/tree-ssa.texi: Update documentation for virtual operands
and the use of push_stmt_changes/pop_stmt_changes.
* doc/invoke.texi: Remove documentation for params
global-var-threshold.
Update documentation on max-aliased-vops.
* tree-into-ssa.c: Cleanup comments, variables and
spacing in various functions.
(regs_to_rename): Declare.
(mem_syms_to_rename): Declare.
(dump_update_ssa): Declare.
(debug_update_ssa): Declare.
(dump_names_replaced_by): Declare.
(debug_names_replaced_by): Declare.
(dump_def_blocks): Declare.
(debug_def_blocks): Declare.
(dump_defs_stack): Declare.
(debug_defs_stack): Declare.
(dump_currdefs): Declare.
(debug_currdefs): Declare.
(mark_def_sites): Do not handle virtual operands.
(compute_idf): Rename from find_idf. Update users.
(register_new_def): Make local. Convert second argument
to 'tree'.
Use BLOCK_DEFS_STACK directly.
If pushing a non-register, also push the underlying
symbol.
(rewrite_stmt): Do not handle virtual operands.
(dump_tree_ssa): Call dump_def_blocks, dump_defs_stack,
dump_currdefs and dump_tree_ssa_stats.
(dump_tree_ssa_stats): Also dump REPL_TBL.
(replace_use): Remove. Update all users to call SET_USE
instead.
(rewrite_blocks): Move code to free memory to
fini_ssa_renamer.
(mark_def_site_blocks): Move initialization code to
init_ssa_renamer.
(init_ssa_renamer): New.
(fini_ssa_renamer): New.
(rewrite_into_ssa): Call them.
(prepare_block_for_update): Process SSA_OP_ALL_USES first
and SSA_OP_ALL_DEFS later. Do not process virtual
operands separately.
(dump_update_ssa): Call dump_decl_set.
(init_update_ssa): Initialize regs_to_rename and
mem_syms_to_rename.
Call init_ssa_renamer.
(delete_update_ssa): Call fini_ssa_renamer.
Free blocks_with_phis_to_rewrite.
(mark_sym_for_renaming): If the variable has
sub-variables, also mark them.
If the variable belongs to a partition, also mark it.
(mark_set_for_renaming): Call mark_sym_for_renaming on
every symbol in the set.
(switch_virtuals_to_full_rewrite): Call
mark_set_for_renaming.
(update_ssa): Separate syms_to_rename into regs_to_rename
and mem_syms_to_rename.
* tree-dump.c (dump_options): Add TDF_MEMSYMS.
* tree-pretty-print.c (debug_generic_expr): Add TDF_MEMSYMS.
(debug_generic_stmt): Likewise.
(debug_tree_chain): Likewise.
(dump_symbols): New.
(dump_generic_node): Check for TDF_MEMSYMS.
Handle MEMORY_PARTITION_TAG.
If the statement references memory and TDF_MEMSYMS is
given, call dump_symbols.
Indicate default names with (D).
(dump_vops): Update for new virtual operator format.
* tree.c (init_ttree): Add MEMORY_PARTITION_TAG to
tree_contains_struct.
(tree_code_size): Handle MEMORY_PARTITION_TAG.
(tree_node_structure): Likewise.
(needs_to_live_in_memory): Handle SSA names.
* tree.h (MTAG_P): Likewise.
(struct tree_memory_partition_tag): Declare.
(MPT_SYMBOLS): Define.
(union tree_node): Add field 'mpt'.
* treestruct.def (TS_MEMORY_PARTITION_TAG): Define.
* tree.def (MEMORY_PARTITION_TAG): Define.
* tree-pass.h (TDF_MEMSYMS): Define.
* params.h (GLOBAL_VAR_THRESHOLD): Remove.
* tree-ssa-alias.c: Include pointer-set.h
(struct alias_map_d): Remove fields total_alias_vops,
grouped_p and may_aliases. Update all users.
(struct mp_info_def): Declare.
(mp_info_t): New type.
(get_smt_for): Rename from get_tmt_for. Update all
users.
(add_may_alias): Add argument ALREADY_ADDED. If given,
use it to avoid adding duplicate entries to alias sets.
(replace_may_alias): Remove. Update all users.
(total_alias_vops_cmp): Remove. Update all users.
(group_aliases_into): Remove. Update all users.
(tree_pointer_compare): Remove. Update all users.
(compact_name_tags): Remove. Update all users.
(group_aliases): Remove. Update all users.
(mark_non_addressable): Move from tree-flow-inline.h.
Remove the symbol from the partition holding it, if
needed.
(dump_mp_info): New.
(debug_mp_info): New.
(sort_mp_info): New.
(create_partition_for): New.
(rewrite_alias_set_for): New.
(compute_memory_partitions): New.
(compute_may_aliases): Call it.
(init_alias_info): If computing aliases for the first
time, mark every memory symbol for renaming.
(have_common_aliases_p): New.
(compute_flow_insensitive_aliasing): Call it.
(setup_pointers_and_addressables): Do not cache
num_referenced_vars.
For register promoted symbols, mark their former
partition for renaming.
(maybe_create_global_var): Only create .GLOBAL_VAR if
there are no call-clobbered variables and a mix of pure
and non-pure functions were found.
(may_alias_p): Tidy comments.
(create_tag_raw): Remove unused variable new_type.
(dump_alias_info): call dump_memory_partitions.
(dump_points_to_info_for): Call dump_decl_set.
(may_be_aliased): Tidy comments and formatting.
* timevar.def (TV_MEMORY_PARTITIONING): Define.
* tree-vectorizer.c (vect_memsyms_to_rename): Rename from
vect_vnames_to_rename. Set DECL_UIDs instead of SSA name
versions in it.
(slpeel_update_phi_nodes_for_guard1): Ignore memory PHIs.
* tree-vect-transform.c (vect_transform_loop): Call
mark_set_for_renaming with vect_memsyms_to_rename.
* tree-flow-inline.h (zero_imm_uses_p): New.
(memory_partition): New.
(set_memory_partition): New.
(factoring_name_p): New.
(symbol_mem_tag): New. Update every function that used
to access the annotation directly.
(set_symbol_mem_tag): Likewise.
* tree-ssa-copy.c (may_propagate_copy): Allow copies
between a partition and a symbol as long as the symbol
belongs to the partition.
(merge_alias_info): Ignore merge requests when memory
partitions are involved.
* tree-ssa.c (verify_ssa_name): Check that default
definitions have empty defining statements.
(verify_use): Remove argument IS_VIRTUAL.
Don't call verify_ssa_name.
(verify_phi_args): Call verify_ssa_name.
(verify_flow_insensitive_alias_info): Handle MPTs.
(verify_flow_sensitive_alias_info): Likewise.
(verify_name_tags): Likewise.
(verify_call_clobbering): Likewise.
(verify_ssa): Check for VOPs only after aliasing
information is available.
Check virtuals and real operands separately.
Call verify_ssa_name on every operand.
(stmt_references_memory_p): Move to tree-ssa-operands.c.
(walk_use_def_chains_1): Guard against NULL PHI
arguments.
* tree-ssa-operands.c (stmt_references_memory_p): Move from
tree-ssa.c.
(get_mpt_for): New.
(dump_memory_partitions): New.
(debug_memory_partitions): New.
* tree-flow.h (struct var_ann_d): Add field mpt.
(struct stmt_ann_d): Add bitfield references_memory.
* Makefile.in (tree-ssa-structalias.o): Include
pointer-set.h
(tree-ssa-alias.o): Likewise.
* tree-ssa-structalias.c: (update_alias_info): Use
STORED_SYMS to determine which variables are being
written to by the store operation.
* tree-ssa-structalias.h (struct alias_info)
<total_alias_vops>: Remove. Update all users.
<written_vars>: Change to a pointer set. Update all
users.
<dereferenced_ptrs_store>: Likewise.
<dereferenced_ptrs_load>: Likewise.
(NUM_REFERENCES): Remove. Update all users.
(NUM_REFERENCES_CLEAR): Remove. Update all users.
(NUM_REFERENCES_INC): Remove. Update all users.
(NUM_REFERENCES_SET): Remove. Update all users.
* params.def (PARAM_GLOBAL_VAR_THRESHOLD): Remove.
Update all users.
(PARAM_MAX_ALIASED_VOPS): Set to 10.
* tree-ssanames.c (make_ssa_name): Initialize
SSA_NAME_IS_DEFAULT_DEF to 0.
2006-12-11 Aldy Hernandez <aldyh@redhat.com>
* tree-ssa-dse.c (aggregate_vardecl_d): New.
(dse_global_data): Add aggregate_vardecl field.
(dse_possible_dead_store_p): New.
Add prev_defvar variable.
Allow immediate uses and previous immediate uses to differ
if they are setting different parts of the whole.
(get_aggregate_vardecl): New.
(dse_record_partial_aggregate_store): New.
(dse_whole_aggregate_clobbered_p): New.
(dse_partial_kill_p): New.
(dse_optimize_stmt): Abstract code checking a possible dead store
into new function dse_possible_dead_store_p().
Call dse_maybe_record_aggregate_store().
When checking whether a STMT and its USE_STMT refer to the
same memory address, check also for partial kills that clobber
the whole.
Move some variable definitions to the block where they are used.
(aggregate_vardecl_hash): New.
(aggregate_vardecl_eq): New.
(aggregate_vardecl_free): New.
(aggregate_whole_store_p): New.
(tree_ssa_dse): Initialize and free aggregate_vardecl.
Mark which aggregate stores we care about.
2006-12-11 Andrew Macleod <amacleod@redhat.com>
* tree-ssa-operands.h (struct vuse_element_d): Declare.
(vuse_element_t): Declare.
(struct vuse_vec_d): Declare.
(vuse_vec_p): Declare.
(VUSE_VECT_NUM_ELEM): Define.
(VUSE_VECT_ELEMENT_NC): Define.
(VUSE_ELEMENT_PTR_NC): Define.
(VUSE_ELEMENT_VAR_NC): Define.
(VUSE_VECT_ELEMENT): Define.
(VUSE_ELEMENT_PTR): Define.
(VUSE_ELEMENT_VAR): Define.
(struct maydef_optype_d) <use_var>: Remove.
<use_ptr>: Remove.
<usev>: Add.
(struct vuse_optype_d) <kill_var>: Remove.
<use_ptr>: Remove.
<usev>: Add.
(struct mustdef_optype_d) <kill_var>: Remove.
<use_ptr>: Remove.
<usev>: Add.
(VUSE_OP_PTR): Add argument. Use VUSE_ELEMENT_PTR.
(VUSE_OP): Add argument. Use VUSE_ELEMENT_PTR.
(VUSE_NUM): Define.
(VUSE_VECT): Define.
(MAYDEF_OP_PTR): Add argument. Use VUSE_OP_PTR.
(MAYDEF_OP): Add argument. Use VUSE_OP.
(MAYDEF_NUM): Define.
(MAYDEF_VECT): Define.
(MUSTDEF_KILL_PTR): Use VUSE_OP_PTR.
(MUSTDEF_KILL): Use VUSE_OP.
(MUSTDEF_NUM): Define.
(MUSTDEF_VECT): Define.
(realloc_maydef): Declare.
(realloc_vuse): Declare.
(struct ssa_operand_iterator_d) <vuse_index>: Add.
<mayuse_index>: Add.
(LOADED_SYMS): Define.
(STORED_SYMS): Define.
(FOR_EACH_SSA_MUSTDEF_OPERAND): Call op_iter_next_mustdef.
* tree-into-ssa.c: Adapt for multi-operand V_MAY_DEF and VUSE
operators.
* tree-pretty-print.c: Likewise.
* tree-ssa-dse.c: Likewise.
* tree-flow-inline.h: Likewise.
(op_iter_next_mustdef): New.
* tree-ssa-operands.c: Likewise.
(ALLOC_OPTYPE): Remove.
Update all users.
(alloc_def): New.
(alloc_use): New.
(alloc_maydef): New.
(alloc_vuse): New.
(alloc_mustdef): New.
(realloc_maydef): New.
(realloc_vuse): New.
2006-12-11 Aldy Hernandez <aldyh@redhat.com>
* tree-ssa-operands.c: Remove build_v_must_defs.
(init_ssa_operands): Delete build_v_must_defs.
(finalize_ssa_v_must_def_ops): Remove.
(finalize_ssa_v_must_defs): Remove.
(finalize_ssa_stmt_operands): Do not call
finalize_ssa_v_must_defs.
(start_ssa_stmt_operands): Do not check build_v_must_defs.
(append_v_must_def): Delete.
(copy_virtual_operands): Do not copy V_MUST_DEFs.
(get_modify_expr_operands): Remove reference to V_MUST_DEF from
comment. Remove opf_kill_def.
(build_ssa_operands): Remove references to v_must_defs.
(copy_virtual_operands): Same.
(copy_virtual_operands): Same.
(fini_ssa_operands): Same.
(free_ssa_operands): Same.
(add_mustdef_op): Remove.
Remove mustdef_optype_p.
(alloc_mustdef): Remove.
Remove references to V_MUST_DEFs in comment at top of file.
(get_expr_operands): Remove opf_kill_def.
(opf_kill_def): Remove.
(add_virtual_operand): Remove opf_kill_def.
(get_indirect_ref_operands): Same.
(get_tmr_operands): Same.
* tree-vectorizer.c (rename_variables_in_bb): Remove
SSA_OP_ALL_KILLS.
* tree-ssa-loop-manip.c (find_uses_to_rename_stmt): Remove
SSA_OP_ALL_KILLS.
(check_loop_closed_ssa_stmt): Same.
* tree-ssa.c (verify_def): Remove V_MUST_DEF from comment.
(verify_use): Same.
(verify_ssa): Remove V_MUST_DEFs traces.
(verify_ssa): Remove SSA_OP_ALL_KILLS.
* tree-into-ssa.c (mark_def_sites): Change SSA_OP_VMUSTDEF to
SSA_OP_VMAYDEF.
(rewrite_update_stmt): Remove SSA_OP_VIRTUAL_KILLS.
(rewrite_stmt): Remove SSA_OP_ALL_KILLS.
* tree-ssa-operands.h (struct stmt_operands_d): Remove V_MUST_DEF
references.
(MUSTDEF_OPS): Remove.
(SSA_OP_VMUSTDEF): Remove.
(FOR_EACH_SSA_MUSTDEF_OPERAND): Remove.
(struct mustdef_optype_d): Remove.
Remove mustdef_optype_p.
(struct stmt_operands_d): Remove mustdef_ops.
(ssa_operand_iterator_d): Remove mustdefs and mustkills.
(SSA_OP_VIRTUAL_DEFS): Remove SSA_OP_VMUSTDEF.
(MUSTDEF_RESULT_PTR): Remove.
(MUSTDEF_RESULT): Remove.
(MUSTDEF_KILL_PTR): Remove.
(MUSTDEF_KILL): Remove.
(MUSTDEF_NUM): Remove.
(MUSTDEF_VECT): Remove.
(SSA_OP_VIRTUAL_KILLS): Remove.
(SSA_OP_ALL_VIRTUALS): Remove SSA_OP_VIRTUAL_KILLS.
(SSA_OP_VMUSTKILL): Remove.
(SSA_OP_ALL_KILLS): Remove.
(SSA_OP_ALL_OPERANDS): Remove SSA_OP_ALL_KILLS.
* tree-flow-inline.h (op_iter_init_def): Remove
SSA_OP_VIRTUAL_KILLS.
(delink_stmt_imm_use): Remove SSA_OP_ALL_KILLS.
* tree-ssa-pre.c (compute_rvuse_and_antic_safe): Remove
SSA_OP_VIRTUAL_KILLS.
* tree-ssa-loop-im.c (determine_max_movement): Remove
SSA_OP_VIRTUAL_KILLS.
(gather_mem_refs_stmt): Same.
(gather_mem_refs_stmt): Same.
* tree-ssa-dce.c (mark_really_necessary_kill_operand_phis): Delete.
(perform_tree_ssa_dce): Remove call to
mark_really_necessary_kill_operand_phis.
* tree-flow-inline.h (op_iter_init): Remove setting of mustdefs
and mustkills.
(op_iter_next_use): Do not check mustkills.
(op_iter_next_def): Do not check mustdefs.
(op_iter_next_tree): Do not check mustkills or mustdefs.
(clear_and_done_ssa_iter): Do not set mustdefs or mustkills.
(op_iter_next_maymustdef): Do not check mustkills.
(op_iter_init_must_and_may_def): Remove SSA_OP_VMUSTKILL.
(op_iter_init_mustdef): Remove.
* tree-ssa-live.c (create_ssa_var_map): Change SSA_OP_VMUSTDEF to
SSA_OP_VMAYDEF.
* tree-ssa-dse.c (dse_optimize_stmt): Remove SSA_OP_VMUSTDEF.
* tree-ssa-ccp.c: Remove V_MUST_DEF traces from comments.
(visit_assignment): Same.
* tree-ssa-copy.c (copy_prop_visit_assignment): Same.
* tree-sra.c (mark_all_v_defs_1): Remove V_MUST_DEF from comment.
* tree-outof-ssa.c (check_replaceable): Remove SSA_OP_VMUSTDEF.
* tree-pretty-print.c (dump_vops): Remove printing of V_MUST_DEF.
Remove kill_p variable.
* tree-dfa.c (struct dfa_stats_d): Remove num_v_must_defs.
(dump_dfa_stats): Remove code related to V_MUST_DEFs.
(collect_dfa_stats_r): Do not set num_v_must_defs.
(mark_new_vars_to_rename): Remove v_must_defs_{before,after}
code.
* tree-into-ssa.c (mark_def_sites): Change SSA_OP_VMUSTKILL to
SSA_OP_VMAYUSE.
* tree-ssa-pre.c (compute_rvuse_and_antic_safe): Remove
SSA_OP_VMUSTDEF and SSA_OP_VMUSTKILL.
* tree-ssa-propagate.c (stmt_makes_single_store): Remove
SSA_OP_VMUSTDEF.
From-SVN: r119760
2006-12-12 02:48:51 +01:00
|
|
|
| TODO_ggc_collect
|
re PR other/35094 (RTL dump file letters hosed and partly undocumented)
* gcc.dg/20050811-2.c: Update dumping flags.
* gcc.dg/sms-2.c: Update dumping flags.
* gcc.dg/var-expand1.c: Update dumping flags.
* gcc.dg/var-expand3.c: Update dumping flags.
* gcc.dg/pr30957-1.c: Update dumping flags.
* gcc.dg/20050811-1.c: Update dumping flags.
* gcc.dg/cpp/cmdlne-dI-M.C: Do not xfail.
* gcc.dg/cpp/cmdlne-dM-M.C: Do not xfail.
PR other/35094
* toplev.c (decode_d_option): Handle all CPP flags.
* tree-vrp.c: Update tree_pass descriptors.
* regrename.c: Update tree_pass descriptors.
* fwprop.c: Update tree_pass descriptors.
* doc/invoke.texi: Remove documentation of dropped -d? flags.
* tree-into-ssa.c: Update tree_pass descriptors.
* tree-dump.c: Update tree_pass descriptors.
* tree-complex.c: Update tree_pass descriptors.
* tree-dump.h: Update tree_pass descriptors.
* see.c: Update tree_pass descriptors.
* cgraphbuild.c: Update tree_pass descriptors.
* tracer.c: Update tree_pass descriptors.
* tree-loop-distribution.c: Update tree_pass descriptors.
* cgraph.c: Update tree_pass descriptors.
* postreload-gcse.c: Update tree_pass descriptors.
* postreload.c: Update tree_pass descriptors.
* tree-ssa-loop-ch.c: Update tree_pass descriptors.
* tree-tailcall.c: Update tree_pass descriptors.
* tree-pass.h (tree_opt_pass): Rename to ...
(opt_pass) ... this one; add "type" field and remove letter field.
(gimple_opt_pass, rtl_opt_pass, simple_ipa_opt_pass): New.
(execute_pass_list, execute_ipa_pass_list, all_passes, all_ipa_passes,
all_lowering_passes): Update declaration.
* ipa-cp.c: Update tree_pass descriptors.
* final.c: Update tree_pass descriptors.
* omp-low.c: Update tree_pass descriptors.
* tree-ssa-dse.c: Update tree_pass descriptors.
* ipa-reference.c: Update tree_pass descriptors.
* tree-ssa-uncprop.c: Update tree_pass descriptors.
* auto-inc-dec.c: Update tree_pass descriptors.
* reorg.c: Update tree_pass descriptors.
* cgraphunit.c: Update tree_pass descriptors.
* tree-ssa-copyrename.c: Update tree_pass descriptors.
* tree-ssa-ccp.c: Update tree_pass descriptors.
* df-core.c: Update tree_pass descriptors.
* mode-switching.c: Update tree_pass descriptors.
* tree-nomudflap.c: Update tree_pass descriptors.
* modulo-sched.c: Update tree_pass descriptors.
* ipa-pure-const.c: Update tree_pass descriptors.
* cse.c: Update tree_pass descriptors.
* web.c: Update tree_pass descriptors.
* tree-stdarg.c: Update tree_pass descriptors.
* tree-ssa-math-opts.c: Update tree_pass descriptors.
* tree-ssa-dom.c: Update tree_pass descriptors.
* tree-nrv.c: Update tree_pass descriptors.
* tree-ssa-alias.c: Update tree_pass descriptors.
* loop-init.c: Update tree_pass descriptors.
* gimple-low.c: Update tree_pass descriptors.
* ipa-inline.c: Update tree_pass descriptors.
* tree-ssa-sink.c: Update tree_pass descriptors.
* global.c: Update tree_pass descriptors.
* ifcvt.c: Update tree_pass descriptors.
* jump.c: Update tree_pass descriptors.
* predict.c: Update tree_pass descriptors.
* tree-ssa-loop.c: Update tree_pass descriptors.
* recog.c: Update tree_pass descriptors.
* dse.c: Update tree_pass descriptors.
* tree-ssa-ifcombine.c: Update tree_pass descriptors.
* tree-eh.c: Update tree_pass descriptors.
* regmove.c: Update tree_pass descriptors.
* local-alloc.c
* function.c: Update tree_pass descriptors.
* tree-vectorizer.c: Update tree_pass descriptors.
* gcse.c: Update tree_pass descriptors.
* ipa-type-escape.c: Update tree_pass descriptors.
* tree-if-conv.c: Update tree_pass descriptors.
* init-regs.c: Update tree_pass descriptors.
* ipa.c: Update tree_pass descriptors.
* tree-ssa-phiopt.c: Update tree_pass descriptors.
* rtl-factoring.c: Update tree_pass descriptors.
* lower-subreg.c: Update tree_pass descriptors.
* bt-load.c: Update tree_pass descriptors.
* tree-dfa.c: Update tree_pass descriptors.
* except.c: Update tree_pass descriptors.
* emit-rtl.c: Update tree_pass descriptors.
* cfgexpand.c: Update tree_pass descriptors.
* tree-cfgcleanup.c: Update tree_pass descriptors.
* cfgcleanup.c: Update tree_pass descriptors.
* tree-ssa-pre.c: Update tree_pass descriptors.
* tree-sra.c: Update tree_pass descriptors.
* tree-mudflap.c: Update tree_pass descriptors.
* tree-ssa-copy.c: Update tree_pass descriptors.
* cfglayout.c: Update tree_pass descriptors.
* tree-ssa-forwprop.c: Update tree_pass descriptors.
* tree-ssa-dce.c: Update tree_pass descriptors.
* tree-ssa.c: Update tree_pass descriptors.
* regclass.c: Update tree_pass descriptors.
* integrate.c: Update tree_pass descriptors.
* tree-optimize.c: Update tree_pass descriptors.
* tree-ssa-phiprop.c: Update tree_pass descriptors.
* tree-object-size.c: Update tree_pass descriptors.
* combine.c: Update tree_pass descriptors.
* tree-outof-ssa.c: Update tree_pass descriptors.
* bb-reorder.c: Update tree_pass descriptors.
* stack-ptr-mod.c: Update tree_pass descriptors.
* var-tracking.c: Update tree_pass descriptors.
* tree-profile.c: Update tree_pass descriptors.
* tree-vect-generic.c: Update tree_pass descriptors.
* reg-stack.c: Update tree_pass descriptors.
* sched-rgn.c: Update tree_pass descriptors.
* tree-ssa-structalias.c: Update tree_pass descriptors.
* tree-cfg.c: Update tree_pass descriptors.
* passes.c (current_pass): Update declaration.
(finish_optimization_passes): Update.
(all_passes, all_ipa_passes, all_lowering_passes): Update declaration.
(register_one_dump_file, register_dump_files_1, next_pass_1):
Update arguments.
(init_optimization_passes): Update handling of new types.
(execute_one_pass, execute_pass_list, execute_ipa_pass_list): Update.
* ipa-struct-reorg.c: Update tree_pass descriptors.
* tree-ssa-reassoc.c: Update tree_pass descriptors.
* combine-stack-adj.c: Update tree_pass descriptors.
* cfgrtl.c: Update tree_pass descriptors.
* dce.c: Update tree_pass descriptors.
* tree-ssanames.c: Update tree_pass descriptors.
From-SVN: r133342
2008-03-19 12:22:40 +01:00
|
|
|
| TODO_verify_ssa /* todo_flags_finish */
|
|
|
|
}
|
2004-05-13 08:41:07 +02:00
|
|
|
};
|
2009-09-17 13:35:38 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* Return true iff PARM (which must be a parm_decl) is an unused scalar
|
|
|
|
parameter. */
|
|
|
|
|
|
|
|
static bool
|
|
|
|
is_unused_scalar_param (tree parm)
|
|
|
|
{
|
|
|
|
tree name;
|
|
|
|
return (is_gimple_reg (parm)
|
|
|
|
&& (!(name = gimple_default_def (cfun, parm))
|
|
|
|
|| has_zero_uses (name)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Scan immediate uses of a default definition SSA name of a parameter PARM and
|
|
|
|
examine whether there are any direct or otherwise infeasible ones. If so,
|
|
|
|
return true, otherwise return false. PARM must be a gimple register with a
|
|
|
|
non-NULL default definition. */
|
|
|
|
|
|
|
|
static bool
|
|
|
|
ptr_parm_has_direct_uses (tree parm)
|
|
|
|
{
|
|
|
|
imm_use_iterator ui;
|
|
|
|
gimple stmt;
|
|
|
|
tree name = gimple_default_def (cfun, parm);
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
FOR_EACH_IMM_USE_STMT (stmt, ui, name)
|
|
|
|
{
|
|
|
|
if (gimple_assign_single_p (stmt))
|
|
|
|
{
|
|
|
|
tree rhs = gimple_assign_rhs1 (stmt);
|
|
|
|
if (rhs == name)
|
|
|
|
ret = true;
|
|
|
|
else if (TREE_CODE (rhs) == ADDR_EXPR)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
rhs = TREE_OPERAND (rhs, 0);
|
|
|
|
}
|
|
|
|
while (handled_component_p (rhs));
|
|
|
|
if (INDIRECT_REF_P (rhs) && TREE_OPERAND (rhs, 0) == name)
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (gimple_code (stmt) == GIMPLE_RETURN)
|
|
|
|
{
|
|
|
|
tree t = gimple_return_retval (stmt);
|
|
|
|
if (t == name)
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
else if (is_gimple_call (stmt))
|
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
for (i = 0; i < gimple_call_num_args (stmt); i++)
|
|
|
|
{
|
|
|
|
tree arg = gimple_call_arg (stmt, i);
|
|
|
|
if (arg == name)
|
|
|
|
{
|
|
|
|
ret = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!is_gimple_debug (stmt))
|
|
|
|
ret = true;
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
BREAK_FROM_IMM_USE_STMT (ui);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Identify candidates for reduction for IPA-SRA based on their type and mark
|
|
|
|
them in candidate_bitmap. Note that these do not necessarily include
|
|
|
|
parameter which are unused and thus can be removed. Return true iff any
|
|
|
|
such candidate has been found. */
|
|
|
|
|
|
|
|
static bool
|
|
|
|
find_param_candidates (void)
|
|
|
|
{
|
|
|
|
tree parm;
|
|
|
|
int count = 0;
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
for (parm = DECL_ARGUMENTS (current_function_decl);
|
|
|
|
parm;
|
|
|
|
parm = TREE_CHAIN (parm))
|
|
|
|
{
|
2009-10-01 13:30:12 +02:00
|
|
|
tree type = TREE_TYPE (parm);
|
2009-09-17 13:35:38 +02:00
|
|
|
|
|
|
|
count++;
|
2009-10-01 13:30:12 +02:00
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
if (TREE_THIS_VOLATILE (parm)
|
2009-10-01 13:30:12 +02:00
|
|
|
|| TREE_ADDRESSABLE (parm)
|
|
|
|
|| is_va_list_type (type))
|
2009-09-17 13:35:38 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (is_unused_scalar_param (parm))
|
|
|
|
{
|
|
|
|
ret = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (POINTER_TYPE_P (type))
|
|
|
|
{
|
|
|
|
type = TREE_TYPE (type);
|
|
|
|
|
|
|
|
if (TREE_CODE (type) == FUNCTION_TYPE
|
|
|
|
|| TYPE_VOLATILE (type)
|
|
|
|
|| !is_gimple_reg (parm)
|
2009-10-01 13:30:12 +02:00
|
|
|
|| is_va_list_type (type)
|
2009-09-17 13:35:38 +02:00
|
|
|
|| ptr_parm_has_direct_uses (parm))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (!AGGREGATE_TYPE_P (type))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!COMPLETE_TYPE_P (type)
|
|
|
|
|| !host_integerp (TYPE_SIZE (type), 1)
|
|
|
|
|| tree_low_cst (TYPE_SIZE (type), 1) == 0
|
|
|
|
|| (AGGREGATE_TYPE_P (type)
|
|
|
|
&& type_internals_preclude_sra_p (type)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bitmap_set_bit (candidate_bitmap, DECL_UID (parm));
|
|
|
|
ret = true;
|
|
|
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
|
|
|
{
|
|
|
|
fprintf (dump_file, "Candidate (%d): ", DECL_UID (parm));
|
|
|
|
print_generic_expr (dump_file, parm, 0);
|
|
|
|
fprintf (dump_file, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func_param_count = count;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Callback of walk_aliased_vdefs, marks the access passed as DATA as
|
|
|
|
maybe_modified. */
|
|
|
|
|
|
|
|
static bool
|
|
|
|
mark_maybe_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
struct access *repr = (struct access *) data;
|
|
|
|
|
|
|
|
repr->grp_maybe_modified = 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Analyze what representatives (in linked lists accessible from
|
|
|
|
REPRESENTATIVES) can be modified by side effects of statements in the
|
|
|
|
current function. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
analyze_modified_params (VEC (access_p, heap) *representatives)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < func_param_count; i++)
|
|
|
|
{
|
2009-11-02 15:13:49 +01:00
|
|
|
struct access *repr;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
2009-11-02 15:13:49 +01:00
|
|
|
for (repr = VEC_index (access_p, representatives, i);
|
|
|
|
repr;
|
|
|
|
repr = repr->next_grp)
|
2009-09-17 13:35:38 +02:00
|
|
|
{
|
2009-11-05 13:09:08 +01:00
|
|
|
struct access *access;
|
|
|
|
bitmap visited;
|
|
|
|
ao_ref ar;
|
2009-11-02 15:13:49 +01:00
|
|
|
|
|
|
|
if (no_accesses_p (repr))
|
|
|
|
continue;
|
2009-11-05 13:09:08 +01:00
|
|
|
if (!POINTER_TYPE_P (TREE_TYPE (repr->base))
|
2009-11-02 15:13:49 +01:00
|
|
|
|| repr->grp_maybe_modified)
|
|
|
|
continue;
|
|
|
|
|
2009-11-05 13:09:08 +01:00
|
|
|
ao_ref_init (&ar, repr->expr);
|
|
|
|
visited = BITMAP_ALLOC (NULL);
|
|
|
|
for (access = repr; access; access = access->next_sibling)
|
2009-11-02 15:13:49 +01:00
|
|
|
{
|
|
|
|
/* All accesses are read ones, otherwise grp_maybe_modified would
|
|
|
|
be trivially set. */
|
|
|
|
walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
|
2009-11-05 13:09:08 +01:00
|
|
|
mark_maybe_modified, repr, &visited);
|
2009-11-02 15:13:49 +01:00
|
|
|
if (repr->grp_maybe_modified)
|
|
|
|
break;
|
|
|
|
}
|
2009-11-05 13:09:08 +01:00
|
|
|
BITMAP_FREE (visited);
|
2009-09-17 13:35:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Propagate distances in bb_dereferences in the opposite direction than the
|
|
|
|
control flow edges, in each step storing the maximum of the current value
|
|
|
|
and the minimum of all successors. These steps are repeated until the table
|
|
|
|
stabilizes. Note that BBs which might terminate the functions (according to
|
|
|
|
final_bbs bitmap) never updated in this way. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
propagate_dereference_distances (void)
|
|
|
|
{
|
|
|
|
VEC (basic_block, heap) *queue;
|
|
|
|
basic_block bb;
|
|
|
|
|
|
|
|
queue = VEC_alloc (basic_block, heap, last_basic_block_for_function (cfun));
|
|
|
|
VEC_quick_push (basic_block, queue, ENTRY_BLOCK_PTR);
|
|
|
|
FOR_EACH_BB (bb)
|
|
|
|
{
|
|
|
|
VEC_quick_push (basic_block, queue, bb);
|
|
|
|
bb->aux = bb;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!VEC_empty (basic_block, queue))
|
|
|
|
{
|
|
|
|
edge_iterator ei;
|
|
|
|
edge e;
|
|
|
|
bool change = false;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
bb = VEC_pop (basic_block, queue);
|
|
|
|
bb->aux = NULL;
|
|
|
|
|
|
|
|
if (bitmap_bit_p (final_bbs, bb->index))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (i = 0; i < func_param_count; i++)
|
|
|
|
{
|
|
|
|
int idx = bb->index * func_param_count + i;
|
|
|
|
bool first = true;
|
|
|
|
HOST_WIDE_INT inh = 0;
|
|
|
|
|
|
|
|
FOR_EACH_EDGE (e, ei, bb->succs)
|
|
|
|
{
|
|
|
|
int succ_idx = e->dest->index * func_param_count + i;
|
|
|
|
|
|
|
|
if (e->src == EXIT_BLOCK_PTR)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (first)
|
|
|
|
{
|
|
|
|
first = false;
|
|
|
|
inh = bb_dereferences [succ_idx];
|
|
|
|
}
|
|
|
|
else if (bb_dereferences [succ_idx] < inh)
|
|
|
|
inh = bb_dereferences [succ_idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!first && bb_dereferences[idx] < inh)
|
|
|
|
{
|
|
|
|
bb_dereferences[idx] = inh;
|
|
|
|
change = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (change && !bitmap_bit_p (final_bbs, bb->index))
|
|
|
|
FOR_EACH_EDGE (e, ei, bb->preds)
|
|
|
|
{
|
|
|
|
if (e->src->aux)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
e->src->aux = e->src;
|
|
|
|
VEC_quick_push (basic_block, queue, e->src);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VEC_free (basic_block, heap, queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Dump a dereferences TABLE with heading STR to file F. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
dump_dereferences_table (FILE *f, const char *str, HOST_WIDE_INT *table)
|
|
|
|
{
|
|
|
|
basic_block bb;
|
|
|
|
|
|
|
|
fprintf (dump_file, str);
|
|
|
|
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
|
|
|
|
{
|
|
|
|
fprintf (f, "%4i %i ", bb->index, bitmap_bit_p (final_bbs, bb->index));
|
|
|
|
if (bb != EXIT_BLOCK_PTR)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < func_param_count; i++)
|
|
|
|
{
|
|
|
|
int idx = bb->index * func_param_count + i;
|
|
|
|
fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", table[idx]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf (f, "\n");
|
|
|
|
}
|
|
|
|
fprintf (dump_file, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Determine what (parts of) parameters passed by reference that are not
|
|
|
|
assigned to are not certainly dereferenced in this function and thus the
|
|
|
|
dereferencing cannot be safely moved to the caller without potentially
|
|
|
|
introducing a segfault. Mark such REPRESENTATIVES as
|
|
|
|
grp_not_necessarilly_dereferenced.
|
|
|
|
|
|
|
|
The dereferenced maximum "distance," i.e. the offset + size of the accessed
|
|
|
|
part is calculated rather than simple booleans are calculated for each
|
|
|
|
pointer parameter to handle cases when only a fraction of the whole
|
|
|
|
aggregate is allocated (see testsuite/gcc.c-torture/execute/ipa-sra-2.c for
|
|
|
|
an example).
|
|
|
|
|
|
|
|
The maximum dereference distances for each pointer parameter and BB are
|
|
|
|
already stored in bb_dereference. This routine simply propagates these
|
|
|
|
values upwards by propagate_dereference_distances and then compares the
|
|
|
|
distances of individual parameters in the ENTRY BB to the equivalent
|
|
|
|
distances of each representative of a (fraction of a) parameter. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
analyze_caller_dereference_legality (VEC (access_p, heap) *representatives)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
|
|
|
dump_dereferences_table (dump_file,
|
|
|
|
"Dereference table before propagation:\n",
|
|
|
|
bb_dereferences);
|
|
|
|
|
|
|
|
propagate_dereference_distances ();
|
|
|
|
|
|
|
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
|
|
|
dump_dereferences_table (dump_file,
|
|
|
|
"Dereference table after propagation:\n",
|
|
|
|
bb_dereferences);
|
|
|
|
|
|
|
|
for (i = 0; i < func_param_count; i++)
|
|
|
|
{
|
|
|
|
struct access *repr = VEC_index (access_p, representatives, i);
|
|
|
|
int idx = ENTRY_BLOCK_PTR->index * func_param_count + i;
|
|
|
|
|
|
|
|
if (!repr || no_accesses_p (repr))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if ((repr->offset + repr->size) > bb_dereferences[idx])
|
|
|
|
repr->grp_not_necessarilly_dereferenced = 1;
|
|
|
|
repr = repr->next_grp;
|
|
|
|
}
|
|
|
|
while (repr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the representative access for the parameter declaration PARM if it is
|
|
|
|
a scalar passed by reference which is not written to and the pointer value
|
|
|
|
is not used directly. Thus, if it is legal to dereference it in the caller
|
|
|
|
and we can rule out modifications through aliases, such parameter should be
|
|
|
|
turned into one passed by value. Return NULL otherwise. */
|
|
|
|
|
|
|
|
static struct access *
|
|
|
|
unmodified_by_ref_scalar_representative (tree parm)
|
|
|
|
{
|
|
|
|
int i, access_count;
|
2009-11-05 13:09:08 +01:00
|
|
|
struct access *repr;
|
2009-09-17 13:35:38 +02:00
|
|
|
VEC (access_p, heap) *access_vec;
|
|
|
|
|
|
|
|
access_vec = get_base_access_vector (parm);
|
|
|
|
gcc_assert (access_vec);
|
2009-11-05 13:09:08 +01:00
|
|
|
repr = VEC_index (access_p, access_vec, 0);
|
|
|
|
if (repr->write)
|
|
|
|
return NULL;
|
|
|
|
repr->group_representative = repr;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
2009-11-05 13:09:08 +01:00
|
|
|
access_count = VEC_length (access_p, access_vec);
|
|
|
|
for (i = 1; i < access_count; i++)
|
2009-09-17 13:35:38 +02:00
|
|
|
{
|
2009-11-05 13:09:08 +01:00
|
|
|
struct access *access = VEC_index (access_p, access_vec, i);
|
2009-09-17 13:35:38 +02:00
|
|
|
if (access->write)
|
|
|
|
return NULL;
|
2009-11-05 13:09:08 +01:00
|
|
|
access->group_representative = repr;
|
|
|
|
access->next_sibling = repr->next_sibling;
|
|
|
|
repr->next_sibling = access;
|
2009-09-17 13:35:38 +02:00
|
|
|
}
|
|
|
|
|
2009-11-05 13:09:08 +01:00
|
|
|
repr->grp_read = 1;
|
|
|
|
repr->grp_scalar_ptr = 1;
|
|
|
|
return repr;
|
2009-09-17 13:35:38 +02:00
|
|
|
}
|
|
|
|
|
2009-11-21 23:56:36 +01:00
|
|
|
/* Return true iff this access precludes IPA-SRA of the parameter it is
|
|
|
|
associated with. */
|
|
|
|
|
|
|
|
static bool
|
|
|
|
access_precludes_ipa_sra_p (struct access *access)
|
|
|
|
{
|
|
|
|
/* Avoid issues such as the second simple testcase in PR 42025. The problem
|
|
|
|
is incompatible assign in a call statement (and possibly even in asm
|
|
|
|
statements). This can be relaxed by using a new temporary but only for
|
|
|
|
non-TREE_ADDRESSABLE types and is probably not worth the complexity. (In
|
|
|
|
intraprocedural SRA we deal with this by keeping the old aggregate around,
|
|
|
|
something we cannot do in IPA-SRA.) */
|
|
|
|
if (access->write
|
|
|
|
&& (is_gimple_call (access->stmt)
|
|
|
|
|| gimple_code (access->stmt) == GIMPLE_ASM))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
/* Sort collected accesses for parameter PARM, identify representatives for
|
|
|
|
each accessed region and link them together. Return NULL if there are
|
|
|
|
different but overlapping accesses, return the special ptr value meaning
|
|
|
|
there are no accesses for this parameter if that is the case and return the
|
|
|
|
first representative otherwise. Set *RO_GRP if there is a group of accesses
|
|
|
|
with only read (i.e. no write) accesses. */
|
|
|
|
|
|
|
|
static struct access *
|
|
|
|
splice_param_accesses (tree parm, bool *ro_grp)
|
|
|
|
{
|
|
|
|
int i, j, access_count, group_count;
|
|
|
|
int agg_size, total_size = 0;
|
|
|
|
struct access *access, *res, **prev_acc_ptr = &res;
|
|
|
|
VEC (access_p, heap) *access_vec;
|
|
|
|
|
|
|
|
access_vec = get_base_access_vector (parm);
|
|
|
|
if (!access_vec)
|
|
|
|
return &no_accesses_representant;
|
|
|
|
access_count = VEC_length (access_p, access_vec);
|
|
|
|
|
|
|
|
qsort (VEC_address (access_p, access_vec), access_count, sizeof (access_p),
|
|
|
|
compare_access_positions);
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
total_size = 0;
|
|
|
|
group_count = 0;
|
|
|
|
while (i < access_count)
|
|
|
|
{
|
|
|
|
bool modification;
|
|
|
|
access = VEC_index (access_p, access_vec, i);
|
|
|
|
modification = access->write;
|
2009-11-21 23:56:36 +01:00
|
|
|
if (access_precludes_ipa_sra_p (access))
|
|
|
|
return NULL;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
|
|
|
/* Access is about to become group representative unless we find some
|
|
|
|
nasty overlap which would preclude us from breaking this parameter
|
|
|
|
apart. */
|
|
|
|
|
|
|
|
j = i + 1;
|
|
|
|
while (j < access_count)
|
|
|
|
{
|
|
|
|
struct access *ac2 = VEC_index (access_p, access_vec, j);
|
|
|
|
if (ac2->offset != access->offset)
|
|
|
|
{
|
|
|
|
/* All or nothing law for parameters. */
|
|
|
|
if (access->offset + access->size > ac2->offset)
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (ac2->size != access->size)
|
|
|
|
return NULL;
|
|
|
|
|
2009-11-21 23:56:36 +01:00
|
|
|
if (access_precludes_ipa_sra_p (ac2))
|
|
|
|
return NULL;
|
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
modification |= ac2->write;
|
2009-11-05 13:09:08 +01:00
|
|
|
ac2->group_representative = access;
|
|
|
|
ac2->next_sibling = access->next_sibling;
|
|
|
|
access->next_sibling = ac2;
|
2009-09-17 13:35:38 +02:00
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
group_count++;
|
|
|
|
access->grp_maybe_modified = modification;
|
|
|
|
if (!modification)
|
|
|
|
*ro_grp = true;
|
|
|
|
*prev_acc_ptr = access;
|
|
|
|
prev_acc_ptr = &access->next_grp;
|
|
|
|
total_size += access->size;
|
|
|
|
i = j;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (POINTER_TYPE_P (TREE_TYPE (parm)))
|
|
|
|
agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))), 1);
|
|
|
|
else
|
|
|
|
agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (parm)), 1);
|
|
|
|
if (total_size >= agg_size)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
gcc_assert (group_count > 0);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Decide whether parameters with representative accesses given by REPR should
|
|
|
|
be reduced into components. */
|
|
|
|
|
|
|
|
static int
|
|
|
|
decide_one_param_reduction (struct access *repr)
|
|
|
|
{
|
|
|
|
int total_size, cur_parm_size, agg_size, new_param_count, parm_size_limit;
|
|
|
|
bool by_ref;
|
|
|
|
tree parm;
|
|
|
|
|
|
|
|
parm = repr->base;
|
|
|
|
cur_parm_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (parm)), 1);
|
|
|
|
gcc_assert (cur_parm_size > 0);
|
|
|
|
|
|
|
|
if (POINTER_TYPE_P (TREE_TYPE (parm)))
|
|
|
|
{
|
|
|
|
by_ref = true;
|
|
|
|
agg_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))), 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
by_ref = false;
|
|
|
|
agg_size = cur_parm_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dump_file)
|
|
|
|
{
|
|
|
|
struct access *acc;
|
|
|
|
fprintf (dump_file, "Evaluating PARAM group sizes for ");
|
|
|
|
print_generic_expr (dump_file, parm, 0);
|
|
|
|
fprintf (dump_file, " (UID: %u): \n", DECL_UID (parm));
|
|
|
|
for (acc = repr; acc; acc = acc->next_grp)
|
|
|
|
dump_access (dump_file, acc, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
total_size = 0;
|
|
|
|
new_param_count = 0;
|
|
|
|
|
|
|
|
for (; repr; repr = repr->next_grp)
|
|
|
|
{
|
|
|
|
gcc_assert (parm == repr->base);
|
|
|
|
new_param_count++;
|
|
|
|
|
|
|
|
if (!by_ref || (!repr->grp_maybe_modified
|
|
|
|
&& !repr->grp_not_necessarilly_dereferenced))
|
|
|
|
total_size += repr->size;
|
|
|
|
else
|
|
|
|
total_size += cur_parm_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
gcc_assert (new_param_count > 0);
|
|
|
|
|
|
|
|
if (optimize_function_for_size_p (cfun))
|
|
|
|
parm_size_limit = cur_parm_size;
|
|
|
|
else
|
|
|
|
parm_size_limit = (PARAM_VALUE (PARAM_IPA_SRA_PTR_GROWTH_FACTOR)
|
|
|
|
* cur_parm_size);
|
|
|
|
|
|
|
|
if (total_size < agg_size
|
|
|
|
&& total_size <= parm_size_limit)
|
|
|
|
{
|
|
|
|
if (dump_file)
|
|
|
|
fprintf (dump_file, " ....will be split into %i components\n",
|
|
|
|
new_param_count);
|
|
|
|
return new_param_count;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The order of the following enums is important, we need to do extra work for
|
|
|
|
UNUSED_PARAMS, BY_VAL_ACCESSES and UNMODIF_BY_REF_ACCESSES. */
|
|
|
|
enum ipa_splicing_result { NO_GOOD_ACCESS, UNUSED_PARAMS, BY_VAL_ACCESSES,
|
|
|
|
MODIF_BY_REF_ACCESSES, UNMODIF_BY_REF_ACCESSES };
|
|
|
|
|
|
|
|
/* Identify representatives of all accesses to all candidate parameters for
|
|
|
|
IPA-SRA. Return result based on what representatives have been found. */
|
|
|
|
|
|
|
|
static enum ipa_splicing_result
|
|
|
|
splice_all_param_accesses (VEC (access_p, heap) **representatives)
|
|
|
|
{
|
|
|
|
enum ipa_splicing_result result = NO_GOOD_ACCESS;
|
|
|
|
tree parm;
|
|
|
|
struct access *repr;
|
|
|
|
|
|
|
|
*representatives = VEC_alloc (access_p, heap, func_param_count);
|
|
|
|
|
|
|
|
for (parm = DECL_ARGUMENTS (current_function_decl);
|
|
|
|
parm;
|
|
|
|
parm = TREE_CHAIN (parm))
|
|
|
|
{
|
|
|
|
if (is_unused_scalar_param (parm))
|
|
|
|
{
|
|
|
|
VEC_quick_push (access_p, *representatives,
|
|
|
|
&no_accesses_representant);
|
|
|
|
if (result == NO_GOOD_ACCESS)
|
|
|
|
result = UNUSED_PARAMS;
|
|
|
|
}
|
|
|
|
else if (POINTER_TYPE_P (TREE_TYPE (parm))
|
|
|
|
&& is_gimple_reg_type (TREE_TYPE (TREE_TYPE (parm)))
|
|
|
|
&& bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
|
|
|
|
{
|
|
|
|
repr = unmodified_by_ref_scalar_representative (parm);
|
|
|
|
VEC_quick_push (access_p, *representatives, repr);
|
|
|
|
if (repr)
|
|
|
|
result = UNMODIF_BY_REF_ACCESSES;
|
|
|
|
}
|
|
|
|
else if (bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
|
|
|
|
{
|
|
|
|
bool ro_grp = false;
|
|
|
|
repr = splice_param_accesses (parm, &ro_grp);
|
|
|
|
VEC_quick_push (access_p, *representatives, repr);
|
|
|
|
|
|
|
|
if (repr && !no_accesses_p (repr))
|
|
|
|
{
|
|
|
|
if (POINTER_TYPE_P (TREE_TYPE (parm)))
|
|
|
|
{
|
|
|
|
if (ro_grp)
|
|
|
|
result = UNMODIF_BY_REF_ACCESSES;
|
|
|
|
else if (result < MODIF_BY_REF_ACCESSES)
|
|
|
|
result = MODIF_BY_REF_ACCESSES;
|
|
|
|
}
|
|
|
|
else if (result < BY_VAL_ACCESSES)
|
|
|
|
result = BY_VAL_ACCESSES;
|
|
|
|
}
|
|
|
|
else if (no_accesses_p (repr) && (result == NO_GOOD_ACCESS))
|
|
|
|
result = UNUSED_PARAMS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
VEC_quick_push (access_p, *representatives, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result == NO_GOOD_ACCESS)
|
|
|
|
{
|
|
|
|
VEC_free (access_p, heap, *representatives);
|
|
|
|
*representatives = NULL;
|
|
|
|
return NO_GOOD_ACCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the index of BASE in PARMS. Abort if it is not found. */
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
get_param_index (tree base, VEC(tree, heap) *parms)
|
|
|
|
{
|
|
|
|
int i, len;
|
|
|
|
|
|
|
|
len = VEC_length (tree, parms);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
if (VEC_index (tree, parms, i) == base)
|
|
|
|
return i;
|
|
|
|
gcc_unreachable ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert the decisions made at the representative level into compact
|
|
|
|
parameter adjustments. REPRESENTATIVES are pointers to first
|
|
|
|
representatives of each param accesses, ADJUSTMENTS_COUNT is the expected
|
|
|
|
final number of adjustments. */
|
|
|
|
|
|
|
|
static ipa_parm_adjustment_vec
|
|
|
|
turn_representatives_into_adjustments (VEC (access_p, heap) *representatives,
|
|
|
|
int adjustments_count)
|
|
|
|
{
|
|
|
|
VEC (tree, heap) *parms;
|
|
|
|
ipa_parm_adjustment_vec adjustments;
|
|
|
|
tree parm;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
gcc_assert (adjustments_count > 0);
|
|
|
|
parms = ipa_get_vector_of_formal_parms (current_function_decl);
|
|
|
|
adjustments = VEC_alloc (ipa_parm_adjustment_t, heap, adjustments_count);
|
|
|
|
parm = DECL_ARGUMENTS (current_function_decl);
|
|
|
|
for (i = 0; i < func_param_count; i++, parm = TREE_CHAIN (parm))
|
|
|
|
{
|
|
|
|
struct access *repr = VEC_index (access_p, representatives, i);
|
|
|
|
|
|
|
|
if (!repr || no_accesses_p (repr))
|
|
|
|
{
|
|
|
|
struct ipa_parm_adjustment *adj;
|
|
|
|
|
|
|
|
adj = VEC_quick_push (ipa_parm_adjustment_t, adjustments, NULL);
|
|
|
|
memset (adj, 0, sizeof (*adj));
|
|
|
|
adj->base_index = get_param_index (parm, parms);
|
|
|
|
adj->base = parm;
|
|
|
|
if (!repr)
|
|
|
|
adj->copy_param = 1;
|
|
|
|
else
|
|
|
|
adj->remove_param = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
struct ipa_parm_adjustment *adj;
|
|
|
|
int index = get_param_index (parm, parms);
|
|
|
|
|
|
|
|
for (; repr; repr = repr->next_grp)
|
|
|
|
{
|
|
|
|
adj = VEC_quick_push (ipa_parm_adjustment_t, adjustments, NULL);
|
|
|
|
memset (adj, 0, sizeof (*adj));
|
|
|
|
gcc_assert (repr->base == parm);
|
|
|
|
adj->base_index = index;
|
|
|
|
adj->base = repr->base;
|
|
|
|
adj->type = repr->type;
|
|
|
|
adj->offset = repr->offset;
|
|
|
|
adj->by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
|
|
|
|
&& (repr->grp_maybe_modified
|
|
|
|
|| repr->grp_not_necessarilly_dereferenced));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VEC_free (tree, heap, parms);
|
|
|
|
return adjustments;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Analyze the collected accesses and produce a plan what to do with the
|
|
|
|
parameters in the form of adjustments, NULL meaning nothing. */
|
|
|
|
|
|
|
|
static ipa_parm_adjustment_vec
|
|
|
|
analyze_all_param_acesses (void)
|
|
|
|
{
|
|
|
|
enum ipa_splicing_result repr_state;
|
|
|
|
bool proceed = false;
|
|
|
|
int i, adjustments_count = 0;
|
|
|
|
VEC (access_p, heap) *representatives;
|
|
|
|
ipa_parm_adjustment_vec adjustments;
|
|
|
|
|
|
|
|
repr_state = splice_all_param_accesses (&representatives);
|
|
|
|
if (repr_state == NO_GOOD_ACCESS)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* If there are any parameters passed by reference which are not modified
|
|
|
|
directly, we need to check whether they can be modified indirectly. */
|
|
|
|
if (repr_state == UNMODIF_BY_REF_ACCESSES)
|
|
|
|
{
|
|
|
|
analyze_caller_dereference_legality (representatives);
|
|
|
|
analyze_modified_params (representatives);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < func_param_count; i++)
|
|
|
|
{
|
|
|
|
struct access *repr = VEC_index (access_p, representatives, i);
|
|
|
|
|
|
|
|
if (repr && !no_accesses_p (repr))
|
|
|
|
{
|
|
|
|
if (repr->grp_scalar_ptr)
|
|
|
|
{
|
|
|
|
adjustments_count++;
|
|
|
|
if (repr->grp_not_necessarilly_dereferenced
|
|
|
|
|| repr->grp_maybe_modified)
|
|
|
|
VEC_replace (access_p, representatives, i, NULL);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
proceed = true;
|
|
|
|
sra_stats.scalar_by_ref_to_by_val++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int new_components = decide_one_param_reduction (repr);
|
|
|
|
|
|
|
|
if (new_components == 0)
|
|
|
|
{
|
|
|
|
VEC_replace (access_p, representatives, i, NULL);
|
|
|
|
adjustments_count++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
adjustments_count += new_components;
|
|
|
|
sra_stats.aggregate_params_reduced++;
|
|
|
|
sra_stats.param_reductions_created += new_components;
|
|
|
|
proceed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (no_accesses_p (repr))
|
|
|
|
{
|
|
|
|
proceed = true;
|
|
|
|
sra_stats.deleted_unused_parameters++;
|
|
|
|
}
|
|
|
|
adjustments_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!proceed && dump_file)
|
|
|
|
fprintf (dump_file, "NOT proceeding to change params.\n");
|
|
|
|
|
|
|
|
if (proceed)
|
|
|
|
adjustments = turn_representatives_into_adjustments (representatives,
|
|
|
|
adjustments_count);
|
|
|
|
else
|
|
|
|
adjustments = NULL;
|
|
|
|
|
|
|
|
VEC_free (access_p, heap, representatives);
|
|
|
|
return adjustments;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If a parameter replacement identified by ADJ does not yet exist in the form
|
|
|
|
of declaration, create it and record it, otherwise return the previously
|
|
|
|
created one. */
|
|
|
|
|
|
|
|
static tree
|
|
|
|
get_replaced_param_substitute (struct ipa_parm_adjustment *adj)
|
|
|
|
{
|
|
|
|
tree repl;
|
|
|
|
if (!adj->new_ssa_base)
|
|
|
|
{
|
|
|
|
char *pretty_name = make_fancy_name (adj->base);
|
|
|
|
|
2009-11-27 23:34:40 +01:00
|
|
|
repl = create_tmp_var (TREE_TYPE (adj->base), "ISR");
|
|
|
|
if (TREE_CODE (TREE_TYPE (repl)) == COMPLEX_TYPE
|
|
|
|
|| TREE_CODE (TREE_TYPE (repl)) == VECTOR_TYPE)
|
|
|
|
DECL_GIMPLE_REG_P (repl) = 1;
|
2009-09-17 13:35:38 +02:00
|
|
|
DECL_NAME (repl) = get_identifier (pretty_name);
|
|
|
|
obstack_free (&name_obstack, pretty_name);
|
|
|
|
|
|
|
|
get_var_ann (repl);
|
|
|
|
add_referenced_var (repl);
|
|
|
|
adj->new_ssa_base = repl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
repl = adj->new_ssa_base;
|
|
|
|
return repl;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find the first adjustment for a particular parameter BASE in a vector of
|
|
|
|
ADJUSTMENTS which is not a copy_param. Return NULL if there is no such
|
|
|
|
adjustment. */
|
|
|
|
|
|
|
|
static struct ipa_parm_adjustment *
|
|
|
|
get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
|
|
|
|
{
|
|
|
|
int i, len;
|
|
|
|
|
|
|
|
len = VEC_length (ipa_parm_adjustment_t, adjustments);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
struct ipa_parm_adjustment *adj;
|
|
|
|
|
|
|
|
adj = VEC_index (ipa_parm_adjustment_t, adjustments, i);
|
|
|
|
if (!adj->copy_param && adj->base == base)
|
|
|
|
return adj;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Callback for scan_function. If the statement STMT defines an SSA_NAME of a
|
|
|
|
parameter which is to be removed because its value is not used, replace the
|
|
|
|
SSA_NAME with a one relating to a created VAR_DECL and replace all of its
|
2009-11-27 23:34:40 +01:00
|
|
|
uses too and return true (update_stmt is then issued for the statement by
|
|
|
|
the caller). DATA is a pointer to an adjustments vector. */
|
2009-09-17 13:35:38 +02:00
|
|
|
|
|
|
|
static bool
|
|
|
|
replace_removed_params_ssa_names (gimple stmt, void *data)
|
|
|
|
{
|
|
|
|
VEC (ipa_parm_adjustment_t, heap) *adjustments;
|
|
|
|
struct ipa_parm_adjustment *adj;
|
|
|
|
tree lhs, decl, repl, name;
|
|
|
|
|
|
|
|
adjustments = (VEC (ipa_parm_adjustment_t, heap) *) data;
|
|
|
|
if (gimple_code (stmt) == GIMPLE_PHI)
|
|
|
|
lhs = gimple_phi_result (stmt);
|
|
|
|
else if (is_gimple_assign (stmt))
|
|
|
|
lhs = gimple_assign_lhs (stmt);
|
|
|
|
else if (is_gimple_call (stmt))
|
|
|
|
lhs = gimple_call_lhs (stmt);
|
|
|
|
else
|
|
|
|
gcc_unreachable ();
|
|
|
|
|
|
|
|
if (TREE_CODE (lhs) != SSA_NAME)
|
|
|
|
return false;
|
|
|
|
decl = SSA_NAME_VAR (lhs);
|
|
|
|
if (TREE_CODE (decl) != PARM_DECL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
adj = get_adjustment_for_base (adjustments, decl);
|
|
|
|
if (!adj)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
repl = get_replaced_param_substitute (adj);
|
|
|
|
name = make_ssa_name (repl, stmt);
|
|
|
|
|
|
|
|
if (dump_file)
|
|
|
|
{
|
|
|
|
fprintf (dump_file, "replacing an SSA name of a removed param ");
|
|
|
|
print_generic_expr (dump_file, lhs, 0);
|
|
|
|
fprintf (dump_file, " with ");
|
|
|
|
print_generic_expr (dump_file, name, 0);
|
|
|
|
fprintf (dump_file, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_gimple_assign (stmt))
|
|
|
|
gimple_assign_set_lhs (stmt, name);
|
|
|
|
else if (is_gimple_call (stmt))
|
|
|
|
gimple_call_set_lhs (stmt, name);
|
|
|
|
else
|
|
|
|
gimple_phi_set_result (stmt, name);
|
|
|
|
|
|
|
|
replace_uses_by (lhs, name);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-11-21 23:56:36 +01:00
|
|
|
/* Callback for scan_function and helper to sra_ipa_modify_assign. If the
|
|
|
|
expression *EXPR should be replaced by a reduction of a parameter, do so.
|
|
|
|
DATA is a pointer to a vector of adjustments. DONT_CONVERT specifies
|
|
|
|
whether the function should care about type incompatibility the current and
|
|
|
|
new expressions. If it is true, the function will leave incompatibility
|
|
|
|
issues to the caller.
|
|
|
|
|
|
|
|
When called directly by scan_function, DONT_CONVERT is true when the EXPR is
|
|
|
|
a write (LHS) expression. */
|
2009-09-17 13:35:38 +02:00
|
|
|
|
|
|
|
static bool
|
|
|
|
sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
|
2009-11-21 23:56:36 +01:00
|
|
|
bool dont_convert, void *data)
|
2009-09-17 13:35:38 +02:00
|
|
|
{
|
|
|
|
ipa_parm_adjustment_vec adjustments;
|
|
|
|
int i, len;
|
|
|
|
struct ipa_parm_adjustment *adj, *cand = NULL;
|
|
|
|
HOST_WIDE_INT offset, size, max_size;
|
|
|
|
tree base, src;
|
|
|
|
|
|
|
|
adjustments = (VEC (ipa_parm_adjustment_t, heap) *) data;
|
|
|
|
len = VEC_length (ipa_parm_adjustment_t, adjustments);
|
|
|
|
|
|
|
|
if (TREE_CODE (*expr) == BIT_FIELD_REF
|
|
|
|
|| TREE_CODE (*expr) == IMAGPART_EXPR
|
|
|
|
|| TREE_CODE (*expr) == REALPART_EXPR)
|
2009-11-21 23:56:36 +01:00
|
|
|
{
|
|
|
|
expr = &TREE_OPERAND (*expr, 0);
|
|
|
|
dont_convert = false;
|
|
|
|
}
|
2009-09-17 13:35:38 +02:00
|
|
|
|
|
|
|
base = get_ref_base_and_extent (*expr, &offset, &size, &max_size);
|
|
|
|
if (!base || size == -1 || max_size == -1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (INDIRECT_REF_P (base))
|
|
|
|
base = TREE_OPERAND (base, 0);
|
|
|
|
|
|
|
|
base = get_ssa_base_param (base);
|
|
|
|
if (!base || TREE_CODE (base) != PARM_DECL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
adj = VEC_index (ipa_parm_adjustment_t, adjustments, i);
|
|
|
|
|
|
|
|
if (adj->base == base &&
|
|
|
|
(adj->offset == offset || adj->remove_param))
|
|
|
|
{
|
|
|
|
cand = adj;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!cand || cand->copy_param || cand->remove_param)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (cand->by_ref)
|
|
|
|
{
|
|
|
|
tree folded;
|
|
|
|
src = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (cand->reduction)),
|
|
|
|
cand->reduction);
|
|
|
|
folded = gimple_fold_indirect_ref (src);
|
|
|
|
if (folded)
|
|
|
|
src = folded;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
src = cand->reduction;
|
|
|
|
|
|
|
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
|
|
|
{
|
|
|
|
fprintf (dump_file, "About to replace expr ");
|
|
|
|
print_generic_expr (dump_file, *expr, 0);
|
|
|
|
fprintf (dump_file, " with ");
|
|
|
|
print_generic_expr (dump_file, src, 0);
|
|
|
|
fprintf (dump_file, "\n");
|
|
|
|
}
|
|
|
|
|
2009-11-21 23:56:36 +01:00
|
|
|
if (!dont_convert
|
|
|
|
&& !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
|
2009-09-17 13:35:38 +02:00
|
|
|
{
|
|
|
|
tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
|
|
|
|
*expr = vce;
|
|
|
|
}
|
2009-11-21 23:56:36 +01:00
|
|
|
else
|
|
|
|
*expr = src;
|
2009-09-17 13:35:38 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Callback for scan_function to process assign statements. Performs
|
|
|
|
essentially the same function like sra_ipa_modify_expr. */
|
|
|
|
|
|
|
|
static enum scan_assign_result
|
2009-11-21 23:56:36 +01:00
|
|
|
sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, void *data)
|
2009-09-17 13:35:38 +02:00
|
|
|
{
|
|
|
|
gimple stmt = *stmt_ptr;
|
2009-11-21 23:56:36 +01:00
|
|
|
tree *lhs_p, *rhs_p;
|
|
|
|
bool any;
|
2009-09-17 13:35:38 +02:00
|
|
|
|
|
|
|
if (!gimple_assign_single_p (stmt))
|
|
|
|
return SRA_SA_NONE;
|
|
|
|
|
2009-11-21 23:56:36 +01:00
|
|
|
rhs_p = gimple_assign_rhs1_ptr (stmt);
|
|
|
|
lhs_p = gimple_assign_lhs_ptr (stmt);
|
|
|
|
|
|
|
|
any = sra_ipa_modify_expr (rhs_p, gsi, true, data);
|
|
|
|
any |= sra_ipa_modify_expr (lhs_p, gsi, true, data);
|
|
|
|
if (any)
|
|
|
|
{
|
2009-12-01 18:39:44 +01:00
|
|
|
tree new_rhs = NULL_TREE;
|
|
|
|
|
2009-11-21 23:56:36 +01:00
|
|
|
if (!useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
|
2009-12-01 18:39:44 +01:00
|
|
|
new_rhs = fold_build1_loc (gimple_location (stmt), VIEW_CONVERT_EXPR,
|
|
|
|
TREE_TYPE (*lhs_p), *rhs_p);
|
|
|
|
else if (REFERENCE_CLASS_P (*rhs_p)
|
|
|
|
&& is_gimple_reg_type (TREE_TYPE (*lhs_p))
|
|
|
|
&& !is_gimple_reg (*lhs_p))
|
|
|
|
/* This can happen when an assignment in between two single field
|
|
|
|
structures is turned into an assignment in between two pointers to
|
|
|
|
scalars (PR 42237). */
|
|
|
|
new_rhs = *rhs_p;
|
|
|
|
|
|
|
|
if (new_rhs)
|
2009-11-21 23:56:36 +01:00
|
|
|
{
|
2009-12-01 18:39:44 +01:00
|
|
|
tree tmp = force_gimple_operand_gsi (gsi, new_rhs, true, NULL_TREE,
|
2009-11-21 23:56:36 +01:00
|
|
|
true, GSI_SAME_STMT);
|
|
|
|
|
|
|
|
gimple_assign_set_rhs_from_tree (gsi, tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return SRA_SA_PROCESSED;
|
|
|
|
}
|
2009-09-17 13:35:38 +02:00
|
|
|
|
2009-11-21 23:56:36 +01:00
|
|
|
return SRA_SA_NONE;
|
2009-09-17 13:35:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Call gimple_debug_bind_reset_value on all debug statements describing
|
|
|
|
gimple register parameters that are being removed or replaced. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
|
|
|
|
{
|
|
|
|
int i, len;
|
|
|
|
|
|
|
|
len = VEC_length (ipa_parm_adjustment_t, adjustments);
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
struct ipa_parm_adjustment *adj;
|
|
|
|
imm_use_iterator ui;
|
|
|
|
gimple stmt;
|
|
|
|
tree name;
|
|
|
|
|
|
|
|
adj = VEC_index (ipa_parm_adjustment_t, adjustments, i);
|
|
|
|
if (adj->copy_param || !is_gimple_reg (adj->base))
|
|
|
|
continue;
|
|
|
|
name = gimple_default_def (cfun, adj->base);
|
|
|
|
if (!name)
|
|
|
|
continue;
|
|
|
|
FOR_EACH_IMM_USE_STMT (stmt, ui, name)
|
|
|
|
{
|
|
|
|
/* All other users must have been removed by scan_function. */
|
|
|
|
gcc_assert (is_gimple_debug (stmt));
|
|
|
|
gimple_debug_bind_reset_value (stmt);
|
|
|
|
update_stmt (stmt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert all callers of NODE to pass parameters as given in ADJUSTMENTS. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
convert_callers (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
|
|
|
|
{
|
|
|
|
tree old_cur_fndecl = current_function_decl;
|
|
|
|
struct cgraph_edge *cs;
|
|
|
|
basic_block this_block;
|
2009-10-01 13:48:24 +02:00
|
|
|
bitmap recomputed_callers = BITMAP_ALLOC (NULL);
|
2009-09-17 13:35:38 +02:00
|
|
|
|
|
|
|
for (cs = node->callers; cs; cs = cs->next_caller)
|
|
|
|
{
|
|
|
|
current_function_decl = cs->caller->decl;
|
|
|
|
push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
|
|
|
|
|
|
|
|
if (dump_file)
|
2009-10-01 13:48:24 +02:00
|
|
|
fprintf (dump_file, "Adjusting call (%i -> %i) %s -> %s\n",
|
|
|
|
cs->caller->uid, cs->callee->uid,
|
2009-09-17 13:35:38 +02:00
|
|
|
cgraph_node_name (cs->caller),
|
|
|
|
cgraph_node_name (cs->callee));
|
|
|
|
|
|
|
|
ipa_modify_call_arguments (cs, cs->call_stmt, adjustments);
|
|
|
|
|
|
|
|
pop_cfun ();
|
|
|
|
}
|
2009-10-01 13:48:24 +02:00
|
|
|
|
|
|
|
for (cs = node->callers; cs; cs = cs->next_caller)
|
|
|
|
if (!bitmap_bit_p (recomputed_callers, cs->caller->uid))
|
|
|
|
{
|
|
|
|
compute_inline_parameters (cs->caller);
|
|
|
|
bitmap_set_bit (recomputed_callers, cs->caller->uid);
|
|
|
|
}
|
|
|
|
BITMAP_FREE (recomputed_callers);
|
|
|
|
|
2009-09-17 13:35:38 +02:00
|
|
|
current_function_decl = old_cur_fndecl;
|
|
|
|
FOR_EACH_BB (this_block)
|
|
|
|
{
|
|
|
|
gimple_stmt_iterator gsi;
|
|
|
|
|
|
|
|
for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
|
|
|
|
{
|
|
|
|
gimple stmt = gsi_stmt (gsi);
|
|
|
|
if (gimple_code (stmt) == GIMPLE_CALL
|
|
|
|
&& gimple_call_fndecl (stmt) == node->decl)
|
|
|
|
{
|
|
|
|
if (dump_file)
|
|
|
|
fprintf (dump_file, "Adjusting recursive call");
|
|
|
|
ipa_modify_call_arguments (NULL, stmt, adjustments);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Perform all the modification required in IPA-SRA for NODE to have parameters
|
|
|
|
as given in ADJUSTMENTS. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
|
|
|
|
{
|
|
|
|
ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
|
|
|
|
scan_function (sra_ipa_modify_expr, sra_ipa_modify_assign,
|
|
|
|
replace_removed_params_ssa_names, false, adjustments);
|
|
|
|
sra_ipa_reset_debug_stmts (adjustments);
|
|
|
|
convert_callers (node, adjustments);
|
|
|
|
cgraph_make_node_local (node);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return false the function is apparently unsuitable for IPA-SRA based on it's
|
|
|
|
attributes, return true otherwise. NODE is the cgraph node of the current
|
|
|
|
function. */
|
|
|
|
|
|
|
|
static bool
|
|
|
|
ipa_sra_preliminary_function_checks (struct cgraph_node *node)
|
|
|
|
{
|
|
|
|
if (!cgraph_node_can_be_local_p (node))
|
|
|
|
{
|
|
|
|
if (dump_file)
|
|
|
|
fprintf (dump_file, "Function not local to this compilation unit.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DECL_VIRTUAL_P (current_function_decl))
|
|
|
|
{
|
|
|
|
if (dump_file)
|
|
|
|
fprintf (dump_file, "Function is a virtual method.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
|
|
|
|
&& node->global.size >= MAX_INLINE_INSNS_AUTO)
|
|
|
|
{
|
|
|
|
if (dump_file)
|
|
|
|
fprintf (dump_file, "Function too big to be made truly local.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!node->callers)
|
|
|
|
{
|
|
|
|
if (dump_file)
|
|
|
|
fprintf (dump_file,
|
|
|
|
"Function has no callers in this compilation unit.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cfun->stdarg)
|
|
|
|
{
|
|
|
|
if (dump_file)
|
|
|
|
fprintf (dump_file, "Function uses stdarg. \n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Perform early interprocedural SRA. */
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
ipa_early_sra (void)
|
|
|
|
{
|
|
|
|
struct cgraph_node *node = cgraph_node (current_function_decl);
|
|
|
|
ipa_parm_adjustment_vec adjustments;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (!ipa_sra_preliminary_function_checks (node))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
sra_initialize ();
|
|
|
|
sra_mode = SRA_MODE_EARLY_IPA;
|
|
|
|
|
|
|
|
if (!find_param_candidates ())
|
|
|
|
{
|
|
|
|
if (dump_file)
|
|
|
|
fprintf (dump_file, "Function has no IPA-SRA candidates.\n");
|
|
|
|
goto simple_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
|
|
|
|
func_param_count
|
|
|
|
* last_basic_block_for_function (cfun));
|
|
|
|
final_bbs = BITMAP_ALLOC (NULL);
|
|
|
|
|
|
|
|
scan_function (build_access_from_expr, build_accesses_from_assign,
|
|
|
|
NULL, true, NULL);
|
|
|
|
if (encountered_apply_args)
|
|
|
|
{
|
|
|
|
if (dump_file)
|
|
|
|
fprintf (dump_file, "Function calls __builtin_apply_args().\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
adjustments = analyze_all_param_acesses ();
|
|
|
|
if (!adjustments)
|
|
|
|
goto out;
|
|
|
|
if (dump_file)
|
|
|
|
ipa_dump_param_adjustments (dump_file, adjustments, current_function_decl);
|
|
|
|
|
|
|
|
modify_function (node, adjustments);
|
|
|
|
VEC_free (ipa_parm_adjustment_t, heap, adjustments);
|
|
|
|
ret = TODO_update_ssa;
|
|
|
|
|
|
|
|
statistics_counter_event (cfun, "Unused parameters deleted",
|
|
|
|
sra_stats.deleted_unused_parameters);
|
|
|
|
statistics_counter_event (cfun, "Scalar parameters converted to by-value",
|
|
|
|
sra_stats.scalar_by_ref_to_by_val);
|
|
|
|
statistics_counter_event (cfun, "Aggregate parameters broken up",
|
|
|
|
sra_stats.aggregate_params_reduced);
|
|
|
|
statistics_counter_event (cfun, "Aggregate parameter components created",
|
|
|
|
sra_stats.param_reductions_created);
|
|
|
|
|
|
|
|
out:
|
|
|
|
BITMAP_FREE (final_bbs);
|
|
|
|
free (bb_dereferences);
|
|
|
|
simple_out:
|
|
|
|
sra_deinitialize ();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return if early ipa sra shall be performed. */
|
|
|
|
static bool
|
|
|
|
ipa_early_sra_gate (void)
|
|
|
|
{
|
|
|
|
return flag_ipa_sra;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct gimple_opt_pass pass_early_ipa_sra =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
GIMPLE_PASS,
|
|
|
|
"eipa_sra", /* name */
|
|
|
|
ipa_early_sra_gate, /* gate */
|
|
|
|
ipa_early_sra, /* execute */
|
|
|
|
NULL, /* sub */
|
|
|
|
NULL, /* next */
|
|
|
|
0, /* static_pass_number */
|
|
|
|
TV_IPA_SRA, /* tv_id */
|
|
|
|
0, /* properties_required */
|
|
|
|
0, /* properties_provided */
|
|
|
|
0, /* properties_destroyed */
|
|
|
|
0, /* todo_flags_start */
|
|
|
|
TODO_dump_func | TODO_dump_cgraph /* todo_flags_finish */
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|