[llvm-commits] [llvm] r157481 - in /llvm/trunk: lib/Transforms/Scalar/BoundsChecking.cpp test/Transforms/BoundsChecking/alloc_size.ll test/Transforms/BoundsChecking/lit.local.cfg test/Transforms/BoundsChecking/simple.ll

Nuno Lopes nunoplopes at sapo.pt
Fri May 25 09:54:05 PDT 2012


Author: nlopes
Date: Fri May 25 11:54:04 2012
New Revision: 157481

URL: http://llvm.org/viewvc/llvm-project?rev=157481&view=rev
Log:
boundschecking:
add support for select
add experimental support for alloc_size metadata

Added:
    llvm/trunk/test/Transforms/BoundsChecking/alloc_size.ll
    llvm/trunk/test/Transforms/BoundsChecking/lit.local.cfg
Modified:
    llvm/trunk/lib/Transforms/Scalar/BoundsChecking.cpp
    llvm/trunk/test/Transforms/BoundsChecking/simple.ll

Modified: llvm/trunk/lib/Transforms/Scalar/BoundsChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/BoundsChecking.cpp?rev=157481&r1=157480&r2=157481&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/BoundsChecking.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/BoundsChecking.cpp Fri May 25 11:54:04 2012
@@ -26,6 +26,7 @@
 #include "llvm/GlobalVariable.h"
 #include "llvm/Instructions.h"
 #include "llvm/Intrinsics.h"
+#include "llvm/Metadata.h"
 #include "llvm/Operator.h"
 #include "llvm/Pass.h"
 using namespace llvm;
