diff --git a/docs/LangRef.rst b/docs/LangRef.rst index 64eca1c3f7b..57abe7f9067 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -14459,10 +14459,10 @@ 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``. +``null`` in address space 0 is used as its pointer argument. If it's ``false``, +``llvm.objectsize`` reports 0 bytes available when given ``null``. Otherwise, if +the ``null`` is in a non-zero address space or if ``true`` is given for the +third argument of ``llvm.objectsize``, we assume its size is unknown. The second and third arguments only accept constants. diff --git a/lib/Analysis/MemoryBuiltins.cpp b/lib/Analysis/MemoryBuiltins.cpp index deacdb9e324..686ad294378 100644 --- a/lib/Analysis/MemoryBuiltins.cpp +++ b/lib/Analysis/MemoryBuiltins.cpp @@ -642,7 +642,14 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitCallSite(CallSite CS) { SizeOffsetType ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull& CPN) { - if (Options.NullIsUnknownSize && CPN.getType()->getAddressSpace() == 0) + // If null is unknown, there's nothing we can do. Additionally, non-zero + // address spaces can make use of null, so we don't presume to know anything + // about that. + // + // TODO: How should this work with address space casts? We currently just drop + // them on the floor, but it's unclear what we should do when a NULL from + // addrspace(1) gets casted to addrspace(0) (or vice-versa). + if (Options.NullIsUnknownSize || CPN.getType()->getAddressSpace()) return unknown(); return std::make_pair(Zero, Zero); } diff --git a/test/Transforms/CodeGenPrepare/basic.ll b/test/Transforms/CodeGenPrepare/basic.ll index b8ca6d6cde9..768209abcdf 100644 --- a/test/Transforms/CodeGenPrepare/basic.ll +++ b/test/Transforms/CodeGenPrepare/basic.ll @@ -46,7 +46,7 @@ entry: ; CHECK-LABEL: @test_objectsize_null_flag_noas0( define i64 @test_objectsize_null_flag_noas0() { entry: - ; CHECK: ret i64 0 + ; CHECK: ret i64 -1 %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 false, i1 true) ret i64 %0 @@ -61,6 +61,24 @@ entry: ret i64 %0 } +; CHECK-LABEL: @test_objectsize_null_known_flag_noas0 +define i64 @test_objectsize_null_known_flag_noas0() { +entry: + ; CHECK: ret i64 -1 + %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 false, + i1 false) + ret i64 %0 +} + +; CHECK-LABEL: @test_objectsize_null_known_flag_min_noas0 +define i64 @test_objectsize_null_known_flag_min_noas0() { +entry: + ; CHECK: ret i64 0 + %0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 true, + i1 false) + 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 diff --git a/test/Transforms/InstCombine/objsize.ll b/test/Transforms/InstCombine/objsize.ll index 86b087567e2..12262c03670 100644 --- a/test/Transforms/InstCombine/objsize.ll +++ b/test/Transforms/InstCombine/objsize.ll @@ -271,7 +271,7 @@ define i32 @test23() { ; 1 is an arbitrary non-zero address space. ; CHECK-LABEL: @test24( -; CHECK: ret i32 0 +; CHECK: llvm.objectsize define i32 @test24() { %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 false, i1 false) @@ -279,7 +279,7 @@ define i32 @test24() { } ; CHECK-LABEL: @test25( -; CHECK: ret i32 0 +; CHECK: llvm.objectsize define i32 @test25() { %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 true, i1 false) @@ -287,7 +287,7 @@ define i32 @test25() { } ; CHECK-LABEL: @test26( -; CHECK: ret i32 0 +; CHECK: llvm.objectsize define i32 @test26() { %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 false, i1 true) @@ -295,7 +295,7 @@ define i32 @test26() { } ; CHECK-LABEL: @test27( -; CHECK: ret i32 0 +; CHECK: llvm.objectsize define i32 @test27() { %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 true, i1 true)