aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms/Scalar
diff options
context:
space:
mode:
authorEric Christopher <echristo@apple.com>2010-02-09 00:35:38 +0000
committerEric Christopher <echristo@apple.com>2010-02-09 00:35:38 +0000
commit1926b648e132631282aa15d25e4f8278f87c24fb (patch)
tree32cf8d41d89dc064e6650a1ea998a588e9e2ea79 /lib/Transforms/Scalar
parentb8d6e98e566724f58344d275a4bd675249bb713a (diff)
downloadexternal_llvm-1926b648e132631282aa15d25e4f8278f87c24fb.zip
external_llvm-1926b648e132631282aa15d25e4f8278f87c24fb.tar.gz
external_llvm-1926b648e132631282aa15d25e4f8278f87c24fb.tar.bz2
Add a new pass to do llvm.objsize lowering using SCEV.
Initial skeleton and SCEVUnknown lowering implemented, the rest should come relatively quickly. Move testcase to new directory. Move pass to right before SimplifyLibCalls - which is moved down a bit so we can take advantage of a few opts. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95628 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar')
-rw-r--r--lib/Transforms/Scalar/ObjectSizeLowering.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/ObjectSizeLowering.cpp b/lib/Transforms/Scalar/ObjectSizeLowering.cpp
new file mode 100644
index 0000000..9660e79
--- /dev/null
+++ b/lib/Transforms/Scalar/ObjectSizeLowering.cpp
@@ -0,0 +1,114 @@
+//===-- ObjectSizeLowering.cpp - Loop unroller pass -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass lowers Intrinsic::objectsize using SCEV to determine minimum or
+// maximum space left in an allocated object.
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "objsize-lower"
+#include "llvm/Constants.h"
+#include "llvm/Module.h"
+#include "llvm/Value.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/ScalarEvolutionExpander.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+ class ObjSizeLower : public FunctionPass {
+ ScalarEvolution *SE;
+ TargetData *TD;
+ public:
+ static char ID; // Pass identification, replacement for typeid
+ ObjSizeLower() : FunctionPass(&ID) {}
+
+ bool runOnFunction(Function &F);
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesCFG();
+ AU.addRequired<ScalarEvolution>();
+ AU.addPreserved<ScalarEvolution>();
+ }
+ private:
+ bool LowerCall(IntrinsicInst *);
+ void ReplaceAllUsesWithUnknown(IntrinsicInst *, bool);
+ };
+}
+
+char ObjSizeLower::ID = 0;
+static RegisterPass<ObjSizeLower> X("objsize-lower",
+ "Object Size Lowering");
+
+// Public interface to the Object Size Lowering pass
+FunctionPass *llvm::createObjectSizeLoweringPass() {
+ return new ObjSizeLower();
+}
+
+/// runOnFunction - Top level algorithm - Loop over each object size intrinsic
+/// and use Scalar Evolutions to get the maximum or minimum size left in the
+/// allocated object at any point.
+bool ObjSizeLower::runOnFunction(Function &F) {
+ SE = &getAnalysis<ScalarEvolution>();
+ TD = getAnalysisIfAvailable<TargetData>();
+
+ // We really need TargetData for size calculations.
+ if (!TD) return false;
+
+ bool Changed = false;
+ for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
+ for (BasicBlock::iterator I = BB->begin(), L = BB->end(); I != L; ) {
+ CallInst *CI = dyn_cast<CallInst>(I++);
+ if (!CI) continue;
+
+ // The only thing we care about are Intrinsic::objectsize calls
+ IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI);
+ if (!II || II->getIntrinsicID() != Intrinsic::objectsize) continue;
+
+ Changed |= LowerCall(II);
+ }
+ }
+ return Changed;
+}
+
+// Unknown for llvm.objsize is -1 for maximum size, and 0 for minimum size.
+void ObjSizeLower::ReplaceAllUsesWithUnknown(IntrinsicInst *II, bool min) {
+ const Type *ReturnTy = II->getCalledFunction()->getReturnType();
+ II->replaceAllUsesWith(ConstantInt::get(ReturnTy, min ? 0 : -1ULL));
+ II->eraseFromParent();
+}
+
+bool ObjSizeLower::LowerCall(IntrinsicInst *II) {
+ ConstantInt *CI = cast<ConstantInt>(II->getOperand(2));
+ bool minimum = (CI->getZExtValue() == 1);
+ Value *Op = II->getOperand(1);
+ const Type *ReturnTy = II->getCalledFunction()->getReturnType();
+
+ // Grab the SCEV for our access.
+ const SCEV *thisEV = SE->getSCEV(Op);
+
+ if (const SCEVUnknown *SU = dyn_cast<SCEVUnknown>(thisEV)) {
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(SU->getValue())) {
+ if (GV->hasDefinitiveInitializer()) {
+ Constant *C = GV->getInitializer();
+ size_t globalSize = TD->getTypeAllocSize(C->getType());
+ II->replaceAllUsesWith(ConstantInt::get(ReturnTy, globalSize));
+ II->eraseFromParent();
+ return true;
+ }
+ }
+ }
+
+ ReplaceAllUsesWithUnknown(II, minimum);
+ return true;
+}