[llvm-commits] [llvm] r95628 - in /llvm/trunk: include/llvm/LinkAllPasses.h include/llvm/Support/StandardPasses.h include/llvm/Transforms/Scalar.h lib/Transforms/Scalar/ObjectSizeLowering.cpp test/Transforms/InstCombine/objsize.ll test/Transforms/ObjSizeLower/ test/Transforms/ObjSizeLower/objsize.ll

Eric Christopher echristo at apple.com
Mon Feb 8 16:35:38 PST 2010


Author: echristo
Date: Mon Feb  8 18:35:38 2010
New Revision: 95628

URL: http://llvm.org/viewvc/llvm-project?rev=95628&view=rev
Log:
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.


Added:
    llvm/trunk/lib/Transforms/Scalar/ObjectSizeLowering.cpp
    llvm/trunk/test/Transforms/ObjSizeLower/
    llvm/trunk/test/Transforms/ObjSizeLower/objsize.ll
      - copied, changed from r95402, llvm/trunk/test/Transforms/InstCombine/objsize.ll
Removed:
    llvm/trunk/test/Transforms/InstCombine/objsize.ll
Modified:
    llvm/trunk/include/llvm/LinkAllPasses.h
    llvm/trunk/include/llvm/Support/StandardPasses.h
    llvm/trunk/include/llvm/Transforms/Scalar.h

Modified: llvm/trunk/include/llvm/LinkAllPasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=95628&r1=95627&r2=95628&view=diff

==============================================================================
--- llvm/trunk/include/llvm/LinkAllPasses.h (original)
+++ llvm/trunk/include/llvm/LinkAllPasses.h Mon Feb  8 18:35:38 2010
@@ -138,6 +138,7 @@
       (void) llvm::createGEPSplitterPass();
       (void) llvm::createSCCVNPass();
       (void) llvm::createABCDPass();
+      (void) llvm::createObjectSizeLoweringPass();
 
       (void)new llvm::IntervalPartition();
       (void)new llvm::FindUsedTypes();

Modified: llvm/trunk/include/llvm/Support/StandardPasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/StandardPasses.h?rev=95628&r1=95627&r2=95628&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Support/StandardPasses.h (original)
+++ llvm/trunk/include/llvm/Support/StandardPasses.h Mon Feb  8 18:35:38 2010
@@ -118,8 +118,6 @@
     // 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 @@
     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));

Modified: llvm/trunk/include/llvm/Transforms/Scalar.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=95628&r1=95627&r2=95628&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Transforms/Scalar.h (original)
+++ llvm/trunk/include/llvm/Transforms/Scalar.h Mon Feb  8 18:35:38 2010
@@ -336,6 +336,12 @@
 //
 FunctionPass *createABCDPass();
 
+//===----------------------------------------------------------------------===//
+//
+// ObjSizeLowering - Lower Intrinsic::objsize
+//
+FunctionPass *createObjectSizeLoweringPass();
+
 } // End llvm namespace
 
 #endif

Added: llvm/trunk/lib/Transforms/Scalar/ObjectSizeLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ObjectSizeLowering.cpp?rev=95628&view=auto

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/ObjectSizeLowering.cpp (added)
+++ llvm/trunk/lib/Transforms/Scalar/ObjectSizeLowering.cpp Mon Feb  8 18:35:38 2010
@@ -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;
+}

Removed: llvm/trunk/test/Transforms/InstCombine/objsize.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/objsize.ll?rev=95627&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/objsize.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/objsize.ll (removed)
@@ -1,52 +0,0 @@
-; Test a pile of objectsize bounds checking.
-; RUN: opt < %s -instcombine -S | FileCheck %s
-; XFAIL: *
-; 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"
-
- at a = private global [60 x i8] zeroinitializer, align 1 ; <[60 x i8]*>
- at .str = private constant [8 x i8] c"abcdefg\00"   ; <[8 x i8]*>
-
-define i32 @foo() nounwind {
-; CHECK: @foo
-; CHECK-NEXT: ret i32 60
-  %1 = call i32 @llvm.objectsize.i32(i8* getelementptr inbounds ([60 x i8]* @a, i32 0, i32 0), i1 false)
-  ret i32 %1
-}
-
-define i8* @bar() nounwind {
-; CHECK: @bar
-entry:
-  %retval = alloca i8*
-  %0 = call i32 @llvm.objectsize.i32(i8* getelementptr inbounds ([60 x i8]* @a, i32 0, i32 0), i1 false)
-  %cmp = icmp ne i32 %0, -1
-; CHECK: br i1 true
-  br i1 %cmp, label %cond.true, label %cond.false
-
-cond.true:
-  %1 = load i8** %retval;
-  ret i8* %1;
-
-cond.false:
-  %2 = load i8** %retval;
-  ret i8* %2;
-}
-
-define i32 @f() nounwind {
-; CHECK: @f
-; CHECK-NEXT: ret i32 0
-  %1 = call i32 @llvm.objectsize.i32(i8* getelementptr ([60 x i8]* @a, i32 1, i32 0), i1 false)
-  ret i32 %1
-}
-
- at window = external global [0 x i8]
-
-define i1 @baz() nounwind {
-; CHECK: @baz
-; CHECK-NEXT: llvm.objectsize.i32
-  %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
-}
-
-declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readonly
\ No newline at end of file

Copied: llvm/trunk/test/Transforms/ObjSizeLower/objsize.ll (from r95402, llvm/trunk/test/Transforms/InstCombine/objsize.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjSizeLower/objsize.ll?p2=llvm/trunk/test/Transforms/ObjSizeLower/objsize.ll&p1=llvm/trunk/test/Transforms/InstCombine/objsize.ll&r1=95402&r2=95628&rev=95628&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/objsize.ll (original)
+++ llvm/trunk/test/Transforms/ObjSizeLower/objsize.ll Mon Feb  8 18:35:38 2010
@@ -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 @@
 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 @@
   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 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





More information about the llvm-commits mailing list