]> git.ipfire.org Git - thirdparty/gcc.git/commit
Update loop iteration estimates after splitting
authorJan Hubicka <jh@suse.cz>
Thu, 3 Aug 2023 20:47:55 +0000 (22:47 +0200)
committerJan Hubicka <jh@suse.cz>
Thu, 3 Aug 2023 20:47:55 +0000 (22:47 +0200)
commitd6ac3aae2a32869d9d37f3bc7783d9bbad27d72b
tree1dbc8e4a296ff280d8916550d6219fc6e1b3d077
parent93236ad9e8fa9208e754e8806dc369e1a79dbdf7
Update loop iteration estimates after splitting

Hmmer's internal function has 4 loops.  The following is the profile at start:

  loop 1:
  estimate 472
  iterations by profile: 473.497707 (reliable) count in:84821 (precise, freq 0.9979)

    loop 2:
    estimate 99
    iterations by profile: 100.000000 (reliable) count in:39848881 (precise, freq 468.8104)

    loop 3:
    estimate 99
    iterations by profile: 100.000000 (reliable) count in:39848881 (precise, freq 468.8104)

  loop 4:
  estimate 100
  iterations by profile: 100.999596 (reliable) execution count:84167 (precise, freq 0.9902)

So the first loops is outer loop and second/third loops are nesed. Fourth loop is not critical.
Precise iteraiton counts are unknown (473 and 100 comes from profile)
Nested loop has following form:

    for (k = 1; k <= M; k++) {
      mc[k] = mpp[k-1]   + tpmm[k-1];
      if ((sc = ip[k-1]  + tpim[k-1]) > mc[k])  mc[k] = sc;
      if ((sc = dpp[k-1] + tpdm[k-1]) > mc[k])  mc[k] = sc;
      if ((sc = xmb  + bp[k])         > mc[k])  mc[k] = sc;
      mc[k] += ms[k];
      if (mc[k] < -INFTY) mc[k] = -INFTY;

      dc[k] = dc[k-1] + tpdd[k-1];
      if ((sc = mc[k-1] + tpmd[k-1]) > dc[k]) dc[k] = sc;
      if (dc[k] < -INFTY) dc[k] = -INFTY;

      if (k < M) {
        ic[k] = mpp[k] + tpmi[k];
        if ((sc = ip[k] + tpii[k]) > ic[k]) ic[k] = sc;
        ic[k] += is[k];
        if (ic[k] < -INFTY) ic[k] = -INFTY;
      }

We do quite some belly dancing here.
 1) loop-ch slightly misupdates profile, so the estimates of 99
    does not match profile setimate of 100.
 2) loops-split splits on if (k < M) and produces two loops.
    It fails to notice that the second loop never iterates.
    It used to misupdate profile a lot which later caused internal
    loop to become cold.  This is fixed now.
 3) loop-dist introduces runtime aliasing checks for both loops
 4) tree vectorizer vectorizes some of the copies of the loop produces
    and drops expected iteration counts
 5) loop peeling peels the loops with expected low iteration counts
 6) complete loop unrolling kills some loops in prologues/epilogues.

We end up with quite many loops and run out of registers:

  iterations by profile: 5.312499 (unreliable, maybe flat)
    this is vectorized internal loops after loop peeling

  iterations by profile: 0.009495 (unreliable, maybe flat)
  iterations by profile: 0.009495 (unreliable, maybe flat)
  iterations by profile: 0.009495 (unreliable, maybe flat)
  iterations by profile: 0.009495 (unreliable, maybe flat)
    Those are all versioned/peeled and vectorized variants of the loop never looping

  iterations by profile: 100.000008 (unreliable)
  iterations by profile: 100.000000 (unreliable)
    Those are variants with failed aliasing checks

  iterations by profile: 9.662853 (unreliable, maybe flat)
  iterations by profile: 4.646072 (unreliable)
  iterations by profile: 100.000007 (unreliable)
  iterations by profile: 5.312500 (unreliable)
  iterations by profile: 473.497707 (reliable)
    This is loop 1

  iterations by profile: 100.999596 (reliable)
    This is the loop 4.

This patch fixes loop iteration estimate update after loop split so we get:

  iterations by profile: 5.312499 (unreliable, maybe flat) entry count:12742188 (guessed, freq 149.9081)
    This is remainder of the peeled vectorized loop 2.  It misses estimate that is correct since after peeling it 6 times it is essentially
    impossible to tell what the remaining loop profile is (without histograms)

  iterations by profile: 0.009496 (unreliable, maybe flat) entry count:374801 (guessed, freq 4.4094)
    Peeled split part of loop 2 (one that never loops).  We ought to work this out
    but at least w

  estimate 99
  iterations by profile: 100.000008 (unreliable) entry count:3945039 (guessed, freq 46.4122)
  estimate 99
  iterations by profile: 100.000000 (unreliable) entry count:35505353 (guessed, freq 417.7100)

  estimate 99
  iterations by profile: 9.662853 (unreliable, maybe flat) entry count:35505353 (guessed, freq 417.7100)
    Profile here mismatches estimate - I will need to work out why.

  estimate 5
  iterations by profile: 4.646072 (unreliable) entry count:31954818 (guessed, freq 375.9390)
    This is vectorized but not peeled loop 3
  estimate 99
  iterations by profile: 100.000007 (unreliable) entry count:7101070 (guessed, freq 83.5420)
    Unvectorized variant of loop 3
  estimate 5
  iterations by profile: 5.312500 (unreliable) entry count:25563855 (guessed, freq 300.7512)
    Another vectorized variant of loop 3
  estimate 472
  iterations by profile: 473.497707 (reliable) entry count:84821 (precise, freq 0.9979)
    Outer loop

  estimate 100
  iterations by profile: 100.999596 (reliable) entry count:84167 (precise, freq 0.9902)
    loop 4, not vectorized/peeled

So there is still work to do on this testcase, but with the patch we prevent 3 useless loops.

Bootstrapped/regtested x86_64-linux, plan to commit it later today.

gcc/ChangeLog:

* tree-ssa-loop-split.cc (split_loop): Update estimated iteration counts.
gcc/tree-ssa-loop-split.cc