diff mbox

[PR64164] drop copyrename, integrate into expand

Message ID orego9x6zw.fsf@livre.home
State New
Headers show

Commit Message

Alexandre Oliva March 28, 2015, 7:21 p.m. UTC
On Mar 27, 2015, Alexandre Oliva <aoliva@redhat.com> wrote:

> This patch reworks the out-of-ssa expander to enable coalescing of SSA
> partitions that don't share the same base name.  This is done only when
> optimizing.

> The test we use to tell whether two partitions can be merged no longer
> demands them to have the same base variable when optimizing, so they
> become eligible for coalescing, as they would after copyrename.  We then
> compute the partitioning we'd get if all coalescible partitions were
> coalesced, using this partition assignment to assign base vars numbers.
> These base var numbers are then used to identify conflicts, which used
> to be based on shared base vars or base types.

> We now propagate base var names during coalescing proper, only towards
> the leader variable.  I'm no longer sure this is still needed, but
> something about handling variables and results led me this way and I
> didn't revisit it.  I might rework that with a later patch, or a later
> revision of this patch; it would require other means to identify
> partitions holding result_decls during merging, or allow that and deal
> with param and result decls in a different way during expand proper.

> I had to fix two lingering bugs in order for the whole thing to work: we
> perform conflict detection after abnormal coalescing, but we computed
> live ranges involving only the partition leaders, so conflicts with
> other names already coalesced wouldn't be detected.

This early abnormal coalescing was only present for a few days in the
trunk, and I was lucky enough to start working on a tree that had it.
It turns out that the fix for it was thus rendered unnecessary, so I
dropped it.  It was the fix for it, that didn't cover the live range
check, that caused the two ICEs I saw in the regressions tests.  Since
the ultimate cause of the problem is gone, and the change that
introduced the check failures, both problems went *poof* after I updated
the tree, resolved the conflicts and dropped the redundant code.

> The other problem was that we didn't track default defs for parms as
> live at entry, so they might end up coalesced.

I improved this a little bit, using the bitmap of partitions containing
default params to check that we only process function-entry defs for
them, rather than for all param decls in case they end up in other
partitions.

> I guess none of these problems would have been exercised in practice,
> because we wouldn't even consider merging ssa names associated with
> different variables.

> In the end, I verified that this fixed the codegen regression in the
> PR64164 testcase, that failed to merge two partitions that could in
> theory be merged, but that wasn't even considered due to differences in
> the SSA var names.

> I'd agree that disregarding the var names and dropping 4 passes is too
> much of a change to fix this one problem, but...  it's something we
> should have long tackled, and it gets this and other jobs done, so...

Regstrapped on x86_64-linux-gnu native and on i686-pc-linux-gnu native
on x86_64, so without lto plugin.  The only regression is in
gcc.dg/guality/pr54200.c, that explicitly disables VTA.  When
optimization is enabled, the different coalescing we perform now causes
VTA-less variable tracking to lose track of variable "z".  This
regression in non-VTA var-tracking is expected and, as richi put it in
PR 64164, I guess we don't care about that, do we? :-)

The other guality regressions I mentioned in my other email turned out
not to be regressions, but preexisting failures that somehow did not
make to the test_summary of my earlier pristine build.

Is this ok to install?


for  gcc/ChangeLog

	PR rtl-optimization/64164
	* Makefile.in (OBJS): Drop tree-ssa-copyrename.o.
	* tree-ssa-copyrename.c: Removed.
	* opts.c (default_options_table): Drop -ftree-copyrename.
	* passes.def: Drop all occurrences of pass_rename_ssa_copies.
	* common.opt (ftree-copyrename): Ignore.
	(ftree-coalesce-vars, ftree-coalesce-inlined-vars): Likewise.
	* doc/invoke.texi: Remove the ignored options above.
	* gimple-expr.c (gimple_can_coalesce_p): Allow coalescing
	across base variables when optimizing.
	* tree-ssa-coalesce.c (build_ssa_conflict_graph): Add
	param_defaults argument.  Process PARM_DECLs's default defs at
	the entry point.
	(attempt_coalesce): Add param_defaults argument, and
	track the presence of default defs for params in each
	partition.  Propagate base var to leader on merge, preferring
	parms and results, named vars, ignored vars, and then anon
	vars.  Refuse to merge a RESULT_DECL partition with a default
	PARM_DECL one.
	(coalesce_partitions): Add param_defaults argument,
	and pass it to attempt_coalesce.
	(dump_part_var_map): New.
	(compute_optimized_partition_bases): New, called by...
	(coalesce_ssa_name): ... when optimizing, disabling
	partition_view_bitmap's base assignment.  Pass local
	param_defaults to coalescer functions.
	* tree-ssa-live.c (var_map_base_init): Note use only when not
	optimizing.
---
 gcc/Makefile.in           |    1 
 gcc/common.opt            |   12 +
 gcc/doc/invoke.texi       |   29 ---
 gcc/gimple-expr.c         |    7 -
 gcc/opts.c                |    1 
 gcc/passes.def            |    5 
 gcc/tree-ssa-coalesce.c   |  342 ++++++++++++++++++++++++++++++-
 gcc/tree-ssa-copyrename.c |  499 ---------------------------------------------
 gcc/tree-ssa-live.c       |    5 
 9 files changed, 347 insertions(+), 554 deletions(-)
 delete mode 100644 gcc/tree-ssa-copyrename.c

Comments

Jeff Law March 31, 2015, 5:11 a.m. UTC | #1
On 03/28/2015 01:21 PM, Alexandre Oliva wrote:
> On Mar 27, 2015, Alexandre Oliva <aoliva@redhat.com> wrote:
>
>> This patch reworks the out-of-ssa expander to enable coalescing of SSA
>> partitions that don't share the same base name.  This is done only when
>> optimizing.
>
>> The test we use to tell whether two partitions can be merged no longer
>> demands them to have the same base variable when optimizing, so they
>> become eligible for coalescing, as they would after copyrename.  We then
>> compute the partitioning we'd get if all coalescible partitions were
>> coalesced, using this partition assignment to assign base vars numbers.
>> These base var numbers are then used to identify conflicts, which used
>> to be based on shared base vars or base types.
>
>> We now propagate base var names during coalescing proper, only towards
>> the leader variable.  I'm no longer sure this is still needed, but
>> something about handling variables and results led me this way and I
>> didn't revisit it.  I might rework that with a later patch, or a later
>> revision of this patch; it would require other means to identify
>> partitions holding result_decls during merging, or allow that and deal
>> with param and result decls in a different way during expand proper.
>
>> I had to fix two lingering bugs in order for the whole thing to work: we
>> perform conflict detection after abnormal coalescing, but we computed
>> live ranges involving only the partition leaders, so conflicts with
>> other names already coalesced wouldn't be detected.
>
> This early abnormal coalescing was only present for a few days in the
> trunk, and I was lucky enough to start working on a tree that had it.
> It turns out that the fix for it was thus rendered unnecessary, so I
> dropped it.  It was the fix for it, that didn't cover the live range
> check, that caused the two ICEs I saw in the regressions tests.  Since
> the ultimate cause of the problem is gone, and the change that
> introduced the check failures, both problems went *poof* after I updated
> the tree, resolved the conflicts and dropped the redundant code.
>
>> The other problem was that we didn't track default defs for parms as
>> live at entry, so they might end up coalesced.
>
> I improved this a little bit, using the bitmap of partitions containing
> default params to check that we only process function-entry defs for
> them, rather than for all param decls in case they end up in other
> partitions.
>
>> I guess none of these problems would have been exercised in practice,
>> because we wouldn't even consider merging ssa names associated with
>> different variables.
>
>> In the end, I verified that this fixed the codegen regression in the
>> PR64164 testcase, that failed to merge two partitions that could in
>> theory be merged, but that wasn't even considered due to differences in
>> the SSA var names.
>
>> I'd agree that disregarding the var names and dropping 4 passes is too
>> much of a change to fix this one problem, but...  it's something we
>> should have long tackled, and it gets this and other jobs done, so...
>
> Regstrapped on x86_64-linux-gnu native and on i686-pc-linux-gnu native
> on x86_64, so without lto plugin.  The only regression is in
> gcc.dg/guality/pr54200.c, that explicitly disables VTA.  When
> optimization is enabled, the different coalescing we perform now causes
> VTA-less variable tracking to lose track of variable "z".  This
> regression in non-VTA var-tracking is expected and, as richi put it in
> PR 64164, I guess we don't care about that, do we? :-)
>
> The other guality regressions I mentioned in my other email turned out
> not to be regressions, but preexisting failures that somehow did not
> make to the test_summary of my earlier pristine build.
>
> Is this ok to install?
>
>
> for  gcc/ChangeLog
>
> 	PR rtl-optimization/64164
> 	* Makefile.in (OBJS): Drop tree-ssa-copyrename.o.
> 	* tree-ssa-copyrename.c: Removed.
> 	* opts.c (default_options_table): Drop -ftree-copyrename.
> 	* passes.def: Drop all occurrences of pass_rename_ssa_copies.
> 	* common.opt (ftree-copyrename): Ignore.
> 	(ftree-coalesce-vars, ftree-coalesce-inlined-vars): Likewise.
> 	* doc/invoke.texi: Remove the ignored options above.
> 	* gimple-expr.c (gimple_can_coalesce_p): Allow coalescing
> 	across base variables when optimizing.
> 	* tree-ssa-coalesce.c (build_ssa_conflict_graph): Add
> 	param_defaults argument.  Process PARM_DECLs's default defs at
> 	the entry point.
> 	(attempt_coalesce): Add param_defaults argument, and
> 	track the presence of default defs for params in each
> 	partition.  Propagate base var to leader on merge, preferring
> 	parms and results, named vars, ignored vars, and then anon
> 	vars.  Refuse to merge a RESULT_DECL partition with a default
> 	PARM_DECL one.
> 	(coalesce_partitions): Add param_defaults argument,
> 	and pass it to attempt_coalesce.
> 	(dump_part_var_map): New.
> 	(compute_optimized_partition_bases): New, called by...
> 	(coalesce_ssa_name): ... when optimizing, disabling
> 	partition_view_bitmap's base assignment.  Pass local
> 	param_defaults to coalescer functions.
> 	* tree-ssa-live.c (var_map_base_init): Note use only when not
> 	optimizing.
> ---
>   gcc/Makefile.in           |    1
>   gcc/common.opt            |   12 +
>   gcc/doc/invoke.texi       |   29 ---
>   gcc/gimple-expr.c         |    7 -
>   gcc/opts.c                |    1
>   gcc/passes.def            |    5
>   gcc/tree-ssa-coalesce.c   |  342 ++++++++++++++++++++++++++++++-
>   gcc/tree-ssa-copyrename.c |  499 ---------------------------------------------
>   gcc/tree-ssa-live.c       |    5
>   9 files changed, 347 insertions(+), 554 deletions(-)
>   delete mode 100644 gcc/tree-ssa-copyrename.c
>
> diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
> index efc93b7..62ae577 100644
> --- a/gcc/gimple-expr.c
> +++ b/gcc/gimple-expr.c
> @@ -399,13 +399,14 @@ copy_var_decl (tree var, tree name, tree type)
>   bool
>   gimple_can_coalesce_p (tree name1, tree name2)
>   {
> -  /* First check the SSA_NAME's associated DECL.  We only want to
> -     coalesce if they have the same DECL or both have no associated DECL.  */
> +  /* First check the SSA_NAME's associated DECL.  Without
> +     optimization, we only want to coalesce if they have the same DECL
> +     or both have no associated DECL.  */
>     tree var1 = SSA_NAME_VAR (name1);
>     tree var2 = SSA_NAME_VAR (name2);
>     var1 = (var1 && (!VAR_P (var1) || !DECL_IGNORED_P (var1))) ? var1 : NULL_TREE;
>     var2 = (var2 && (!VAR_P (var2) || !DECL_IGNORED_P (var2))) ? var2 : NULL_TREE;
> -  if (var1 != var2)
> +  if (var1 != var2 && !optimize)
>       return false;
So when when the base variables are different and we are optimizing, 
this allows coalescing, right?

What I don't see is a corresponding change to var_map_base_init to 
ensure we build a conflict graph which includes objects when 
SSA_NAME_VARs are not the same.  I see a vague reference in 
var_map_base_init's header comment that refers us to coalesce_ssa_name.

It appears that compute_optimized_partition_bases handles this by 
creating a partitions of things that are related by copies/phis 
regardless of their underlying named object, type, etc.  Right?





> index 1d598b2..f8fd0ef 100644
> --- a/gcc/passes.def
> +++ b/gcc/passes.def
[ ... ]
Hard to argue with removing a pass that gets called 5 times!


> @@ -890,6 +900,36 @@ build_ssa_conflict_graph (tree_live_info_p liveinfo)
>   	    live_track_process_def (live, result, graph);
>   	}
>
> +      /* Pretend there are defs for params' default defs at the start
> +	 of the (post-)entry block.  We run after abnormal coalescing,
> +	 so we can't assume the leader variable is the default
> +	 definition, but because of SSA_NAME_VAR adjustments in
> +	 attempt_coalesce, we can assume that if there is any
> +	 PARM_DECL in the partition, it will be the leader's
> +	 SSA_NAME_VAR.  */
So the issue here is you want to iterate over the objects live at the 
entry block, which would include any SSA_NAMEs which result from 
PARM_DECLs.  I don't guess there's an easier way to do that other than 
iterating over everything live in that initial block?

And the second second EXECUTE_IF_SET_IN_BITMAP iterates over everything 
in the partitions associated with the SSA_NAMES that are live at the the 
entry block, right?

I don't guess it'd be more efficient to walk over the SSA_NAMEs looking 
for anything marked as a default definition, then map that back to a 
partition since we'd have to look at every SSA_NAME whereas your code 
only looks at paritions that are live in the entry block, then looks at 
the elements in those partitions.

> @@ -1126,11 +1166,12 @@ create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy)
>
>   static inline bool
>   attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
> -		  FILE *debug)
> +		  bitmap param_defaults, FILE *debug)
[ ... ]
So the bulk of the changes into this routine are really about picking a 
good leader, which presumably is how we're able to get the desired 
effects on debuginfo that we used to get from tree-ssa-copyrename.c?


