Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -12294,8 +12294,8 @@ :: - declare i32 @llvm.objectsize.i32(i8* , i1 ) - declare i64 @llvm.objectsize.i64(i8* , i1 ) + declare i32 @llvm.objectsize.i32(i8* , i1 , i1 ) + declare i64 @llvm.objectsize.i64(i8* , i1 , i1 ) Overview: """"""""" @@ -12310,11 +12310,15 @@ Arguments: """""""""" -The ``llvm.objectsize`` intrinsic takes two arguments. The first -argument is a pointer to or into the ``object``. The second argument is -a boolean and determines whether ``llvm.objectsize`` returns 0 (if true) -or -1 (if false) when the object size is unknown. The second argument -only accepts constants. +The ``llvm.objectsize`` intrinsic takes three arguments. The first argument is +a pointer to or into the ``object``. The second argument determines whether +``llvm.objectsize`` returns 0 (if true) or -1 (if false) when the object size +is unknown. The third argument controls how ``llvm.objectsize`` acts when +``null`` is used as its pointer argument. If true, ``null`` is treated as an +opaque value with an unknown number of bytes. Otherwise, ``llvm.objectsize`` +reports 0 bytes available when given ``null``. + +The second and third arguments only accept constants. Semantics: """""""""" Index: include/llvm/Analysis/MemoryBuiltins.h =================================================================== --- include/llvm/Analysis/MemoryBuiltins.h +++ include/llvm/Analysis/MemoryBuiltins.h @@ -139,7 +139,8 @@ /// a condition and corresponding value will be returned (min or max). bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, bool RoundToAlign = false, - ObjSizeMode Mode = ObjSizeMode::Exact); + ObjSizeMode Mode = ObjSizeMode::Exact, + bool *FromNull = nullptr); /// Try to turn a call to @llvm.objectsize into an integer value of the given /// Type. Returns null on failure. @@ -151,7 +152,20 @@ const TargetLibraryInfo *TLI, bool MustSucceed); -typedef std::pair SizeOffsetType; +struct SizeOffsetType { + APInt Size; + APInt Offset; + // Whether or not a null pointer appeared when calculating this + // SizeOffsetType's value. + bool FromNull; + + SizeOffsetType(APInt Size, APInt Offset, bool FromNull = false) + : Size(std::move(Size)), Offset(std::move(Offset)), FromNull(FromNull) {} + + bool bothKnown() const { + return Size.getBitWidth() > 1 && Offset.getBitWidth() > 1; + } +}; /// \brief Evaluate the size and offset of an object pointed to by a Value* /// statically. Fails if size or offset are not known at compile time. @@ -169,7 +183,7 @@ APInt align(APInt Size, uint64_t Align); SizeOffsetType unknown() { - return std::make_pair(APInt(), APInt()); + return {APInt(), APInt(), false}; } public: @@ -179,18 +193,6 @@ SizeOffsetType compute(Value *V); - static bool knownSize(const SizeOffsetType &SizeOffset) { - return SizeOffset.first.getBitWidth() > 1; - } - - static bool knownOffset(const SizeOffsetType &SizeOffset) { - return SizeOffset.second.getBitWidth() > 1; - } - - static bool bothKnown(const SizeOffsetType &SizeOffset) { - return knownSize(SizeOffset) && knownOffset(SizeOffset); - } - // These are "private", except they can't actually be made private. Only // compute() should be used by external users. SizeOffsetType visitAllocaInst(AllocaInst &I); Index: include/llvm/IR/Intrinsics.td =================================================================== --- include/llvm/IR/Intrinsics.td +++ include/llvm/IR/Intrinsics.td @@ -438,7 +438,8 @@ def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; // Internal interface for object size checking -def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, llvm_i1_ty], +def int_objectsize : Intrinsic<[llvm_anyint_ty], + [llvm_anyptr_ty, llvm_i1_ty, llvm_i1_ty], [IntrNoMem]>, GCCBuiltin<"__builtin_object_size">; Index: lib/Analysis/MemoryBuiltins.cpp =================================================================== --- lib/Analysis/MemoryBuiltins.cpp +++ lib/Analysis/MemoryBuiltins.cpp @@ -384,9 +384,9 @@ // Utility functions to compute size of objects. // static APInt getSizeWithOverflow(const SizeOffsetType &Data) { - if (Data.second.isNegative() || Data.first.ult(Data.second)) - return APInt(Data.first.getBitWidth(), 0); - return Data.first - Data.second; + if (Data.Offset.isNegative() || Data.Size.ult(Data.Offset)) + return APInt(Data.Size.getBitWidth(), 0); + return Data.Size - Data.Offset; } /// \brief Compute the size of the object pointed by Ptr. Returns true and the @@ -395,13 +395,15 @@ /// byval arguments, and global variables. bool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, bool RoundToAlign, - llvm::ObjSizeMode Mode) { - ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), - RoundToAlign, Mode); + llvm::ObjSizeMode Mode, bool *FromNull) { + ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), RoundToAlign, + Mode); SizeOffsetType Data = Visitor.compute(const_cast(Ptr)); - if (!Visitor.bothKnown(Data)) + if (!Data.bothKnown()) return false; + if (FromNull) + *FromNull = Data.FromNull; Size = getSizeWithOverflow(Data).getZExtValue(); return true; } @@ -425,10 +427,18 @@ // 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; + bool ValueIsFromNull; auto *ResultType = cast(ObjectSize->getType()); - if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, false, Mode) && - isUIntN(ResultType->getBitWidth(), Size)) + if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, false, Mode, + &ValueIsFromNull) && + isUIntN(ResultType->getBitWidth(), Size)) { + bool NullIsUnknownSize = + cast(ObjectSize->getArgOperand(2))->isOne(); + // Lower this eagerly, because we'll likely not be able to do better. + if (ValueIsFromNull && NullIsUnknownSize) + return ConstantInt::get(ResultType, MaxVal ? -1ULL : 0); return ConstantInt::get(ResultType, Size); + } if (!MustSucceed) return nullptr; @@ -501,12 +511,12 @@ APInt Size(IntTyBits, DL.getTypeAllocSize(I.getAllocatedType())); if (!I.isArrayAllocation()) - return std::make_pair(align(Size, I.getAlignment()), Zero); + return {align(Size, I.getAlignment()), Zero}; Value *ArraySize = I.getArraySize(); if (const ConstantInt *C = dyn_cast(ArraySize)) { Size *= C->getValue().zextOrSelf(IntTyBits); - return std::make_pair(align(Size, I.getAlignment()), Zero); + return {align(Size, I.getAlignment()), Zero}; } return unknown(); } @@ -519,7 +529,7 @@ } PointerType *PT = cast(A.getType()); APInt Size(IntTyBits, DL.getTypeAllocSize(PT->getElementType())); - return std::make_pair(align(Size, A.getParamAlignment()), Zero); + return {align(Size, A.getParamAlignment()), Zero}; } SizeOffsetType ObjectSizeOffsetVisitor::visitCallSite(CallSite CS) { @@ -544,7 +554,7 @@ if (Size.ugt(MaxSize)) Size = MaxSize + 1; } - return std::make_pair(Size, Zero); + return {Size, Zero}; } ConstantInt *Arg = dyn_cast(CS.getArgument(FnData->FstParam)); @@ -572,7 +582,7 @@ // Size is determined by just 1 parameter. if (FnData->SndParam < 0) - return std::make_pair(Size, Zero); + return {Size, Zero}; Arg = dyn_cast(CS.getArgument(FnData->SndParam)); if (!Arg) @@ -584,7 +594,7 @@ bool Overflow; Size = Size.umul_ov(NumElems, Overflow); - return Overflow ? unknown() : std::make_pair(Size, Zero); + return Overflow ? unknown() : SizeOffsetType{Size, Zero}; // TODO: handle more standard functions (+ wchar cousins): // - strdup / strndup @@ -597,7 +607,7 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull&) { - return std::make_pair(Zero, Zero); + return {Zero, Zero, /*FromNull=*/true}; } SizeOffsetType @@ -614,10 +624,11 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitGEPOperator(GEPOperator &GEP) { SizeOffsetType PtrData = compute(GEP.getPointerOperand()); APInt Offset(IntTyBits, 0); - if (!bothKnown(PtrData) || !GEP.accumulateConstantOffset(DL, Offset)) + if (!PtrData.bothKnown() || !GEP.accumulateConstantOffset(DL, Offset)) return unknown(); - return std::make_pair(PtrData.first, PtrData.second + Offset); + PtrData.Offset += Offset; + return PtrData; } SizeOffsetType ObjectSizeOffsetVisitor::visitGlobalAlias(GlobalAlias &GA) { @@ -631,7 +642,7 @@ return unknown(); APInt Size(IntTyBits, DL.getTypeAllocSize(GV.getType()->getElementType())); - return std::make_pair(align(Size, GV.getAlignment()), Zero); + return {align(Size, GV.getAlignment()), Zero}; } SizeOffsetType ObjectSizeOffsetVisitor::visitIntToPtrInst(IntToPtrInst&) { @@ -650,11 +661,17 @@ } SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) { - SizeOffsetType TrueSide = compute(I.getTrueValue()); + SizeOffsetType TrueSide = compute(I.getTrueValue()); SizeOffsetType FalseSide = compute(I.getFalseValue()); - if (bothKnown(TrueSide) && bothKnown(FalseSide)) { - if (TrueSide == FalseSide) { - return TrueSide; + if (TrueSide.bothKnown() && FalseSide.bothKnown()) { + // We need to preserve the null bit if we're going to return either TrueSide + // or FalseSide. + TrueSide.FromNull |= FalseSide.FromNull; + FalseSide.FromNull = TrueSide.FromNull; + + if (TrueSide.Size == FalseSide.Size && + TrueSide.Offset == FalseSide.Offset) { + return TrueSide; } APInt TrueResult = getSizeWithOverflow(TrueSide); @@ -678,7 +695,7 @@ } SizeOffsetType ObjectSizeOffsetVisitor::visitUndefValue(UndefValue&) { - return std::make_pair(Zero, Zero); + return {Zero, Zero}; } SizeOffsetType ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) { @@ -721,9 +738,9 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) { ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, RoundToAlign); SizeOffsetType Const = Visitor.compute(V); - if (Visitor.bothKnown(Const)) - return std::make_pair(ConstantInt::get(Context, Const.first), - ConstantInt::get(Context, Const.second)); + if (Const.bothKnown()) + return std::make_pair(ConstantInt::get(Context, Const.Size), + ConstantInt::get(Context, Const.Offset)); V = V->stripPointerCasts(); Index: lib/IR/AutoUpgrade.cpp =================================================================== --- lib/IR/AutoUpgrade.cpp +++ lib/IR/AutoUpgrade.cpp @@ -203,12 +203,13 @@ case 'o': // We only need to change the name to match the mangling including the // address space. - if (F->arg_size() == 2 && Name.startswith("objectsize.")) { + if (Name.startswith("objectsize.")) { Type *Tys[2] = { F->getReturnType(), F->arg_begin()->getType() }; - if (F->getName() != Intrinsic::getName(Intrinsic::objectsize, Tys)) { + if (F->arg_size() == 2 || + F->getName() != Intrinsic::getName(Intrinsic::objectsize, Tys)) { rename(F); - NewFn = Intrinsic::getDeclaration(F->getParent(), - Intrinsic::objectsize, Tys); + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::objectsize, + Tys); return true; } } @@ -1770,11 +1771,16 @@ CI->eraseFromParent(); return; - case Intrinsic::objectsize: + case Intrinsic::objectsize: { + Value *NullIsUnknownSize = CI->getNumArgOperands() == 2 + ? Builder.getFalse() + : CI->getArgOperand(2); CI->replaceAllUsesWith(Builder.CreateCall( - NewFn, {CI->getArgOperand(0), CI->getArgOperand(1)}, Name)); + NewFn, {CI->getArgOperand(0), CI->getArgOperand(1), NullIsUnknownSize}, + Name)); CI->eraseFromParent(); return; + } case Intrinsic::ctpop: { CI->replaceAllUsesWith(Builder.CreateCall(NewFn, {CI->getArgOperand(0)})); Index: lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp +++ lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp @@ -822,8 +822,8 @@ { Intr->getType(), PointerType::get(SrcTy, AMDGPUAS::LOCAL_ADDRESS) } ); - CallInst *NewCall - = Builder.CreateCall(ObjectSize, { Src, Intr->getOperand(1) }); + CallInst *NewCall = Builder.CreateCall( + ObjectSize, {Src, Intr->getOperand(1), Intr->getOperand(2)}); Intr->replaceAllUsesWith(NewCall); Intr->eraseFromParent(); continue; Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -2746,9 +2746,9 @@ bool AddressSanitizer::isSafeAccess(ObjectSizeOffsetVisitor &ObjSizeVis, Value *Addr, uint64_t TypeSize) const { SizeOffsetType SizeOffset = ObjSizeVis.compute(Addr); - if (!ObjSizeVis.bothKnown(SizeOffset)) return false; - uint64_t Size = SizeOffset.first.getZExtValue(); - int64_t Offset = SizeOffset.second.getSExtValue(); + if (!SizeOffset.bothKnown()) return false; + uint64_t Size = SizeOffset.Size.getZExtValue(); + int64_t Offset = SizeOffset.Offset.getSExtValue(); // Three checks are required to ensure safety: // . Offset >= 0 (since the offset is given from the base ptr) // . Size >= Offset (unsigned) Index: test/Assembler/auto_upgrade_intrinsics.ll =================================================================== --- test/Assembler/auto_upgrade_intrinsics.ll +++ test/Assembler/auto_upgrade_intrinsics.ll @@ -53,11 +53,20 @@ define i32 @test.objectsize() { ; CHECK-LABEL: @test.objectsize( -; CHECK: @llvm.objectsize.i32.p0i8 +; CHECK: @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) %s = call i32 @llvm.objectsize.i32(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false) ret i32 %s } +declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) nounwind readonly +define i64 @test.objectsize.2() { +; CHECK-LABEL: @test.objectsize.2( +; CHECK: @llvm.objectsize.i64.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) + %s = call i64 @llvm.objectsize.i64.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false) + ret i64 %s +} + + declare <2 x double> @llvm.masked.load.v2f64(<2 x double>* %ptrs, i32, <2 x i1> %mask, <2 x double> %src0) define <2 x double> @tests.masked.load(<2 x double>* %ptr, <2 x i1> %mask, <2 x double> %passthru) { Index: test/CodeGen/AMDGPU/promote-alloca-mem-intrinsics.ll =================================================================== --- test/CodeGen/AMDGPU/promote-alloca-mem-intrinsics.ll +++ test/CodeGen/AMDGPU/promote-alloca-mem-intrinsics.ll @@ -8,7 +8,7 @@ declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0 -declare i32 @llvm.objectsize.i32.p0i8(i8*, i1) #1 +declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1) #1 ; CHECK-LABEL: @promote_with_memcpy( ; CHECK: getelementptr inbounds [64 x [17 x i32]], [64 x [17 x i32]] addrspace(3)* @promote_with_memcpy.alloca, i32 0, i32 %{{[0-9]+}} @@ -52,11 +52,11 @@ ; CHECK-LABEL: @promote_with_objectsize( ; CHECK: [[PTR:%[0-9]+]] = getelementptr inbounds [64 x [17 x i32]], [64 x [17 x i32]] addrspace(3)* @promote_with_objectsize.alloca, i32 0, i32 %{{[0-9]+}} -; CHECK: call i32 @llvm.objectsize.i32.p3i8(i8 addrspace(3)* %alloca.bc, i1 false) +; CHECK: call i32 @llvm.objectsize.i32.p3i8(i8 addrspace(3)* %alloca.bc, i1 false, i1 false) define void @promote_with_objectsize(i32 addrspace(1)* %out) #0 { %alloca = alloca [17 x i32], align 4 %alloca.bc = bitcast [17 x i32]* %alloca to i8* - %size = call i32 @llvm.objectsize.i32.p0i8(i8* %alloca.bc, i1 false) + %size = call i32 @llvm.objectsize.i32.p0i8(i8* %alloca.bc, i1 false, i1 false) store i32 %size, i32 addrspace(1)* %out ret void } Index: test/Transforms/InstCombine/memset_chk-1.ll =================================================================== --- test/Transforms/InstCombine/memset_chk-1.ll +++ test/Transforms/InstCombine/memset_chk-1.ll @@ -69,7 +69,7 @@ entry: %call49 = call i64 @strlen(i8* %a) %add180 = add i64 %call49, 1 - %yo107 = call i64 @llvm.objectsize.i64.p0i8(i8* %b, i1 false) + %yo107 = call i64 @llvm.objectsize.i64.p0i8(i8* %b, i1 false, i1 false) %call50 = call i8* @__memmove_chk(i8* %b, i8* %a, i64 %add180, i64 %yo107) ; CHECK: %strlen = call i64 @strlen(i8* %b) ; CHECK-NEXT: %strchr2 = getelementptr i8, i8* %b, i64 %strlen @@ -87,7 +87,7 @@ declare i8* @__memmove_chk(i8*, i8*, i64, i64) declare i8* @strrchr(i8*, i32) declare i64 @strlen(i8* nocapture) -declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) +declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1) declare i8* @__memset_chk(i8*, i32, i64, i64) @@ -100,7 +100,7 @@ br i1 %cmp, label %cleanup, label %if.end if.end: %bc = bitcast i8* %call to float* - %call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false) + %call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false, i1 false) %call3 = tail call i8* @__memset_chk(i8* nonnull %call, i32 0, i64 %size, i64 %call2) #1 br label %cleanup cleanup: @@ -114,7 +114,7 @@ ; CHECK-NEXT: br i1 %cmp, label %cleanup, label %if.end ; CHECK: if.end: ; CHECK-NEXT: %bc = bitcast i8* %call to float* -; CHECK-NEXT: %call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false) +; CHECK-NEXT: %call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false, i1 false) ; CHECK-NEXT: %call3 = tail call i8* @__memset_chk(i8* nonnull %call, i32 0, i64 %size, i64 %call2) ; CHECK-NEXT: br label %cleanup ; CHECK: cleanup: Index: test/Transforms/InstCombine/objsize.ll =================================================================== --- test/Transforms/InstCombine/objsize.ll +++ test/Transforms/InstCombine/objsize.ll @@ -8,7 +8,7 @@ define i32 @foo() nounwind { ; CHECK-LABEL: @foo( ; CHECK-NEXT: ret i32 60 - %1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false) + %1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) ret i32 %1 } @@ -16,7 +16,7 @@ ; CHECK-LABEL: @bar( entry: %retval = alloca i8* - %0 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false) + %0 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) %cmp = icmp ne i32 %0, -1 ; CHECK: br i1 true br i1 %cmp, label %cond.true, label %cond.false @@ -33,7 +33,7 @@ define i32 @f() nounwind { ; CHECK-LABEL: @f( ; CHECK-NEXT: ret i32 0 - %1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr ([60 x i8], [60 x i8]* @a, i32 1, i32 0), i1 false) + %1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr ([60 x i8], [60 x i8]* @a, i32 1, i32 0), i1 false, i1 false) ret i32 %1 } @@ -42,7 +42,7 @@ define i1 @baz() nounwind { ; CHECK-LABEL: @baz( ; CHECK-NEXT: objectsize - %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 0), i1 false) + %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 0), i1 false, i1 false) %2 = icmp eq i32 %1, -1 ret i1 %2 } @@ -51,7 +51,7 @@ ; CHECK-LABEL: @test1( ; CHECK: objectsize.i32.p0i8 entry: - %0 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 10), i1 false) ; [#uses=1] + %0 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 10), i1 false, i1 false) ; [#uses=1] %1 = icmp eq i32 %0, -1 ; [#uses=1] br i1 %1, label %"47", label %"46" @@ -67,7 +67,7 @@ define i32 @test2() nounwind { ; CHECK-LABEL: @test2( ; CHECK-NEXT: ret i32 34 - %1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr (i8, i8* bitcast ([9 x i32]* @.str5 to i8*), i32 2), i1 false) + %1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr (i8, i8* bitcast ([9 x i32]* @.str5 to i8*), i32 2), i1 false, i1 false) ret i32 %1 } @@ -76,7 +76,7 @@ declare i8* @__memcpy_chk(i8*, i8*, i32, i32) nounwind -declare i32 @llvm.objectsize.i32.p0i8(i8*, i1) nounwind readonly +declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1) nounwind readonly declare i8* @__inline_memcpy_chk(i8*, i8*, i32) nounwind inlinehint @@ -88,7 +88,7 @@ bb11: %0 = getelementptr inbounds float, float* getelementptr inbounds ([480 x float], [480 x float]* @array, i32 0, i32 128), i32 -127 ; [#uses=1] %1 = bitcast float* %0 to i8* ; [#uses=1] - %2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false) ; [#uses=1] + %2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false, i1 false) ; [#uses=1] %3 = call i8* @__memcpy_chk(i8* undef, i8* undef, i32 512, i32 %2) nounwind ; [#uses=0] ; CHECK: unreachable unreachable @@ -110,7 +110,7 @@ entry: %0 = alloca %struct.data, align 8 %1 = bitcast %struct.data* %0 to i8* - %2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false) nounwind + %2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false, i1 false) nounwind ; CHECK-NOT: @llvm.objectsize ; CHECK: @llvm.memset.p0i8.i32(i8* %1, i8 0, i32 1824, i32 8, i1 false) %3 = call i8* @__memset_chk(i8* %1, i32 0, i32 1824, i32 %2) nounwind @@ -125,7 +125,7 @@ ; CHECK-LABEL: @test5( entry: %0 = tail call noalias i8* @malloc(i32 20) nounwind - %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false) + %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false, i1 false) %2 = load i8*, i8** @s, align 8 ; CHECK-NOT: @llvm.objectsize ; CHECK: @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* %1, i32 10, i32 1, i1 false) @@ -137,7 +137,7 @@ ; CHECK-LABEL: @test6( entry: %0 = tail call noalias i8* @malloc(i32 20) nounwind - %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false) + %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false, i1 false) %2 = load i8*, i8** @s, align 8 ; CHECK-NOT: @llvm.objectsize ; CHECK: @__memcpy_chk(i8* %0, i8* %1, i32 30, i32 20) @@ -154,7 +154,7 @@ %alloc = call noalias i8* @malloc(i32 48) nounwind store i8* %alloc, i8** %esc %gep = getelementptr inbounds i8, i8* %alloc, i32 16 - %objsize = call i32 @llvm.objectsize.i32.p0i8(i8* %gep, i1 false) nounwind readonly + %objsize = call i32 @llvm.objectsize.i32.p0i8(i8* %gep, i1 false, i1 false) nounwind readonly ; CHECK: ret i32 32 ret i32 %objsize } @@ -166,7 +166,7 @@ %alloc = call noalias i8* @calloc(i32 5, i32 7) nounwind store i8* %alloc, i8** %esc %gep = getelementptr inbounds i8, i8* %alloc, i32 5 - %objsize = call i32 @llvm.objectsize.i32.p0i8(i8* %gep, i1 false) nounwind readonly + %objsize = call i32 @llvm.objectsize.i32.p0i8(i8* %gep, i1 false, i1 false) nounwind readonly ; CHECK: ret i32 30 ret i32 %objsize } @@ -178,7 +178,7 @@ define i32 @test9(i8** %esc) { %call = tail call i8* @strdup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0)) nounwind store i8* %call, i8** %esc, align 8 - %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true) + %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false) ; CHECK: ret i32 8 ret i32 %1 } @@ -187,7 +187,7 @@ define i32 @test10(i8** %esc) { %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 3) nounwind store i8* %call, i8** %esc, align 8 - %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true) + %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false) ; CHECK: ret i32 4 ret i32 %1 } @@ -196,7 +196,7 @@ define i32 @test11(i8** %esc) { %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 7) nounwind store i8* %call, i8** %esc, align 8 - %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true) + %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false) ; CHECK: ret i32 8 ret i32 %1 } @@ -205,7 +205,7 @@ define i32 @test12(i8** %esc) { %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 8) nounwind store i8* %call, i8** %esc, align 8 - %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true) + %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false) ; CHECK: ret i32 8 ret i32 %1 } @@ -214,7 +214,7 @@ define i32 @test13(i8** %esc) { %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 57) nounwind store i8* %call, i8** %esc, align 8 - %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true) + %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false) ; CHECK: ret i32 8 ret i32 %1 } @@ -225,7 +225,7 @@ ; CHECK-NEXT: ret i32 60 define i32 @test18() { %bc = bitcast [60 x i8]* @globalalias to i8* - %1 = call i32 @llvm.objectsize.i32.p0i8(i8* %bc, i1 false) + %1 = call i32 @llvm.objectsize.i32.p0i8(i8* %bc, i1 false, i1 false) ret i32 %1 } @@ -235,7 +235,20 @@ ; CHECK: llvm.objectsize define i32 @test19() { %bc = bitcast [60 x i8]* @globalalias2 to i8* - %1 = call i32 @llvm.objectsize.i32.p0i8(i8* %bc, i1 false) + %1 = call i32 @llvm.objectsize.i32.p0i8(i8* %bc, i1 false, i1 false) ret i32 %1 } +; CHECK-LABEL: @test20( +; CHECK: ret i32 -1 +define i32 @test20() { + %1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 false, i1 true) + ret i32 %1 +} + +; CHECK-LABEL: @test21( +; CHECK: ret i32 0 +define i32 @test21() { + %1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 true, i1 true) + ret i32 %1 +} Index: test/Transforms/InstCombine/stpcpy_chk-1.ll =================================================================== --- test/Transforms/InstCombine/stpcpy_chk-1.ll +++ test/Transforms/InstCombine/stpcpy_chk-1.ll @@ -64,10 +64,10 @@ %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false) +; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) ; CHECK-NEXT: %1 = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 %len) ; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11) - %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false) + %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false) %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 %len) ret i8* %ret } @@ -81,7 +81,7 @@ ; CHECK-NEXT: %strlen = call i32 @strlen(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)) ; CHECK-NEXT: %1 = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 %strlen ; CHECK-NEXT: ret i8* %1 - %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false) + %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false) %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %dst, i32 %len) ret i8* %ret } @@ -100,4 +100,4 @@ } declare i8* @__stpcpy_chk(i8*, i8*, i32) nounwind -declare i32 @llvm.objectsize.i32.p0i8(i8*, i1) nounwind readonly +declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1) nounwind readonly Index: test/Transforms/InstCombine/strcpy_chk-1.ll =================================================================== --- test/Transforms/InstCombine/strcpy_chk-1.ll +++ test/Transforms/InstCombine/strcpy_chk-1.ll @@ -64,10 +64,10 @@ %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false) +; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) ; CHECK-NEXT: %1 = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 %len) ; CHECK-NEXT: ret i8* %1 - %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false) + %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false) %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 %len) ret i8* %ret } @@ -78,10 +78,10 @@ ; CHECK-LABEL: @test_simplify6( %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 -; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false) +; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false) ; CHECK-NEXT: %ret = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i32 %len) ; CHECK-NEXT: ret i8* %ret - %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false) + %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false) %ret = call i8* @__strcpy_chk(i8* %dst, i8* %dst, i32 %len) ret i8* %ret } @@ -100,4 +100,4 @@ } declare i8* @__strcpy_chk(i8*, i8*, i32) nounwind -declare i32 @llvm.objectsize.i32.p0i8(i8*, i1) nounwind readonly +declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1) nounwind readonly