@@ -118,6 +119,9 @@
 /// incurr at run-time.
 ConstTriState BoundsChecking::computeAllocSize(Value *Alloc, uint64_t &Size,
                                      Value* &SizeValue) {
+  IntegerType *RetTy = TD->getIntPtrType(Fn->getContext());
+
+  // global variable with definitive size
   if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Alloc)) {
     if (GV->hasDefinitiveInitializer()) {
       Constant *C = GV->getInitializer();
@@ -126,6 +130,7 @@
     }
     return Dunno;
 
+  // stack allocation
   } else if (AllocaInst *AI = dyn_cast<AllocaInst>(Alloc)) {
     if (!AI->getAllocatedType()->isSized())
       return Dunno;
@@ -147,68 +152,117 @@
     SizeValue = Builder->CreateMul(SizeValue, ArraySize);
     return NotConst;
 
-  } else if (CallInst *CI = dyn_cast<CallInst>(Alloc)) {
-    Function *Callee = CI->getCalledFunction();
-    if (!Callee || !Callee->isDeclaration())
+  // ptr = select(ptr1, ptr2)
+  } else if (SelectInst *SI = dyn_cast<SelectInst>(Alloc)) {
+    uint64_t SizeFalse;
+    Value *SizeValueFalse;
+    ConstTriState TrueConst = computeAllocSize(SI->getTrueValue(), Size,
+                                               SizeValue);
+    ConstTriState FalseConst = computeAllocSize(SI->getFalseValue(), SizeFalse,
+                                                SizeValueFalse);
+
+    if (TrueConst == Const && FalseConst == Const && Size == SizeFalse)
+      return Const;
+
+    if (Penalty < 2 || (TrueConst == Dunno && FalseConst == Dunno))
       return Dunno;
 
-    FunctionType *FTy = Callee->getFunctionType();
-    if (FTy->getNumParams() == 1) {
+    // if one of the branches is Dunno, assume it is ok and check just the other
+    APInt MaxSize = APInt::getMaxValue(TD->getTypeSizeInBits(RetTy));
+
+    if (TrueConst == Const)
+      SizeValue = ConstantInt::get(RetTy, Size);
+    else if (TrueConst == Dunno)
+      SizeValue = ConstantInt::get(RetTy, MaxSize);
+
+    if (FalseConst == Const)
+      SizeValueFalse = ConstantInt::get(RetTy, SizeFalse);
+    else if (FalseConst == Dunno)
+      SizeValueFalse = ConstantInt::get(RetTy, MaxSize);
+
+    SizeValue = Builder->CreateSelect(SI->getCondition(), SizeValue,
+                                      SizeValueFalse);
+    return NotConst;
+
+  // call allocation function
+  } else if (CallInst *CI = dyn_cast<CallInst>(Alloc)) {
+    SmallVector<unsigned, 4> Args;
+
+    if (MDNode *MD = CI->getMetadata("alloc_size")) {
+      for (unsigned i = 0, e = MD->getNumOperands(); i != e; ++i)
+        Args.push_back(cast<ConstantInt>(MD->getOperand(i))->getZExtValue());
+
+    } else if (Function *Callee = CI->getCalledFunction()) {
+      FunctionType *FTy = Callee->getFunctionType();
+
       // alloc(size)
-      if ((FTy->getParamType(0)->isIntegerTy(32) ||
-           FTy->getParamType(0)->isIntegerTy(64)) &&
-          (Callee->getName() == "malloc" ||
-           Callee->getName() == "valloc" ||
-           Callee->getName() == "_Znwj"  || // operator new(unsigned int)
-           Callee->getName() == "_Znwm"  || // operator new(unsigned long)
-           Callee->getName() == "_Znaj"  || // operator new[](unsigned int)
-           Callee->getName() == "_Znam")) { // operator new[](unsigned long)
-        SizeValue = CI->getArgOperand(0);
-        if (ConstantInt *Arg = dyn_cast<ConstantInt>(SizeValue)) {
-          Size = Arg->getZExtValue();
-          return Const;
+      if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy()) {
+        if ((Callee->getName() == "malloc" ||
+             Callee->getName() == "valloc" ||
+             Callee->getName() == "_Znwj"  || // operator new(unsigned int)
+             Callee->getName() == "_Znwm"  || // operator new(unsigned long)
+             Callee->getName() == "_Znaj"  || // operator new[](unsigned int)
+             Callee->getName() == "_Znam")) {
+          Args.push_back(0);
+        }
+      } else if (FTy->getNumParams() == 2) {
+        // alloc(_, x)
+        if (FTy->getParamType(1)->isIntegerTy() &&
+            ((Callee->getName() == "realloc" ||
+              Callee->getName() == "reallocf"))) {
+          Args.push_back(1);
+
+        // alloc(x, y)
+        } else if (FTy->getParamType(0)->isIntegerTy() &&
+                   FTy->getParamType(1)->isIntegerTy() &&
+                   Callee->getName() == "calloc") {
+          Args.push_back(0);
+          Args.push_back(1);
         }
-        return Penalty >= 2 ? NotConst : Dunno;
       }
-      return Dunno;
     }
 
-    if (FTy->getNumParams() == 2) {
-      // alloc(x, y) and return buffer of size x * y
-      if (((FTy->getParamType(0)->isIntegerTy(32) &&
-            FTy->getParamType(1)->isIntegerTy(32)) ||
-           (FTy->getParamType(0)->isIntegerTy(64) &&
-            FTy->getParamType(1)->isIntegerTy(64))) &&
-          Callee->getName() == "calloc") {
-        Value *Arg1 = CI->getArgOperand(0);
-        Value *Arg2 = CI->getArgOperand(1);
-        if (ConstantInt *CI1 = dyn_cast<ConstantInt>(Arg1)) {
-          if (ConstantInt *CI2 = dyn_cast<ConstantInt>(Arg2)) {
-            Size = (CI1->getValue() * CI2->getValue()).getZExtValue();
-            return Const;
-          }
-        }
+    if (Args.empty())
+      return Dunno;
 
-        if (Penalty < 2)
-          return Dunno;
+    // check if all arguments are constant. if so, the object size is also const
+    bool AllConst = true;
+    for (SmallVectorImpl<unsigned>::iterator I = Args.begin(), E = Args.end();
+         I != E; ++I) {
+      if (!isa<ConstantInt>(CI->getArgOperand(*I))) {
+        AllConst = false;
+        break;
+      }
+    }
 
-        SizeValue = Builder->CreateMul(Arg1, Arg2);
-        return NotConst;
+    if (AllConst) {
+      Size = 1;
+      for (SmallVectorImpl<unsigned>::iterator I = Args.begin(), E = Args.end();
+           I != E; ++I) {
+        ConstantInt *Arg = cast<ConstantInt>(CI->getArgOperand(*I));
+        Size *= (size_t)Arg->getZExtValue();
       }
+      return Const;
+    }
 
-      // realloc(ptr, size)
-      if ((FTy->getParamType(1)->isIntegerTy(32) ||
-           FTy->getParamType(1)->isIntegerTy(64)) &&
-          (Callee->getName() == "realloc" ||
-           Callee->getName() == "reallocf")) {
-        SizeValue = CI->getArgOperand(1);
-        if (ConstantInt *Arg = dyn_cast<ConstantInt>(SizeValue)) {
-          Size = Arg->getZExtValue();
-          return Const;
-        }
-        return Penalty >= 2 ? NotConst : Dunno;
+    if (Penalty < 2)
+      return Dunno;
+
+    // not all arguments are constant, so create a sequence of multiplications
+    bool First = true;
+    for (SmallVectorImpl<unsigned>::iterator I = Args.begin(), E = Args.end();
+         I != E; ++I) {
+      Value *Arg = CI->getArgOperand(*I);
+      if (First) {
+        SizeValue = Arg;
+        First = false;
+        continue;
       }
+      SizeValue = Builder->CreateMul(SizeValue, Arg);
     }
+
+    return NotConst;
+
     // TODO: handle more standard functions:
     // - strdup / strndup
     // - strcpy / strncpy
@@ -216,7 +270,7 @@
     // - strcat / strncat
   }
 
-  DEBUG(dbgs() << "computeAllocSize failed:\n" << *Alloc);
+  DEBUG(dbgs() << "computeAllocSize failed:\n" << *Alloc << "\n");
   return Dunno;
 }
 

Added: llvm/trunk/test/Transforms/BoundsChecking/alloc_size.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/BoundsChecking/alloc_size.ll?rev=157481&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/BoundsChecking/alloc_size.ll (added)
+++ llvm/trunk/test/Transforms/BoundsChecking/alloc_size.ll Fri May 25 11:54:04 2012
@@ -0,0 +1,43 @@
+; RUN: opt < %s -bounds-checking -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+
+declare i64* @alloc(i32, i8, i32)
+declare i32* @alloc2(i32, i32)
+
+; CHECK: @f1
+define void @f1(i32 %x) {
+  %call = tail call i32* @alloc2(i32 %x, i32 4) nounwind, !alloc_size !0
+; CHECK: trap
+  store i32 3, i32* %call, align 4
+  ret void
+}
+
+; CHECK: @f2
+define void @f2() {
+  %call1 = tail call i32* @alloc2(i32 2, i32 4) nounwind, !alloc_size !0
+  %arrayidx = getelementptr i32* %call1, i64 2
+; CHECK: br label
+  store i32 3, i32* %arrayidx, align 4
+  ret void
+}
+
+; CHECK: @f3
+define void @f3(i32 %x, i8 %y) {
+  %call = tail call i64* @alloc(i32 %x, i8 %y, i32 7) nounwind, !alloc_size !1
+; CHECK: trap
+  store i64 27, i64* %call, align 4
+  ret void
+}
+
+; CHECK: @f4
+define void @f4() {
+  %call1 = tail call i32* @alloc2(i32 2, i32 4) nounwind, !alloc_size !0
+  %arrayidx = getelementptr i32* %call1, i64 1
+; CHECK-NOT: trap
+  store i32 3, i32* %arrayidx, align 4
+; CHECK: ret
+  ret void
+}
+
+!0 = metadata !{i32 0, i32 1}
+!1 = metadata !{i32 2}

Added: llvm/trunk/test/Transforms/BoundsChecking/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/BoundsChecking/lit.local.cfg?rev=157481&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/BoundsChecking/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/BoundsChecking/lit.local.cfg Fri May 25 11:54:04 2012
@@ -0,0 +1 @@
+config.suffixes = ['.ll', '.c', '.cpp']

Modified: llvm/trunk/test/Transforms/BoundsChecking/simple.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/BoundsChecking/simple.ll?rev=157481&r1=157480&r2=157481&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/BoundsChecking/simple.ll (original)
+++ llvm/trunk/test/Transforms/BoundsChecking/simple.ll Fri May 25 11:54:04 2012
@@ -76,3 +76,34 @@
   %2 = load i128* %1, align 4
   ret void
 }
+
+; CHECK: @f8
+define void @f8() nounwind {
+  %1 = alloca i128
+  %2 = alloca i128
+  %3 = select i1 undef, i128* %1, i128* %2
+; CHECK-NOT: trap
+  %4 = load i128* %3, align 4
+  ret void
+}
+
+; CHECK: @f9
+define void @f9(i128* %arg) nounwind {
+  %1 = alloca i128
+  %2 = select i1 undef, i128* %arg, i128* %1
+; CHECK: br i1 false
+  %3 = load i128* %2, align 4
+  ret void
+}
+
+; CHECK: @f10
+define void @f10(i64 %x, i64 %y) nounwind {
+  %1 = alloca i128, i64 %x
+  %2 = alloca i128, i64 %y
+  %3 = select i1 undef, i128* %1, i128* %2
+; CHECK: select
+; CHECK: select
+; CHECK: trap
+  %4 = load i128* %3, align 4
+  ret void
+}





More information about the llvm-commits mailing list