> @@ -1158,6 +1199,70 @@ attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
>       {
>         var1 = partition_to_var (map, p1);
>         var2 = partition_to_var (map, p2);
> +
> +      tree leader;
> +
> +      if (var1 == var2 || !SSA_NAME_VAR (var2)
> +	  || SSA_NAME_VAR (var1) == SSA_NAME_VAR (var2))
> +	{
> +	  leader = SSA_NAME_VAR (var1);
> +	  default_def = (leader && TREE_CODE (leader) == PARM_DECL
> +			 && (SSA_NAME_IS_DEFAULT_DEF (var1)
> +			     || bitmap_bit_p (param_defaults, p1)));
> +	}
So some comments about the various cases here might help.  I can sort 
them out if I read the code, but one could argue that a block comment on 
the rules for how to select the partition leader would be better.

Is the special casing of PARM_DECLs + RESULT_DECLs really a failing of 
not handling one or both properly when computing liveness information?

I'm not aware of an inherent reason why a PARM_DECL couldn't coalesce 
with a related RESULT_DECL if they are otherwise non-conflicting and 
related by a copy/phi.


> @@ -1272,6 +1415,178 @@ ssa_name_var_hash::equal (const value_type *n1, const compare_type *n2)
> +
> +/* Fill in MAP's partition_to_base_index, with one index for each
> +   partition of SSA names USED_IN_COPIES and related by CL
> +   coalesce possibilities.  */
> +
> +static void
> +compute_optimized_partition_bases (var_map map, bitmap used_in_copies,
> +				   coalesce_list_p cl)
Presumably ordering of unioning of the partitions doesn't matter here as 
we're looking at coalesce possibilities rather than things we have 
actually coalesced?  Thus it's OK (?) to handle the names occurring in 
abnormal PHIs after those names that are associated by a copy.

This is all probably OK, but I want to make sure I understand what's 
happening before a final approval.

jeff
Steven Bosscher March 31, 2015, 6:55 a.m. UTC | #2
On Sat, Mar 28, 2015 at 8:21 PM, Alexandre Oliva wrote:
> Regstrapped on x86_64-linux-gnu native and on i686-pc-linux-gnu native
> on x86_64, so without lto plugin.  The only regression is in
> gcc.dg/guality/pr54200.c, that explicitly disables VTA.

What about memory footprint? IIRC this pass was in part introduced to
reduce the number of VAR_DECLs.

Ciao!
Steven
Richard Biener March 31, 2015, 1:30 p.m. UTC | #3
On Tue, Mar 31, 2015 at 8:55 AM, Steven Bosscher <stevenb.gcc@gmail.com> wrote:
> On Sat, Mar 28, 2015 at 8:21 PM, Alexandre Oliva wrote:
>> Regstrapped on x86_64-linux-gnu native and on i686-pc-linux-gnu native
>> on x86_64, so without lto plugin.  The only regression is in
>> gcc.dg/guality/pr54200.c, that explicitly disables VTA.
>
> What about memory footprint? IIRC this pass was in part introduced to
> reduce the number of VAR_DECLs.

That's no longer necessary as we now drop VAR_DECLs from non-user vars
completely at into-SSA time.  We have "anonymous" SSA names without
associated decls.

Richard.

> Ciao!
> Steven
Richard Biener March 31, 2015, 2:06 p.m. UTC | #4
On Sat, Mar 28, 2015 at 8:21 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Mar 27, 2015, Alexandre Oliva <aoliva@redhat.com> wrote:
>
>> This patch reworks the out-of-ssa expander to enable coalescing of SSA
>> partitions that don't share the same base name.  This is done only when
>> optimizing.
>
>> The test we use to tell whether two partitions can be merged no longer
>> demands them to have the same base variable when optimizing, so they
>> become eligible for coalescing, as they would after copyrename.  We then
>> compute the partitioning we'd get if all coalescible partitions were
>> coalesced, using this partition assignment to assign base vars numbers.
>> These base var numbers are then used to identify conflicts, which used
>> to be based on shared base vars or base types.
>
>> We now propagate base var names during coalescing proper, only towards
>> the leader variable.  I'm no longer sure this is still needed, but
>> something about handling variables and results led me this way and I
>> didn't revisit it.  I might rework that with a later patch, or a later
>> revision of this patch; it would require other means to identify
>> partitions holding result_decls during merging, or allow that and deal
>> with param and result decls in a different way during expand proper.
>
>> I had to fix two lingering bugs in order for the whole thing to work: we
>> perform conflict detection after abnormal coalescing, but we computed
>> live ranges involving only the partition leaders, so conflicts with
>> other names already coalesced wouldn't be detected.
>
> This early abnormal coalescing was only present for a few days in the
> trunk, and I was lucky enough to start working on a tree that had it.
> It turns out that the fix for it was thus rendered unnecessary, so I
> dropped it.  It was the fix for it, that didn't cover the live range
> check, that caused the two ICEs I saw in the regressions tests.  Since
> the ultimate cause of the problem is gone, and the change that
> introduced the check failures, both problems went *poof* after I updated
> the tree, resolved the conflicts and dropped the redundant code.
>
>> The other problem was that we didn't track default defs for parms as
>> live at entry, so they might end up coalesced.
>
> I improved this a little bit, using the bitmap of partitions containing
> default params to check that we only process function-entry defs for
> them, rather than for all param decls in case they end up in other
> partitions.
>
>> I guess none of these problems would have been exercised in practice,
>> because we wouldn't even consider merging ssa names associated with
>> different variables.
>
>> In the end, I verified that this fixed the codegen regression in the
>> PR64164 testcase, that failed to merge two partitions that could in
>> theory be merged, but that wasn't even considered due to differences in
>> the SSA var names.
>
>> I'd agree that disregarding the var names and dropping 4 passes is too
>> much of a change to fix this one problem, but...  it's something we
>> should have long tackled, and it gets this and other jobs done, so...
>
> Regstrapped on x86_64-linux-gnu native and on i686-pc-linux-gnu native
> on x86_64, so without lto plugin.  The only regression is in
> gcc.dg/guality/pr54200.c, that explicitly disables VTA.  When
> optimization is enabled, the different coalescing we perform now causes
> VTA-less variable tracking to lose track of variable "z".  This
> regression in non-VTA var-tracking is expected and, as richi put it in
> PR 64164, I guess we don't care about that, do we? :-)

Apart from at -O0, yes.

> The other guality regressions I mentioned in my other email turned out
> not to be regressions, but preexisting failures that somehow did not
> make to the test_summary of my earlier pristine build.
>
> Is this ok to install?

I think this is stage1 material.  Some comments in-line

>
> for  gcc/ChangeLog
>
>         PR rtl-optimization/64164
>         * Makefile.in (OBJS): Drop tree-ssa-copyrename.o.
>         * tree-ssa-copyrename.c: Removed.
>         * opts.c (default_options_table): Drop -ftree-copyrename.
>         * passes.def: Drop all occurrences of pass_rename_ssa_copies.
>         * common.opt (ftree-copyrename): Ignore.
>         (ftree-coalesce-vars, ftree-coalesce-inlined-vars): Likewise.
>         * doc/invoke.texi: Remove the ignored options above.
>         * gimple-expr.c (gimple_can_coalesce_p): Allow coalescing
>         across base variables when optimizing.
>         * tree-ssa-coalesce.c (build_ssa_conflict_graph): Add
>         param_defaults argument.  Process PARM_DECLs's default defs at
>         the entry point.
>         (attempt_coalesce): Add param_defaults argument, and
>         track the presence of default defs for params in each
>         partition.  Propagate base var to leader on merge, preferring
>         parms and results, named vars, ignored vars, and then anon
>         vars.  Refuse to merge a RESULT_DECL partition with a default
>         PARM_DECL one.
>         (coalesce_partitions): Add param_defaults argument,
>         and pass it to attempt_coalesce.
>         (dump_part_var_map): New.
>         (compute_optimized_partition_bases): New, called by...
>         (coalesce_ssa_name): ... when optimizing, disabling
>         partition_view_bitmap's base assignment.  Pass local
>         param_defaults to coalescer functions.
>         * tree-ssa-live.c (var_map_base_init): Note use only when not
>         optimizing.
> ---
>  gcc/Makefile.in           |    1
>  gcc/common.opt            |   12 +
>  gcc/doc/invoke.texi       |   29 ---
>  gcc/gimple-expr.c         |    7 -
>  gcc/opts.c                |    1
>  gcc/passes.def            |    5
>  gcc/tree-ssa-coalesce.c   |  342 ++++++++++++++++++++++++++++++-
>  gcc/tree-ssa-copyrename.c |  499 ---------------------------------------------
>  gcc/tree-ssa-live.c       |    5
>  9 files changed, 347 insertions(+), 554 deletions(-)
>  delete mode 100644 gcc/tree-ssa-copyrename.c
>
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index f924fb8..990c4e9 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -1428,7 +1428,6 @@ OBJS = \
>         tree-ssa-ccp.o \
>         tree-ssa-coalesce.o \
>         tree-ssa-copy.o \
> -       tree-ssa-copyrename.o \
>         tree-ssa-dce.o \
>         tree-ssa-dom.o \
>         tree-ssa-dse.o \
> diff --git a/gcc/common.opt b/gcc/common.opt
> index b49ac46..fefaee7 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -2207,16 +2207,16 @@ Common Report Var(flag_tree_ch) Optimization
>  Enable loop header copying on trees
>
>  ftree-coalesce-inlined-vars
> -Common Report Var(flag_ssa_coalesce_vars,1) Init(2) RejectNegative Optimization
> -Enable coalescing of copy-related user variables that are inlined
> +Common Ignore RejectNegative
> +Does nothing.  Preserved for backward compatibility.
>
>  ftree-coalesce-vars
> -Common Report Var(flag_ssa_coalesce_vars,2) Optimization
> -Enable coalescing of all copy-related user variables
> +Common Ignore
> +Does nothing.  Preserved for backward compatibility.
>
>  ftree-copyrename
> -Common Report Var(flag_tree_copyrename) Optimization
> -Replace SSA temporaries with better names in copies
> +Common Ignore
> +Does nothing.  Preserved for backward compatibility.
>
>  ftree-copy-prop
>  Common Report Var(flag_tree_copy_prop) Optimization
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 9749727..5d2c516 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -442,8 +442,7 @@ Objective-C and Objective-C++ Dialects}.
>  -fstack-protector-explicit -fstdarg-opt -fstrict-aliasing @gol
>  -fstrict-overflow -fthread-jumps -ftracer -ftree-bit-ccp @gol
>  -ftree-builtin-call-dce -ftree-ccp -ftree-ch @gol
> --ftree-coalesce-inline-vars -ftree-coalesce-vars -ftree-copy-prop @gol
> --ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse @gol
> +-ftree-copy-prop -ftree-dce -ftree-dominator-opts -ftree-dse @gol
>  -ftree-forwprop -ftree-fre -ftree-loop-if-convert @gol
>  -ftree-loop-if-convert-stores -ftree-loop-im @gol
>  -ftree-phiprop -ftree-loop-distribution -ftree-loop-distribute-patterns @gol
> @@ -8822,32 +8821,6 @@ Perform scalar replacement of aggregates.  This pass replaces structure
>  references with scalars to prevent committing structures to memory too
>  early.  This flag is enabled by default at @option{-O} and higher.
>
> -@item -ftree-copyrename
> -@opindex ftree-copyrename
> -Perform copy renaming on trees.  This pass attempts to rename compiler
> -temporaries to other variables at copy locations, usually resulting in
> -variable names which more closely resemble the original variables.  This flag
> -is enabled by default at @option{-O} and higher.
> -
> -@item -ftree-coalesce-inlined-vars
> -@opindex ftree-coalesce-inlined-vars
> -Tell the copyrename pass (see @option{-ftree-copyrename}) to attempt to
> -combine small user-defined variables too, but only if they are inlined
> -from other functions.  It is a more limited form of
> -@option{-ftree-coalesce-vars}.  This may harm debug information of such
> -inlined variables, but it keeps variables of the inlined-into
> -function apart from each other, such that they are more likely to
> -contain the expected values in a debugging session.
> -
> -@item -ftree-coalesce-vars
> -@opindex ftree-coalesce-vars
> -Tell the copyrename pass (see @option{-ftree-copyrename}) to attempt to
> -combine small user-defined variables too, instead of just compiler
> -temporaries.  This may severely limit the ability to debug an optimized
> -program compiled with @option{-fno-var-tracking-assignments}.  In the
> -negated form, this flag prevents SSA coalescing of user variables,
> -including inlined ones.  This option is enabled by default.
> -
>  @item -ftree-ter
>  @opindex ftree-ter
>  Perform temporary expression replacement during the SSA->normal phase.  Single
> diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
> index efc93b7..62ae577 100644
> --- a/gcc/gimple-expr.c
> +++ b/gcc/gimple-expr.c
> @@ -399,13 +399,14 @@ copy_var_decl (tree var, tree name, tree type)
>  bool
>  gimple_can_coalesce_p (tree name1, tree name2)
>  {
> -  /* First check the SSA_NAME's associated DECL.  We only want to
> -     coalesce if they have the same DECL or both have no associated DECL.  */
> +  /* First check the SSA_NAME's associated DECL.  Without
> +     optimization, we only want to coalesce if they have the same DECL
> +     or both have no associated DECL.  */
>    tree var1 = SSA_NAME_VAR (name1);
>    tree var2 = SSA_NAME_VAR (name2);
>    var1 = (var1 && (!VAR_P (var1) || !DECL_IGNORED_P (var1))) ? var1 : NULL_TREE;
>    var2 = (var2 && (!VAR_P (var2) || !DECL_IGNORED_P (var2))) ? var2 : NULL_TREE;
> -  if (var1 != var2)
> +  if (var1 != var2 && !optimize)
>      return false;
>
>    /* Now check the types.  If the types are the same, then we should
> diff --git a/gcc/opts.c b/gcc/opts.c
> index 39c190d..8149421 100644
> --- a/gcc/opts.c
> +++ b/gcc/opts.c
> @@ -453,7 +453,6 @@ static const struct default_options default_options_table[] =
>      { OPT_LEVELS_1_PLUS, OPT_ftree_dse, NULL, 1 },
>      { OPT_LEVELS_1_PLUS, OPT_ftree_ter, NULL, 1 },
>      { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_sra, NULL, 1 },
> -    { OPT_LEVELS_1_PLUS, OPT_ftree_copyrename, NULL, 1 },
>      { OPT_LEVELS_1_PLUS, OPT_ftree_fre, NULL, 1 },
>      { OPT_LEVELS_1_PLUS, OPT_ftree_copy_prop, NULL, 1 },
>      { OPT_LEVELS_1_PLUS, OPT_ftree_sink, NULL, 1 },
> diff --git a/gcc/passes.def b/gcc/passes.def
> index 1d598b2..f8fd0ef 100644
> --- a/gcc/passes.def
> +++ b/gcc/passes.def
> @@ -77,7 +77,6 @@ along with GCC; see the file COPYING3.  If not see
>        NEXT_PASS (pass_all_early_optimizations);
>        PUSH_INSERT_PASSES_WITHIN (pass_all_early_optimizations)
>           NEXT_PASS (pass_remove_cgraph_callee_edges);
> -         NEXT_PASS (pass_rename_ssa_copies);
>           NEXT_PASS (pass_object_sizes);
>           NEXT_PASS (pass_ccp);
>           /* After CCP we rewrite no longer addressed locals into SSA
> @@ -154,7 +153,6 @@ along with GCC; see the file COPYING3.  If not see
>        /* Initial scalar cleanups before alias computation.
>          They ensure memory accesses are not indirect wherever possible.  */
>        NEXT_PASS (pass_strip_predict_hints);
> -      NEXT_PASS (pass_rename_ssa_copies);
>        NEXT_PASS (pass_ccp);
>        /* After CCP we rewrite no longer addressed locals into SSA
>          form if possible.  */
> @@ -182,7 +180,6 @@ along with GCC; see the file COPYING3.  If not see
>        NEXT_PASS (pass_stdarg);
>        NEXT_PASS (pass_lower_complex);
>        NEXT_PASS (pass_sra);
> -      NEXT_PASS (pass_rename_ssa_copies);
>        /* The dom pass will also resolve all __builtin_constant_p calls
>           that are still there to 0.  This has to be done after some
>          propagations have already run, but before some more dead code
> @@ -291,7 +288,6 @@ along with GCC; see the file COPYING3.  If not see
>        NEXT_PASS (pass_fold_builtins);
>        NEXT_PASS (pass_optimize_widening_mul);
>        NEXT_PASS (pass_tail_calls);
> -      NEXT_PASS (pass_rename_ssa_copies);
>        /* FIXME: If DCE is not run before checking for uninitialized uses,
>          we may get false warnings (e.g., testsuite/gcc.dg/uninit-5.c).
>          However, this also causes us to misdiagnose cases that should be
> @@ -326,7 +322,6 @@ along with GCC; see the file COPYING3.  If not see
>        NEXT_PASS (pass_dce);
>        NEXT_PASS (pass_asan);
>        NEXT_PASS (pass_tsan);
> -      NEXT_PASS (pass_rename_ssa_copies);
>        /* ???  We do want some kind of loop invariant motion, but we possibly
>           need to adjust LIM to be more friendly towards preserving accurate
>          debug information here.  */
> diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c
> index 1afeefe..8557d84 100644
> --- a/gcc/tree-ssa-coalesce.c
> +++ b/gcc/tree-ssa-coalesce.c
> @@ -825,13 +825,23 @@ live_track_clear_base_vars (live_track_p ptr)
>     base variable are added.  */
>
>  static ssa_conflicts_p
> -build_ssa_conflict_graph (tree_live_info_p liveinfo)
> +build_ssa_conflict_graph (tree_live_info_p liveinfo, bitmap param_defaults)
>  {
>    ssa_conflicts_p graph;
>    var_map map;
>    basic_block bb;
>    ssa_op_iter iter;
>    live_track_p live;
> +  basic_block entry;
> +
> +  /* If we are optimizing, we may attempt to coalesce variables from
> +     different base variables, including different parameters, so we
> +     have to make sure default defs live at the entry block conflict
> +     with each other.  */
> +  if (optimize)
> +    entry = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
> +  else
> +    entry = NULL;
>
>    map = live_var_map (liveinfo);
>    graph = ssa_conflicts_new (num_var_partitions (map));
> @@ -890,6 +900,36 @@ build_ssa_conflict_graph (tree_live_info_p liveinfo)
>             live_track_process_def (live, result, graph);
>         }
>
> +      /* Pretend there are defs for params' default defs at the start
> +        of the (post-)entry block.  We run after abnormal coalescing,
> +        so we can't assume the leader variable is the default
> +        definition, but because of SSA_NAME_VAR adjustments in
> +        attempt_coalesce, we can assume that if there is any
> +        PARM_DECL in the partition, it will be the leader's
> +        SSA_NAME_VAR.  */
> +      if (bb == entry)
> +       {
> +         unsigned base;
> +         bitmap_iterator bi;
> +         EXECUTE_IF_SET_IN_BITMAP (live->live_base_var, 0, base, bi)
> +           {
> +             bitmap_iterator bi2;
> +             unsigned part;
> +             EXECUTE_IF_SET_IN_BITMAP (live->live_base_partitions[base],
> +                                       0, part, bi2)
> +               {
> +                 tree var = partition_to_var (map, part);
> +                 if (!SSA_NAME_VAR (var)
> +                     || TREE_CODE (SSA_NAME_VAR (var)) != PARM_DECL
> +                     || !(SSA_NAME_IS_DEFAULT_DEF (var)
> +                          || (param_defaults
> +                              && bitmap_bit_p (param_defaults, part))))
> +                   continue;
> +                 live_track_process_def (live, var, graph);
> +               }
> +           }
> +       }
> +

This looks somewhat awkward to me ;)  Is it really important to allow
coalescing PARM_DECL-based SSA vars with sth else?  At least
abnormal coalescing doesn't need to do that, so just walking over
the function decls parameters and making their default-def live
should be enough?

