Bug 22586 - GVN-PRE could do strength reduction
Summary: GVN-PRE could do strength reduction
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.1.0
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization, TREE
Depends on: 37242
Blocks: 32120
  Show dependency treegraph
 
Reported: 2005-07-21 12:04 UTC by Steven Bosscher
Modified: 2012-06-28 01:27 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-03-03 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Steven Bosscher 2005-07-21 12:04:48 UTC
There doesn't appear to be any reason why GVN-PRE couldn't be extended to 
do strength reduction.  If this is added, the strength reduction currently 
done in DOM and IVOPTS may be removed or simplified.  The implementation in 
IVOPTS only works on loops, and the transformations done in DOM only works 
in a few special cases and only on a branch of the dominator tree (i.e. not 
a global pass). 
 
Also, GVN-PRE could replace the flag_unsafe_math_optimizations trick that 
used to be in expr.c and is now in tree-ssa-loop-im.c: 
 
      /* If divisor is invariant, convert a/b to a*(1/b), allowing reciprocal 
         to be hoisted out of loop, saving expensive divide.  */ 
 
Adding this transformation as a special case of "strength reduction" to 
GVN-PRE would allow the transformation to be done on straight-line code as 
well (the code in expr.c used to do this, but we don't do the transformation 
anymore at the moment). 
 
Consider as an example: 
 
int 
foo (int a[], int b[], int i) 
{ 
  a[i] = b[i] + 2; 
  i++; 
  a[i] = b[i] + 2; 
  i++; 
  a[i] = b[i] + 2; 
  i++; 
  a[i] = b[i] + 2; 
  i++; 
  return i; 
} 
 
"GCC 4.1.0 20050721 (experimental)" produces the following .vars dump: 
 
foo (a, b, i) 
{ 
  int * temp.44; 
  int * temp.43; 
  int * temp.42; 
  int * D.1608; 
 
<bb 0>: 
  D.1608 = (int *) ((long unsigned int) i * 4); 
  *(D.1608 + a) = *(D.1608 + b) + 2; 
  temp.42 = (int *) ((long unsigned int) (i + 1) * 4); 
  *(a + temp.42) = *(b + temp.42) + 2; 
  temp.43 = (int *) ((long unsigned int) (i + 2) * 4); 
  *(a + temp.43) = *(b + temp.43) + 2; 
  temp.44 = (int *) ((long unsigned int) (i + 3) * 4); 
  *(a + temp.44) = *(b + temp.44) + 2; 
  return i + 4; 
 
} 
 
Note the redundant computations of "i*4".  Indeed, we don't optimize these 
away on RTL either.
Comment 1 Andrew Pinski 2005-07-21 16:15:28 UTC
Confirmed.  Note there is a pass at the tree level which already does the replace "a/b to a*(1/b)" at the 
rtl level.
Comment 2 Andrew Pinski 2008-02-23 05:27:11 UTC
*** Bug 35308 has been marked as a duplicate of this bug. ***
Comment 3 Andrew Pinski 2012-03-03 23:59:23 UTC
Related to PR 32120, actually I think PR 32120 is really asking for strength reduction just it was not called that in the bug report.
Comment 4 Andrew Pinski 2012-03-05 05:30:43 UTC
(In reply to comment #3)
> Related to PR 32120, actually I think PR 32120 is really asking for strength
> reduction just it was not called that in the bug report.

And it needs PR 37242 to fix the (long unsigned int) (i + 1)*4 and (long unsigned int) (i)*4 issue.
Comment 5 Bill Schmidt 2012-06-28 01:27:43 UTC
This specific case is handled by the new strength reduction pass.  Some more complex scenarios will be added later.