This is an archive of the discontinued LLVM Phabricator instance.

[PGO] Value profile support for value ranges
ClosedPublic

Authored by xur on Jan 20 2017, 1:21 PM.

Details

Summary

This patch adds profile run time support to profile a range of values.

It has two adjustable parameters: SmallVal and LargeVal size less than or equal to SmallVal will be precisely profiled. size greater than SmallVal but less than LargeVal will have one count size greater than or equal to LargeVale will have one count. These parameters are passed from compiler.

This interface is going to used in profiling the size of memory intrinsic calls.

Diff Detail

Repository
rL LLVM

Event Timeline

xur created this revision.Jan 20 2017, 1:21 PM
davidxl edited edge metadata.Jan 23 2017, 10:22 AM

A general comment.

The range profiling should not be limited to just memory intrinsics. It should be designed to be a more general interval profiler. Interval profiler is also useful for other value profiling transformations such as mod operation for integer values (x%y). The value profiler can do interval profiling for division x/y and track resulting values in interval [0, 1].

In a more general form, an interval profiler API should specify the following things

  1. counter index
  2. interval start and end (inclusive) : [S, E]
  3. optionally specify the start value of a large value range [SL, inf)

3 + (E-S+1) values will be tracked:
(-inf, S) one value
[S,E] one for each in the range
[E, SL) one value
[SL, inf) for one.

The client (instrumentor) decides the the interval boundaries depending on the value profile kind.

In fact, I don't there is a need for compiler_rt change at all for the interval/range profiling. The compiler_rt API should be kept simple. In other words, interval profiling should already be 'lowered' into regular value profiling in the instrumentation lowering phase. The instrumentation lowering will general inline sequence that collapse ranges into single value depending on the value profile kind. Only the __llvm_profile_instrument_target low level interface is needed.

The only downside of this approach that we can not override the range definitions at runtime -- but I don't think that is worth the complexity introduced.

xur updated this revision to Diff 85664.Jan 24 2017, 5:16 PM

changed the patch based on David's review comments:
(1) reuse __llvm_profile_instrument_target as much as possible and make the new function a wrapper.
(3) use parameter rather global variables.
(2) supported signed type.

changes in InstrProfData.inc is mostly to sync with the compiler.

The raw profile format version needs to change too.

lib/profile/InstrProfData.inc
156 ↗(On Diff #85664)

remove this line

158 ↗(On Diff #85664)

change this line to

#ifdef VALUE_RANGE_PROF

lib/profile/InstrProfilingValue.c
223 ↗(On Diff #85664)

Describe it more clearly to cover information such as: the target values are partitioned into multiple regions/ranges. There is one contiguous region which is precise -- every value in the range is tracked individually. A value outside the precise region will be collapsed into one value depending on the region it falls in.

228 ↗(On Diff #85664)

There are three regions:

  1. (-inf, StartVal) and (PreciseLast, LargeValue) belong to one region -- all values here should be mapped to one value
  2. [PreciseStart, PreciseLast]
  3. Large values: [LargeValue, +inf) maps to one value.
231 ↗(On Diff #85664)

for range/interval profiling, it is simpler to make target value Int64 type. With this, we can get rid of SignedType parameter. LargeTargetValue is also optional. The default value of MIN_INT64 indicates it is not specified.

233 ↗(On Diff #85664)

StartValue --> PreciseRangeStart

234 ↗(On Diff #85664)

PreciseRangeLast

xur updated this revision to Diff 85960.Jan 26 2017, 1:25 PM
xur marked an inline comment as done.

Integrated David's review comments.

xur added a comment.Jan 27 2017, 11:26 AM

It seems I have to fall back the latest change in InstrProfData.inc. We have to use #else clause "VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx))" because one of the version need to append INSTR_PROF_COMMA.

xur updated this revision to Diff 86087.Jan 27 2017, 11:31 AM

drop the recent change in InstrProfData.inc

vsk edited edge metadata.Jan 27 2017, 4:13 PM

Could you add periods where appropriate in your patch description? It's a little hard to parse it as-is.

Also, this is missing a test. You can add one without the llvm changes, see e.g test/profile/instrprof-value-prof*.

Finally, what's the raw profile change that's needed?

lib/profile/InstrProfilingValue.c
244 ↗(On Diff #86087)

Please clang-format this function body.

251 ↗(On Diff #86087)

IIUC we get precise counts if TargetValue is in [PreciseRangeStart, PreciseRangeLast], or if LargeValue == INT64_MIN. If so, that doesn't seem quite right, because I thought you only wanted precise counts for in-range values.

xur marked an inline comment as done.Jan 30 2017, 4:21 PM

One reply to vsk's comment in inlined.

I'll add a test per vsk's suggestion. Patch description will also be updated when I upload the new patch.

lib/profile/InstrProfilingValue.c
251 ↗(On Diff #86087)

I don't see a problem here: if LargeValue is INT64_MIN, we will go the second if in the else branch -- this collapse the out of range values.

xur added a comment.Jan 30 2017, 4:41 PM

To vsk: if seems hard to add a test without the compiler part of change. We can add the calls to __llvm_profile_instrument_range(). But to check the result, we need llvm-profdata to dump the counters.

How about I added the test in projects/compiler-rt/test/profile after committing the compiler change?

xur updated this revision to Diff 86367.Jan 30 2017, 4:47 PM

Integrated part of vsk's review comments.

Updated description:

This patch adds profile run time support to profile a range of values.

The target values are partitioned into multiple regions/ranges. There is one
contiguous region which is precise -- every value in the range is tracked
individually. A value outside the precise region will be collapsed into one
value depending on the region it falls in.

There are three regions:

  1. (-inf, PreciseRangeStart) and (PreciseRangeLast, LargeRangeValue) belong to one region -- all values here should be mapped to one value of "PreciseRangeLast + 1".
  2. [PreciseRangeStart, PreciseRangeLast]
  3. Large values: [LargeValue, +inf) maps to one value of LargeValue.

The range for large values is optional. The default value of MIN_INT64 indicates it is not specified.

This interface is going to be used in profiling the size of memory intrinsic calls.

vsk added a comment.Jan 30 2017, 4:54 PM
In D28964#661149, @xur wrote:

To vsk: if seems hard to add a test without the compiler part of change. We can add the calls to __llvm_profile_instrument_range(). But to check the result, we need llvm-profdata to dump the counters.

How about I added the test in projects/compiler-rt/test/profile after committing the compiler change?

Makes sense to me.

lib/profile/InstrProfilingValue.c
251 ↗(On Diff #86087)

Ah, right, sorry about that

This revision is now accepted and ready to land.Mar 15 2017, 12:44 PM
This revision was automatically updated to reflect the committed changes.