That is, that param_defaults bitmap looks ugly to me.

>       live_track_clear_base_vars (live);
>      }
>
> @@ -1126,11 +1166,12 @@ create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy)
>
>  static inline bool
>  attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
> -                 FILE *debug)
> +                 bitmap param_defaults, FILE *debug)
>  {
>    int z;
>    tree var1, var2;
>    int p1, p2;
> +  bool default_def = false;
>
>    p1 = var_to_partition (map, ssa_name (x));
>    p2 = var_to_partition (map, ssa_name (y));
> @@ -1158,6 +1199,70 @@ attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
>      {
>        var1 = partition_to_var (map, p1);
>        var2 = partition_to_var (map, p2);
> +
> +      tree leader;
> +
> +      if (var1 == var2 || !SSA_NAME_VAR (var2)
> +         || SSA_NAME_VAR (var1) == SSA_NAME_VAR (var2))
> +       {
> +         leader = SSA_NAME_VAR (var1);
> +         default_def = (leader && TREE_CODE (leader) == PARM_DECL
> +                        && (SSA_NAME_IS_DEFAULT_DEF (var1)
> +                            || bitmap_bit_p (param_defaults, p1)));
> +       }
> +      else if (!SSA_NAME_VAR (var1))
> +       {
> +         leader = SSA_NAME_VAR (var2);
> +         default_def = (leader && TREE_CODE (leader) == PARM_DECL
> +                        && (SSA_NAME_IS_DEFAULT_DEF (var2)
> +                            || bitmap_bit_p (param_defaults, p2)));
> +       }
> +      else if ((TREE_CODE (SSA_NAME_VAR (var1)) == PARM_DECL
> +               && (SSA_NAME_IS_DEFAULT_DEF (var1)
> +                   || bitmap_bit_p (param_defaults, p1)))
> +              || TREE_CODE (SSA_NAME_VAR (var1)) == RESULT_DECL)
> +       {
> +         if ((TREE_CODE (SSA_NAME_VAR (var2)) == PARM_DECL
> +              && (SSA_NAME_IS_DEFAULT_DEF (var2)
> +                  || bitmap_bit_p (param_defaults, p2)))
> +             || TREE_CODE (SSA_NAME_VAR (var2)) == RESULT_DECL)
> +           {
> +             /* We only have one RESULT_DECL, and two PARM_DECL
> +                DEFAULT_DEFs would have conflicted, so we know either
> +                one of var1 or var2 is a PARM_DECL, and the other is
> +                a RESULT_DECL.  */
> +             if (debug)
> +               fprintf (debug, ": Cannot coalesce PARM_DECL and RESULT_DECL\n");
> +             return false;
> +           }
> +         leader = SSA_NAME_VAR (var1);
> +         default_def = TREE_CODE (leader) == PARM_DECL;
> +       }
> +      else if ((TREE_CODE (SSA_NAME_VAR (var2)) == PARM_DECL
> +               && (SSA_NAME_IS_DEFAULT_DEF (var2)
> +                   || bitmap_bit_p (param_defaults, p2)))
> +              || TREE_CODE (SSA_NAME_VAR (var2)) == RESULT_DECL)
> +       {
> +         leader = SSA_NAME_VAR (var2);
> +         default_def = TREE_CODE (leader) == PARM_DECL;
> +       }
> +      else if (TREE_CODE (SSA_NAME_VAR (var1)) == PARM_DECL)
> +       leader = SSA_NAME_VAR (var1);
> +      else if (TREE_CODE (SSA_NAME_VAR (var2)) == PARM_DECL)
> +       leader = SSA_NAME_VAR (var2);
> +      else if (TREE_CODE (SSA_NAME_VAR (var1)) == VAR_DECL
> +              && !DECL_IGNORED_P (SSA_NAME_VAR (var1)))
> +       leader = SSA_NAME_VAR (var1);
> +      else if (TREE_CODE (SSA_NAME_VAR (var2)) == VAR_DECL
> +              && !DECL_IGNORED_P (SSA_NAME_VAR (var2)))
> +       leader = SSA_NAME_VAR (var2);
> +      else if (TREE_CODE (SSA_NAME_VAR (var1)) == VAR_DECL)
> +       leader = SSA_NAME_VAR (var1);
> +      else if (TREE_CODE (SSA_NAME_VAR (var2)) == VAR_DECL)
> +       leader = SSA_NAME_VAR (var2);
> +      else /* What else could it be?  */
> +       gcc_unreachable ();
> +

definitely comments missing in this spaghetti...

>        z = var_union (map, var1, var2);
>        if (z == NO_PARTITION)
>         {
> @@ -1173,8 +1278,46 @@ attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
>        else
>         ssa_conflicts_merge (graph, p2, p1);
>
> +      if (z == p1)
> +       {
> +         if (SSA_NAME_VAR (var1) != leader)
> +           {
> +             replace_ssa_name_symbol (var1, leader);
> +             if (debug)
> +               {
> +                 fprintf (debug, ": Renamed ");
> +                 print_generic_expr (debug, var1, TDF_SLIM);
> +               }
> +           }
> +         if (default_def)
> +           {
> +             if (SSA_NAME_IS_DEFAULT_DEF (var2))
> +               bitmap_clear_bit (param_defaults, p2);
> +             bitmap_set_bit (param_defaults, p1);
> +           }
> +       }
> +      else
> +       {
> +         if (SSA_NAME_VAR (var2) != leader)
> +           {
> +             replace_ssa_name_symbol (var2, leader);
> +             if (debug)
> +               {
> +                 fprintf (debug, ": Renamed ");
> +                 print_generic_expr (debug, var2, TDF_SLIM);
> +               }
> +           }
> +         if (default_def)
> +           {
> +             if (SSA_NAME_IS_DEFAULT_DEF (var1))
> +               bitmap_clear_bit (param_defaults, p1);
> +             bitmap_set_bit (param_defaults, p2);
> +           }
> +       }

or seeing this, why coalesce default-defs at all?  Either they are param values
or they have indetermined values (and thus we can and do pick whatever is
available at expansion time)?

> +
>        if (debug)
>         fprintf (debug, ": Success -> %d\n", z);
> +
>        return true;
>      }
>
> @@ -1190,7 +1333,7 @@ attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
>
>  static void
>  coalesce_partitions (var_map map, ssa_conflicts_p graph, coalesce_list_p cl,
> -                    FILE *debug)
> +                    bitmap param_defaults, FILE *debug)
>  {
>    int x = 0, y = 0;
>    tree var1, var2;
> @@ -1226,7 +1369,7 @@ coalesce_partitions (var_map map, ssa_conflicts_p graph, coalesce_list_p cl,
>                 if (debug)
>                   fprintf (debug, "Abnormal coalesce: ");
>
> -               if (!attempt_coalesce (map, graph, v1, v2, debug))
> +               if (!attempt_coalesce (map, graph, v1, v2, param_defaults, debug))
>                   fail_abnormal_edge_coalesce (v1, v2);
>               }
>           }
> @@ -1244,7 +1387,7 @@ coalesce_partitions (var_map map, ssa_conflicts_p graph, coalesce_list_p cl,
>
>        if (debug)
>         fprintf (debug, "Coalesce list: ");
> -      attempt_coalesce (map, graph, x, y, debug);
> +      attempt_coalesce (map, graph, x, y, param_defaults, debug);
>      }
>  }
>
> @@ -1272,6 +1415,178 @@ ssa_name_var_hash::equal (const value_type *n1, const compare_type *n2)
>  }
>
>
> +/* Output partition map MAP with coalescing plan PART to file F.  */
> +
> +void
> +dump_part_var_map (FILE *f, partition part, var_map map)
> +{
> +  int t;
> +  unsigned x, y;
> +  int p;
> +
> +  fprintf (f, "\nCoalescible Partition map \n\n");
> +
> +  for (x = 0; x < map->num_partitions; x++)
> +    {
> +      if (map->view_to_partition != NULL)
> +       p = map->view_to_partition[x];
> +      else
> +       p = x;
> +
> +      if (ssa_name (p) == NULL_TREE
> +         || virtual_operand_p (ssa_name (p)))
> +        continue;
> +
> +      t = 0;
> +      for (y = 1; y < num_ssa_names; y++)
> +        {
> +         tree var = version_to_var (map, y);
> +         if (!var)
> +           continue;
> +         int q = var_to_partition (map, var);
> +         p = partition_find (part, q);
> +         gcc_assert (map->partition_to_base_index[q]
> +                     == map->partition_to_base_index[p]);
> +
> +         if (p == (int)x)
> +           {
> +             if (t++ == 0)
> +               {
> +                 fprintf (f, "Partition %d, base %d (", x,
> +                          map->partition_to_base_index[q]);
> +                 print_generic_expr (f, partition_to_var (map, q), TDF_SLIM);
> +                 fprintf (f, " - ");
> +               }
> +             fprintf (f, "%d ", y);
> +           }
> +       }
> +      if (t != 0)
> +       fprintf (f, ")\n");
> +    }
> +  fprintf (f, "\n");
> +}
> +
> +/* Fill in MAP's partition_to_base_index, with one index for each
> +   partition of SSA names USED_IN_COPIES and related by CL
> +   coalesce possibilities.  */
> +
> +static void
> +compute_optimized_partition_bases (var_map map, bitmap used_in_copies,
> +                                  coalesce_list_p cl)
> +{
> +  int parts = num_var_partitions (map);
> +  partition tentative = partition_new (parts);
> +
> +  /* Partition the SSA versions so that, for each coalescible
> +     pair, both of its members are in the same partition in
> +     TENTATIVE.  */
> +  gcc_assert (!cl->sorted);
> +  coalesce_pair_p node;
> +  coalesce_iterator_type ppi;
> +  FOR_EACH_PARTITION_PAIR (node, ppi, cl)
> +    {
> +      tree v1 = ssa_name (node->first_element);
> +      int p1 = partition_find (tentative, var_to_partition (map, v1));
> +      tree v2 = ssa_name (node->second_element);
> +      int p2 = partition_find (tentative, var_to_partition (map, v2));
> +
> +      if (p1 == p2)
> +       continue;
> +
> +      partition_union (tentative, p1, p2);
> +    }
> +
> +  /* We have to deal with cost one pairs too.  */
> +  for (cost_one_pair_d *co = cl->cost_one_list; co; co = co->next)
> +    {
> +      tree v1 = ssa_name (co->first_element);
> +      int p1 = partition_find (tentative, var_to_partition (map, v1));
> +      tree v2 = ssa_name (co->second_element);
> +      int p2 = partition_find (tentative, var_to_partition (map, v2));
> +
> +      if (p1 == p2)
> +       continue;
> +
> +      partition_union (tentative, p1, p2);
> +    }
> +
> +  /* And also with abnormal edges.  */
> +  basic_block bb;
> +  edge e;
> +  edge_iterator ei;
> +  FOR_EACH_BB_FN (bb, cfun)
> +    {
> +      FOR_EACH_EDGE (e, ei, bb->preds)
> +       if (e->flags & EDGE_ABNORMAL)
> +         {
> +           gphi_iterator gsi;
> +           for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
> +                gsi_next (&gsi))
> +             {
> +               gphi *phi = gsi.phi ();
> +               tree arg = PHI_ARG_DEF (phi, e->dest_idx);
> +               if (SSA_NAME_IS_DEFAULT_DEF (arg)
> +                   && (!SSA_NAME_VAR (arg)
> +                       || TREE_CODE (SSA_NAME_VAR (arg)) != PARM_DECL))
> +                 continue;
> +
> +               tree res = PHI_RESULT (phi);
> +
> +               int p1 = partition_find (tentative, var_to_partition (map, res));
> +               int p2 = partition_find (tentative, var_to_partition (map, arg));
> +
> +               if (p1 == p2)
> +                 continue;
> +
> +               partition_union (tentative, p1, p2);
> +             }
> +         }
> +    }

So the above does full coalescing ignoring conflicts.

