Re: How do I modify SSA and copy basic blocks?

2013-04-26 Thread Richard Biener
On Thu, Apr 25, 2013 at 8:28 PM, Steve Ellcey  wrote:
> On Thu, 2013-04-25 at 09:53 +0200, Richard Biener wrote:
>
>> We have gimple_duplicate_sese_region for this.  It may be not perfect though.
>> Eventually it should be changed to handle SEME regions as well and all
>> loop copying / versioning code should use it as well (though I don't think
>> any of the loop copying / versioning code handles multiple exits).
>>
>> I've slowly started to move us in this direction by removing duplicate
>> functionality
>> in the compiler as I come along it ...
>>
>> Richard.
>
> One thing I have noticed with this routine is that I am trying to call
> gimple_duplicate_sese_region before the various loop optimizations and
> before the loop information is all set up (not sure if that is good or
> bad, right now it just is).  So I died when calling set_loop_copy.  I
> put that call and the other loop uses in an 'if (loop)' block to make
> that assertion stop and I was then able to copy one (SEME) block with
> this routine.  When I tried to copy a second block with a second call,
> it died in iterate_fix_dominators.  I tried removing all the dominator
> information after creating my first new block hoping it would correctly
> regenerate everything before doing the second block but that didn't seem
> to work.

I think you need to init/finalize SSA updating, but I've never seen the
dominator fixup issue.  Maybe simply call loop_optimizer_init () in
your pass (well, no longer needed since I just committed the patch that
should make loops available everywhere).

Richard.

> Steve Ellcey
> sell...@imgtec.com
>
>


Re: How do I modify SSA and copy basic blocks?

2013-04-25 Thread Steve Ellcey
On Thu, 2013-04-25 at 09:53 +0200, Richard Biener wrote:

> We have gimple_duplicate_sese_region for this.  It may be not perfect though.
> Eventually it should be changed to handle SEME regions as well and all
> loop copying / versioning code should use it as well (though I don't think
> any of the loop copying / versioning code handles multiple exits).
> 
> I've slowly started to move us in this direction by removing duplicate
> functionality
> in the compiler as I come along it ...
> 
> Richard.

One thing I have noticed with this routine is that I am trying to call
gimple_duplicate_sese_region before the various loop optimizations and
before the loop information is all set up (not sure if that is good or
bad, right now it just is).  So I died when calling set_loop_copy.  I
put that call and the other loop uses in an 'if (loop)' block to make
that assertion stop and I was then able to copy one (SEME) block with
this routine.  When I tried to copy a second block with a second call,
it died in iterate_fix_dominators.  I tried removing all the dominator
information after creating my first new block hoping it would correctly
regenerate everything before doing the second block but that didn't seem
to work.

Steve Ellcey
sell...@imgtec.com




Re: How do I modify SSA and copy basic blocks?

2013-04-25 Thread Steve Ellcey
On Thu, 2013-04-25 at 09:53 +0200, Richard Biener wrote:

> > Interesting you should mention this; one of the things I really want to get
> > back to is a more generic mechanism to copy block regions.
> 
> We have gimple_duplicate_sese_region for this.  It may be not perfect though.
> Eventually it should be changed to handle SEME regions as well and all
> loop copying / versioning code should use it as well (though I don't think
> any of the loop copying / versioning code handles multiple exits).
> 
> I've slowly started to move us in this direction by removing duplicate
> functionality
> in the compiler as I come along it ...
> 
> Richard.

This looks interesting.  If it handled SEME regions I think I could use
it because any single block by itself is going to be an SEME region,
right?  I notice the routine does not update the SSA web.  Is there a
reason for that?  It looks like copy_loop_headers calls update_ssa after
it calls gimple_duplicate_sese_region (the only use of
gimple_duplicate_sese_region that I see).  Unfortunately, at least some
of the blocks I want to copy have multiple exit edges where an SSA
variable defined in that block is needed on each of the exit edges from
the block.  Do you know what bad things will happen if I call this with
a block that is SEME instead of SESE?  Is there anyway (even if it was a
hack) that I could compensate for it by regenerating some of the
information, i.e. freeing the dominator information so it gets
recalculated from scratch or something like that?

