diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index fa42b6e35ab..4929f4070ff 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -230,7 +230,6 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) { return 0; } - /// visitCallInst - CallInst simplification. This mostly only handles folding /// of intrinsic instructions. For normal calls, it allows visitCallSite to do /// the heavy lifting. @@ -304,6 +303,25 @@ 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); + + if (!TD) break; + Op1 = Op1->stripPointerCasts(); + + if (GlobalVariable *GV = dyn_cast(Op1)) { + if (GV->hasDefinitiveInitializer()) { + Constant *C = GV->getInitializer(); + size_t globalSize = TD->getTypeAllocSize(C->getType()); + return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, globalSize)); + } else { + Constant *RetVal = ConstantInt::get(ReturnTy, Min ? 0 : -1ULL); + return ReplaceInstUsesWith(CI, RetVal); + } + } + } case Intrinsic::bswap: // bswap(bswap(x)) -> x if (IntrinsicInst *Operand = dyn_cast(II->getOperand(1))) diff --git a/test/Transforms/InstCombine/objsize.ll b/test/Transforms/InstCombine/objsize.ll index 41d071517df..69e09f61f7c 100644 --- a/test/Transforms/InstCombine/objsize.ll +++ b/test/Transforms/InstCombine/objsize.ll @@ -1,6 +1,5 @@ ; 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" @@ -32,9 +31,10 @@ cond.false: ret i8* %2; } +; FIXME: Should be ret i32 0 define i32 @f() nounwind { ; CHECK: @f -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: llvm.objectsize.i32 %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 i32 @f() nounwind { define i1 @baz() nounwind { ; CHECK: @baz -; CHECK-NEXT: llvm.objectsize.i32 +; CHECK-NEXT: ret i1 true %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