[cfe-commits] r134697 - /cfe/trunk/lib/Analysis/UninitializedValues.cpp

Chris Lattner clattner at apple.com
Fri Jul 8 09:16:47 PDT 2011


On Jul 8, 2011, at 4:19 AM, Chandler Carruth wrote:

> Author: chandlerc
> Date: Fri Jul  8 06:19:06 2011
> New Revision: 134697
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=134697&view=rev
> Log:
> Make the worklist in the uninitialized values checker actually a queue.
> Previously, despite the names 'enqueue' and 'dequeue', it behaved as
> a stack and visited blocks in a LIFO fashion. This interacts badly with
> extremely broad CFGs *inside* of a loop (such as a large switch inside
> a state machine) where every block updates a different variable.

Wow, this is a great win.  With dataflow, the standard traversal order is a reverse postorder traversal (e.g. as vended by llvm/include/llvm/ADT/PostOrderIterator.h).  Did you consider using a RPOT?

-Chris


> 
> When encountering such a CFG, the checker visited blocks in essentially
> a "depth first" order due to the stack-like behavior of the work list.
> Combined with each block updating a different variable, the saturation
> logic of the checker caused it to re-traverse blocks [1,N-1] of the
> broad CFG inside the loop after traversing block N. These re-traversals
> were to propagate the variable values derived from block N. Assuming
> approximately the same number of variables as inner blocks exist, the
> end result is O(N^2) updates. By making this a queue, we also make the
> traversal essentially "breadth-first" across each of the N inner blocks
> of the loop. Then all of this state is propagated around to all N inner
> blocks of the loop. The result is O(N) updates.
> 
> The truth is in the numbers:
> Before, gcc.c:   96409 block visits  (max: 61546,   avg: 591)
> After,  gcc.c:   69958 block visits  (max: 33090,   avg: 429)
> Before, PR10183: 2540494 block vists (max: 2536495, avg: 37360)
> After,  PR10183: 137803 block visits (max: 134406,  avg: 2026)
> 
> The nearly 20x reduction in work for PR10183 corresponds to a roughly
> 100x speedup in compile time.
> 
> I've tested it on all the code I can get my hands on, and I've seen no
> slowdowns due to this change. Where I've collected stats, the ammount of
> work done is on average less. I'll also commit shortly some synthetic
> test cases useful in analyzing the performance of CFG-based warnings.
> 
> Submitting this based on Doug's feedback that post-commit review should
> be good. Ted, please review! Hopefully this helps compile times until
> then.
> 
> Modified:
>    cfe/trunk/lib/Analysis/UninitializedValues.cpp
> 
> Modified: cfe/trunk/lib/Analysis/UninitializedValues.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UninitializedValues.cpp?rev=134697&r1=134696&r2=134697&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Analysis/UninitializedValues.cpp (original)
> +++ cfe/trunk/lib/Analysis/UninitializedValues.cpp Fri Jul  8 06:19:06 2011
> @@ -288,28 +288,28 @@
> public:
>   DataflowWorklist(const CFG &cfg) : enqueuedBlocks(cfg.getNumBlockIDs()) {}
> 
> -  void enqueue(const CFGBlock *block);
>   void enqueueSuccessors(const CFGBlock *block);
>   const CFGBlock *dequeue();
> -  
> };
> }
> 
> -void DataflowWorklist::enqueue(const CFGBlock *block) {
> -  if (!block)
> -    return;
> -  unsigned idx = block->getBlockID();
> -  if (enqueuedBlocks[idx])
> -    return;
> -  worklist.push_back(block);
> -  enqueuedBlocks[idx] = true;
> -}
> -
> void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) {
> +  unsigned OldWorklistSize = worklist.size();
>   for (CFGBlock::const_succ_iterator I = block->succ_begin(),
>        E = block->succ_end(); I != E; ++I) {
> -    enqueue(*I);
> +    const CFGBlock *Successor = *I;
> +    if (!Successor || enqueuedBlocks[Successor->getBlockID()])
> +      continue;
> +    worklist.push_back(Successor);
> +    enqueuedBlocks[Successor->getBlockID()] = true;
>   }
> +  if (OldWorklistSize == 0 || OldWorklistSize == worklist.size())
> +    return;
> +
> +  // Rotate the newly added blocks to the start of the worklist so that it forms
> +  // a proper queue when we pop off the end of the worklist.
> +  std::rotate(worklist.begin(), worklist.begin() + OldWorklistSize,
> +              worklist.end());
> }
> 
> const CFGBlock *DataflowWorklist::dequeue() {
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits




More information about the cfe-commits mailing list