RFC: Profiling Enhancements (GSoC)

Hi all,

In light of the expected removal of ProfileInfo this is a request for comments on the next few items that I now plan to work on for GSoC.

Planned tasks:

#0 Add support for determining branch weight metadata by profiling

At the absolute minimum this will require writing a new profile loader which will set branch weight metadata based on profiling data.

#1 Optionally use profiling support to heuristics within:
        * Loop unrolling
        * Loop unswitching
        * Inliner

The existing BranchProbabilityInfo, and BlockFrequencyInfo are not used in Transforms/*/* at all, just in CodeGen/*. Is there a reason for this, or is it quite possible to use them in Transforms/*/* passes? The original plan was to test these using ProfileEstimator, now the static heuristics within BranchProbability could be used instead until branch weight metadata is successfully maintained through CFG altering passes.

#2 Make the profiler more JIT friendly

The ProfileInfo based profiling support is not very friendly towards PGO within a JIT context. The main issue is that profiling data must go via the filing system. This will be addressed by providing a new libprofile_rt.so runtime library for JITs to use. This is planned to be demonstrated and documented by adding an extra chapter to the Kaleidoscope tutorial. (There is also an issue of profiling a single function rather than a whole program.)

(For the record, there are also future plans to work on #3 profiling the targets of indirect function calls (highly likely) and #4 path profiling (not nearly as likely), but as it is not yet clear when these will be worked on I'll seek comment on these at a future date.)

Regards,
Alastair.

Hi Alastair,

In addition to your planned tasks, you might want to put in some work to ensure branch probabilities are not lost during optimization. One known issue is LLVM optimizer can turn branchy code into switch statements and it would completely discard probability. Here is a simple example:

static void func2(int N, const int *a, const int *b, int *c) __attribute__((always_inline));
void func4(int N, const int *a, const int *b, int *c) __attribute__((noinline));
void func8(int N, const int *a, const int *b, int *c) __attribute__((noinline));

void func2(int N, const int *a, const int *b, int *c) { *c = 2 + *a + *b; }
void func4(int N, const int *a, const int *b, int *c) { *c = 4 + *a + *b; }
void func8(int N, const int *a, const int *b, int *c) { *c = 8 + *a + *b; }

extern void func(int N, const int *a, const int *b, int *c)
{
  if ( __builtin_expect(N==2, 1) )
    func2(N, a, b, c);
  else if ( __builtin_expect(N==4, 0) )
    func4(N, a, b,c);
   else
     func8(N, a, b,c );
}

Thanks,

Evan

Hi Evan,

In addition to your planned tasks, you might want to put in some work
to ensure branch probabilities are not lost during optimization. One
known issue is LLVM optimizer can turn branchy code into switch
statements and it would completely discard probability.

Yes, I should of mentioned this in my email. It was mentioned in the other thread that this was always part of my plan, but probably post-GSoC.

Preserving branch metadata, however, seems easier than preserving ProfileInfo, so I may be able to get started on this sooner. I've only just started looking at how to this though.

Here is a simple example: <snip>

Thank you, I'll have a look at where the information becomes inaccurate for this example, and probably write quite a few more!

Regards,
Alastair.