Skip to content
  1. Dec 22, 2011
  2. Dec 21, 2011
  3. Dec 07, 2011
  4. Nov 27, 2011
    • Chandler Carruth's avatar
      Prevent rotating the blocks of a loop (and thus getting a backedge to be · 4f567207
      Chandler Carruth authored
      fallthrough) in cases where we might fail to rotate an exit to an outer
      loop onto the end of the loop chain.
      
      Having *some* rotation, but not performing this rotation, is the primary
      fix of thep performance regression with -enable-block-placement for
      Olden/em3d (a whopping 30% regression). Still working on reducing the
      test case that actually exercises this and the new rotation strategy out
      of this code, but I want to check if this regresses other test cases
      first as that may indicate it isn't the correct fix.
      
      llvm-svn: 145195
      4f567207
    • Chandler Carruth's avatar
      Take two on rotating the block ordering of loops. My previous attempt · 03adbd46
      Chandler Carruth authored
      was centered around the premise of laying out a loop in a chain, and
      then rotating that chain. This is good for preserving contiguous layout,
      but bad for actually making sane rotations. In order to keep it safe,
      I had to essentially make it impossible to rotate deeply nested loops.
      The information needed to correctly reason about a deeply nested loop is
      actually available -- *before* we layout the loop. We know the inner
      loops are already fused into chains, etc. We lose information the moment
      we actually lay out the loop.
      
      The solution was the other alternative for this algorithm I discussed
      with Benjamin and some others: rather than rotating the loop
      after-the-fact, try to pick a profitable starting block for the loop's
      layout, and then use our existing layout logic. I was worried about the
      complexity of this "pick" step, but it turns out such complexity is
      needed to handle all the important cases I keep teasing out of benchmarks.
      
      This is, I'm afraid, a bit of a work-in-progress. It is still
      misbehaving on some likely important cases I'm investigating in Olden.
      It also isn't really tested. I'm going to try to craft some interesting
      nested-loop test cases, but it's likely to be extremely time consuming
      and I don't want to go there until I'm sure I'm testing the correct
      behavior. Sadly I can't come up with a way of getting simple, fine
      grained test cases for this logic. We need complex loop structures to
      even trigger much of it.
      
      llvm-svn: 145183
      03adbd46
    • Chandler Carruth's avatar
      Fix an impressive type-o / spell-o Duncan noticed. · 9e466841
      Chandler Carruth authored
      llvm-svn: 145181
      9e466841
    • Chandler Carruth's avatar
      Rework a bit of the implementation of loop block rotation to not rely so · a0545809
      Chandler Carruth authored
      heavily on AnalyzeBranch. That routine doesn't behave as we want given
      that rotation occurs mid-way through re-ordering the function. Instead
      merely check that there are not unanalyzable branching constructs
      present, and then reason about the CFG via successor lists. This
      actually simplifies my mental model for all of this as well.
      
      The concrete result is that we now will rotate more loop chains. I've
      added a test case from Olden highlighting the effect. There is still
      a bit more to do here though in order to regain all of the performance
      in Olden.
      
      llvm-svn: 145179
      a0545809
    • Chandler Carruth's avatar
      Introduce a loop block rotation optimization to the new block placement · 9ffb97e6
      Chandler Carruth authored
      pass. This is designed to achieve one of the important optimizations
      that the old code placement pass did, but more simply.
      
      This is a somewhat rough and *very* conservative version of the
      transform. We could get a lot fancier here if there are profitable cases
      to do so. In particular, this only looks for a single pattern, it
      insists that the loop backedge being rotated away is the last backedge
      in the chain, and it doesn't provide any means of doing better in-loop
      placement due to the rotation. However, it appears that it will handle
      the important loops I am finding in the LLVM test suite.
      
      llvm-svn: 145158
      9ffb97e6
  5. Nov 24, 2011
    • Chandler Carruth's avatar
      Fix a silly use-after-free issue. A much earlier version of this code · 7adee1a0
      Chandler Carruth authored
      need lots of fanciness around retaining a reference to a Chain's slot in
      the BlockToChain map, but that's all gone now. We can just go directly
      to allocating the new chain (which will update the mapping for us) and
      using it.
      
      Somewhat gross mechanically generated test case replicates the issue
      Duncan spotted when actually testing this out.
      
      llvm-svn: 145120
      7adee1a0
    • Chandler Carruth's avatar
      When adding blocks to the list of those which no longer have any CFG · d394bafd
      Chandler Carruth authored
      conflicts, we should only be adding the first block of the chain to the
      list, lest we try to merge into the middle of that chain. Most of the
      places we were doing this we already happened to be looking at the first
      block, but there is no reason to assume that, and in some cases it was
      clearly wrong.
      
      I've added a couple of tests here. One already worked, but I like having
      an explicit test for it. The other is reduced from a test case Duncan
      reduced for me and used to crash. Now it is handled correctly.
      
      llvm-svn: 145119
      d394bafd
  6. Nov 23, 2011
    • Chandler Carruth's avatar
      Relax an invariant that block placement was trying to assert a bit · 99fe42fb
      Chandler Carruth authored
      further. This invariant just wasn't going to work in the face of
      unanalyzable branches; we need to be resillient to the phenomenon of
      chains poking into a loop and poking out of a loop. In fact, we already
      were, we just needed to not assert on it.
      
      This was found during a bootstrap with block placement turned on.
      
      llvm-svn: 145100
      99fe42fb
    • Chandler Carruth's avatar
      Fix a crash in block placement due to an inner loop that happened to be · 4a87aa0c
      Chandler Carruth authored
      reversed in the function's original ordering, and we happened to
      encounter it while handling an outer unnatural CFG structure.
      
      Thanks to the test case reduced from GCC's source by Benjamin Kramer.
      This may also fix a crasher in gzip that Duncan reduced for me, but
      I haven't yet gotten to testing that one.
      
      llvm-svn: 145094
      4a87aa0c
  7. Nov 20, 2011
    • Chandler Carruth's avatar
      The logic for breaking the CFG in the presence of hot successors didn't · 18dfac38
      Chandler Carruth authored
      properly account for the *global* probability of the edge being taken.
      This manifested as a very large number of unconditional branches to
      blocks being merged against the CFG even though they weren't
      particularly hot within the CFG.
      
      The fix is to check whether the edge being merged is both locally hot
      relative to other successors for the source block, and globally hot
      compared to other (unmerged) predecessors of the destination block.
      
      This introduces a new crasher on GCC single-source, but it's currently
      behind a flag, and Ben has offered to work on the reduction. =]
      
      llvm-svn: 145010
      18dfac38
  8. Nov 19, 2011
    • Chandler Carruth's avatar
      Move the handling of unanalyzable branches out of the loop-driven chain · f3dc9eff
      Chandler Carruth authored
      formation phase and into the initial walk of the basic blocks. We
      essentially pre-merge all blocks where unanalyzable fallthrough exists,
      as we won't be able to update the terminators effectively after any
      reorderings. This is quite a bit more principled as there may be CFGs
      where the second half of the unanalyzable pair has some analyzable
      predecessor that gets placed first. Then it may get placed next,
      implicitly breaking the unanalyzable branch even though we never even
      looked at the part that isn't analyzable. I've included a test case that
      triggers this (thanks Benjamin yet again!), and I'm hoping to synthesize
      some more general ones as I dig into related issues.
      
      Also, to make this new scheme work we have to be able to handle branches
      into the middle of a chain, so add this check. We always fallback on the
      incoming ordering.
      
      Finally, this starts to really underscore a known limitation of the
      current implementation -- we don't consider broken predecessors when
      merging successors. This can caused major missed opportunities, and is
      something I'm planning on looking at next (modulo more bug reports).
      
      llvm-svn: 144994
      f3dc9eff
  9. Nov 15, 2011
    • Chandler Carruth's avatar
      Rather than trying to use the loop block sequence *or* the function · 9b548a7f
      Chandler Carruth authored
      block sequence when recovering from unanalyzable control flow
      constructs, *always* use the function sequence. I'm not sure why I ever
      went down the path of trying to use the loop sequence, it is
      fundamentally not the correct sequence to use. We're trying to preserve
      the incoming layout in the cases of unreasonable control flow, and that
      is only encoded at the function level. We already have a filter to
      select *exactly* the sub-set of blocks within the function that we're
      trying to form into a chain.
      
      The resulting code layout is also significantly better because of this.
      In several places we were ending up with completely unreasonable control
      flow constructs due to the ordering chosen by the loop structure for its
      internal storage. This change removes a completely wasteful vector of
      basic blocks, saving memory allocation in the common case even though it
      costs us CPU in the fairly rare case of unnatural loops. Finally, it
      fixes the latest crasher reduced out of GCC's single source. Thanks
      again to Benjamin Kramer for the reduction, my bugpoint skills failed at
      it.
      
      llvm-svn: 144627
      9b548a7f
  10. Nov 14, 2011
    • Chandler Carruth's avatar
      It helps to deallocate memory as well as allocate it. =] This actually · fd9b4d98
      Chandler Carruth authored
      cleans up all the chains allocated during the processing of each
      function so that for very large inputs we don't just grow memory usage
      without bound.
      
      llvm-svn: 144533
      fd9b4d98
    • Chandler Carruth's avatar
      Remove an over-eager assert that was firing on one of the ARM regression · 0a31d149
      Chandler Carruth authored
      tests when I forcibly enabled block placement.
      
      It is apparantly possible for an unanalyzable block to fallthrough to
      a non-loop block. I don't actually beleive this is correct, I believe
      that 'canFallThrough' is returning true needlessly for the code
      construct, and I've left a bit of a FIXME on the verification code to
      try to track down why this is coming up.
      
      Anyways, removing the assert doesn't degrade the correctness of the algorithm.
      
      llvm-svn: 144532
      0a31d149
    • Chandler Carruth's avatar
      Begin chipping away at one of the biggest quadratic-ish behaviors in · 0af6a0bb
      Chandler Carruth authored
      this pass. We're leaving already merged blocks on the worklist, and
      scanning them again and again only to determine each time through that
      indeed they aren't viable. We can instead remove them once we're going
      to have to scan the worklist. This is the easy way to implement removing
      them. If this remains on the profile (as I somewhat suspect it will), we
      can get a lot more clever here, as the worklist's order is essentially
      irrelevant. We can use swapping and fold the two loops to reduce
      overhead even when there are many blocks on the worklist but only a few
      of them are removed.
      
      llvm-svn: 144531
      0af6a0bb
    • Chandler Carruth's avatar
      Under the hood, MBPI is doing a linear scan of every successor every · 84cd44c7
      Chandler Carruth authored
      time it is queried to compute the probability of a single successor.
      This makes computing the probability of every successor of a block in
      sequence... really really slow. ;] This switches to a linear walk of the
      successors rather than a quadratic one. One of several quadratic
      behaviors slowing this pass down.
      
      I'm not really thrilled with moving the sum code into the public
      interface of MBPI, but I don't (at the moment) have ideas for a better
      interface. My direction I'm thinking in for a better interface is to
      have MBPI actually retain much more state and make *all* of these
      queries cheap. That's a lot of work, and would require invasive changes.
      Until then, this seems like the least bad (ie, least quadratic)
      solution. Suggestions welcome.
      
      llvm-svn: 144530
      84cd44c7
    • Chandler Carruth's avatar
      Teach machine block placement to cope with unnatural loops. These don't · 1071cfa4
      Chandler Carruth authored
      get loop info structures associated with them, and so we need some way
      to make forward progress selecting and placing basic blocks. The
      technique used here is pretty brutal -- it just scans the list of blocks
      looking for the first unplaced candidate. It keeps placing blocks like
      this until the CFG becomes tractable.
      
      The cost is somewhat unfortunate, it requires allocating a vector of all
      basic block pointers eagerly. I have some ideas about how to simplify
      and optimize this, but I'm trying to get the logic correct first.
      
      Thanks to Benjamin Kramer for the reduced test case out of GCC. Sadly
      there are other bugs that GCC is tickling that I'm reducing and working
      on now.
      
      llvm-svn: 144516
      1071cfa4
  11. Nov 13, 2011
    • Chandler Carruth's avatar
      Cleanup some 80-columns violations and poor formatting. These snuck by · c4a2cb34
      Chandler Carruth authored
      when I was reading through the code for style.
      
      llvm-svn: 144513
      c4a2cb34
    • Chandler Carruth's avatar
      Enhance the assertion mechanisms in place to make it easier to catch · 8e1d9067
      Chandler Carruth authored
      when we fail to place all the blocks of a loop. Currently this is
      happening for unnatural loops, and this logic helps more immediately
      point to the problem.
      
      llvm-svn: 144504
      8e1d9067
    • Chandler Carruth's avatar
      Teach MBP to force-merge layout successors for blocks with unanalyzable · 0bb42c0f
      Chandler Carruth authored
      branches that also may involve fallthrough. In the case of blocks with
      no fallthrough, we can still re-order the blocks profitably. For example
      instruction decoding will in some cases continue past an indirect jump,
      making laying out its most likely successor there profitable.
      
      Note, no test case. I don't know how to write a test case that exercises
      this logic, but it matches the described desired semantics in
      discussions with Jakob and others. If anyone has a nice example of IR
      that will trigger this, that would be lovely.
      
      Also note, there are still assertion failures in real world code with
      this. I'm digging into those next, now that I know this isn't the cause.
      
      llvm-svn: 144499
      0bb42c0f
    • Chandler Carruth's avatar
      Hoist another gross nested loop into a helper method. · f9213fe7
      Chandler Carruth authored
      llvm-svn: 144498
      f9213fe7
    • Chandler Carruth's avatar
      Add a missing doxygen comment for a helper method. · eb4ec3ae
      Chandler Carruth authored
      llvm-svn: 144497
      eb4ec3ae
    • Chandler Carruth's avatar
      Hoist a nested loop into its own method. · b336172f
      Chandler Carruth authored
      llvm-svn: 144496
      b336172f
    • Chandler Carruth's avatar
      Rewrite #3 of machine block placement. This is based somewhat on the · 8d150789
      Chandler Carruth authored
      second algorithm, but only loosely. It is more heavily based on the last
      discussion I had with Andy. It continues to walk from the inner-most
      loop outward, but there is a key difference. With this algorithm we
      ensure that as we visit each loop, the entire loop is merged into
      a single chain. At the end, the entire function is treated as a "loop",
      and merged into a single chain. This chain forms the desired sequence of
      blocks within the function. Switching to a single algorithm removes my
      biggest problem with the previous approaches -- they had different
      behavior depending on which system triggered the layout. Now there is
      exactly one algorithm and one basis for the decision making.
      
      The other key difference is how the chain is formed. This is based
      heavily on the idea Andy mentioned of keeping a worklist of blocks that
      are viable layout successors based on the CFG. Having this set allows us
      to consistently select the best layout successor for each block. It is
      expensive though.
      
      The code here remains very rough. There is a lot that needs to be done
      to clean up the code, and to make the runtime cost of this pass much
      lower. Very much WIP, but this was a giant chunk of code and I'd rather
      folks see it sooner than later. Everything remains behind a flag of
      course.
      
      I've added a couple of tests to exercise the issues that this iteration
      was motivated by: loop structure preservation. I've also fixed one test
      that was exhibiting the broken behavior of the previous version.
      
      llvm-svn: 144495
      8d150789
  12. Nov 02, 2011
    • Chandler Carruth's avatar
      Begin collecting some of the statistics for block placement discussed on · ae4e800c
      Chandler Carruth authored
      the mailing list. Suggestions for other statistics to collect would be
      awesome. =]
      
      Currently these are implemented as a separate pass guarded by a separate
      flag. I'm not thrilled by that, but I wanted to be able to collect the
      statistics for the old code placement as well as the new in order to
      have a point of comparison. I'm planning on folding them into the single
      pass if / when there is only one pass of interest.
      
      llvm-svn: 143537
      ae4e800c
  13. Oct 24, 2011
  14. Oct 23, 2011
    • Chandler Carruth's avatar
      Now that we have comparison on probabilities, add some static functions · fd7475e9
      Chandler Carruth authored
      to get important constant branch probabilities and use them for finding
      the best branch out of a set of possibilities.
      
      llvm-svn: 142762
      fd7475e9
    • Chandler Carruth's avatar
      Remove a commented out line of code that snuck by my auditing. · 446210b6
      Chandler Carruth authored
      llvm-svn: 142761
      446210b6
    • Chandler Carruth's avatar
      Completely re-write the algorithm behind MachineBlockPlacement based on · bd1be4d0
      Chandler Carruth authored
      discussions with Andy. Fundamentally, the previous algorithm is both
      counter productive on several fronts and prioritizing things which
      aren't necessarily the most important: static branch prediction.
      
      The new algorithm uses the existing loop CFG structure information to
      walk through the CFG itself to layout blocks. It coalesces adjacent
      blocks within the loop where the CFG allows based on the most likely
      path taken. Finally, it topologically orders the block chains that have
      been formed. This allows it to choose a (mostly) topologically valid
      ordering which still priorizes fallthrough within the structural
      constraints.
      
      As a final twist in the algorithm, it does violate the CFG when it
      discovers a "hot" edge, that is an edge that is more than 4x hotter than
      the competing edges in the CFG. These are forcibly merged into
      a fallthrough chain.
      
      Future transformations that need te be added are rotation of loop exit
      conditions to be fallthrough, and better isolation of cold block chains.
      I'm also planning on adding statistics to model how well the algorithm
      does at laying out blocks based on the probabilities it receives.
      
      The old tests mostly still pass, and I have some new tests to add, but
      the nested loops are still behaving very strangely. This almost seems
      like working-as-intended as it rotated the exit branch to be
      fallthrough, but I'm not convinced this is actually the best layout. It
      is well supported by the probabilities for loops we currently get, but
      those are pretty broken for nested loops, so this may change later.
      
      llvm-svn: 142743
      bd1be4d0
  15. Oct 21, 2011
    • Chandler Carruth's avatar
      Add loop aligning to MachineBlockPlacement based on review discussion so · 8b9737cb
      Chandler Carruth authored
      it's a bit more plausible to use this instead of CodePlacementOpt. The
      code for this was shamelessly stolen from CodePlacementOpt, and then
      trimmed down a bit. There doesn't seem to be much utility in returning
      true/false from this pass as we may or may not have rewritten all of the
      blocks. Also, the statistic of counting how many loops were aligned
      doesn't seem terribly important so I removed it. If folks would like it
      to be included, I'm happy to add it back.
      
      This was probably the most egregious of the missing features, and now
      I'm going to start gathering some performance numbers and looking at
      specific loop structures that have different layout between the two.
      
      Test is updated to include both basic loop alignment and nested loop
      alignment.
      
      llvm-svn: 142645
      8b9737cb
    • Chandler Carruth's avatar
      Implement a block placement pass based on the branch probability and · 10281425
      Chandler Carruth authored
      block frequency analyses. This differs substantially from the existing
      block-placement pass in LLVM:
      
      1) It operates on the Machine-IR in the CodeGen layer. This exposes much
         more (and more precise) information and opportunities. Also, the
         results are more stable due to fewer transforms ocurring after the
         pass runs.
      2) It uses the generalized probability and frequency analyses. These can
         model static heuristics, code annotation derived heuristics as well
         as eventual profile loading. By basing the optimization on the
         analysis interface it can work from any (or a combination) of these
         inputs.
      3) It uses a more aggressive algorithm, both building chains from tho
         bottom up to maximize benefit, and using an SCC-based walk to layout
         chains of blocks in a profitable ordering without O(N^2) iterations
         which the old pass involves.
      
      The pass is currently gated behind a flag, and not enabled by default
      because it still needs to grow some important features. Most notably, it
      needs to support loop aligning and careful layout of loop structures
      much as done by hand currently in CodePlacementOpt. Once it supports
      these, and has sufficient testing and quality tuning, it should replace
      both of these passes.
      
      Thanks to Nick Lewycky and Richard Smith for help authoring & debugging
      this, and to Jakob, Andy, Eric, Jim, and probably a few others I'm
      forgetting for reviewing and answering all my questions. Writing
      a backend pass is *sooo* much better now than it used to be. =D
      
      llvm-svn: 142641
      10281425
Loading