[llvm] r290214 - [Analysis] Centralize objectsize lowering logic.

George Burgess IV via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 20 15:46:37 PST 2016


Author: gbiv
Date: Tue Dec 20 17:46:36 2016
New Revision: 290214

URL: http://llvm.org/viewvc/llvm-project?rev=290214&view=rev
Log:
[Analysis] Centralize objectsize lowering logic.

We're currently doing nearly the same thing for @llvm.objectsize in
three different places: two of them are missing checks for overflow,
and one of them could subtly break if InstCombine gets much smarter
about removing alloc sites. Seems like a good idea to not do that.

Modified:
    llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h
    llvm/trunk/lib/Analysis/MemoryBuiltins.cpp
    llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
    llvm/trunk/test/Transforms/CodeGenPrepare/builtin-condition.ll

Modified: llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h?rev=290214&r1=290213&r2=290214&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h (original)
+++ llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h Tue Dec 20 17:46:36 2016
@@ -141,6 +141,16 @@ bool getObjectSize(const Value *Ptr, uin
                    const TargetLibraryInfo *TLI, bool RoundToAlign = false,
                    ObjSizeMode Mode = ObjSizeMode::Exact);
 
+/// Try to turn a call to @llvm.objectsize into an integer value of the given
+/// Type. Returns null on failure.
+/// If MustSucceed is true, this function will not return null, and may return
+/// conservative values governed by the second argument of the call to
+/// objectsize.
+ConstantInt *lowerObjectSizeCall(IntrinsicInst *ObjectSize,
+                                 const DataLayout &DL,
+                                 const TargetLibraryInfo *TLI,
+                                 bool MustSucceed);
+
 typedef std::pair<APInt, APInt> SizeOffsetType;
 
 /// \brief Evaluate the size and offset of an object pointed to by a Value*

Modified: llvm/trunk/lib/Analysis/MemoryBuiltins.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryBuiltins.cpp?rev=290214&r1=290213&r2=290214&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/MemoryBuiltins.cpp (original)
+++ llvm/trunk/lib/Analysis/MemoryBuiltins.cpp Tue Dec 20 17:46:36 2016
@@ -388,6 +388,36 @@ bool llvm::getObjectSize(const Value *Pt
   return true;
 }
 
