Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/docs/LangRef.rst @@ -12759,8 +12759,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: """"""""" @@ -12775,11 +12775,16 @@ 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 it's true and the pointer is in +address space 0, ``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: llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h =================================================================== --- llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h +++ llvm/trunk/include/llvm/Analysis/MemoryBuiltins.h @@ -32,12 +32,6 @@ class Type; class Value; -enum class ObjSizeMode { - Exact = 0, - Min = 1, - Max = 2 -}; - /// \brief Tests if a value is a call or invoke to a library function that /// allocates or reallocates memory (either malloc, calloc, realloc, or strdup /// like). @@ -129,17 +123,36 @@ // Utility functions to compute size of objects. // +/// Various options to control the behavior of getObjectSize. +struct ObjectSizeOpts { + /// Controls how we handle conditional statements with unknown conditions. + enum class Mode : uint8_t { + /// Fail to evaluate an unknown condition. + Exact, + /// Evaluate all branches of an unknown condition. If all evaluations + /// succeed, pick the minimum size. + Min, + /// Same as Min, except we pick the maximum size of all of the branches. + Max + }; + + /// How we want to evaluate this object's size. + Mode EvalMode = Mode::Exact; + /// Whether to round the result up to the alignment of allocas, byval + /// arguments, and global variables. + bool RoundToAlign = false; + /// If this is true, null pointers in address space 0 will be treated as + /// though they can't be evaluated. Otherwise, null is always considered to + /// point to a 0 byte region of memory. + bool NullIsUnknownSize = false; +}; + /// \brief Compute the size of the object pointed by Ptr. Returns true and the /// object size in Size if successful, and false otherwise. In this context, by /// object we mean the region of memory starting at Ptr to the end of the /// underlying object pointed to by Ptr. -/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas, -/// byval arguments, and global variables. -/// If Mode is Min or Max the size will be evaluated even if it depends on -/// 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); + const TargetLibraryInfo *TLI, ObjectSizeOpts Opts = {}); /// Try to turn a call to @llvm.objectsize into an integer value of the given /// Type. Returns null on failure. @@ -160,8 +173,7 @@ const DataLayout &DL; const TargetLibraryInfo *TLI; - bool RoundToAlign; - ObjSizeMode Mode; + ObjectSizeOpts Options; unsigned IntTyBits; APInt Zero; SmallPtrSet SeenInsts; @@ -174,8 +186,7 @@ public: ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, - LLVMContext &Context, bool RoundToAlign = false, - ObjSizeMode Mode = ObjSizeMode::Exact); + LLVMContext &Context, ObjectSizeOpts Options = {}); SizeOffsetType compute(Value *V); Index: llvm/trunk/include/llvm/IR/Intrinsics.td =================================================================== --- llvm/trunk/include/llvm/IR/Intrinsics.td +++ llvm/trunk/include/llvm/IR/Intrinsics.td @@ -441,7 +441,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: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp +++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp @@ -127,7 +127,9 @@ const TargetLibraryInfo &TLI, bool RoundToAlign = false) { uint64_t Size; - if (getObjectSize(V, Size, DL, &TLI, RoundToAlign)) + ObjectSizeOpts Opts; + Opts.RoundToAlign = RoundToAlign; + if (getObjectSize(V, Size, DL, &TLI, Opts)) return Size; return MemoryLocation::UnknownSize; } Index: llvm/trunk/lib/Analysis/MemoryBuiltins.cpp =================================================================== --- llvm/trunk/lib/Analysis/MemoryBuiltins.cpp +++ llvm/trunk/lib/Analysis/MemoryBuiltins.cpp @@ -394,10 +394,8 @@ /// If RoundToAlign is true, then Size is rounded up to the aligment of allocas, /// 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); + const TargetLibraryInfo *TLI, ObjectSizeOpts Opts) { + ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), Opts); SizeOffsetType Data = Visitor.compute(const_cast(Ptr)); if (!Visitor.bothKnown(Data)) return false; @@ -414,19 +412,23 @@ "ObjectSize must be a call to llvm.objectsize!"); bool MaxVal = cast(ObjectSize->getArgOperand(1))->isZero(); - ObjSizeMode Mode; + ObjectSizeOpts EvalOptions; // Unless we have to fold this to something, try to be as accurate as // possible. if (MustSucceed) - Mode = MaxVal ? ObjSizeMode::Max : ObjSizeMode::Min; + EvalOptions.EvalMode = + MaxVal ? ObjectSizeOpts::Mode::Max : ObjectSizeOpts::Mode::Min; else - Mode = ObjSizeMode::Exact; + EvalOptions.EvalMode = ObjectSizeOpts::Mode::Exact; + + EvalOptions.NullIsUnknownSize = + cast(ObjectSize->getArgOperand(2))->isOne(); // 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(ObjectSize->getType()); - if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, false, Mode) && + if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, EvalOptions) && isUIntN(ResultType->getBitWidth(), Size)) return ConstantInt::get(ResultType, Size); @@ -443,7 +445,7 @@ APInt ObjectSizeOffsetVisitor::align(APInt Size, uint64_t Align) { - if (RoundToAlign && Align) + if (Options.RoundToAlign && Align) return APInt(IntTyBits, alignTo(Size.getZExtValue(), Align)); return Size; } @@ -451,9 +453,8 @@ ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, - bool RoundToAlign, - ObjSizeMode Mode) - : DL(DL), TLI(TLI), RoundToAlign(RoundToAlign), Mode(Mode) { + ObjectSizeOpts Options) + : DL(DL), TLI(TLI), Options(Options) { // Pointer size must be rechecked for each object visited since it could have // a different address space. } @@ -596,7 +597,9 @@ } SizeOffsetType -ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull&) { +ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull& CPN) { + if (Options.NullIsUnknownSize && CPN.getType()->getAddressSpace() == 0) + return unknown(); return std::make_pair(Zero, Zero); } @@ -663,12 +666,12 @@ if (TrueResult == FalseResult) { return TrueSide; } - if (Mode == ObjSizeMode::Min) { + if (Options.EvalMode == ObjectSizeOpts::Mode::Min) { if (TrueResult.slt(FalseResult)) return TrueSide; return FalseSide; } - if (Mode == ObjSizeMode::Max) { + if (Options.EvalMode == ObjectSizeOpts::Mode::Max) { if (TrueResult.sgt(FalseResult)) return TrueSide; return FalseSide; @@ -719,7 +722,10 @@ } SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) { - ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, RoundToAlign); + ObjectSizeOpts ObjSizeOptions; + ObjSizeOptions.RoundToAlign = RoundToAlign; + + ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, ObjSizeOptions); SizeOffsetType Const = Visitor.compute(V); if (Visitor.bothKnown(Const)) return std::make_pair(ConstantInt::get(Context, Const.first), Index: llvm/trunk/lib/IR/AutoUpgrade.cpp =================================================================== --- llvm/trunk/lib/IR/AutoUpgrade.cpp +++ llvm/trunk/lib/IR/AutoUpgrade.cpp @@ -495,12 +495,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; } } @@ -1954,10 +1955,14 @@ Builder.CreateCall(NewFn, {CI->getArgOperand(0), Builder.getFalse()}); break; - case Intrinsic::objectsize: - NewCall = - Builder.CreateCall(NewFn, {CI->getArgOperand(0), CI->getArgOperand(1)}); + case Intrinsic::objectsize: { + Value *NullIsUnknownSize = CI->getNumArgOperands() == 2 + ? Builder.getFalse() + : CI->getArgOperand(2); + NewCall = Builder.CreateCall( + NewFn, {CI->getArgOperand(0), CI->getArgOperand(1), NullIsUnknownSize}); break; + } case Intrinsic::ctpop: NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)}); Index: llvm/trunk/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp +++ llvm/trunk/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp @@ -855,8 +855,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: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -2185,8 +2185,9 @@ (ClInstrumentationWithCallsThreshold >= 0 && ToInstrument.size() > (unsigned)ClInstrumentationWithCallsThreshold); const DataLayout &DL = F.getParent()->getDataLayout(); - ObjectSizeOffsetVisitor ObjSizeVis(DL, TLI, F.getContext(), - /*RoundToAlign=*/true); + ObjectSizeOpts ObjSizeOpts; + ObjSizeOpts.RoundToAlign = true; + ObjectSizeOffsetVisitor ObjSizeVis(DL, TLI, F.getContext(), ObjSizeOpts); // Instrument. int NumInstrumented = 0; Index: llvm/trunk/test/Assembler/auto_upgrade_intrinsics.ll =================================================================== --- llvm/trunk/test/Assembler/auto_upgrade_intrinsics.ll +++ llvm/trunk/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: llvm/trunk/test/CodeGen/AMDGPU/promote-alloca-mem-intrinsics.ll =================================================================== --- llvm/trunk/test/CodeGen/AMDGPU/promote-alloca-mem-intrinsics.ll +++ llvm/trunk/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: llvm/trunk/test/Transforms/CodeGenPrepare/basic.ll =================================================================== --- llvm/trunk/test/Transforms/CodeGenPrepare/basic.ll +++ llvm/trunk/test/Transforms/CodeGenPrepare/basic.ll @@ -9,7 +9,7 @@ ; rdar://8785296 define i32 @test1(i8* %ptr) nounwind ssp noredzone align 2 { entry: - %0 = tail call i64 @llvm.objectsize.i64(i8* %ptr, i1 false) + %0 = tail call i64 @llvm.objectsize.i64(i8* %ptr, i1 false, i1 false) %1 = icmp ugt i64 %0, 3 br i1 %1, label %T, label %trap @@ -25,6 +25,44 @@ ret i32 4 } -declare i64 @llvm.objectsize.i64(i8*, i1) nounwind readonly +; CHECK-LABEL: @test_objectsize_null_flag( +define i64 @test_objectsize_null_flag(i8* %ptr) { +entry: + ; CHECK: ret i64 -1 + %0 = tail call i64 @llvm.objectsize.i64(i8* null, i1 false, i1 true) + ret i64 %0 +} + +; CHECK-LABEL: @test_objectsize_null_flag_min( +define i64 @test_objectsize_null_flag_min(i8* %ptr) { +entry: + ; CHECK: ret i64 0 + %0 = tail call i64 @llvm.objectsize.i64(i8* null, i1 true, i1 true) + ret i64 %0 +} + +; Test foldable null pointers because we evaluate them with non-exact modes in +; CodeGenPrepare. +; CHECK-LABEL: @test_objectsize_null_flag_noas0( +define i64 @test_objectsize_null_flag_noas0() { +entry: + ; CHECK: ret i64 0 + %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 false, + i1 true) + ret i64 %0 +} + +; CHECK-LABEL: @test_objectsize_null_flag_min_noas0( +define i64 @test_objectsize_null_flag_min_noas0() { +entry: + ; CHECK: ret i64 0 + %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 true, + i1 true) + ret i64 %0 +} + + +declare i64 @llvm.objectsize.i64(i8*, i1, i1) nounwind readonly +declare i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)*, i1, i1) nounwind readonly declare void @llvm.trap() nounwind Index: llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/intrinsics.ll =================================================================== --- llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/intrinsics.ll +++ llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/intrinsics.ll @@ -1,18 +1,18 @@ ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s ; CHECK-LABEL: @objectsize_group_to_flat_i32( -; CHECK: %val = call i32 @llvm.objectsize.i32.p3i8(i8 addrspace(3)* %group.ptr, i1 true) +; CHECK: %val = call i32 @llvm.objectsize.i32.p3i8(i8 addrspace(3)* %group.ptr, i1 true, i1 false) define i32 @objectsize_group_to_flat_i32(i8 addrspace(3)* %group.ptr) #0 { %cast = addrspacecast i8 addrspace(3)* %group.ptr to i8 addrspace(4)* - %val = call i32 @llvm.objectsize.i32.p4i8(i8 addrspace(4)* %cast, i1 true) + %val = call i32 @llvm.objectsize.i32.p4i8(i8 addrspace(4)* %cast, i1 true, i1 false) ret i32 %val } ; CHECK-LABEL: @objectsize_global_to_flat_i64( -; CHECK: %val = call i64 @llvm.objectsize.i64.p3i8(i8 addrspace(3)* %global.ptr, i1 true) +; CHECK: %val = call i64 @llvm.objectsize.i64.p3i8(i8 addrspace(3)* %global.ptr, i1 true, i1 false) define i64 @objectsize_global_to_flat_i64(i8 addrspace(3)* %global.ptr) #0 { %cast = addrspacecast i8 addrspace(3)* %global.ptr to i8 addrspace(4)* - %val = call i64 @llvm.objectsize.i64.p4i8(i8 addrspace(4)* %cast, i1 true) + %val = call i64 @llvm.objectsize.i64.p4i8(i8 addrspace(4)* %cast, i1 true, i1 false) ret i64 %val } @@ -80,8 +80,8 @@ ret i64 %ret } -declare i32 @llvm.objectsize.i32.p4i8(i8 addrspace(4)*, i1) #1 -declare i64 @llvm.objectsize.i64.p4i8(i8 addrspace(4)*, i1) #1 +declare i32 @llvm.objectsize.i32.p4i8(i8 addrspace(4)*, i1, i1) #1 +declare i64 @llvm.objectsize.i64.p4i8(i8 addrspace(4)*, i1, i1) #1 declare i32 @llvm.amdgcn.atomic.inc.i32.p4i32(i32 addrspace(4)* nocapture, i32) #2 declare i64 @llvm.amdgcn.atomic.inc.i64.p4i64(i64 addrspace(4)* nocapture, i64) #2 declare i32 @llvm.amdgcn.atomic.dec.i32.p4i32(i32 addrspace(4)* nocapture, i32) #2 Index: llvm/trunk/test/Transforms/InstCombine/memset_chk-1.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/memset_chk-1.ll +++ llvm/trunk/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: llvm/trunk/test/Transforms/InstCombine/objsize.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/objsize.ll +++ llvm/trunk/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,9 @@ 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 i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)*, i1, i1) nounwind readonly declare i8* @__inline_memcpy_chk(i8*, i8*, i32) nounwind inlinehint @@ -88,7 +90,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 +112,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 +127,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 +139,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 +156,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 +168,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 +180,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 +189,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 +198,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 +207,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 +216,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 +227,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 +237,67 @@ ; 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 0 +define i32 @test20() { + %1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 false, i1 false) + 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 false) + ret i32 %1 +} + +; CHECK-LABEL: @test22( +; CHECK: llvm.objectsize +define i32 @test22() { + %1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 false, i1 true) + ret i32 %1 +} + +; CHECK-LABEL: @test23( +; CHECK: llvm.objectsize +define i32 @test23() { + %1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 true, i1 true) ret i32 %1 } +; 1 is an arbitrary non-zero address space. +; CHECK-LABEL: @test24( +; CHECK: ret i32 0 +define i32 @test24() { + %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 false, + i1 false) + ret i32 %1 +} + +; CHECK-LABEL: @test25( +; CHECK: ret i32 0 +define i32 @test25() { + %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 true, + i1 false) + ret i32 %1 +} + +; CHECK-LABEL: @test26( +; CHECK: ret i32 0 +define i32 @test26() { + %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 false, + i1 true) + ret i32 %1 +} + +; CHECK-LABEL: @test27( +; CHECK: ret i32 0 +define i32 @test27() { + %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 true, + i1 true) + ret i32 %1 +} Index: llvm/trunk/test/Transforms/InstCombine/stpcpy_chk-1.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/stpcpy_chk-1.ll +++ llvm/trunk/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: llvm/trunk/test/Transforms/InstCombine/strcpy_chk-1.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/strcpy_chk-1.ll +++ llvm/trunk/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