Skip to content
  1. Aug 07, 2012
  2. Apr 16, 2012
    • Chandler Carruth's avatar
      Flip the new block-placement pass to be on by default. · 4190b507
      Chandler Carruth authored
      This is mostly to test the waters. I'd like to get results from FNT
      build bots and other bots running on non-x86 platforms.
      
      This feature has been pretty heavily tested over the last few months by
      me, and it fixes several of the execution time regressions caused by the
      inlining work by preventing inlining decisions from radically impacting
      block layout.
      
      I've seen very large improvements in yacr2 and ackermann benchmarks,
      along with the expected noise across all of the benchmark suite whenever
      code layout changes. I've analyzed all of the regressions and fixed
      them, or found them to be impossible to fix. See my email to llvmdev for
      more details.
      
      I'd like for this to be in 3.1 as it complements the inliner changes,
      but if any failures are showing up or anyone has concerns, it is just
      a flag flip and so can be easily turned off.
      
      I'm switching it on tonight to try and get at least one run through
      various folks' performance suites in case SPEC or something else has
      serious issues with it. I'll watch bots and revert if anything shows up.
      
      llvm-svn: 154816
      4190b507
    • Chandler Carruth's avatar
      Add a somewhat hacky heuristic to do something different from whole-loop · 8c0b41d6
      Chandler Carruth authored
      rotation. When there is a loop backedge which is an unconditional
      branch, we will end up with a branch somewhere no matter what. Try
      placing this backedge in a fallthrough position above the loop header as
      that will definitely remove at least one branch from the loop iteration,
      where whole loop rotation may not.
      
      I haven't seen any benchmarks where this is important but loop-blocks.ll
      tests for it, and so this will be covered when I flip the default.
      
      llvm-svn: 154812
      8c0b41d6
    • Chandler Carruth's avatar
      Tweak the loop rotation logic to check whether the loop is naturally · 8c74c7b1
      Chandler Carruth authored
      laid out in a form with a fallthrough into the header and a fallthrough
      out of the bottom. In that case, leave the loop alone because any
      rotation will introduce unnecessary branches. If either side looks like
      it will require an explicit branch, then the rotation won't add any, do
      it to ensure the branch occurs outside of the loop (if possible) and
      maximize the benefit of the fallthrough in the bottom.
      
      llvm-svn: 154806
      8c74c7b1
    • Chandler Carruth's avatar
      Rewrite how machine block placement handles loop rotation. · ccc7e42b
      Chandler Carruth authored
      This is a complex change that resulted from a great deal of
      experimentation with several different benchmarks. The one which proved
      the most useful is included as a test case, but I don't know that it
      captures all of the relevant changes, as I didn't have specific
      regression tests for each, they were more the result of reasoning about
      what the old algorithm would possibly do wrong. I'm also failing at the
      moment to craft more targeted regression tests for these changes, if
      anyone has ideas, it would be welcome.
      
      The first big thing broken with the old algorithm is the idea that we
      can take a basic block which has a loop-exiting successor and a looping
      successor and use the looping successor as the layout top in order to
      get that particular block to be the bottom of the loop after layout.
      This happens to work in many cases, but not in all.
      
      The second big thing broken was that we didn't try to select the exit
      which fell into the nearest enclosing loop (to which we exit at all). As
      a consequence, even if the rotation worked perfectly, it would result in
      one of two bad layouts. Either the bottom of the loop would get
      fallthrough, skipping across a nearer enclosing loop and thereby making
      it discontiguous, or it would be forced to take an explicit jump over
      the nearest enclosing loop to earch its successor. The point of the
      rotation is to get fallthrough, so we need it to fallthrough to the
      nearest loop it can.
      
      The fix to the first issue is to actually layout the loop from the loop
      header, and then rotate the loop such that the correct exiting edge can
      be a fallthrough edge. This is actually much easier than I anticipated
      because we can handle all the hard parts of finding a viable rotation
      before we do the layout. We just store that, and then rotate after
      layout is finished. No inner loops get split across the post-rotation
      backedge because we check for them when selecting the rotation.
      
      That fix exposed a latent problem with our exitting block selection --
      we should allow the backedge to point into the middle of some inner-loop
      chain as there is no real penalty to it, the whole point is that it
      *won't* be a fallthrough edge. This may have blocked the rotation at all
      in some cases, I have no idea and no test case as I've never seen it in
      practice, it was just noticed by inspection.
      
      Finally, all of these fixes, and studying the loops they produce,
      highlighted another problem: in rotating loops like this, we sometimes
      fail to align the destination of these backwards jumping edges. Fix this
      by actually walking the backwards edges rather than relying on loopinfo.
      
      This fixes regressions on heapsort if block placement is enabled as well
      as lots of other cases where the previous logic would introduce an
      abundance of unnecessary branches into the execution.
      
      llvm-svn: 154783
      ccc7e42b
  3. Nov 27, 2011
    • 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
      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
    • Chris Lattner's avatar
      Upgrade syntax of tests using volatile instructions to use 'load volatile'... · 6a144a22
      Chris Lattner authored
      Upgrade syntax of tests using volatile instructions to use 'load volatile' instead of 'volatile load', which is archaic.
      
      llvm-svn: 145171
      6a144a22
    • 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
  4. 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
  5. Nov 23, 2011
  6. Nov 22, 2011
    • Chandler Carruth's avatar
      Fix a devilish miscompile exposed by block placement. The · ee54feb6
      Chandler Carruth authored
      updateTerminator code didn't correctly handle EH terminators in one very
      specific case. AnalyzeBranch would find no terminator instruction, and
      so the fallback in updateTerminator is to assume fallthrough. This is
      correct, but the destination of the fallthrough was assumed to be the
      first successor.
      
      This is *almost always* true, but in certain cases the loop
      transformations will cause the landing pad to be the first successor!
      Instead of this brittle logic, actually look through the successors for
      a non-landing-pad accessor, and to assert if more than one is found.
      
      This will hopefully fix some (if not all) of the self host miscompiles
      with block placement. Thanks to Benjamin Kramer for reporting, Nick
      Lewycky for an initial stab at a reduction, and Duncan for endless
      advice on EH (which I know nothing about) as well as reviewing the
      actual fix.
      
      llvm-svn: 145062
      ee54feb6
  7. Nov 20, 2011
    • NAKAMURA Takumi's avatar
      test/CodeGen/X86/block-placement.ll: Relax expressions for Win32. · 76dfa038
      NAKAMURA Takumi authored
      llvm-svn: 145011
      76dfa038
    • 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
    • Chandler Carruth's avatar
      Add some comments to the latest test case I added here to document what · 20df3953
      Chandler Carruth authored
      is actually being tested. Also add some FileCheck goodness to much more
      carefully ensure that the result is the desired result. Before this test
      would only have failed through an assert failure if the underlying fix
      were reverted.
      
      Also, add some weight metadata and a comment explaining exactly what is
      going on to a trick section of the test case. Originally, we were
      getting very unlucky and trying to form a block chain that isn't
      actually profitable. I'm working on a fix to avoid forming these
      unprofitable chains, and that would also have masked any failure from
      this test case. The easy solution is to add some metadata that makes it
      *really* profitable to form the bad chain here.
      
      llvm-svn: 145006
      20df3953
  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
      Fix an overflow bug in MachineBranchProbabilityInfo. This pass relied on · ed5aa547
      Chandler Carruth authored
      the sum of the edge weights not overflowing uint32, and crashed when
      they did. This is generally safe as BranchProbabilityInfo tries to
      provide this guarantee. However, the CFG can get modified during codegen
      in a way that grows the *sum* of the edge weights. This doesn't seem
      unreasonable (imagine just adding more blocks all with the default
      weight of 16), but it is hard to come up with a case that actually
      triggers 32-bit overflow. Fortuately, the single-source GCC build is
      good at this. The solution isn't very pretty, but its no worse than the
      previous code. We're already summing all of the edge weights on each
      query, we can sum them, check for an overflow, compute a scale, and sum
      them again.
      
      I've included a *greatly* reduced test case out of the GCC source that
      triggers it. It's a pretty lame test, as it clearly is just barely
      triggering the overflow. I'd like to have something that is much more
      definitive, but I don't understand the fundamental pattern that triggers
      an explosion in the edge weight sums.
      
      The buggy code is duplicated within this file. I'll colapse them into
      a single implementation in a subsequent commit.
      
      llvm-svn: 144526
      ed5aa547
    • 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
      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. Oct 23, 2011
    • 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
  13. Oct 21, 2011
    • Chandler Carruth's avatar
      Don't hard code the desired alignment for loops -- it isn't 16-bytes on · 70a38058
      Chandler Carruth authored
      all x86 systems. Sorry for the breakage.
      
      llvm-svn: 142656
      70a38058
    • 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
      Add a very basic test for MachineBlockPlacement. This is essentially the · ddfeaafd
      Chandler Carruth authored
      canonical example I used when developing it, and is one of the primary
      motivating real-world use cases for __builtin_expect (when burried under
      a macro).
      
      I'm working on more test cases here, but I'm trying to make sure both
      that the pass is doing the right thing with the test cases and that they
      aren't too brittle to changes elsewhere in the code generation pipeline.
      
      Feedback and/or suggestions on how to test this are very welcome.
      Especially feedback on whether testing the block comments is a good
      strategy; I couldn't find any good examples to steal from but all the
      other ideas I had were a lot uglier or more fragile.
      
      llvm-svn: 142644
      ddfeaafd
Loading