Following is a simple example:

#include <stdio.h>
void foo (char*, FILE*);
char* hprofStartupp(char *outputFileName, char *ctx)
{
    char fileName[1000];
    FILE *fp;
    sprintf(fileName, outputFileName);
    if (access(fileName, 1) == 0) {
        free(ctx);               //A
        return 0;                //A
    }

    fp = fopen(fileName, 0);
    if (fp == 0) {
        free(ctx);               //B
        return 0;                //B
    }

    foo(outputFileName, fp);

    return ctx;
}

Basic block A and basic block B are exact same. They do some cleanup work and
exit the function. This pattern is quite common in large software. GCC failed
to merge them in this test case. With options -march=armv7-a -mthumb -Os, gcc
generates:

        ...
        bl      access
        mov     r7, r0
        cbnz    r0, .L2
        mov     r0, r4    //C
        mov     r4, r7    //C
        bl      free      //C
        b       .L3       //C
.L2:
        mov     r0, sp
        movs    r1, #0
        bl      fopen
        mov     r5, r0
        cbnz    r0, .L4
        mov     r0, r4    //D
        mov     r4, r5    //D
        bl      free      //D
        b       .L3       //D
.L4:
        ...

Here basic block C corresponds to basic block A, and basic block D corresponds
basic block B. They can be merged as following:

        ...
        bl      access
        mov     r5, r0
        cbz     r0, .L9
.L2:
        mov     r0, sp
        movs    r1, #0
        bl      fopen
        mov     r5, r0
        cbnz    r0, .L4
.L9:
        mov     r0, r4    
        mov     r4, r5   
        bl      free     
        b       .L3      
.L4:
        ...

The rtl cfg optimization can do some merge optimization. But it often fails due
to difference of register numbers. We may need to do this at tree level.


-- 
           Summary: Same basic blocks should be merged
           Product: gcc
           Version: 4.6.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: carrot at google dot com
 GCC build triplet: i686-linux
  GCC host triplet: i686-linux
GCC target triplet: arm-eabi


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

Reply via email to