+ConstantInt *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize,
+                                       const DataLayout &DL,
+                                       const TargetLibraryInfo *TLI,
+                                       bool MustSucceed) {
+  assert(ObjectSize->getIntrinsicID() == Intrinsic::objectsize &&
+         "ObjectSize must be a call to llvm.objectsize!");
+
+  bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand(1))->isZero();
+  ObjSizeMode Mode;
+  // Unless we have to fold this to something, try to be as accurate as
+  // possible.
+  if (MustSucceed)
+    Mode = MaxVal ? ObjSizeMode::Max : ObjSizeMode::Min;
+  else
+    Mode = ObjSizeMode::Exact;
+
+  // FIXME: Does it make sense to just return a failure value if the size won't
+  // fit in the output and `!MustSucceed`?
+  uint64_t Size;
+  auto *ResultType = cast<IntegerType>(ObjectSize->getType());
+  if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, false, Mode) &&
+      isUIntN(ResultType->getBitWidth(), Size))
+    return ConstantInt::get(ResultType, Size);
+
+  if (!MustSucceed)
+    return nullptr;
+
+  return ConstantInt::get(ResultType, MaxVal ? -1ULL : 0);
+}
+
 STATISTIC(ObjectVisitorArgument,
           "Number of arguments with unsolved size and offset");
 STATISTIC(ObjectVisitorLoad,

Modified: llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp?rev=290214&r1=290213&r2=290214&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp Tue Dec 20 17:46:36 2016
@@ -1948,18 +1948,8 @@ bool CodeGenPrepare::optimizeCallInst(Ca
     default: break;
     case Intrinsic::objectsize: {
       // Lower all uses of llvm.objectsize.*
-      uint64_t Size;
-      Type *ReturnTy = CI->getType();
-      Constant *RetVal = nullptr;
-      ConstantInt *Op1 = cast<ConstantInt>(II->getArgOperand(1));
-      ObjSizeMode Mode = Op1->isZero() ? ObjSizeMode::Max : ObjSizeMode::Min;
-      if (getObjectSize(II->getArgOperand(0),
-                        Size, *DL, TLInfo, false, Mode)) {
-        RetVal = ConstantInt::get(ReturnTy, Size);
-      } else {
-        RetVal = ConstantInt::get(ReturnTy,
-                                  Mode == ObjSizeMode::Min ? 0 : -1ULL);
-      }
+      ConstantInt *RetVal =
+          lowerObjectSizeCall(II, *DL, TLInfo, /*MustSucceed=*/true);
       // Substituting this can cause recursive simplifications, which can
       // invalidate our iterator.  Use a WeakVH to hold onto it in case this
       // happens.

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=290214&r1=290213&r2=290214&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Tue Dec 20 17:46:36 2016
@@ -1440,17 +1440,12 @@ Instruction *InstCombiner::visitCallInst
 
   switch (II->getIntrinsicID()) {
   default: break;
-  case Intrinsic::objectsize: {
-    uint64_t Size;
-    if (getObjectSize(II->getArgOperand(0), Size, DL, &TLI)) {
-      APInt APSize(II->getType()->getIntegerBitWidth(), Size);
-      // Equality check to be sure that `Size` can fit in a value of type
-      // `II->getType()`
-      if (APSize == Size)
-        return replaceInstUsesWith(CI, ConstantInt::get(II->getType(), APSize));
-    }
+  case Intrinsic::objectsize:
+    if (ConstantInt *N =
+            lowerObjectSizeCall(II, DL, &TLI, /*MustSucceed=*/false))
+      return replaceInstUsesWith(CI, N);
     return nullptr;
-  }
+
   case Intrinsic::bswap: {
     Value *IIOperand = II->getArgOperand(0);
     Value *X = nullptr;

Modified: llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=290214&r1=290213&r2=290214&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp Tue Dec 20 17:46:36 2016
@@ -2027,12 +2027,9 @@ Instruction *InstCombiner::visitAllocSit
 
       if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
         if (II->getIntrinsicID() == Intrinsic::objectsize) {
-          uint64_t Size;
-          if (!getObjectSize(II->getArgOperand(0), Size, DL, &TLI)) {
-            ConstantInt *CI = cast<ConstantInt>(II->getArgOperand(1));
-            Size = CI->isZero() ? -1ULL : 0;
-          }
-          replaceInstUsesWith(*I, ConstantInt::get(I->getType(), Size));
+          ConstantInt *Result = lowerObjectSizeCall(II, DL, &TLI,
+                                                    /*MustSucceed=*/true);
+          replaceInstUsesWith(*I, Result);
           eraseInstFromFunction(*I);
           Users[i] = nullptr; // Skip examining in the next loop.
         }

Modified: llvm/trunk/test/Transforms/CodeGenPrepare/builtin-condition.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/CodeGenPrepare/builtin-condition.ll?rev=290214&r1=290213&r2=290214&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/CodeGenPrepare/builtin-condition.ll (original)
+++ llvm/trunk/test/Transforms/CodeGenPrepare/builtin-condition.ll Tue Dec 20 17:46:36 2016
@@ -1,5 +1,38 @@
 ; RUN: opt -codegenprepare -S  < %s | FileCheck %s
 
+; Ensure we act sanely on overflow.
+; CHECK-LABEL: define i32 @bar
+define i32 @bar() {
+entry:
+  ; CHECK: ret i32 -1
+  %az = alloca [2147483649 x i32], align 16
+  %a = alloca i8*, align 8
+  %arraydecay = getelementptr inbounds [2147483649 x i32], [2147483649 x i32]* %az, i32 0, i32 0
+  %0 = bitcast i32* %arraydecay to i8*
+  store i8* %0, i8** %a, align 8
+  %1 = load i8*, i8** %a, align 8
+  %2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false)
+  ret i32 %2
+}
+
+; CHECK-LABEL: define i32 @baz
+define i32 @baz(i32 %n) {
+entry:
+  ; CHECK: ret i32 -1
+  %az = alloca [1 x i32], align 16
+  %bz = alloca [4294967297 x i32], align 16
+  %tobool = icmp ne i32 %n, 0
+  %arraydecay = getelementptr inbounds [1 x i32], [1 x i32]* %az, i64 0, i64 0
+  %arraydecay1 = getelementptr inbounds [4294967297 x i32], [4294967297 x i32]* %bz, i64 0, i64 0
+  %cond = select i1 %tobool, i32* %arraydecay, i32* %arraydecay1
+  %0 = bitcast i32* %cond to i8*
+  %1 = call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false)
+  ret i32 %1
+}
+
+declare i32 @llvm.objectsize.i32.p0i8(i8*, i1)
+
+; The following tests were generated by:
 ; #include<stdlib.h>
 ; #define STATIC_BUF_SIZE 10
 ; #define LARGER_BUF_SIZE 30
@@ -87,4 +120,4 @@ entry:
   ret void
 }
 
-declare i32 @printf(i8* nocapture readonly, ...)
\ No newline at end of file
+declare i32 @printf(i8* nocapture readonly, ...)




More information about the llvm-commits mailing list