> +
> +  map->partition_to_base_index = XCNEWVEC (int, parts);
> +  auto_vec<unsigned int> index_map (parts);
> +  if (parts)
> +    index_map.quick_grow (parts);
> +
> +  const unsigned no_part = -1;
> +  unsigned count = parts;
> +  while (count)
> +    index_map[--count] = no_part;
> +
> +  /* Initialize MAP's mapping from partition to base index, using
> +     as base indices an enumeration of the TENTATIVE partitions in
> +     which each SSA version ended up, so that we compute conflicts
> +     between all SSA versions that ended up in the same potential
> +     coalesce partition.  */
> +  bitmap_iterator bi;
> +  unsigned i;
> +  EXECUTE_IF_SET_IN_BITMAP (used_in_copies, 0, i, bi)
> +    {
> +      int pidx = var_to_partition (map, ssa_name (i));
> +      int base = partition_find (tentative, pidx);
> +      if (index_map[base] != no_part)
> +       continue;
> +      index_map[base] = count++;
> +    }
> +
> +  map->num_basevars = count;

Did you do any statistics on how the number of basevars changes with your patch
compared to trunk?

So apart from possibly simplifying the patch by not dealing with
default-def coalesces
of PARAM_DECLs and ignoring them for conflict purposes for others (as
tree-ssa-live.c
does) the patch looks good to me.

Richard.

> +  EXECUTE_IF_SET_IN_BITMAP (used_in_copies, 0, i, bi)
> +    {
> +      int pidx = var_to_partition (map, ssa_name (i));
> +      int base = partition_find (tentative, pidx);
> +      gcc_assert (index_map[base] < count);
> +      map->partition_to_base_index[pidx] = index_map[base];
> +    }
> +
> +  if (dump_file && (dump_flags & TDF_DETAILS))
> +    dump_part_var_map (dump_file, tentative, map);
> +
> +  partition_delete (tentative);
> +}
> +
> +
>  /* Reduce the number of copies by coalescing variables in the function.  Return
>     a partition map with the resulting coalesces.  */
>
> @@ -1332,7 +1647,12 @@ coalesce_ssa_name (void)
>      dump_var_map (dump_file, map);
>
>    /* Don't calculate live ranges for variables not in the coalesce list.  */
> -  partition_view_bitmap (map, used_in_copies, true);
> +  partition_view_bitmap (map, used_in_copies, !optimize);
> +
> +  /* If we are optimizing, compute the base indices ourselves.  */
> +  if (optimize)
> +    compute_optimized_partition_bases (map, used_in_copies, cl);
> +
>    BITMAP_FREE (used_in_copies);
>
>    if (num_var_partitions (map) < 1)
> @@ -1341,6 +1661,8 @@ coalesce_ssa_name (void)
>        return map;
>      }
>
> +  bitmap param_defaults = BITMAP_ALLOC (NULL);
> +
>    if (dump_file && (dump_flags & TDF_DETAILS))
>      dump_var_map (dump_file, map);
>
> @@ -1350,7 +1672,7 @@ coalesce_ssa_name (void)
>      dump_live_info (dump_file, liveinfo, LIVEDUMP_ENTRY);
>
>    /* Build a conflict graph.  */
> -  graph = build_ssa_conflict_graph (liveinfo);
> +  graph = build_ssa_conflict_graph (liveinfo, param_defaults);
>    delete_tree_live_info (liveinfo);
>    if (dump_file && (dump_flags & TDF_DETAILS))
>      ssa_conflicts_dump (dump_file, graph);
> @@ -1370,10 +1692,10 @@ coalesce_ssa_name (void)
>      dump_var_map (dump_file, map);
>
>    /* Now coalesce everything in the list.  */
> -  coalesce_partitions (map, graph, cl,
> -                      ((dump_flags & TDF_DETAILS) ? dump_file
> -                                                  : NULL));
> +  coalesce_partitions (map, graph, cl, param_defaults,
> +                      ((dump_flags & TDF_DETAILS) ? dump_file : NULL));
>
> +  BITMAP_FREE (param_defaults);
>    delete_coalesce_list (cl);
>    ssa_conflicts_delete (graph);
>
> diff --git a/gcc/tree-ssa-copyrename.c b/gcc/tree-ssa-copyrename.c
> deleted file mode 100644
> index f3cb56e..0000000
> --- a/gcc/tree-ssa-copyrename.c
> +++ /dev/null
> @@ -1,499 +0,0 @@
> -/* Rename SSA copies.
> -   Copyright (C) 2004-2015 Free Software Foundation, Inc.
> -   Contributed by Andrew MacLeod <amacleod@redhat.com>
> -
> -This file is part of GCC.
> -
> -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.
> -
> -GCC is distributed in the hope that it will be useful,
> -but WITHOUT ANY WARRANTY; without even the implied warranty of
> -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> -GNU General Public License for more details.
> -
> -You should have received a copy of the GNU General Public License
> -along with GCC; see the file COPYING3.  If not see
> -<http://www.gnu.org/licenses/>.  */
> -
> -#include "config.h"
> -#include "system.h"
> -#include "coretypes.h"
> -#include "tm.h"
> -#include "hash-set.h"
> -#include "machmode.h"
> -#include "vec.h"
> -#include "double-int.h"
> -#include "input.h"
> -#include "alias.h"
> -#include "symtab.h"
> -#include "wide-int.h"
> -#include "inchash.h"
> -#include "tree.h"
> -#include "fold-const.h"
> -#include "predict.h"
> -#include "hard-reg-set.h"
> -#include "function.h"
> -#include "dominance.h"
> -#include "cfg.h"
> -#include "basic-block.h"
> -#include "tree-ssa-alias.h"
> -#include "internal-fn.h"
> -#include "gimple-expr.h"
> -#include "is-a.h"
> -#include "gimple.h"
> -#include "gimple-iterator.h"
> -#include "flags.h"
> -#include "tree-pretty-print.h"
> -#include "bitmap.h"
> -#include "gimple-ssa.h"
> -#include "stringpool.h"
> -#include "tree-ssanames.h"
> -#include "hashtab.h"
> -#include "rtl.h"
> -#include "statistics.h"
> -#include "real.h"
> -#include "fixed-value.h"
> -#include "insn-config.h"
> -#include "expmed.h"
> -#include "dojump.h"
> -#include "explow.h"
> -#include "calls.h"
> -#include "emit-rtl.h"
> -#include "varasm.h"
> -#include "stmt.h"
> -#include "expr.h"
> -#include "tree-dfa.h"
> -#include "tree-inline.h"
> -#include "tree-ssa-live.h"
> -#include "tree-pass.h"
> -#include "langhooks.h"
> -
> -static struct
> -{
> -  /* Number of copies coalesced.  */
> -  int coalesced;
> -} stats;
> -
> -/* The following routines implement the SSA copy renaming phase.
> -
> -   This optimization looks for copies between 2 SSA_NAMES, either through a
> -   direct copy, or an implicit one via a PHI node result and its arguments.
> -
> -   Each copy is examined to determine if it is possible to rename the base
> -   variable of one of the operands to the same variable as the other operand.
> -   i.e.
> -   T.3_5 = <blah>
> -   a_1 = T.3_5
> -
> -   If this copy couldn't be copy propagated, it could possibly remain in the
> -   program throughout the optimization phases.   After SSA->normal, it would
> -   become:
> -
> -   T.3 = <blah>
> -   a = T.3
> -
> -   Since T.3_5 is distinct from all other SSA versions of T.3, there is no
> -   fundamental reason why the base variable needs to be T.3, subject to
> -   certain restrictions.  This optimization attempts to determine if we can
> -   change the base variable on copies like this, and result in code such as:
> -
> -   a_5 = <blah>
> -   a_1 = a_5
> -
> -   This gives the SSA->normal pass a shot at coalescing a_1 and a_5. If it is
> -   possible, the copy goes away completely. If it isn't possible, a new temp
> -   will be created for a_5, and you will end up with the exact same code:
> -
> -   a.8 = <blah>
> -   a = a.8
> -
> -   The other benefit of performing this optimization relates to what variables
> -   are chosen in copies.  Gimplification of the program uses temporaries for
> -   a lot of things. expressions like
> -
> -   a_1 = <blah>
> -   <blah2> = a_1
> -
> -   get turned into
> -
> -   T.3_5 = <blah>
> -   a_1 = T.3_5
> -   <blah2> = a_1
> -
> -   Copy propagation is done in a forward direction, and if we can propagate
> -   through the copy, we end up with:
> -
> -   T.3_5 = <blah>
> -   <blah2> = T.3_5
> -
> -   The copy is gone, but so is all reference to the user variable 'a'. By
> -   performing this optimization, we would see the sequence:
> -
> -   a_5 = <blah>
> -   a_1 = a_5
> -   <blah2> = a_1
> -
> -   which copy propagation would then turn into:
> -
> -   a_5 = <blah>
> -   <blah2> = a_5
> -
> -   and so we still retain the user variable whenever possible.  */
> -
> -
> -/* Coalesce the partitions in MAP representing VAR1 and VAR2 if it is valid.
> -   Choose a representative for the partition, and send debug info to DEBUG.  */
> -
> -static void
> -copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug)
> -{
> -  int p1, p2, p3;
> -  tree root1, root2;
> -  tree rep1, rep2;
> -  bool ign1, ign2, abnorm;
> -
> -  gcc_assert (TREE_CODE (var1) == SSA_NAME);
> -  gcc_assert (TREE_CODE (var2) == SSA_NAME);
> -
> -  register_ssa_partition (map, var1);
> -  register_ssa_partition (map, var2);
> -
> -  p1 = partition_find (map->var_partition, SSA_NAME_VERSION (var1));
> -  p2 = partition_find (map->var_partition, SSA_NAME_VERSION (var2));
> -
> -  if (debug)
> -    {
> -      fprintf (debug, "Try : ");
> -      print_generic_expr (debug, var1, TDF_SLIM);
> -      fprintf (debug, "(P%d) & ", p1);
> -      print_generic_expr (debug, var2, TDF_SLIM);
> -      fprintf (debug, "(P%d)", p2);
> -    }
> -
> -  gcc_assert (p1 != NO_PARTITION);
> -  gcc_assert (p2 != NO_PARTITION);
> -
> -  if (p1 == p2)
> -    {
> -      if (debug)
> -       fprintf (debug, " : Already coalesced.\n");
> -      return;
> -    }
> -
> -  rep1 = partition_to_var (map, p1);
> -  rep2 = partition_to_var (map, p2);
> -  root1 = SSA_NAME_VAR (rep1);
> -  root2 = SSA_NAME_VAR (rep2);
> -  if (!root1 && !root2)
> -    return;
> -
> -  /* Don't coalesce if one of the variables occurs in an abnormal PHI.  */
> -  abnorm = (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rep1)
> -           || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rep2));
> -  if (abnorm)
> -    {
> -      if (debug)
> -       fprintf (debug, " : Abnormal PHI barrier.  No coalesce.\n");
> -      return;
> -    }
> -
> -  /* Partitions already have the same root, simply merge them.  */
> -  if (root1 == root2)
> -    {
> -      p1 = partition_union (map->var_partition, p1, p2);
> -      if (debug)
> -       fprintf (debug, " : Same root, coalesced --> P%d.\n", p1);
> -      return;
> -    }
> -
> -  /* Never attempt to coalesce 2 different parameters.  */
> -  if ((root1 && TREE_CODE (root1) == PARM_DECL)
> -      && (root2 && TREE_CODE (root2) == PARM_DECL))
> -    {
> -      if (debug)
> -        fprintf (debug, " : 2 different PARM_DECLS. No coalesce.\n");
> -      return;
> -    }
> -
> -  if ((root1 && TREE_CODE (root1) == RESULT_DECL)
> -      != (root2 && TREE_CODE (root2) == RESULT_DECL))
> -    {
> -      if (debug)
> -        fprintf (debug, " : One root a RESULT_DECL. No coalesce.\n");
> -      return;
> -    }
> -
> -  ign1 = !root1 || (TREE_CODE (root1) == VAR_DECL && DECL_IGNORED_P (root1));
> -  ign2 = !root2 || (TREE_CODE (root2) == VAR_DECL && DECL_IGNORED_P (root2));
> -
> -  /* Refrain from coalescing user variables, if requested.  */
> -  if (!ign1 && !ign2)
> -    {
> -      if (flag_ssa_coalesce_vars && DECL_FROM_INLINE (root2))
> -       ign2 = true;
> -      else if (flag_ssa_coalesce_vars && DECL_FROM_INLINE (root1))
> -       ign1 = true;
> -      else if (flag_ssa_coalesce_vars != 2)
> -       {
> -         if (debug)
> -           fprintf (debug, " : 2 different USER vars. No coalesce.\n");
> -         return;
> -       }
> -      else
> -       ign2 = true;
> -    }
> -
> -  /* If both values have default defs, we can't coalesce.  If only one has a
> -     tag, make sure that variable is the new root partition.  */
> -  if (root1 && ssa_default_def (cfun, root1))
> -    {
> -      if (root2 && ssa_default_def (cfun, root2))
> -       {
> -         if (debug)
> -           fprintf (debug, " : 2 default defs. No coalesce.\n");
> -         return;
> -       }
> -      else
> -        {
> -         ign2 = true;
> -         ign1 = false;
> -       }
> -    }
> -  else if (root2 && ssa_default_def (cfun, root2))
> -    {
> -      ign1 = true;
> -      ign2 = false;
> -    }
> -
> -  /* Do not coalesce if we cannot assign a symbol to the partition.  */
> -  if (!(!ign2 && root2)
> -      && !(!ign1 && root1))
> -    {
> -      if (debug)
> -       fprintf (debug, " : Choosen variable has no root.  No coalesce.\n");
> -      return;
> -    }
> -
> -  /* Don't coalesce if the new chosen root variable would be read-only.
> -     If both ign1 && ign2, then the root var of the larger partition
> -     wins, so reject in that case if any of the root vars is TREE_READONLY.
> -     Otherwise reject only if the root var, on which replace_ssa_name_symbol
> -     will be called below, is readonly.  */
> -  if (((root1 && TREE_READONLY (root1)) && ign2)
> -      || ((root2 && TREE_READONLY (root2)) && ign1))
> -    {
> -      if (debug)
> -       fprintf (debug, " : Readonly variable.  No coalesce.\n");
> -      return;
> -    }
> -
> -  /* Don't coalesce if the two variables aren't type compatible .  */
> -  if (!types_compatible_p (TREE_TYPE (var1), TREE_TYPE (var2))
> -      /* There is a disconnect between the middle-end type-system and
> -         VRP, avoid coalescing enum types with different bounds.  */
> -      || ((TREE_CODE (TREE_TYPE (var1)) == ENUMERAL_TYPE
> -          || TREE_CODE (TREE_TYPE (var2)) == ENUMERAL_TYPE)
> -         && TREE_TYPE (var1) != TREE_TYPE (var2)))
> -    {
> -      if (debug)
> -       fprintf (debug, " : Incompatible types.  No coalesce.\n");
> -      return;
> -    }
> -
> -  /* Merge the two partitions.  */
> -  p3 = partition_union (map->var_partition, p1, p2);
> -
> -  /* Set the root variable of the partition to the better choice, if there is
> -     one.  */
> -  if (!ign2 && root2)
> -    replace_ssa_name_symbol (partition_to_var (map, p3), root2);
> -  else if (!ign1 && root1)
> -    replace_ssa_name_symbol (partition_to_var (map, p3), root1);
> -  else
> -    gcc_unreachable ();
> -
> -  if (debug)
> -    {
> -      fprintf (debug, " --> P%d ", p3);
> -      print_generic_expr (debug, SSA_NAME_VAR (partition_to_var (map, p3)),
> -                         TDF_SLIM);
> -      fprintf (debug, "\n");
> -    }
> -}
> -
> -
> -namespace {
> -
> -const pass_data pass_data_rename_ssa_copies =
> -{
> -  GIMPLE_PASS, /* type */
> -  "copyrename", /* name */
> -  OPTGROUP_NONE, /* optinfo_flags */
> -  TV_TREE_COPY_RENAME, /* tv_id */
> -  ( PROP_cfg | PROP_ssa ), /* properties_required */
> -  0, /* properties_provided */
> -  0, /* properties_destroyed */
> -  0, /* todo_flags_start */
> -  0, /* todo_flags_finish */
> -};
> -
> -class pass_rename_ssa_copies : public gimple_opt_pass
> -{
> -public:
> -  pass_rename_ssa_copies (gcc::context *ctxt)
> -    : gimple_opt_pass (pass_data_rename_ssa_copies, ctxt)
> -  {}
> -
> -  /* opt_pass methods: */
> -  opt_pass * clone () { return new pass_rename_ssa_copies (m_ctxt); }
> -  virtual bool gate (function *) { return flag_tree_copyrename != 0; }
> -  virtual unsigned int execute (function *);
> -
> -}; // class pass_rename_ssa_copies
> -
> -/* This function will make a pass through the IL, and attempt to coalesce any
> -   SSA versions which occur in PHI's or copies.  Coalescing is accomplished by
> -   changing the underlying root variable of all coalesced version.  This will
> -   then cause the SSA->normal pass to attempt to coalesce them all to the same
> -   variable.  */
> -
> -unsigned int
> -pass_rename_ssa_copies::execute (function *fun)
> -{
> -  var_map map;
> -  basic_block bb;
> -  tree var, part_var;
> -  gimple stmt;
> -  unsigned x;
> -  FILE *debug;
> -
> -  memset (&stats, 0, sizeof (stats));
> -
> -  if (dump_file && (dump_flags & TDF_DETAILS))
> -    debug = dump_file;
> -  else
> -    debug = NULL;
> -
> -  map = init_var_map (num_ssa_names);
> -
> -  FOR_EACH_BB_FN (bb, fun)
> -    {
> -      /* Scan for real copies.  */
> -      for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
> -          gsi_next (&gsi))
> -       {
> -         stmt = gsi_stmt (gsi);
> -         if (gimple_assign_ssa_name_copy_p (stmt))
> -           {
> -             tree lhs = gimple_assign_lhs (stmt);
> -             tree rhs = gimple_assign_rhs1 (stmt);
> -
> -             copy_rename_partition_coalesce (map, lhs, rhs, debug);
> -           }
> -       }
> -    }
> -
> -  FOR_EACH_BB_FN (bb, fun)
> -    {
> -      /* Treat PHI nodes as copies between the result and each argument.  */
> -      for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
> -          gsi_next (&gsi))
> -        {
> -          size_t i;
> -         tree res;
> -         gphi *phi = gsi.phi ();
> -         res = gimple_phi_result (phi);
> -
> -         /* Do not process virtual SSA_NAMES.  */
> -         if (virtual_operand_p (res))
> -           continue;
> -
> -         /* Make sure to only use the same partition for an argument
> -            as the result but never the other way around.  */
> -         if (SSA_NAME_VAR (res)
> -             && !DECL_IGNORED_P (SSA_NAME_VAR (res)))
> -           for (i = 0; i < gimple_phi_num_args (phi); i++)
> -             {
> -               tree arg = PHI_ARG_DEF (phi, i);
> -               if (TREE_CODE (arg) == SSA_NAME)
> -                 copy_rename_partition_coalesce (map, res, arg,
> -                                                 debug);
> -             }
> -         /* Else if all arguments are in the same partition try to merge
> -            it with the result.  */
> -         else
> -           {
> -             int all_p_same = -1;
> -             int p = -1;
> -             for (i = 0; i < gimple_phi_num_args (phi); i++)
> -               {
> -                 tree arg = PHI_ARG_DEF (phi, i);
> -                 if (TREE_CODE (arg) != SSA_NAME)
> -                   {
> -                     all_p_same = 0;
> -                     break;
> -                   }
> -                 else if (all_p_same == -1)
> -                   {
> -                     p = partition_find (map->var_partition,
> -                                         SSA_NAME_VERSION (arg));
> -                     all_p_same = 1;
> -                   }
> -                 else if (all_p_same == 1
> -                          && p != partition_find (map->var_partition,
> -                                                  SSA_NAME_VERSION (arg)))
> -                   {
> -                     all_p_same = 0;
> -                     break;
> -                   }
> -               }
> -             if (all_p_same == 1)
> -               copy_rename_partition_coalesce (map, res,
> -                                               PHI_ARG_DEF (phi, 0),
> -                                               debug);
> -           }
> -        }
> -    }
> -
> -  if (debug)
> -    dump_var_map (debug, map);
> -
> -  /* Now one more pass to make all elements of a partition share the same
> -     root variable.  */
> -
> -  for (x = 1; x < num_ssa_names; x++)
> -    {
> -      part_var = partition_to_var (map, x);
> -      if (!part_var)
> -        continue;
> -      var = ssa_name (x);
> -      if (SSA_NAME_VAR (var) == SSA_NAME_VAR (part_var))
> -       continue;
> -      if (debug)
> -        {
> -         fprintf (debug, "Coalesced ");
> -         print_generic_expr (debug, var, TDF_SLIM);
> -         fprintf (debug, " to ");
> -         print_generic_expr (debug, part_var, TDF_SLIM);
> -         fprintf (debug, "\n");
> -       }
> -      stats.coalesced++;
> -      replace_ssa_name_symbol (var, SSA_NAME_VAR (part_var));
> -    }
> -
> -  statistics_counter_event (fun, "copies coalesced",
> -                           stats.coalesced);
> -  delete_var_map (map);
> -  return 0;
> -}
> -
> -} // anon namespace
> -
> -gimple_opt_pass *
> -make_pass_rename_ssa_copies (gcc::context *ctxt)
> -{
> -  return new pass_rename_ssa_copies (ctxt);
> -}
> diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
> index e0c42669..46b1869 100644
> --- a/gcc/tree-ssa-live.c
> +++ b/gcc/tree-ssa-live.c
> @@ -119,7 +119,10 @@ tree_int_map_hasher::equal (const value_type *v, const compare_type *c)
>  }
>
>
> -/* This routine will initialize the basevar fields of MAP.  */
> +/* This routine will initialize the basevar fields of MAP with base
> +   names, when we are not optimizing.  When optimizing, we'll use
> +   partition numbers as base index numbers, see coalesce_ssa_name in
> +   tree-ssa-coalesce.c.  */
>
>  static void
>  var_map_base_init (var_map map)
>
>
> --
> Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
> You must be the change you wish to see in the world. -- Gandhi
> Be Free! -- http://FSFLA.org/   FSF Latin America board member
> Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer
Alexandre Oliva April 3, 2015, 1:17 p.m. UTC | #5
On Mar 31, 2015, Jeff Law <law@redhat.com> wrote:

