mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
9a45dae8e1
Summary: Every single benchmark i can run, on large and small cfgs, fully connected, etc, across 3 different platforms (x86, arm., and PPC) says that the current pred iterator cache is a losing proposition. I can't find a case where it's faster than just walking preds, and in some cases, it's 5-10% slower. This is due to copying the preds. It also degrades into copying the entire cfg. The one operation that is occasionally faster is the cached size. This makes that operation faster by not relying on having the copies available. I'm not even sure that is faster enough to be worth it. I, again, have trouble finding cases where this takes long enough in a pass to be worth caching compared to a million other things they could cache or improve. My suggestion: We next remove the get() interface. We do stronger benchmarking of size(). We probably end up killing this entire cache. / Reviewers: chandlerc Subscribers: aemerson, llvm-commits, trentxintong Differential Revision: https://reviews.llvm.org/D30873 llvm-svn: 297733
82 lines
2.6 KiB
C++
82 lines
2.6 KiB
C++
//===- PredIteratorCache.h - pred_iterator Cache ----------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the PredIteratorCache class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_IR_PREDITERATORCACHE_H
|
|
#define LLVM_IR_PREDITERATORCACHE_H
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/IR/CFG.h"
|
|
#include "llvm/Support/Allocator.h"
|
|
|
|
namespace llvm {
|
|
|
|
/// PredIteratorCache - This class is an extremely trivial cache for
|
|
/// predecessor iterator queries. This is useful for code that repeatedly
|
|
/// wants the predecessor list for the same blocks.
|
|
class PredIteratorCache {
|
|
/// BlockToPredsMap - Pointer to null-terminated list.
|
|
mutable DenseMap<BasicBlock *, BasicBlock **> BlockToPredsMap;
|
|
mutable DenseMap<BasicBlock *, unsigned> BlockToPredCountMap;
|
|
|
|
/// Memory - This is the space that holds cached preds.
|
|
BumpPtrAllocator Memory;
|
|
|
|
private:
|
|
/// GetPreds - Get a cached list for the null-terminated predecessor list of
|
|
/// the specified block. This can be used in a loop like this:
|
|
/// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI)
|
|
/// use(*PI);
|
|
/// instead of:
|
|
/// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
|
|
BasicBlock **GetPreds(BasicBlock *BB) {
|
|
BasicBlock **&Entry = BlockToPredsMap[BB];
|
|
if (Entry)
|
|
return Entry;
|
|
|
|
SmallVector<BasicBlock *, 32> PredCache(pred_begin(BB), pred_end(BB));
|
|
PredCache.push_back(nullptr); // null terminator.
|
|
|
|
BlockToPredCountMap[BB] = PredCache.size() - 1;
|
|
|
|
Entry = Memory.Allocate<BasicBlock *>(PredCache.size());
|
|
std::copy(PredCache.begin(), PredCache.end(), Entry);
|
|
return Entry;
|
|
}
|
|
|
|
unsigned GetNumPreds(BasicBlock *BB) const {
|
|
auto Result = BlockToPredCountMap.find(BB);
|
|
if (Result != BlockToPredCountMap.end())
|
|
return Result->second;
|
|
return BlockToPredCountMap[BB] = std::distance(pred_begin(BB), pred_end(BB));
|
|
}
|
|
|
|
public:
|
|
size_t size(BasicBlock *BB) const { return GetNumPreds(BB); }
|
|
ArrayRef<BasicBlock *> get(BasicBlock *BB) {
|
|
return makeArrayRef(GetPreds(BB), GetNumPreds(BB));
|
|
}
|
|
|
|
/// clear - Remove all information.
|
|
void clear() {
|
|
BlockToPredsMap.clear();
|
|
BlockToPredCountMap.clear();
|
|
Memory.Reset();
|
|
}
|
|
};
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif
|