Steve Ellcey
sell...@imgtec.com




Re: How do I modify SSA and copy basic blocks?

2013-04-25 Thread Zdenek Dvorak
Hi,

> On Tue, 2013-04-23 at 15:24 -0600, Jeff Law wrote:
> 
> > Well, you have to copy the blocks, adjust the edges and rewrite the SSA 
> > graph.  I'd use duplicate_block to help.
> > 
> > You really want to look at tree-ssa-threadupdate.c.  There's a nice big 
> > block comment which gives the high level view of what needs to happen 
> > when you copy a block for this kind of optimization.  Feel free to 
> > ignore the implementation which has to be fairly efficient when there's 
> > a large number of edges to update.
> > 
> > Jeff
> 
> I think I understand the high level work, it is mapping that hight level
> description to the low level calls that I am having trouble with. 

I'd suggest looking at gimple_duplicate_sese_region in tree-cfg.c.  It does
not do exactly what you need, but it deals with a somewhat similar situation,

Zdenek


Re: How do I modify SSA and copy basic blocks?

2013-04-25 Thread Richard Biener
On Thu, Apr 25, 2013 at 5:03 AM, Jeff Law  wrote:
> On 04/24/2013 04:54 PM, Steve Ellcey wrote:
>>
>>
>> I am still having trouble with this and with figuring out how to
>> straighten out my PHI nodes.  I have decided to try a slightly different
>> tack and see if I could create a routine that would do a generic basic
>> block copy, handling all the needed bookkeeping internally and fixing
>> all the PHI nodes after the copy.  I am trying to create a slow but
>> dependable and easy to use function and would consider completely
>> regenerating all the PHI information if that was the easiest thing to
>> do.  Here is what I have so far:
>
> Interesting you should mention this; one of the things I really want to get
> back to is a more generic mechanism to copy block regions.

We have gimple_duplicate_sese_region for this.  It may be not perfect though.
Eventually it should be changed to handle SEME regions as well and all
loop copying / versioning code should use it as well (though I don't think
any of the loop copying / versioning code handles multiple exits).

I've slowly started to move us in this direction by removing duplicate
functionality
in the compiler as I come along it ...

Richard.

> Threading is really just path isolation by copying and some
> equivalency/redundancy elimination enabled by the path isolation.
>
> We're missing a lot of threading opportunities because the current method
> for copying blocks is so limited.  There's finally some good literature on
> this stuff, both in terms of finding the redundancies that lead to useful
> optimization and in terms of identifying regions of blocks that need to be
> copied.  All the nonsense we do needs to be reformulated using better known
> methods.
>
>
>>
>>
>> /* Copy the basic block that is the destination block of orig_edge, then
>> modify/replace the edge in orig_edge->src basic block with a new edge
>> that goes to the new block.  Fix up any PHI nodes that may need to be
>> updated.  Remove the dominance info since it may have been messed up.
>> */
>>
>> edge
>> duplicate_succ_block (edge orig_edge)
>> {
>>edge new_edge;
>>basic_block orig_block, new_block;
>>
>>initialize_original_copy_tables ();
>>orig_block = orig_edge->dest;
>>fprintf(stderr, "Duplicating block %d\n", orig_block->index);
>>new_block = duplicate_block (orig_block, NULL, NULL);
>>update_destination_phis (orig_block, new_block);
>>new_edge = redirect_edge_and_branch (orig_edge, new_block);
>>remove_phi_args (orig_edge);
>>free_dominance_info (CDI_DOMINATORS);
>>free_original_copy_tables ();
>>return new_edge;
>> }
>>
>> When I use this to copy a block I get a failure from verify_ssa.
>
> Well, with that structure you need to update PHIs at the destination of
> every outgoing edge from new_block.  That's one of the reasons you want to
> delete the control statement and dead edges in the copy -- that leaves you
> just updating the single successor of new_block.
>
> You don't mention why verify_ssa fails.  I'd hazard a guess you've got a use
> not dominated by its set.   It'll be important to know where the use occurs
> and where the dominating set is supposed to be.  Presumably you call into
> update_ssa or whatever it's called these days before trying to verify_ssa?
>
>
>
>>
>> The block I am trying to copy (based on my original example) is:
>>
>>:
>># s_1 = PHI 
>># t_3 = PHI <0(2), t_2(7)>
>># c_4 = PHI 
>>if (c_4 != 0)
>>  goto ;
>>else
>>  goto ;
>>
>> There are two edges leading here (from block 2 and block 7) and I want
>> to change the 2->8 edge to be a 2->8_prime edge where 8_prime is my new
>> basic block.  That obviously affects the PHI nodes in both block 8 and
>> the new 8_prime block.  I don't think any other PHI's are affected in
>> this case, but obviously, I would like my routine to work on any block I
>> want to copy even if it does affect PHI nodes in successor blocks.
>
> You have to update the PHIs in bb3 & bb9.  You want to copy the PHI arg
> associated with 8->3 for the 8'->3 edge, similarly for for PHI args
> associated with the 8->9 edge to the 8'->9 edge.  See copy_phi_args.
>
> jeff
>
>