>> -  if (var1 != var2)
>> +  if (var1 != var2 && !optimize)
>> return false;
> So when when the base variables are different and we are optimizing,
> this allows coalescing, right?

Yeah.

> What I don't see is a corresponding change to var_map_base_init to
> ensure we build a conflict graph which includes objects when
> SSA_NAME_VARs are not the same.  I see a vague reference in
> var_map_base_init's header comment that refers us to
> coalesce_ssa_name.

> It appears that compute_optimized_partition_bases handles this by
> creating a partitions of things that are related by copies/phis
> regardless of their underlying named object, type, etc.  Right?

Correct.  I guess it makes sense to move partition base computation to a
single location.  Since compute_optimized_partition_bases relies on data
structures local to this source file, I'm moving the non-optimized
version to tree-ssa-coalesce.c, and dropping support for basevar
initialization from tree-ssa-live.c.


> Hard to argue with removing a pass that gets called 5 times!

:-)


>> @@ -890,6 +900,36 @@ build_ssa_conflict_graph (tree_live_info_p liveinfo)
>> live_track_process_def (live, result, graph);
>> }
>> 
>> +      /* Pretend there are defs for params' default defs at the start
>> +	 of the (post-)entry block.  We run after abnormal coalescing,
>> +	 so we can't assume the leader variable is the default
>> +	 definition, but because of SSA_NAME_VAR adjustments in
>> +	 attempt_coalesce, we can assume that if there is any
>> +	 PARM_DECL in the partition, it will be the leader's
>> +	 SSA_NAME_VAR.  */

This comment is outdated.  Since we no longer have abnormal coalescing
before building the conflict graph, we can just test whether each
SSA_NAME is a default def for a PARM_DECL and be done with it.

> So the issue here is you want to iterate over the objects live at the
> entry block, which would include any SSA_NAMEs which result from
> PARM_DECLs.  I don't guess there's an easier way to do that other than
> iterating over everything live in that initial block?

We could iterate over all SSA_NAMEs, but that would probably be more
costly.  There shouldn't be very many live variables at the function
entry, so using the live bitmaps is likely to save us time, especially
on functions with lots of SSA_NAMEs.

> And the second second EXECUTE_IF_SET_IN_BITMAP iterates over
> everything in the partitions associated with the SSA_NAMES that are
> live at the the entry block, right?

Yeah, we iterate over the bases in live_base_var, because the per-base
bitmaps are only accurate when the corresponding live_base_var bit is
iset.

>> @@ -1126,11 +1166,12 @@ create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy)
>> 
>> static inline bool
>> attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
>> -		  FILE *debug)
>> +		  bitmap param_defaults, FILE *debug)
> [ ... ]
> So the bulk of the changes into this routine are really about picking
> a good leader, which presumably is how we're able to get the desired
> effects on debuginfo that we used to get from tree-ssa-copyrename.c?

This has nothing to do with debuginfo, I'm afraid.  We just had to keep
track of parm and result decls to avoid coalescing them together, and
parm decl default defs to promote them to leaders, because expand copies
incoming REGs to pseudos in PARM_DECL's DECL_RTL.  We should fill that
in with the RTL created for the default def for the PARM_DECL.  At the
end, I believe we also copy the RESULT_DECL DECL_RTL to the actual
return register or rtl.  I didn't want to tackle the reworking of these
expanders to avoid problems out of copying incoming parms to one pseudo
and then reading it from another, as I observed before I made this
change.  I'm now tackling that, so that we can refrain from touching the
base vars altogether, and not refrain from coalescing parms and results.

> So some comments about the various cases here might help.  I can sort
> them out if I read the code, but one could argue that a block comment
> on the rules for how to select the partition leader would be better.

*nod*.  I won't bother, though, if this code ends up gone in the next
iteration of the patch ;-)

> Is the special casing of PARM_DECLs + RESULT_DECLs really a failing of
> not handling one or both properly when computing liveness information?

No, it's about RTL assignment and copying to/from hard regs.  We assign
RTL to PARM_DECLs and RESULT_DECLs explicitly in the expander, but we
can't assign different RTL to them if they are coalesced in a single
partition.

> I'm not aware of an inherent reason why a PARM_DECL couldn't coalesce
> with a related RESULT_DECL if they are otherwise non-conflicting and
> related by a copy/phi.

Indeed, there isn't any inherent reason.  It was just a restriction I
carried over from copyrename, and that I postponed cleaning up.

> Presumably ordering of unioning of the partitions doesn't matter here
> as we're looking at coalesce possibilities rather than things we have
> actually coalesced?  Thus it's OK (?) to handle the names occurring in
> abnormal PHIs after those names that are associated by a copy.

Yeah, they'll end up with the same basevar one way or another.
Alexandre Oliva April 3, 2015, 1:28 p.m. UTC | #6
On Mar 31, 2015, Richard Biener <richard.guenther@gmail.com> wrote:

>> +                     || !(SSA_NAME_IS_DEFAULT_DEF (var)
>> +                          || (param_defaults
>> +                              && bitmap_bit_p (param_defaults, part))))

> This looks somewhat awkward to me ;)  Is it really important to allow
> coalescing PARM_DECL-based SSA vars with sth else?

It's a valid optimization.  I can't say it's really important, but if
the only objection is to param_defaults, I'm getting rid of it.

> At least abnormal coalescing doesn't need to do that, so just walking
> over the function decls parameters and making their default-def live
> should be enough?

It should.  We'd have to duplicate logic of parameters, including static
chain and whatnot.  I figured this would make it more resilient to
changes elsewhere.

>> +      else if (TREE_CODE (SSA_NAME_VAR (var2)) == VAR_DECL)
>> +       leader = SSA_NAME_VAR (var2);
>> +      else /* What else could it be?  */
>> +       gcc_unreachable ();
>> +

> definitely comments missing in this spaghetti...

I'm trying to remove the spaghetting now.

> or seeing this, why coalesce default-defs at all?

Why not?  (the referenced code is gone from my local tree, BTW)

> Either they are param values or they have indetermined values (and
> thus we can and do pick whatever is available at expansion time)?

If they are param values, we want to have them available; if they
aren't, whatever we coalesce with is good.


> So the above does full coalescing ignoring conflicts.

Yeah.  We want to tell what we'd get if all coalesce possibilities are
taken, so that we can assign the same basevar to all partitions so that
we detect conflicts.

> Did you do any statistics on how the number of basevars changes with your patch
> compared to trunk?

'fraid I didn't run any statistics whatsoever.  I didn't think it was
important, since it's pretty much just doing copyrename during coalesce.
Truth be told, this has since relaxed some of the constraints from
copyrename, and I'm going to relax some more in the next iteration, so I
guess some statistics wouldn't be a bad idea.  Is there any specific
testcase you're interested in, or something like a GCC bootstrap or
somesuch?
Jeff Law April 6, 2015, 3:57 p.m. UTC | #7
On 04/03/2015 07:28 AM, Alexandre Oliva wrote:
> On Mar 31, 2015, Richard Biener <richard.guenther@gmail.com> wrote:
>
>>> +                     || !(SSA_NAME_IS_DEFAULT_DEF (var)
>>> +                          || (param_defaults
>>> +                              && bitmap_bit_p (param_defaults, part))))
>
>> This looks somewhat awkward to me ;)  Is it really important to allow
>> coalescing PARM_DECL-based SSA vars with sth else?
>
> It's a valid optimization.  I can't say it's really important, but if
> the only objection is to param_defaults, I'm getting rid of it.
I doubt it's terribly important, but I agree it's a valid optimization. 
  Do you have a testcase where it triggers?  Can we include that too so 
that if someone wants to remove this later for some reason or another 
we'd at least have a chance of seeing a regression.

ISTM it can only trigger when the PARM is tied to another object via a 
copy and the PARM and other object have non-overlapping lifetimes.  I'd 
expect that this may happen at PHIs where the PARM appears on the RHS 
and dies at that point -- the PARM and the PHI result are likely not 
going to conflict and thus may coalesce.


