Add ConstantExpr handling to Intrinsic::objectsize lowering.
authorEric Christopher <echristo@apple.com>
Thu, 11 Feb 2010 01:48:54 +0000 (01:48 +0000)
committerEric Christopher <echristo@apple.com>
Thu, 11 Feb 2010 01:48:54 +0000 (01:48 +0000)
Update testcase accordingly now that we can optimize another
section.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95846 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineCalls.cpp
test/Transforms/InstCombine/objsize.ll

index 4929f4070ff0972f43904b0be33765e32380bb58..1371fa7f1adcdb49ce1f3b7d92f45592cf124bfe 100644 (file)
@@ -308,9 +308,14 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
     Value *Op1 = II->getOperand(1);
     bool Min = (cast<ConstantInt>(II->getOperand(2))->getZExtValue() == 1);
     
+    // We need target data for just about everything so depend on it.
     if (!TD) break;
+    
+    // Get to the real allocated thing and offset as fast as possible.
     Op1 = Op1->stripPointerCasts();
     
+    // If we've stripped down to a single global variable that we
+    // can know the size of then just return that.
     if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Op1)) {
       if (GV->hasDefinitiveInitializer()) {
         Constant *C = GV->getInitializer();
@@ -320,7 +325,27 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
         Constant *RetVal = ConstantInt::get(ReturnTy, Min ? 0 : -1ULL);
         return ReplaceInstUsesWith(CI, RetVal);
       }
-    }
+    } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Op1)) {
+      
+      // Only handle constant GEPs here.
+      if (CE->getOpcode() != Instruction::GetElementPtr) break;
+      GEPOperator *GEP = cast<GEPOperator>(CE);
+      
+      // Get what we're pointing to and its size.
+      const PointerType *PT = 
+        cast<PointerType>(GEP->getPointerOperand()->getType());
+      size_t Size = TD->getTypeAllocSize(PT->getElementType());
+      
+      // Get the current byte offset into the thing.
+      SmallVector<Value*, 8> Ops(CE->op_begin()+1, CE->op_end());
+      size_t Offset = TD->getIndexedOffset(PT, &Ops[0], Ops.size());
+
+      assert(Size >= Offset);
+      
+      Constant *RetVal = ConstantInt::get(ReturnTy, Size-Offset);
+      return ReplaceInstUsesWith(CI, RetVal);
+      
+    } 
   }
   case Intrinsic::bswap:
     // bswap(bswap(x)) -> x
index 69e09f61f7cd7d385dc858380d03c07c17b45bfa..2bcdd914e33ebc4431a10adcc94a19b07929cc89 100644 (file)
@@ -31,10 +31,9 @@ cond.false:
   ret i8* %2;
 }
 
-; FIXME: Should be ret i32 0
 define i32 @f() nounwind {
 ; CHECK: @f
-; CHECK-NEXT: llvm.objectsize.i32
+; 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
 }