summaryrefslogtreecommitdiffstats
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
commit9f85e7eb161cb46b675ca0e4d0b7f1dbd07a0063 (patch)
tree7fc13e55bb65260d4686413dd40c9dd5e7685271
parent60db0a6ba5af0ba551f1e4db83776912f2ca011c (diff)
downloadbcm5719-llvm-9f85e7eb161cb46b675ca0e4d0b7f1dbd07a0063.tar.gz
bcm5719-llvm-9f85e7eb161cb46b675ca0e4d0b7f1dbd07a0063.zip
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. llvm-svn: 95628
-rw-r--r--llvm/include/llvm/LinkAllPasses.h1
-rw-r--r--llvm/include/llvm/Support/StandardPasses.h5
-rw-r--r--llvm/include/llvm/Transforms/Scalar.h6
-rw-r--r--llvm/lib/Transforms/Scalar/ObjectSizeLowering.cpp114
-rw-r--r--llvm/test/Transforms/ObjSizeLower/objsize.ll (renamed from llvm/test/Transforms/InstCombine/objsize.ll)10
5 files changed, 129 insertions, 7 deletions
diff --git a/llvm/include/llvm/LinkAllPasses.h b/llvm/include/llvm/LinkAllPasses.h
index a7e2e05b931..49bb713bb6e 100644
--- a/llvm/include/llvm/LinkAllPasses.h
+++ b/llvm/include/llvm/LinkAllPasses.h
@@ -138,6 +138,7 @@ namespace {
(void) llvm::createGEPSplitterPass();
(void) llvm::createSCCVNPass();
(void) llvm::createABCDPass();
+ (void) llvm::createObjectSizeLoweringPass();
(void)new llvm::IntervalPartition();
(void)new llvm::FindUsedTypes();
diff --git a/llvm/include/llvm/Support/StandardPasses.h b/llvm/include/llvm/Support/StandardPasses.h
index f233c18de3b..6de1b3aeb73 100644
--- a/llvm/include/llvm/Support/StandardPasses.h
+++ b/llvm/include/llvm/Support/StandardPasses.h
@@ -118,8 +118,6 @@ namespace llvm {
// Start of function pass.
PM->add(createScalarReplAggregatesPass()); // Break up aggregate allocas
- if (SimplifyLibCalls)
- PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations
PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl.
PM->add(createJumpThreadingPass()); // Thread jumps.
PM->add(createCFGSimplificationPass()); // Merge & remove BBs
@@ -128,6 +126,9 @@ namespace llvm {
PM->add(createTailCallEliminationPass()); // Eliminate tail calls
PM->add(createCFGSimplificationPass()); // Merge & remove BBs
PM->add(createReassociatePass()); // Reassociate expressions
+ PM->add(createObjectSizeLoweringPass()); // Lower Intrinsic::objsize
+ if (SimplifyLibCalls)
+ PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations
PM->add(createLoopRotatePass()); // Rotate Loop
PM->add(createLICMPass()); // Hoist loop invariants
PM->add(createLoopUnswitchPass(OptimizeSize || OptimizationLevel < 3));
diff --git a/llvm/include/llvm/Transforms/Scalar.h b/llvm/include/llvm/Transforms/Scalar.h
index 7159f86e1e1..c24a12d0cf8 100644
--- a/llvm/include/llvm/Transforms/Scalar.h
+++ b/llvm/include/llvm/Transforms/Scalar.h
@@ -336,6 +336,12 @@ FunctionPass *createSCCVNPass();
//
FunctionPass *createABCDPass();
+//===----------------------------------------------------------------------===//
+//
+// ObjSizeLowering - Lower Intrinsic::objsize
+//
+FunctionPass *createObjectSizeLoweringPass();
+
} // End llvm namespace
#endif
diff --git a/llvm/lib/Transforms/Scalar/ObjectSizeLowering.cpp b/llvm/lib/Transforms/Scalar/ObjectSizeLowering.cpp
new file mode 100644
index 00000000000..9660e796c55
--- /dev/null
+++ b/llvm/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;
+}
diff --git a/llvm/test/Transforms/InstCombine/objsize.ll b/llvm/test/Transforms/ObjSizeLower/objsize.ll
index 41d071517df..bcc1f835df5 100644
--- a/llvm/test/Transforms/InstCombine/objsize.ll
+++ b/llvm/test/Transforms/ObjSizeLower/objsize.ll
@@ -1,6 +1,5 @@
; Test a pile of objectsize bounds checking.
-; RUN: opt < %s -instcombine -S | FileCheck %s
-; XFAIL: *
+; RUN: opt < %s -objsize-lower -S | FileCheck %s
; We need target data to get the sizes of the arrays and structures.
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
@@ -19,8 +18,8 @@ define i8* @bar() nounwind {
entry:
%retval = alloca i8*
%0 = call i32 @llvm.objectsize.i32(i8* getelementptr inbounds ([60 x i8]* @a, i32 0, i32 0), i1 false)
+; CHECK: %cmp = icmp ne i32 60, -1
%cmp = icmp ne i32 %0, -1
-; CHECK: br i1 true
br i1 %cmp, label %cond.true, label %cond.false
cond.true:
@@ -32,9 +31,10 @@ cond.false:
ret i8* %2;
}
+; FIXME: This should return 0.
define i32 @f() nounwind {
; CHECK: @f
-; CHECK-NEXT: ret i32 0
+; CHECK-NEXT: ret i32 -1
%1 = call i32 @llvm.objectsize.i32(i8* getelementptr ([60 x i8]* @a, i32 1, i32 0), i1 false)
ret i32 %1
}
@@ -43,7 +43,7 @@ define i32 @f() nounwind {
define i1 @baz() nounwind {
; CHECK: @baz
-; CHECK-NEXT: llvm.objectsize.i32
+; CHECK-NEXT: icmp eq i32 -1, -1
%1 = tail call i32 @llvm.objectsize.i32(i8* getelementptr inbounds ([0 x i8]* @window, i32 0, i32 0), i1 false)
%2 = icmp eq i32 %1, -1
ret i1 %2
OpenPOWER on IntegriCloud