>
>> At least abnormal coalescing doesn't need to do that, so just walking
>> over the function decls parameters and making their default-def live
>> should be enough?
>
> It should.  We'd have to duplicate logic of parameters, including static
> chain and whatnot.  I figured this would make it more resilient to
> changes elsewhere.
This ties in a bit to my comment about whether or not we've got proper 
life information for PARMs.  I'd generally prefer to see us get the life 
information corrrect.


>
>>> +      else if (TREE_CODE (SSA_NAME_VAR (var2)) == VAR_DECL)
>>> +       leader = SSA_NAME_VAR (var2);
>>> +      else /* What else could it be?  */
>>> +       gcc_unreachable ();
>>> +
>
>> definitely comments missing in this spaghetti...
>
> I'm trying to remove the spaghetting now.
Good :-)

>
>> or seeing this, why coalesce default-defs at all?
>
> Why not?  (the referenced code is gone from my local tree, BTW)
>
>> Either they are param values or they have indetermined values (and
>> thus we can and do pick whatever is available at expansion time)?
>
> If they are param values, we want to have them available; if they
> aren't, whatever we coalesce with is good.
Agreed.  Didn't we recently change the coalescing code to allow 
coalescing non-PARM default defs more aggressively:

Author: glisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Mon Nov 3 10:47:04 2014 +0000

     2014-11-03  Marc Glisse  <marc.glisse@inria.fr>

         PR tree-optimization/60770
     gcc/
         * tree-into-ssa.c (rewrite_update_stmt): Return whether the
         statement should be removed.
         (maybe_register_def): Likewise. Replace clobbers with default
         definitions.
         (rewrite_dom_walker::before_dom_children): Remove statement if
         rewrite_update_stmt says so.
         * tree-ssa-live.c: Include tree-ssa.h.
         (set_var_live_on_entry): Do not mark undefined variables as live.
         (verify_live_on_entry): Do not check undefined variables.
         * tree-ssa.h (ssa_undefined_value_p): New parameter for the case
         of partially undefined variables.
         * tree-ssa.c (ssa_undefined_value_p): Likewise.
         (execute_update_addresses_taken): Do not drop clobbers.

     gcc/testsuite/
         * gcc.dg/tree-ssa/pr60770-1.c: New file.

  > guess some statistics wouldn't be a bad idea.  Is there any specific
> testcase you're interested in, or something like a GCC bootstrap or
> somesuch?
Not from me.  bootstrap or .i files from gcc bootstrap would seem to be 
sufficient to me.

jeff
Jeff Law April 6, 2015, 4:08 p.m. UTC | #8
On 04/03/2015 07:17 AM, Alexandre Oliva wrote:
>>> @@ -890,6 +900,36 @@ build_ssa_conflict_graph (tree_live_info_p liveinfo)
>>> live_track_process_def (live, result, graph);
>>> }
>>>
>>> +      /* Pretend there are defs for params' default defs at the start
>>> +	 of the (post-)entry block.  We run after abnormal coalescing,
>>> +	 so we can't assume the leader variable is the default
>>> +	 definition, but because of SSA_NAME_VAR adjustments in
>>> +	 attempt_coalesce, we can assume that if there is any
>>> +	 PARM_DECL in the partition, it will be the leader's
>>> +	 SSA_NAME_VAR.  */
>
> This comment is outdated.  Since we no longer have abnormal coalescing
> before building the conflict graph, we can just test whether each
> SSA_NAME is a default def for a PARM_DECL and be done with it.
OK.  Please update the comment :-0

>
>> So the issue here is you want to iterate over the objects live at the
>> entry block, which would include any SSA_NAMEs which result from
>> PARM_DECLs.  I don't guess there's an easier way to do that other than
>> iterating over everything live in that initial block?
>
> We could iterate over all SSA_NAMEs, but that would probably be more
> costly.  There shouldn't be very many live variables at the function
> entry, so using the live bitmaps is likely to save us time, especially
> on functions with lots of SSA_NAMEs.
Agreed.  Iterating over the SSA_NAMEs was what came to mind when I 
pondered this a bit more and I'd rejected it for the same reason.

Can we get to the SSA_NAMEs associated with the PARM_DECLs from the 
function decl?  I can't think of a way off the top of my head, but if we 
could, then that'd avoid the iteration over the bitmap of live variables.

But then again, the bitmap of live variables ought to be small, 
particularly if we're not marking non-PARM default defs as live anymore 
(see patch reference in my prior message).

>> So the bulk of the changes into this routine are really about picking
>> a good leader, which presumably is how we're able to get the desired
>> effects on debuginfo that we used to get from tree-ssa-copyrename.c?
>
> This has nothing to do with debuginfo, I'm afraid.  We just had to keep
> track of parm and result decls to avoid coalescing them together, and
> parm decl default defs to promote them to leaders, because expand copies
> incoming REGs to pseudos in PARM_DECL's DECL_RTL.  We should fill that
> in with the RTL created for the default def for the PARM_DECL.  At the
> end, I believe we also copy the RESULT_DECL DECL_RTL to the actual
> return register or rtl.  I didn't want to tackle the reworking of these
> expanders to avoid problems out of copying incoming parms to one pseudo
> and then reading it from another, as I observed before I made this
> change.  I'm now tackling that, so that we can refrain from touching the
> base vars altogether, and not refrain from coalescing parms and results.
Hmmm, so the real issue here is the expansion setup of parms and 
results.  I hadn't pondered that aspect.  I'd encourage fixing the 
expansion code too if you can see a path for that.

Basically I just don't like special casing things like this -- 
coalescing should be driven by life information/conflict graph and a 
copy relationship between the two candidate objects.

Overall it looks like you're on the right path and we'll just need to 
iterate a bit more.

jeff
diff mbox

Patch

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index f924fb8..990c4e9 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1428,7 +1428,6 @@  OBJS = \
 	tree-ssa-ccp.o \
 	tree-ssa-coalesce.o \
 	tree-ssa-copy.o \
-	tree-ssa-copyrename.o \
 	tree-ssa-dce.o \
 	tree-ssa-dom.o \
 	tree-ssa-dse.o \
diff --git a/gcc/common.opt b/gcc/common.opt
index b49ac46..fefaee7 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -2207,16 +2207,16 @@  Common Report Var(flag_tree_ch) Optimization
 Enable loop header copying on trees
 
 ftree-coalesce-inlined-vars
-Common Report Var(flag_ssa_coalesce_vars,1) Init(2) RejectNegative Optimization
-Enable coalescing of copy-related user variables that are inlined
+Common Ignore RejectNegative
+Does nothing.  Preserved for backward compatibility.
 
 ftree-coalesce-vars
-Common Report Var(flag_ssa_coalesce_vars,2) Optimization
-Enable coalescing of all copy-related user variables
+Common Ignore
+Does nothing.  Preserved for backward compatibility.
 
 ftree-copyrename
-Common Report Var(flag_tree_copyrename) Optimization
-Replace SSA temporaries with better names in copies
+Common Ignore
+Does nothing.  Preserved for backward compatibility.
 
 ftree-copy-prop
 Common Report Var(flag_tree_copy_prop) Optimization
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9749727..5d2c516 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -442,8 +442,7 @@  Objective-C and Objective-C++ Dialects}.
 -fstack-protector-explicit -fstdarg-opt -fstrict-aliasing @gol
 -fstrict-overflow -fthread-jumps -ftracer -ftree-bit-ccp @gol
 -ftree-builtin-call-dce -ftree-ccp -ftree-ch @gol
--ftree-coalesce-inline-vars -ftree-coalesce-vars -ftree-copy-prop @gol
--ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse @gol
+-ftree-copy-prop -ftree-dce -ftree-dominator-opts -ftree-dse @gol
 -ftree-forwprop -ftree-fre -ftree-loop-if-convert @gol
 -ftree-loop-if-convert-stores -ftree-loop-im @gol
 -ftree-phiprop -ftree-loop-distribution -ftree-loop-distribute-patterns @gol
@@ -8822,32 +8821,6 @@  Perform scalar replacement of aggregates.  This pass replaces structure
 references with scalars to prevent committing structures to memory too
 early.  This flag is enabled by default at @option{-O} and higher.
 
-@item -ftree-copyrename
-@opindex ftree-copyrename
-Perform copy renaming on trees.  This pass attempts to rename compiler
-temporaries to other variables at copy locations, usually resulting in
-variable names which more closely resemble the original variables.  This flag
-is enabled by default at @option{-O} and higher.
-
-@item -ftree-coalesce-inlined-vars
-@opindex ftree-coalesce-inlined-vars
-Tell the copyrename pass (see @option{-ftree-copyrename}) to attempt to
-combine small user-defined variables too, but only if they are inlined
-from other functions.  It is a more limited form of
-@option{-ftree-coalesce-vars}.  This may harm debug information of such
-inlined variables, but it keeps variables of the inlined-into
-function apart from each other, such that they are more likely to
-contain the expected values in a debugging session.
-
-@item -ftree-coalesce-vars
-@opindex ftree-coalesce-vars
-Tell the copyrename pass (see @option{-ftree-copyrename}) to attempt to
-combine small user-defined variables too, instead of just compiler
-temporaries.  This may severely limit the ability to debug an optimized
-program compiled with @option{-fno-var-tracking-assignments}.  In the
-negated form, this flag prevents SSA coalescing of user variables,
-including inlined ones.  This option is enabled by default.
-
 @item -ftree-ter
 @opindex ftree-ter
 Perform temporary expression replacement during the SSA->normal phase.  Single
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index efc93b7..62ae577 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -399,13 +399,14 @@  copy_var_decl (tree var, tree name, tree type)
 bool
 gimple_can_coalesce_p (tree name1, tree name2)
 {
-  /* First check the SSA_NAME's associated DECL.  We only want to
-     coalesce if they have the same DECL or both have no associated DECL.  */
+  /* First check the SSA_NAME's associated DECL.  Without
+     optimization, we only want to coalesce if they have the same DECL
+     or both have no associated DECL.  */
   tree var1 = SSA_NAME_VAR (name1);
   tree var2 = SSA_NAME_VAR (name2);
   var1 = (var1 && (!VAR_P (var1) || !DECL_IGNORED_P (var1))) ? var1 : NULL_TREE;
   var2 = (var2 && (!VAR_P (var2) || !DECL_IGNORED_P (var2))) ? var2 : NULL_TREE;
-  if (var1 != var2)
+  if (var1 != var2 && !optimize)
     return false;
 
   /* Now check the types.  If the types are the same, then we should
diff --git a/gcc/opts.c b/gcc/opts.c
index 39c190d..8149421 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -453,7 +453,6 @@  static const struct default_options default_options_table[] =
     { OPT_LEVELS_1_PLUS, OPT_ftree_dse, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_ter, NULL, 1 },
     { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_sra, NULL, 1 },
-    { OPT_LEVELS_1_PLUS, OPT_ftree_copyrename, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_fre, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_copy_prop, NULL, 1 },
     { OPT_LEVELS_1_PLUS, OPT_ftree_sink, NULL, 1 },
diff --git a/gcc/passes.def b/gcc/passes.def
index 1d598b2..f8fd0ef 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -77,7 +77,6 @@  along with GCC; see the file COPYING3.  If not see
       NEXT_PASS (pass_all_early_optimizations);
       PUSH_INSERT_PASSES_WITHIN (pass_all_early_optimizations)
 	  NEXT_PASS (pass_remove_cgraph_callee_edges);
-	  NEXT_PASS (pass_rename_ssa_copies);
 	  NEXT_PASS (pass_object_sizes);
 	  NEXT_PASS (pass_ccp);
 	  /* After CCP we rewrite no longer addressed locals into SSA
@@ -154,7 +153,6 @@  along with GCC; see the file COPYING3.  If not see
       /* Initial scalar cleanups before alias computation.
 	 They ensure memory accesses are not indirect wherever possible.  */
       NEXT_PASS (pass_strip_predict_hints);
-      NEXT_PASS (pass_rename_ssa_copies);
       NEXT_PASS (pass_ccp);
       /* After CCP we rewrite no longer addressed locals into SSA
 	 form if possible.  */
@@ -182,7 +180,6 @@  along with GCC; see the file COPYING3.  If not see
       NEXT_PASS (pass_stdarg);
       NEXT_PASS (pass_lower_complex);
       NEXT_PASS (pass_sra);
-      NEXT_PASS (pass_rename_ssa_copies);
       /* The dom pass will also resolve all __builtin_constant_p calls
          that are still there to 0.  This has to be done after some
 	 propagations have already run, but before some more dead code
@@ -291,7 +288,6 @@  along with GCC; see the file COPYING3.  If not see
       NEXT_PASS (pass_fold_builtins);
       NEXT_PASS (pass_optimize_widening_mul);
       NEXT_PASS (pass_tail_calls);
-      NEXT_PASS (pass_rename_ssa_copies);
       /* FIXME: If DCE is not run before checking for uninitialized uses,
 	 we may get false warnings (e.g., testsuite/gcc.dg/uninit-5.c).
 	 However, this also causes us to misdiagnose cases that should be
@@ -326,7 +322,6 @@  along with GCC; see the file COPYING3.  If not see
       NEXT_PASS (pass_dce);
       NEXT_PASS (pass_asan);
       NEXT_PASS (pass_tsan);
-      NEXT_PASS (pass_rename_ssa_copies);
       /* ???  We do want some kind of loop invariant motion, but we possibly
          need to adjust LIM to be more friendly towards preserving accurate
 	 debug information here.  */
diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c
index 1afeefe..8557d84 100644
--- a/gcc/tree-ssa-coalesce.c
+++ b/gcc/tree-ssa-coalesce.c
@@ -825,13 +825,23 @@  live_track_clear_base_vars (live_track_p ptr)
    base variable are added.  */
 
 static ssa_conflicts_p
-build_ssa_conflict_graph (tree_live_info_p liveinfo)
+build_ssa_conflict_graph (tree_live_info_p liveinfo, bitmap param_defaults)
 {
   ssa_conflicts_p graph;
   var_map map;
   basic_block bb;
   ssa_op_iter iter;
   live_track_p live;
+  basic_block entry;
+
+  /* If we are optimizing, we may attempt to coalesce variables from
+     different base variables, including different parameters, so we
+     have to make sure default defs live at the entry block conflict
+     with each other.  */
+  if (optimize)
+    entry = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+  else
+    entry = NULL;
 
   map = live_var_map (liveinfo);
   graph = ssa_conflicts_new (num_var_partitions (map));
@@ -890,6 +900,36 @@  build_ssa_conflict_graph (tree_live_info_p liveinfo)
 	    live_track_process_def (live, result, graph);
 	}
 
+      /* Pretend there are defs for params' default defs at the start
+	 of the (post-)entry block.  We run after abnormal coalescing,
+	 so we can't assume the leader variable is the default
+	 definition, but because of SSA_NAME_VAR adjustments in
+	 attempt_coalesce, we can assume that if there is any
+	 PARM_DECL in the partition, it will be the leader's
+	 SSA_NAME_VAR.  */
+      if (bb == entry)
+	{
+	  unsigned base;
+	  bitmap_iterator bi;
+	  EXECUTE_IF_SET_IN_BITMAP (live->live_base_var, 0, base, bi)
+	    {
+	      bitmap_iterator bi2;
+	      unsigned part;
+	      EXECUTE_IF_SET_IN_BITMAP (live->live_base_partitions[base],
+					0, part, bi2)
+		{
+		  tree var = partition_to_var (map, part);
+		  if (!SSA_NAME_VAR (var)
+		      || TREE_CODE (SSA_NAME_VAR (var)) != PARM_DECL
+		      || !(SSA_NAME_IS_DEFAULT_DEF (var)
+			   || (param_defaults
+			       && bitmap_bit_p (param_defaults, part))))
+		    continue;
+		  live_track_process_def (live, var, graph);
+		}
+	    }
+	}
+
      live_track_clear_base_vars (live);
     }
 