Re: How do I modify SSA and copy basic blocks?

2013-04-24 Thread Jeff Law

On 04/24/2013 04:54 PM, Steve Ellcey wrote:


I am still having trouble with this and with figuring out how to
straighten out my PHI nodes.  I have decided to try a slightly different
tack and see if I could create a routine that would do a generic basic
block copy, handling all the needed bookkeeping internally and fixing
all the PHI nodes after the copy.  I am trying to create a slow but
dependable and easy to use function and would consider completely
regenerating all the PHI information if that was the easiest thing to
do.  Here is what I have so far:
Interesting you should mention this; one of the things I really want to 
get back to is a more generic mechanism to copy block regions.


Threading is really just path isolation by copying and some 
equivalency/redundancy elimination enabled by the path isolation.


We're missing a lot of threading opportunities because the current 
method for copying blocks is so limited.  There's finally some good 
literature on this stuff, both in terms of finding the redundancies that 
lead to useful optimization and in terms of identifying regions of 
blocks that need to be copied.  All the nonsense we do needs to be 
reformulated using better known methods.





/* Copy the basic block that is the destination block of orig_edge, then
modify/replace the edge in orig_edge->src basic block with a new edge
that goes to the new block.  Fix up any PHI nodes that may need to be
updated.  Remove the dominance info since it may have been messed up.  */

edge
duplicate_succ_block (edge orig_edge)
{
   edge new_edge;
   basic_block orig_block, new_block;

   initialize_original_copy_tables ();
   orig_block = orig_edge->dest;
   fprintf(stderr, "Duplicating block %d\n", orig_block->index);
   new_block = duplicate_block (orig_block, NULL, NULL);
   update_destination_phis (orig_block, new_block);
   new_edge = redirect_edge_and_branch (orig_edge, new_block);
   remove_phi_args (orig_edge);
   free_dominance_info (CDI_DOMINATORS);
   free_original_copy_tables ();
   return new_edge;
}

When I use this to copy a block I get a failure from verify_ssa.
Well, with that structure you need to update PHIs at the destination of 
every outgoing edge from new_block.  That's one of the reasons you want 
to delete the control statement and dead edges in the copy -- that 
leaves you just updating the single successor of new_block.


You don't mention why verify_ssa fails.  I'd hazard a guess you've got a 
use not dominated by its set.   It'll be important to know where the use 
occurs and where the dominating set is supposed to be.  Presumably you 
call into update_ssa or whatever it's called these days before trying to 
verify_ssa?





The block I am trying to copy (based on my original example) is:

   :
   # s_1 = PHI 
   # t_3 = PHI <0(2), t_2(7)>
   # c_4 = PHI 
   if (c_4 != 0)
 goto ;
   else
 goto ;

