From a862326bc72be147d9f668b84b9187258e690dc4 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 5 Mar 2010 20:47:23 +0000 Subject: [PATCH] Instcombine should turn llvm.objectsize of a alloca with static size to an integer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97827 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineCalls.cpp | 31 +++++++++++++------ test/Transforms/InstCombine/objsize.ll | 20 ++++++++++++ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 88d8abdeb73..a241f169f28 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -304,29 +304,39 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { switch (II->getIntrinsicID()) { default: break; case Intrinsic::objectsize: { - const Type *ReturnTy = CI.getType(); - Value *Op1 = II->getOperand(1); - bool Min = (cast(II->getOperand(2))->getZExtValue() == 1); - // We need target data for just about everything so depend on it. if (!TD) break; + const Type *ReturnTy = CI.getType(); + bool Min = (cast(II->getOperand(2))->getZExtValue() == 1); + // Get to the real allocated thing and offset as fast as possible. - Op1 = Op1->stripPointerCasts(); + Value *Op1 = II->getOperand(1)->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(Op1)) { if (GV->hasDefinitiveInitializer()) { Constant *C = GV->getInitializer(); - uint64_t globalSize = TD->getTypeAllocSize(C->getType()); - return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, globalSize)); + uint64_t GlobalSize = TD->getTypeAllocSize(C->getType()); + return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, GlobalSize)); } else { + // Can't determine size of the GV. Constant *RetVal = ConstantInt::get(ReturnTy, Min ? 0 : -1ULL); return ReplaceInstUsesWith(CI, RetVal); } - } else if (ConstantExpr *CE = dyn_cast(Op1)) { - + } else if (AllocaInst *AI = dyn_cast(Op1)) { + // Get alloca size. + if (AI->getAllocatedType()->isSized()) { + uint64_t AllocaSize = TD->getTypeAllocSize(AI->getAllocatedType()); + if (AI->isArrayAllocation()) { + const ConstantInt *C = dyn_cast(AI->getArraySize()); + if (!C) break; + AllocaSize *= C->getZExtValue(); + } + return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, AllocaSize)); + } + } else if (ConstantExpr *CE = dyn_cast(Op1)) { // Only handle constant GEPs here. if (CE->getOpcode() != Instruction::GetElementPtr) break; GEPOperator *GEP = cast(CE); @@ -361,6 +371,9 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { return ReplaceInstUsesWith(CI, RetVal); } + + // Do not return "I don't know" here. Later optimization passes could + // make it possible to evaluate objectsize to a constant. break; } case Intrinsic::bswap: diff --git a/test/Transforms/InstCombine/objsize.ll b/test/Transforms/InstCombine/objsize.ll index 9df122499e6..bf1a37f975d 100644 --- a/test/Transforms/InstCombine/objsize.ll +++ b/test/Transforms/InstCombine/objsize.ll @@ -102,4 +102,24 @@ bb12: unreachable } +; rdar://7718857 + +%struct.data = type { [100 x i32], [100 x i32], [1024 x i8] } + +define i32 @test4() nounwind ssp { +; CHECK: @test4 +entry: + %0 = alloca %struct.data, align 8 + %1 = bitcast %struct.data* %0 to i8* + %2 = call i64 @llvm.objectsize.i64(i8* %1, i1 false) nounwind +; CHECK-NOT: @llvm.objectsize +; CHECK: @__memset_chk(i8* %1, i32 0, i64 1824, i64 1824) + %3 = call i8* @__memset_chk(i8* %1, i32 0, i64 1824, i64 %2) nounwind + ret i32 0 +} + +declare i8* @__memset_chk(i8*, i32, i64, i64) nounwind + declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readonly + +declare i64 @llvm.objectsize.i64(i8*, i1) nounwind readonly