@@ -1126,11 +1166,12 @@  create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy)
 
 static inline bool
 attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
-		  FILE *debug)
+		  bitmap param_defaults, FILE *debug)
 {
   int z;
   tree var1, var2;
   int p1, p2;
+  bool default_def = false;
 
   p1 = var_to_partition (map, ssa_name (x));
   p2 = var_to_partition (map, ssa_name (y));
@@ -1158,6 +1199,70 @@  attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
     {
       var1 = partition_to_var (map, p1);
       var2 = partition_to_var (map, p2);
+
+      tree leader;
+
+      if (var1 == var2 || !SSA_NAME_VAR (var2)
+	  || SSA_NAME_VAR (var1) == SSA_NAME_VAR (var2))
+	{
+	  leader = SSA_NAME_VAR (var1);
+	  default_def = (leader && TREE_CODE (leader) == PARM_DECL
+			 && (SSA_NAME_IS_DEFAULT_DEF (var1)
+			     || bitmap_bit_p (param_defaults, p1)));
+	}
+      else if (!SSA_NAME_VAR (var1))
+	{
+	  leader = SSA_NAME_VAR (var2);
+	  default_def = (leader && TREE_CODE (leader) == PARM_DECL
+			 && (SSA_NAME_IS_DEFAULT_DEF (var2)
+			     || bitmap_bit_p (param_defaults, p2)));
+	}
+      else if ((TREE_CODE (SSA_NAME_VAR (var1)) == PARM_DECL
+		&& (SSA_NAME_IS_DEFAULT_DEF (var1)
+		    || bitmap_bit_p (param_defaults, p1)))
+	       || TREE_CODE (SSA_NAME_VAR (var1)) == RESULT_DECL)
+	{
+	  if ((TREE_CODE (SSA_NAME_VAR (var2)) == PARM_DECL
+	       && (SSA_NAME_IS_DEFAULT_DEF (var2)
+		   || bitmap_bit_p (param_defaults, p2)))
+	      || TREE_CODE (SSA_NAME_VAR (var2)) == RESULT_DECL)
+	    {
+	      /* We only have one RESULT_DECL, and two PARM_DECL
+		 DEFAULT_DEFs would have conflicted, so we know either
+		 one of var1 or var2 is a PARM_DECL, and the other is
+		 a RESULT_DECL.  */
+	      if (debug)
+		fprintf (debug, ": Cannot coalesce PARM_DECL and RESULT_DECL\n");
+	      return false;
+	    }
+	  leader = SSA_NAME_VAR (var1);
+	  default_def = TREE_CODE (leader) == PARM_DECL;
+	}
+      else if ((TREE_CODE (SSA_NAME_VAR (var2)) == PARM_DECL
+		&& (SSA_NAME_IS_DEFAULT_DEF (var2)
+		    || bitmap_bit_p (param_defaults, p2)))
+	       || TREE_CODE (SSA_NAME_VAR (var2)) == RESULT_DECL)
+	{
+	  leader = SSA_NAME_VAR (var2);
+	  default_def = TREE_CODE (leader) == PARM_DECL;
+	}
+      else if (TREE_CODE (SSA_NAME_VAR (var1)) == PARM_DECL)
+	leader = SSA_NAME_VAR (var1);
+      else if (TREE_CODE (SSA_NAME_VAR (var2)) == PARM_DECL)
+	leader = SSA_NAME_VAR (var2);
+      else if (TREE_CODE (SSA_NAME_VAR (var1)) == VAR_DECL
+	       && !DECL_IGNORED_P (SSA_NAME_VAR (var1)))
+	leader = SSA_NAME_VAR (var1);
+      else if (TREE_CODE (SSA_NAME_VAR (var2)) == VAR_DECL
+	       && !DECL_IGNORED_P (SSA_NAME_VAR (var2)))
+	leader = SSA_NAME_VAR (var2);
+      else if (TREE_CODE (SSA_NAME_VAR (var1)) == VAR_DECL)
+	leader = SSA_NAME_VAR (var1);
+      else if (TREE_CODE (SSA_NAME_VAR (var2)) == VAR_DECL)
+	leader = SSA_NAME_VAR (var2);
+      else /* What else could it be?  */
+	gcc_unreachable ();
+
       z = var_union (map, var1, var2);
       if (z == NO_PARTITION)
 	{
@@ -1173,8 +1278,46 @@  attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
       else
 	ssa_conflicts_merge (graph, p2, p1);
 
+      if (z == p1)
+	{
+	  if (SSA_NAME_VAR (var1) != leader)
+	    {
+	      replace_ssa_name_symbol (var1, leader);
+	      if (debug)
+		{
+		  fprintf (debug, ": Renamed ");
+		  print_generic_expr (debug, var1, TDF_SLIM);
+		}
+	    }
+	  if (default_def)
+	    {
+	      if (SSA_NAME_IS_DEFAULT_DEF (var2))
+		bitmap_clear_bit (param_defaults, p2);
+	      bitmap_set_bit (param_defaults, p1);
+	    }
+	}
+      else
+	{
+	  if (SSA_NAME_VAR (var2) != leader)
+	    {
+	      replace_ssa_name_symbol (var2, leader);
+	      if (debug)
+		{
+		  fprintf (debug, ": Renamed ");
+		  print_generic_expr (debug, var2, TDF_SLIM);
+		}
+	    }
+	  if (default_def)
+	    {
+	      if (SSA_NAME_IS_DEFAULT_DEF (var1))
+		bitmap_clear_bit (param_defaults, p1);
+	      bitmap_set_bit (param_defaults, p2);
+	    }
+	}
+
       if (debug)
 	fprintf (debug, ": Success -> %d\n", z);
+
       return true;
     }
 
@@ -1190,7 +1333,7 @@  attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y,
 
 static void
 coalesce_partitions (var_map map, ssa_conflicts_p graph, coalesce_list_p cl,
-		     FILE *debug)
+		     bitmap param_defaults, FILE *debug)
 {
   int x = 0, y = 0;
   tree var1, var2;
@@ -1226,7 +1369,7 @@  coalesce_partitions (var_map map, ssa_conflicts_p graph, coalesce_list_p cl,
 		if (debug)
 		  fprintf (debug, "Abnormal coalesce: ");
 
-		if (!attempt_coalesce (map, graph, v1, v2, debug))
+		if (!attempt_coalesce (map, graph, v1, v2, param_defaults, debug))
 		  fail_abnormal_edge_coalesce (v1, v2);
 	      }
 	  }
@@ -1244,7 +1387,7 @@  coalesce_partitions (var_map map, ssa_conflicts_p graph, coalesce_list_p cl,
 
       if (debug)
 	fprintf (debug, "Coalesce list: ");
-      attempt_coalesce (map, graph, x, y, debug);
+      attempt_coalesce (map, graph, x, y, param_defaults, debug);
     }
 }
 
@@ -1272,6 +1415,178 @@  ssa_name_var_hash::equal (const value_type *n1, const compare_type *n2)
 }
 
 
+/* Output partition map MAP with coalescing plan PART to file F.  */
+
+void
+dump_part_var_map (FILE *f, partition part, var_map map)
+{
+  int t;
+  unsigned x, y;
+  int p;
+
+  fprintf (f, "\nCoalescible Partition map \n\n");
+
+  for (x = 0; x < map->num_partitions; x++)
+    {
+      if (map->view_to_partition != NULL)
+	p = map->view_to_partition[x];
+      else
+	p = x;
+
+      if (ssa_name (p) == NULL_TREE
+	  || virtual_operand_p (ssa_name (p)))
+        continue;
+
+      t = 0;
+      for (y = 1; y < num_ssa_names; y++)
+        {
+	  tree var = version_to_var (map, y);
+	  if (!var)
+	    continue;
+	  int q = var_to_partition (map, var);
+	  p = partition_find (part, q);
+	  gcc_assert (map->partition_to_base_index[q]
+		      == map->partition_to_base_index[p]);
+
+	  if (p == (int)x)
+	    {
+	      if (t++ == 0)
+	        {
+		  fprintf (f, "Partition %d, base %d (", x,
+			   map->partition_to_base_index[q]);
+		  print_generic_expr (f, partition_to_var (map, q), TDF_SLIM);
+		  fprintf (f, " - ");
+		}
+	      fprintf (f, "%d ", y);
+	    }
+	}
+      if (t != 0)
+	fprintf (f, ")\n");
+    }
+  fprintf (f, "\n");
+}
+
+/* Fill in MAP's partition_to_base_index, with one index for each
+   partition of SSA names USED_IN_COPIES and related by CL
+   coalesce possibilities.  */
+
+static void
+compute_optimized_partition_bases (var_map map, bitmap used_in_copies,
+				   coalesce_list_p cl)
+{
+  int parts = num_var_partitions (map);
+  partition tentative = partition_new (parts);
+
+  /* Partition the SSA versions so that, for each coalescible
+     pair, both of its members are in the same partition in
+     TENTATIVE.  */
+  gcc_assert (!cl->sorted);
+  coalesce_pair_p node;
+  coalesce_iterator_type ppi;
+  FOR_EACH_PARTITION_PAIR (node, ppi, cl)
+    {
+      tree v1 = ssa_name (node->first_element);
+      int p1 = partition_find (tentative, var_to_partition (map, v1));
+      tree v2 = ssa_name (node->second_element);
+      int p2 = partition_find (tentative, var_to_partition (map, v2));
+
+      if (p1 == p2)
+	continue;
+
+      partition_union (tentative, p1, p2);
+    }
+
+  /* We have to deal with cost one pairs too.  */
+  for (cost_one_pair_d *co = cl->cost_one_list; co; co = co->next)
+    {
+      tree v1 = ssa_name (co->first_element);
+      int p1 = partition_find (tentative, var_to_partition (map, v1));
+      tree v2 = ssa_name (co->second_element);
+      int p2 = partition_find (tentative, var_to_partition (map, v2));
+
+      if (p1 == p2)
+	continue;
+
+      partition_union (tentative, p1, p2);
+    }
+
+  /* And also with abnormal edges.  */
+  basic_block bb;
+  edge e;
+  edge_iterator ei;
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      FOR_EACH_EDGE (e, ei, bb->preds)
+	if (e->flags & EDGE_ABNORMAL)
+	  {
+	    gphi_iterator gsi;
+	    for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+		 gsi_next (&gsi))
+	      {
+		gphi *phi = gsi.phi ();
+		tree arg = PHI_ARG_DEF (phi, e->dest_idx);
+		if (SSA_NAME_IS_DEFAULT_DEF (arg)
+		    && (!SSA_NAME_VAR (arg)
+			|| TREE_CODE (SSA_NAME_VAR (arg)) != PARM_DECL))
+		  continue;
+
+		tree res = PHI_RESULT (phi);
+
+		int p1 = partition_find (tentative, var_to_partition (map, res));
+		int p2 = partition_find (tentative, var_to_partition (map, arg));
+
+		if (p1 == p2)
+		  continue;
+
+		partition_union (tentative, p1, p2);
+	      }
+	  }
+    }
+  
+
+  map->partition_to_base_index = XCNEWVEC (int, parts);
+  auto_vec<unsigned int> index_map (parts);
+  if (parts)
+    index_map.quick_grow (parts);
+
+  const unsigned no_part = -1;
+  unsigned count = parts;
+  while (count)
+    index_map[--count] = no_part;
+
+  /* Initialize MAP's mapping from partition to base index, using
+     as base indices an enumeration of the TENTATIVE partitions in
+     which each SSA version ended up, so that we compute conflicts
+     between all SSA versions that ended up in the same potential
+     coalesce partition.  */
+  bitmap_iterator bi;
+  unsigned i;
+  EXECUTE_IF_SET_IN_BITMAP (used_in_copies, 0, i, bi)
+    {
+      int pidx = var_to_partition (map, ssa_name (i));
+      int base = partition_find (tentative, pidx);
+      if (index_map[base] != no_part)
+	continue;
+      index_map[base] = count++;
+    }
+
+  map->num_basevars = count;
+
+  EXECUTE_IF_SET_IN_BITMAP (used_in_copies, 0, i, bi)
+    {
+      int pidx = var_to_partition (map, ssa_name (i));
+      int base = partition_find (tentative, pidx);
+      gcc_assert (index_map[base] < count);
+      map->partition_to_base_index[pidx] = index_map[base];
+    }
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    dump_part_var_map (dump_file, tentative, map);
+
+  partition_delete (tentative);
+}
+
+
 /* Reduce the number of copies by coalescing variables in the function.  Return
    a partition map with the resulting coalesces.  */
 
@@ -1332,7 +1647,12 @@  coalesce_ssa_name (void)
     dump_var_map (dump_file, map);
 
   /* Don't calculate live ranges for variables not in the coalesce list.  */
-  partition_view_bitmap (map, used_in_copies, true);
+  partition_view_bitmap (map, used_in_copies, !optimize);
+
+  /* If we are optimizing, compute the base indices ourselves.  */
+  if (optimize)
+    compute_optimized_partition_bases (map, used_in_copies, cl);
+
   BITMAP_FREE (used_in_copies);
 
   if (num_var_partitions (map) < 1)
@@ -1341,6 +1661,8 @@  coalesce_ssa_name (void)
       return map;
     }
 
+  bitmap param_defaults = BITMAP_ALLOC (NULL);
+
   if (dump_file && (dump_flags & TDF_DETAILS))
     dump_var_map (dump_file, map);
 
@@ -1350,7 +1672,7 @@  coalesce_ssa_name (void)
     dump_live_info (dump_file, liveinfo, LIVEDUMP_ENTRY);
 
   /* Build a conflict graph.  */
-  graph = build_ssa_conflict_graph (liveinfo);
+  graph = build_ssa_conflict_graph (liveinfo, param_defaults);
   delete_tree_live_info (liveinfo);
   if (dump_file && (dump_flags & TDF_DETAILS))
     ssa_conflicts_dump (dump_file, graph);
@@ -1370,10 +1692,10 @@  coalesce_ssa_name (void)
     dump_var_map (dump_file, map);
 
   /* Now coalesce everything in the list.  */
-  coalesce_partitions (map, graph, cl,
-		       ((dump_flags & TDF_DETAILS) ? dump_file
-						   : NULL));
+  coalesce_partitions (map, graph, cl, param_defaults,
+		       ((dump_flags & TDF_DETAILS) ? dump_file : NULL));
 
+  BITMAP_FREE (param_defaults);
   delete_coalesce_list (cl);
   ssa_conflicts_delete (graph);
 