There are two edges leading here (from block 2 and block 7) and I want
to change the 2->8 edge to be a 2->8_prime edge where 8_prime is my new
basic block.  That obviously affects the PHI nodes in both block 8 and
the new 8_prime block.  I don't think any other PHI's are affected in
this case, but obviously, I would like my routine to work on any block I
want to copy even if it does affect PHI nodes in successor blocks.
You have to update the PHIs in bb3 & bb9.  You want to copy the PHI arg 
associated with 8->3 for the 8'->3 edge, similarly for for PHI args 
associated with the 8->9 edge to the 8'->9 edge.  See copy_phi_args.


jeff




Re: How do I modify SSA and copy basic blocks?

2013-04-24 Thread Steve Ellcey
On Wed, 2013-04-24 at 15:54 -0700, Steve Ellcey wrote:

> 
> /* Copy the basic block that is the destination block of orig_edge, then
>modify/replace the edge in orig_edge->src basic block with a new edge
>that goes to the new block.  Fix up any PHI nodes that may need to be
>updated.  Remove the dominance info since it may have been messed up.  */
> 
> edge
> duplicate_succ_block (edge orig_edge)
> {
>   edge new_edge;
>   basic_block orig_block, new_block;
> 
>   initialize_original_copy_tables ();
>   orig_block = orig_edge->dest;
>   fprintf(stderr, "Duplicating block %d\n", orig_block->index);
>   new_block = duplicate_block (orig_block, NULL, NULL);
>   update_destination_phis (orig_block, new_block);
>   new_edge = redirect_edge_and_branch (orig_edge, new_block);
>   remove_phi_args (orig_edge);
>   free_dominance_info (CDI_DOMINATORS);
>   free_original_copy_tables ();
>   return new_edge;
> }

Following up to my own reply, I  tried adding:

update_ssa (TODO_update_ssa);

to fix up the SSA code but that did not help, I  tried it both with and
without the calls to update_destination_phis & remove_phi_args.

Steve Ellcey
sell...@imgtec.com




Re: How do I modify SSA and copy basic blocks?

2013-04-24 Thread Steve Ellcey
On Wed, 2013-04-24 at 14:31 -0600, Jeff Law wrote:
> On 04/24/2013 11:38 AM, Steve Ellcey wrote:

> Just do duplicate_block (B, NULL, NULL)
> 
> Then I'd remove the switch statement and the outgoing edges from B' 
> except the edge B'->C.
> 
> Then I'd fixup the PHIs in C.  That's update_destination_phis.
> 
> 
> Then you need to wire up A->B'.  If B' has PHIs, then you'll have to fix 
> those as well as any PHIs in C.  Note that PHIs in B just lost an 
> argument, but that'll be handled automatically when you redirect the 
> edge from A->B to A->B'.
> 
> I think that's the proper sequencing (and I certainly had to read the 
> code, it's been a long time since I looked at it in this level of detail)

I am still having trouble with this and with figuring out how to
straighten out my PHI nodes.  I have decided to try a slightly different
tack and see if I could create a routine that would do a generic basic
block copy, handling all the needed bookkeeping internally and fixing
all the PHI nodes after the copy.  I am trying to create a slow but
dependable and easy to use function and would consider completely
regenerating all the PHI information if that was the easiest thing to
do.  Here is what I have so far:


/* Copy the basic block that is the destination block of orig_edge, then
   modify/replace the edge in orig_edge->src basic block with a new edge
   that goes to the new block.  Fix up any PHI nodes that may need to be
   updated.  Remove the dominance info since it may have been messed up.  */

edge
duplicate_succ_block (edge orig_edge)
{
  edge new_edge;
  basic_block orig_block, new_block;

  initialize_original_copy_tables ();
  orig_block = orig_edge->dest;
  fprintf(stderr, "Duplicating block %d\n", orig_block->index);
  new_block = duplicate_block (orig_block, NULL, NULL);
  update_destination_phis (orig_block, new_block);
  new_edge = redirect_edge_and_branch (orig_edge, new_block);
  remove_phi_args (orig_edge);
  free_dominance_info (CDI_DOMINATORS);
  free_original_copy_tables ();
  return new_edge;
}

When I use this to copy a block I get a failure from verify_ssa.

