http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54154

             Bug #: 54154
           Summary: cprop_hardreg generates redundant instructions
    Classification: Unclassified
           Product: gcc
           Version: 4.6.3
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: paulo.ma...@csr.com


Created attachment 27922
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=27922
Before cprop_hardreg

Hello,

I have touched this subject before:
* http://gcc.gnu.org/ml/gcc/2010-08/msg00347.html
* http://gcc.gnu.org/ml/gcc/2011-03/msg00214.html

and it looks like a long standing issue so I am wary of reporting a bug but I
think I did find the culprit code. So, unless you consider this a feature
somehow I reckon it's a bug.

cprop_hardreg grabs an insn chain and through forward propagation of registers
ends up generating redundant passes where the src and dest are the same (same
regnumber, same mode).

Consider the program (obtained using creduce):
int a;
int fn1 ();
void fn2 ();
int fn3 ();
int
fn4 ()
{
    if (fn1 ())
        return 0;
    a = fn3 ();
    if (a != (1 << (32 - (9 + 9))) - 1)
        fn2 (0, a);
    return (1 << (32 - (9 + 9))) - 1;
}

Now, after compiling for my backend with -Os I get before cprop_hardreg (after
ce3) [real logs attached]:

#8     reg AL <- call fn1
#50/51 if_then_else AL != 0
         goto label 34

#12    AL <- call fn3
#13    AH <- AL
#14    mem sym a <- AH
#48/49 if_then_else AH == 16383
         goto label 38

#17    AL <- 0
#19    call fn2
#4     AL <- 16383
#43    jump label 20

label 34:
#3     AL <- 0
#45    jump label 20

label 38:
#5     AL <- AH

label 20:
       return

the number after '#' is the insn number.

cprop_hardreg decided to replace AH with AL so the top of cprop_hardreg shows:
rescanning insn with uid = 14.
deleting insn with uid = 14.
insn 14: replaced reg 0 with 1
insn 48: replaced reg 0 with 1
rescanning insn with uid = 48.
deleting insn with uid = 48.
rescanning insn with uid = 5.
deleting insn with uid = 5.
insn 5: replaced reg 0 with 1

reg 0 is AH and reg 1 is AL. 
When you replace in insn 5, AH by AL you get the insn AL <- AL and that's #5
after cprop_hardreg.

I find it strange that there's no code checking if set dest is equal to
replacement and if it is, simply remove insn.

I think this is a bug and should be fixed.

Reply via email to