diff --git a/gcc/tree-ssa-copyrename.c b/gcc/tree-ssa-copyrename.c
deleted file mode 100644
index f3cb56e..0000000
--- a/gcc/tree-ssa-copyrename.c
+++ /dev/null
@@ -1,499 +0,0 @@ 
-/* Rename SSA copies.
-   Copyright (C) 2004-2015 Free Software Foundation, Inc.
-   Contributed by Andrew MacLeod <amacleod@redhat.com>
-
-This file is part of GCC.
-
-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.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "vec.h"
-#include "double-int.h"
-#include "input.h"
-#include "alias.h"
-#include "symtab.h"
-#include "wide-int.h"
-#include "inchash.h"
-#include "tree.h"
-#include "fold-const.h"
-#include "predict.h"
-#include "hard-reg-set.h"
-#include "function.h"
-#include "dominance.h"
-#include "cfg.h"
-#include "basic-block.h"
-#include "tree-ssa-alias.h"
-#include "internal-fn.h"
-#include "gimple-expr.h"
-#include "is-a.h"
-#include "gimple.h"
-#include "gimple-iterator.h"
-#include "flags.h"
-#include "tree-pretty-print.h"
-#include "bitmap.h"
-#include "gimple-ssa.h"
-#include "stringpool.h"
-#include "tree-ssanames.h"
-#include "hashtab.h"
-#include "rtl.h"
-#include "statistics.h"
-#include "real.h"
-#include "fixed-value.h"
-#include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
-#include "tree-dfa.h"
-#include "tree-inline.h"
-#include "tree-ssa-live.h"
-#include "tree-pass.h"
-#include "langhooks.h"
-
-static struct
-{
-  /* Number of copies coalesced.  */
-  int coalesced;
-} stats;
-
-/* The following routines implement the SSA copy renaming phase.
-
-   This optimization looks for copies between 2 SSA_NAMES, either through a
-   direct copy, or an implicit one via a PHI node result and its arguments.
-
-   Each copy is examined to determine if it is possible to rename the base
-   variable of one of the operands to the same variable as the other operand.
-   i.e.
-   T.3_5 = <blah>
-   a_1 = T.3_5
-
-   If this copy couldn't be copy propagated, it could possibly remain in the
-   program throughout the optimization phases.   After SSA->normal, it would
-   become:
-
-   T.3 = <blah>
-   a = T.3
-
-   Since T.3_5 is distinct from all other SSA versions of T.3, there is no
-   fundamental reason why the base variable needs to be T.3, subject to
-   certain restrictions.  This optimization attempts to determine if we can
-   change the base variable on copies like this, and result in code such as:
-
-   a_5 = <blah>
-   a_1 = a_5
-
-   This gives the SSA->normal pass a shot at coalescing a_1 and a_5. If it is
-   possible, the copy goes away completely. If it isn't possible, a new temp
-   will be created for a_5, and you will end up with the exact same code:
-
-   a.8 = <blah>
-   a = a.8
-
-   The other benefit of performing this optimization relates to what variables
-   are chosen in copies.  Gimplification of the program uses temporaries for
-   a lot of things. expressions like
-
-   a_1 = <blah>
-   <blah2> = a_1
-
-   get turned into
-
-   T.3_5 = <blah>
-   a_1 = T.3_5
-   <blah2> = a_1
-
-   Copy propagation is done in a forward direction, and if we can propagate
-   through the copy, we end up with:
-
-   T.3_5 = <blah>
-   <blah2> = T.3_5
-
-   The copy is gone, but so is all reference to the user variable 'a'. By
-   performing this optimization, we would see the sequence:
-
-   a_5 = <blah>
-   a_1 = a_5
-   <blah2> = a_1
-
-   which copy propagation would then turn into:
-
-   a_5 = <blah>
-   <blah2> = a_5
-
-   and so we still retain the user variable whenever possible.  */
-
-
-/* Coalesce the partitions in MAP representing VAR1 and VAR2 if it is valid.
-   Choose a representative for the partition, and send debug info to DEBUG.  */
-
-static void
-copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug)
-{
-  int p1, p2, p3;
-  tree root1, root2;
-  tree rep1, rep2;
-  bool ign1, ign2, abnorm;
-
-  gcc_assert (TREE_CODE (var1) == SSA_NAME);
-  gcc_assert (TREE_CODE (var2) == SSA_NAME);
-
-  register_ssa_partition (map, var1);
-  register_ssa_partition (map, var2);
-
-  p1 = partition_find (map->var_partition, SSA_NAME_VERSION (var1));
-  p2 = partition_find (map->var_partition, SSA_NAME_VERSION (var2));
-
-  if (debug)
-    {
-      fprintf (debug, "Try : ");
-      print_generic_expr (debug, var1, TDF_SLIM);
-      fprintf (debug, "(P%d) & ", p1);
-      print_generic_expr (debug, var2, TDF_SLIM);
-      fprintf (debug, "(P%d)", p2);
-    }
-
-  gcc_assert (p1 != NO_PARTITION);
-  gcc_assert (p2 != NO_PARTITION);
-
-  if (p1 == p2)
-    {
-      if (debug)
-	fprintf (debug, " : Already coalesced.\n");
-      return;
-    }
-
-  rep1 = partition_to_var (map, p1);
-  rep2 = partition_to_var (map, p2);
-  root1 = SSA_NAME_VAR (rep1);
-  root2 = SSA_NAME_VAR (rep2);
-  if (!root1 && !root2)
-    return;
-
-  /* Don't coalesce if one of the variables occurs in an abnormal PHI.  */
-  abnorm = (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rep1)
-	    || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rep2));
-  if (abnorm)
-    {
-      if (debug)
-	fprintf (debug, " : Abnormal PHI barrier.  No coalesce.\n");
-      return;
-    }
-
-  /* Partitions already have the same root, simply merge them.  */
-  if (root1 == root2)
-    {
-      p1 = partition_union (map->var_partition, p1, p2);
-      if (debug)
-	fprintf (debug, " : Same root, coalesced --> P%d.\n", p1);
-      return;
-    }
-
-  /* Never attempt to coalesce 2 different parameters.  */
-  if ((root1 && TREE_CODE (root1) == PARM_DECL)
-      && (root2 && TREE_CODE (root2) == PARM_DECL))
-    {
-      if (debug)
-        fprintf (debug, " : 2 different PARM_DECLS. No coalesce.\n");
-      return;
-    }
-
-  if ((root1 && TREE_CODE (root1) == RESULT_DECL)
-      != (root2 && TREE_CODE (root2) == RESULT_DECL))
-    {
-      if (debug)
-        fprintf (debug, " : One root a RESULT_DECL. No coalesce.\n");
-      return;
-    }
-
-  ign1 = !root1 || (TREE_CODE (root1) == VAR_DECL && DECL_IGNORED_P (root1));
-  ign2 = !root2 || (TREE_CODE (root2) == VAR_DECL && DECL_IGNORED_P (root2));
-
-  /* Refrain from coalescing user variables, if requested.  */
-  if (!ign1 && !ign2)
-    {
-      if (flag_ssa_coalesce_vars && DECL_FROM_INLINE (root2))
-	ign2 = true;
-      else if (flag_ssa_coalesce_vars && DECL_FROM_INLINE (root1))
-	ign1 = true;
-      else if (flag_ssa_coalesce_vars != 2)
-	{
-	  if (debug)
-	    fprintf (debug, " : 2 different USER vars. No coalesce.\n");
-	  return;
-	}
-      else
-	ign2 = true;
-    }
-
-  /* If both values have default defs, we can't coalesce.  If only one has a
-     tag, make sure that variable is the new root partition.  */
-  if (root1 && ssa_default_def (cfun, root1))
-    {
-      if (root2 && ssa_default_def (cfun, root2))
-	{
-	  if (debug)
-	    fprintf (debug, " : 2 default defs. No coalesce.\n");
-	  return;
-	}
-      else
-        {
-	  ign2 = true;
-	  ign1 = false;
-	}
-    }
-  else if (root2 && ssa_default_def (cfun, root2))
-    {
-      ign1 = true;
-      ign2 = false;
-    }
-
-  /* Do not coalesce if we cannot assign a symbol to the partition.  */
-  if (!(!ign2 && root2)
-      && !(!ign1 && root1))
-    {
-      if (debug)
-	fprintf (debug, " : Choosen variable has no root.  No coalesce.\n");
-      return;
-    }
-
-  /* Don't coalesce if the new chosen root variable would be read-only.
-     If both ign1 && ign2, then the root var of the larger partition
-     wins, so reject in that case if any of the root vars is TREE_READONLY.
-     Otherwise reject only if the root var, on which replace_ssa_name_symbol
-     will be called below, is readonly.  */
-  if (((root1 && TREE_READONLY (root1)) && ign2)
-      || ((root2 && TREE_READONLY (root2)) && ign1))
-    {
-      if (debug)
-	fprintf (debug, " : Readonly variable.  No coalesce.\n");
-      return;
-    }
-
-  /* Don't coalesce if the two variables aren't type compatible .  */
-  if (!types_compatible_p (TREE_TYPE (var1), TREE_TYPE (var2))
-      /* There is a disconnect between the middle-end type-system and
-         VRP, avoid coalescing enum types with different bounds.  */
-      || ((TREE_CODE (TREE_TYPE (var1)) == ENUMERAL_TYPE
-	   || TREE_CODE (TREE_TYPE (var2)) == ENUMERAL_TYPE)
-	  && TREE_TYPE (var1) != TREE_TYPE (var2)))
-    {
-      if (debug)
-	fprintf (debug, " : Incompatible types.  No coalesce.\n");
-      return;
-    }
-
-  /* Merge the two partitions.  */
-  p3 = partition_union (map->var_partition, p1, p2);
-
-  /* Set the root variable of the partition to the better choice, if there is
-     one.  */
-  if (!ign2 && root2)
-    replace_ssa_name_symbol (partition_to_var (map, p3), root2);
-  else if (!ign1 && root1)
-    replace_ssa_name_symbol (partition_to_var (map, p3), root1);
-  else
-    gcc_unreachable ();
-
-  if (debug)
-    {
-      fprintf (debug, " --> P%d ", p3);
-      print_generic_expr (debug, SSA_NAME_VAR (partition_to_var (map, p3)),
-			  TDF_SLIM);
-      fprintf (debug, "\n");
-    }
-}
-
-
-namespace {
-
-const pass_data pass_data_rename_ssa_copies =
-{
-  GIMPLE_PASS, /* type */
-  "copyrename", /* name */
-  OPTGROUP_NONE, /* optinfo_flags */
-  TV_TREE_COPY_RENAME, /* tv_id */
-  ( PROP_cfg | PROP_ssa ), /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  0, /* todo_flags_finish */
-};
-
-class pass_rename_ssa_copies : public gimple_opt_pass
-{
-public:
-  pass_rename_ssa_copies (gcc::context *ctxt)
-    : gimple_opt_pass (pass_data_rename_ssa_copies, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  opt_pass * clone () { return new pass_rename_ssa_copies (m_ctxt); }
-  virtual bool gate (function *) { return flag_tree_copyrename != 0; }
-  virtual unsigned int execute (function *);
-
-}; // class pass_rename_ssa_copies
-
-/* This function will make a pass through the IL, and attempt to coalesce any
-   SSA versions which occur in PHI's or copies.  Coalescing is accomplished by
-   changing the underlying root variable of all coalesced version.  This will
-   then cause the SSA->normal pass to attempt to coalesce them all to the same
-   variable.  */
-
-unsigned int
-pass_rename_ssa_copies::execute (function *fun)
-{
-  var_map map;
-  basic_block bb;
-  tree var, part_var;
-  gimple stmt;
-  unsigned x;
-  FILE *debug;
-
-  memset (&stats, 0, sizeof (stats));
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    debug = dump_file;
-  else
-    debug = NULL;
-
-  map = init_var_map (num_ssa_names);
-
-  FOR_EACH_BB_FN (bb, fun)
-    {
-      /* Scan for real copies.  */
-      for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
-	   gsi_next (&gsi))
-	{
-	  stmt = gsi_stmt (gsi);
-	  if (gimple_assign_ssa_name_copy_p (stmt))
-	    {
-	      tree lhs = gimple_assign_lhs (stmt);
-	      tree rhs = gimple_assign_rhs1 (stmt);
-
-	      copy_rename_partition_coalesce (map, lhs, rhs, debug);
-	    }
-	}
-    }
-
-  FOR_EACH_BB_FN (bb, fun)
-    {
-      /* Treat PHI nodes as copies between the result and each argument.  */
-      for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
-	   gsi_next (&gsi))
-        {
-          size_t i;
-	  tree res;
-	  gphi *phi = gsi.phi ();
-	  res = gimple_phi_result (phi);
-
-	  /* Do not process virtual SSA_NAMES.  */
-	  if (virtual_operand_p (res))
-	    continue;
-
-	  /* Make sure to only use the same partition for an argument
-	     as the result but never the other way around.  */
-	  if (SSA_NAME_VAR (res)
-	      && !DECL_IGNORED_P (SSA_NAME_VAR (res)))
-	    for (i = 0; i < gimple_phi_num_args (phi); i++)
-	      {
-		tree arg = PHI_ARG_DEF (phi, i);
-		if (TREE_CODE (arg) == SSA_NAME)
-		  copy_rename_partition_coalesce (map, res, arg,
-						  debug);
-	      }
-	  /* Else if all arguments are in the same partition try to merge
-	     it with the result.  */
-	  else
-	    {
-	      int all_p_same = -1;
-	      int p = -1;
-	      for (i = 0; i < gimple_phi_num_args (phi); i++)
-		{
-		  tree arg = PHI_ARG_DEF (phi, i);
-		  if (TREE_CODE (arg) != SSA_NAME)
-		    {
-		      all_p_same = 0;
-		      break;
-		    }
-		  else if (all_p_same == -1)
-		    {
-		      p = partition_find (map->var_partition,
-					  SSA_NAME_VERSION (arg));
-		      all_p_same = 1;
-		    }
-		  else if (all_p_same == 1
-			   && p != partition_find (map->var_partition,
-						   SSA_NAME_VERSION (arg)))
-		    {
-		      all_p_same = 0;
-		      break;
-		    }
-		}
-	      if (all_p_same == 1)
-		copy_rename_partition_coalesce (map, res,
-						PHI_ARG_DEF (phi, 0),
-						debug);
-	    }
-        }
-    }
-
-  if (debug)
-    dump_var_map (debug, map);
-
-  /* Now one more pass to make all elements of a partition share the same
-     root variable.  */
-
-  for (x = 1; x < num_ssa_names; x++)
-    {
-      part_var = partition_to_var (map, x);
-      if (!part_var)
-        continue;
-      var = ssa_name (x);
-      if (SSA_NAME_VAR (var) == SSA_NAME_VAR (part_var))
-	continue;
-      if (debug)
-        {
-	  fprintf (debug, "Coalesced ");
-	  print_generic_expr (debug, var, TDF_SLIM);
-	  fprintf (debug, " to ");
-	  print_generic_expr (debug, part_var, TDF_SLIM);
-	  fprintf (debug, "\n");
-	}
-      stats.coalesced++;
-      replace_ssa_name_symbol (var, SSA_NAME_VAR (part_var));
-    }
-
-  statistics_counter_event (fun, "copies coalesced",
-			    stats.coalesced);
-  delete_var_map (map);
-  return 0;
-}
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_rename_ssa_copies (gcc::context *ctxt)
-{
-  return new pass_rename_ssa_copies (ctxt);
-}
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index e0c42669..46b1869 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -119,7 +119,10 @@  tree_int_map_hasher::equal (const value_type *v, const compare_type *c)
 }
 
 
-/* This routine will initialize the basevar fields of MAP.  */
+/* This routine will initialize the basevar fields of MAP with base
+   names, when we are not optimizing.  When optimizing, we'll use
+   partition numbers as base index numbers, see coalesce_ssa_name in
+   tree-ssa-coalesce.c.  */
 
 static void
 var_map_base_init (var_map map)