The block I am trying to copy (based on my original example) is:

  :
  # s_1 = PHI 
  # t_3 = PHI <0(2), t_2(7)>
  # c_4 = PHI 
  if (c_4 != 0)
goto ;
  else
goto ;

There are two edges leading here (from block 2 and block 7) and I want
to change the 2->8 edge to be a 2->8_prime edge where 8_prime is my new
basic block.  That obviously affects the PHI nodes in both block 8 and
the new 8_prime block.  I don't think any other PHI's are affected in
this case, but obviously, I would like my routine to work on any block I
want to copy even if it does affect PHI nodes in successor blocks.

Steve Ellcey
sell...@mips.com




Re: How do I modify SSA and copy basic blocks?

2013-04-24 Thread Jeff Law

On 04/24/2013 11:38 AM, Steve Ellcey wrote:


I think I understand the high level work, it is mapping that hight level
description to the low level calls that I am having trouble with.  Lets
say I have basic blocks A, B, and C, and edges from A to B and B to C.
There may also be other edges leading into B and C that I do not want to
change.  Now I want to make a copy of B (B') and change the A->B edge to
be A->B'.

I think this would be:

B_prime = duplicate_block (B, find_edge (A, B), B);

Just do duplicate_block (B, NULL, NULL)

Then I'd remove the switch statement and the outgoing edges from B' 
except the edge B'->C.


Then I'd fixup the PHIs in C.  That's update_destination_phis.


Then you need to wire up A->B'.  If B' has PHIs, then you'll have to fix 
those as well as any PHIs in C.  Note that PHIs in B just lost an 
argument, but that'll be handled automatically when you redirect the 
edge from A->B to A->B'.


I think that's the proper sequencing (and I certainly had to read the 
code, it's been a long time since I looked at it in this level of detail)







This leads to several questions.  Why does it matter what basic block
I put this new block 'after' (the 3rd arg to duplicate_block).  Do all
blocks have at least one edge leading out of them or will a block 'fall'
into the next block if there is no succ edges?  Or does 'after' just
affect where the block shows up in debug tree listings?
The AFTER argument shouldn't matter.  All edges are explicit.  If a 
block has a fall-thru path, it'll have an edge and the edge should be 
marked with EDGE_FALLTHRU.




Looking at the code in tree-ssa-threadupdate.c and trans-mem.c I am
guessing I need to call initialize_original_copy_tables before calling
duplicate_block and free_original_copy_tables after it, right?  I am
also assuming I can do a series of duplicate_block calls between the
initialize and free calls if I need to.
Yes, you'll need to initialize & free them and you can do as many 
duplicate_block calls as you'd like.




tree-ssa-threadupdate.c has a static routine called
update_destination_phis to update the phi's in a new block, I made a
copy of this routine and used it in my code to try and update the phi
nodes in my new block B'.  I am not sure if that is sufficient or not
for updating the phi nodes in my new block.  Do I also need to do
something to adjust the phi nodes in the block I copied (B)
In your example, it's updating the PHIs in block C.  When you copy B, 
any successor nodes with PHIs will now have PHIs with an uninitialized 
argument.  That routine finds the PHI argument associated with the edge 
B'->C and initializes its value to be the same as the PHI arg associated 
with the edge B->C.






So I basically am duplicating blocks with:

initialize_original_copy_tables ();
B_prime = duplicate_block (B, find_edge (A, B), A);
update_destination_phis (B, B_prime);
free_original_copy_tables ();

But my code segfaults in nearest_common_dominator, called by update_ssa
after my pass has changed the code.  I think I need to do more to fix
any PHI nodes in B and B' but I am not sure what.  I also notice that
copy_bbs in cfghooks (which calls duplicate_block) has calls to
get_immediate_dominator and set_immediate_dominator, maybe I need to
copy that code as well?
Make sure you call free_dominance_info.  THe code might be looking at 
cached dominance info and getting confused as hell.  Threading jumps 
like this mucks up the dominance info beyond easy repair.




jeff


Re: How do I modify SSA and copy basic blocks?

2013-04-24 Thread Steve Ellcey
On Tue, 2013-04-23 at 15:24 -0600, Jeff Law wrote:

> Well, you have to copy the blocks, adjust the edges and rewrite the SSA 
> graph.  I'd use duplicate_block to help.
> 
> You really want to look at tree-ssa-threadupdate.c.  There's a nice big 
> block comment which gives the high level view of what needs to happen 
> when you copy a block for this kind of optimization.  Feel free to 
> ignore the implementation which has to be fairly efficient when there's 
> a large number of edges to update.
> 
> Jeff

I think I understand the high level work, it is mapping that hight level
description to the low level calls that I am having trouble with.  Lets
say I have basic blocks A, B, and C, and edges from A to B and B to C.
There may also be other edges leading into B and C that I do not want to
change.  Now I want to make a copy of B (B') and change the A->B edge to
be A->B'.

I think this would be:

B_prime = duplicate_block (B, find_edge (A, B), B);

This leads to several questions.  Why does it matter what basic block
I put this new block 'after' (the 3rd arg to duplicate_block).  Do all
blocks have at least one edge leading out of them or will a block 'fall'
into the next block if there is no succ edges?  Or does 'after' just
affect where the block shows up in debug tree listings?

Looking at the code in tree-ssa-threadupdate.c and trans-mem.c I am
guessing I need to call initialize_original_copy_tables before calling
duplicate_block and free_original_copy_tables after it, right?  I am
also assuming I can do a series of duplicate_block calls between the
initialize and free calls if I need to.

tree-ssa-threadupdate.c has a static routine called
update_destination_phis to update the phi's in a new block, I made a
copy of this routine and used it in my code to try and update the phi
nodes in my new block B'.  I am not sure if that is sufficient or not
for updating the phi nodes in my new block.  Do I also need to do
something to adjust the phi nodes in the block I copied (B)

So I basically am duplicating blocks with:

initialize_original_copy_tables ();
B_prime = duplicate_block (B, find_edge (A, B), A);
update_destination_phis (B, B_prime);
free_original_copy_tables ();

But my code segfaults in nearest_common_dominator, called by update_ssa
after my pass has changed the code.  I think I need to do more to fix
any PHI nodes in B and B' but I am not sure what.  I also notice that
copy_bbs in cfghooks (which calls duplicate_block) has calls to
get_immediate_dominator and set_immediate_dominator, maybe I need to 
copy that code as well?

Steve Ellcey
sell...@imgtec.com






Re: How do I modify SSA and copy basic blocks?

2013-04-23 Thread Jeff Law

On 04/23/2013 02:43 PM, Steve Ellcey wrote:


I think I have code that finds the path that I am interested in, but when
I try to use copy_bbs to copy the basic blocks in order to create my new path,
I get segfaults.  I was wondering if anyone could help me understand what I
need to do, in addition to calling copy_bbs, to create my new path and keep
the various ssa and cfg information up to date, either by modifying it or by
blowing it away and regenerating it, I am not worried about compilation speed
at this point so if regenerating all the SSA/cfg data is easiest, I am happy
to do that.
Well, you have to copy the blocks, adjust the edges and rewrite the SSA 
graph.  I'd use duplicate_block to help.


You really want to look at tree-ssa-threadupdate.c.  There's a nice big 
block comment which gives the high level view of what needs to happen 
when you copy a block for this kind of optimization.  Feel free to 
ignore the implementation which has to be fairly efficient when there's 
a large number of edges to update.


Jeff


How do I modify SSA and copy basic blocks?

2013-04-23 Thread Steve Ellcey
I decided to take a crack at the coremark optimization (PR 54742) for switch
statements.  Since I couldn't figure out the existing jump threading
optimization enough to extend it properly, I decided to try a plugin
optimization pass just for this case and see if I could get that to work.

The basic idea is to find a path from where a variable is assigned a constant
value to where that variable is used in a switch statement.  Then I want to
duplicate the blocks in that path (thus removing any alternative entry points
into the path that may give the variable a different value) and plug it into
the cfg.

I think I have code that finds the path that I am interested in, but when
I try to use copy_bbs to copy the basic blocks in order to create my new path,
I get segfaults.  I was wondering if anyone could help me understand what I
need to do, in addition to calling copy_bbs, to create my new path and keep
the various ssa and cfg information up to date, either by modifying it or by
blowing it away and regenerating it, I am not worried about compilation speed
at this point so if regenerating all the SSA/cfg data is easiest, I am happy
to do that.

Attached is my plugin as it exists right now and a simple test case using a
switch statement.  I am not including the actual coremark code because it is
copyrighted.  If you run my example you will see output showing 4 places where
I think I can do my optimization.  For example we assign t the value of 0 in
block 2 and from there we go to block 8 and (possibly) to block 3 where we have
our switch statement.

So what I try to do is copy blocks 8 and 3 and change the edge from block
2 to block 8 to go from block 2 to my new copy of block 8 which should
then go to the new copy of block 3.  After this we should be able to
optimize the new copy of block 3 to finish with a goto to the 'case 0'
label instead of with a switch/goto.

If you remove the '#if 0' in my code where I comment out the call to
copy_bbs, you will get a seg fault, this is the code that I need help
with.  For example, If I copy block 8 and block 3, and there is an edge
from 8 to 3, does copy_bbs automatically create a new edge pointing from the
copy of block 8 to block 3 and replace that in the copied blocks?  I think it
does, but I am not sure. 

Steve Ellcey
sell...@imgtec.com



Output from the test program using my new optimization phase.

In plugin, registering new pass
Block 2 assigns variable t a constant value of 0
Basic blocks (leading from basic block 2 to switch) are:
  8
  3
Block 4 assigns variable t a constant value of 1
Basic blocks (leading from basic block 4 to switch) are:
  7
  8
  3
Block 5 assigns variable t a constant value of 2
Basic blocks (leading from basic block 5 to switch) are:
  7
  8
  3
Block 6 assigns variable t a constant value of 1
Basic blocks (leading from basic block 6 to switch) are:
  7
  8
  3

/* This file implements an optimization where, when a variable is set
   to a constant value and there is a path that leads from this definition
   to a switch statement that uses that variable as its controlling expression
   we duplicate the blocks on this path and change the switch goto to a
   direct goto to the label of the switch block that control would goto based
   on the value of the variable.  */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int plugin_is_GPL_compatible;

/* Helper function for find_path, visited_bbs is used to make sure we don't
   fall into an infinite loop.  */

static int
find_path_1(basic_block start_bb, basic_block end_bb, struct pointer_set_t *visited_bbs)
{
  edge_iterator ei;
  edge e;

  if (start_bb == end_bb) return 1;
  if (!pointer_set_insert (visited_bbs, start_bb))
{
  FOR_EACH_EDGE (e, ei, start_bb->succs)
	if (find_path_1 (e->dest, end_bb, visited_bbs)) return 1;
}
return 0;
}

/* Return 1 if there is a path from start_bb to end_bb and 0 if there
   is not.  */

static int
find_path(basic_block start_bb, basic_block end_bb)
{
  edge_iterator ei;
  edge e;
  struct pointer_set_t *visited_bbs;
  int p = 0;

  if (start_bb == end_bb) return 1;

  visited_bbs = pointer_set_create ();
  if (!pointer_set_insert (visited_bbs, start_bb))
{
  FOR_EACH_EDGE (e, ei, start_bb->succs)
	if (find_path_1 (e->dest, end_bb, visited_bbs))
	  {
	p = 1;
	break;
	  }
}
  pointer_set_destroy (visited_bbs);
  return p;
}

/* bbs_list[0] is the block with the switch statement,
   bbs_list[n-1] is the block where the switch statement variable is assigned
 a constant value,
   The entries in between make a (reverse) path between the two.

   We don't want to copy bb_list[n-1], we want to leave that alone and
   copy bb_list[n-2]...bb_list[0], and change the edge from bb_list[n-1]
   to bb_list[n-2] to point to the copy of bb_list[n-2].  Then we 
   should change the switch in bb_list[0] to a simple goto, but maybe we
   can let a later optimization phase (constant propogati