https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/121789
>From b7b0a7a8a04e579c512c13bf114613ced56b8fe5 Mon Sep 17 00:00:00 2001 From: Florian Hahn <f...@fhahn.com> Date: Mon, 6 Jan 2025 13:39:55 +0000 Subject: [PATCH 1/5] [Clang] Add __builtin_assume_dereferenceable to encode deref assumption. This patch adds a new __builtin_assume_dereferenceable to encode dereferenceability of a pointer using llvm.assume with an operand bundle. For now the builtin only accepts constant sizes, I am planning to drop this restriction in a follow-up change. This can be used to better optimize cases where a pointer is known to be dereferenceable, e.g. unconditionally loading from p2 when vectorizing the loop. int *get_ptr(); void foo(int* src, int x) { int *p2 = get_ptr(); __builtin_assume_aligned(p2, 4); __builtin_assume_dereferenceable(p2, 4000); for (unsigned I = 0; I != 1000; ++I) { int x = src[I]; if (x == 0) x = p2[I]; src[I] = x; } } --- clang/docs/LanguageExtensions.rst | 35 ++++++++++++++++ clang/include/clang/Basic/Builtins.td | 6 +++ clang/lib/CodeGen/CGBuiltin.cpp | 10 +++++ .../CodeGen/builtin-assume-dereferenceable.c | 34 +++++++++++++++ .../Sema/builtin-assume-dereferenceable.c | 41 +++++++++++++++++++ llvm/include/llvm/IR/IRBuilder.h | 5 +++ llvm/lib/IR/IRBuilder.cpp | 10 +++++ 7 files changed, 141 insertions(+) create mode 100644 clang/test/CodeGen/builtin-assume-dereferenceable.c create mode 100644 clang/test/Sema/builtin-assume-dereferenceable.c diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 973cf8f9d091c..3e9b9a0a3483a 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -2866,6 +2866,41 @@ etc.). Query for this feature with ``__has_builtin(__builtin_assume_separate_storage)``. +``__builtin_assume_dereferenceable`` +------------------------------------- + +``__builtin_assume_derefernceable`` is used to provide the optimizer with the +knowledge that the pointer argument P is dereferenceable up to the specified +number of bytes. + +**Syntax**: + +.. code-block:: c++ + + __builtin_assume_dereferenceable(const void *, size_t) + +**Example of Use**: + +.. code-block:: c++ + + int foo(int *x, int y) { + __builtin_assume_dereferenceable(x, 4); + int z = 0; + if (y == 1) { + // The optimizer may execute the load of x unconditionally. + z = *x; + } + return z; + } + +**Description**: + +The arguments to this function provide a start pointer ``P`` and a size ``S``. +``P`` must be non-null and ``S`` at least 1. The optimizer may assume that +``S`` bytes are dereferenceable starting at ``P``. + +Query for this feature with ``__has_builtin(__builtin_assume_dereferenceable)``. + ``__builtin_offsetof`` ---------------------- diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 29939242596ba..398cd3094802f 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -839,6 +839,12 @@ def BuiltinAssumeAligned : Builtin { let Prototype = "void*(void const*, size_t, ...)"; } +def BuiltinAssumeDereferenceable : Builtin { + let Spellings = ["__builtin_assume_dereferenceable"]; + let Attributes = [NoThrow, Const, Constexpr]; + let Prototype = "void(void const*, _Constant size_t)"; +} + def BuiltinFree : Builtin { let Spellings = ["__builtin_free"]; let Attributes = [FunctionWithBuiltinPrefix, NoThrow]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 361e4c4bf2e2e..f04c252d10282 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3839,6 +3839,16 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, AlignmentCI, OffsetValue); return RValue::get(PtrValue); } + case Builtin::BI__builtin_assume_dereferenceable: { + const Expr *Ptr = E->getArg(0); + Value *PtrValue = EmitScalarExpr(Ptr); + Value *SizeValue = EmitScalarExpr(E->getArg(1)); + if (SizeValue->getType() != IntPtrTy) + SizeValue = + Builder.CreateIntCast(SizeValue, IntPtrTy, false, "casted.size"); + Builder.CreateDereferenceableAssumption(PtrValue, SizeValue); + return RValue::get(nullptr); + } case Builtin::BI__assume: case Builtin::BI__builtin_assume: { if (E->getArg(0)->HasSideEffects(getContext())) diff --git a/clang/test/CodeGen/builtin-assume-dereferenceable.c b/clang/test/CodeGen/builtin-assume-dereferenceable.c new file mode 100644 index 0000000000000..cadffd4a84c26 --- /dev/null +++ b/clang/test/CodeGen/builtin-assume-dereferenceable.c @@ -0,0 +1,34 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// CHECK-LABEL: @test1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0]], i64 10) ] +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret i32 [[TMP2]] +// +int test1(int *a) { + __builtin_assume_dereferenceable(a, 10); + return a[0]; +} + +// CHECK-LABEL: @test2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0]], i64 32) ] +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret i32 [[TMP2]] +// +int test2(int *a) { + __builtin_assume_dereferenceable(a, 32ull); + return a[0]; +} diff --git a/clang/test/Sema/builtin-assume-dereferenceable.c b/clang/test/Sema/builtin-assume-dereferenceable.c new file mode 100644 index 0000000000000..07b23022043cd --- /dev/null +++ b/clang/test/Sema/builtin-assume-dereferenceable.c @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -DSIZE_T_64 -fsyntax-only -Wno-strict-prototypes -triple x86_64-linux -verify %s + +int test1(int *a) { + __builtin_assume_dereferenceable(a, 32); + return a[0]; +} + +int test2(int *a) { + __builtin_assume_dereferenceable(a, 32ull); + return a[0]; +} + +int test3(int *a) { + __builtin_assume_dereferenceable(a, 32u); + return a[0]; +} + +int test4(int *a, unsigned size) { + a = __builtin_assume_dereferenceable(a, size); // expected-error {{argument to '__builtin_assume_dereferenceable' must be a constant integer}} + return a[0]; +} + +int test5(int *a, unsigned long long size) { + a = __builtin_assume_dereferenceable(a, size); // expected-error {{argument to '__builtin_assume_dereferenceable' must be a constant integer}} + return a[0]; +} + +int test6(float a) { + __builtin_assume_dereferenceable(a, 2); // expected-error {{passing 'float' to parameter of incompatible type 'const void *'}} + return 0;; +} + +int test7(int *a) { + __builtin_assume_dereferenceable(a, 32, 1); // expected-error {{too many arguments to function call, expected 2, have 3}} + return a[0]; +} + +int test8(int *a) { + __builtin_assume_dereferenceable(a); // expected-error {{too few arguments to function call, expected 2, have 1}} + return a[0]; +} diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 1692f7dfb7fa7..7e51a16d51632 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -2684,6 +2684,11 @@ class IRBuilderBase { CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, Value *Alignment, Value *OffsetValue = nullptr); + + /// Create an assume intrinsic call that represents an dereferencable + /// assumption on the provided pointer. + /// + CallInst *CreateDereferenceableAssumption(Value *PtrValue, Value *SizeValue); }; /// This provides a uniform API for creating instructions and inserting diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index d46ae206890e8..134459265cecb 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -1284,6 +1284,16 @@ CallInst *IRBuilderBase::CreateAlignmentAssumption(const DataLayout &DL, return CreateAlignmentAssumptionHelper(DL, PtrValue, Alignment, OffsetValue); } +CallInst *IRBuilderBase::CreateDereferenceableAssumption(Value *PtrValue, + Value *SizeValue) { + assert(isa<PointerType>(PtrValue->getType()) && + "trying to create an deferenceable assumption on a non-pointer?"); + SmallVector<Value *, 4> Vals({PtrValue, SizeValue}); + OperandBundleDefT<Value *> DereferenceableOpB("dereferenceable", Vals); + return CreateAssumption(ConstantInt::getTrue(getContext()), + {DereferenceableOpB}); +} + IRBuilderDefaultInserter::~IRBuilderDefaultInserter() = default; IRBuilderCallbackInserter::~IRBuilderCallbackInserter() = default; IRBuilderFolder::~IRBuilderFolder() = default; >From 2d2dbab427b5badfa94d8c140d389b2403ac3495 Mon Sep 17 00:00:00 2001 From: Florian Hahn <f...@fhahn.com> Date: Wed, 8 Jan 2025 12:13:27 +0000 Subject: [PATCH 2/5] !fixup address latest comments, thanks! --- clang/include/clang/Basic/Builtins.td | 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 4 +++- .../CodeGen/builtin-assume-dereferenceable.c | 2 ++ .../builtin-assume-dereferenceable.cpp} | 18 ++++++++++++++++-- llvm/include/llvm/IR/IRBuilder.h | 5 ++++- llvm/lib/IR/IRBuilder.cpp | 8 ++++++++ 6 files changed, 34 insertions(+), 5 deletions(-) rename clang/test/{Sema/builtin-assume-dereferenceable.c => SemaCXX/builtin-assume-dereferenceable.cpp} (57%) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 398cd3094802f..0e5df338dd2e5 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -841,7 +841,7 @@ def BuiltinAssumeAligned : Builtin { def BuiltinAssumeDereferenceable : Builtin { let Spellings = ["__builtin_assume_dereferenceable"]; - let Attributes = [NoThrow, Const, Constexpr]; + let Attributes = [NoThrow, Const]; let Prototype = "void(void const*, _Constant size_t)"; } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f04c252d10282..4ba1c4fb824a5 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3841,12 +3841,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, } case Builtin::BI__builtin_assume_dereferenceable: { const Expr *Ptr = E->getArg(0); + const Expr *Size= E->getArg(1); Value *PtrValue = EmitScalarExpr(Ptr); - Value *SizeValue = EmitScalarExpr(E->getArg(1)); + Value *SizeValue = EmitScalarExpr(Size); if (SizeValue->getType() != IntPtrTy) SizeValue = Builder.CreateIntCast(SizeValue, IntPtrTy, false, "casted.size"); Builder.CreateDereferenceableAssumption(PtrValue, SizeValue); + Builder.CreateNonNullAssumption(PtrValue); return RValue::get(nullptr); } case Builtin::BI__assume: diff --git a/clang/test/CodeGen/builtin-assume-dereferenceable.c b/clang/test/CodeGen/builtin-assume-dereferenceable.c index cadffd4a84c26..bf632f6e10182 100644 --- a/clang/test/CodeGen/builtin-assume-dereferenceable.c +++ b/clang/test/CodeGen/builtin-assume-dereferenceable.c @@ -7,6 +7,7 @@ // CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0]], i64 10) ] +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 8 // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 0 // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 @@ -23,6 +24,7 @@ int test1(int *a) { // CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0]], i64 32) ] +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 8 // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 0 // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 diff --git a/clang/test/Sema/builtin-assume-dereferenceable.c b/clang/test/SemaCXX/builtin-assume-dereferenceable.cpp similarity index 57% rename from clang/test/Sema/builtin-assume-dereferenceable.c rename to clang/test/SemaCXX/builtin-assume-dereferenceable.cpp index 07b23022043cd..b79b7c059567e 100644 --- a/clang/test/Sema/builtin-assume-dereferenceable.c +++ b/clang/test/SemaCXX/builtin-assume-dereferenceable.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -DSIZE_T_64 -fsyntax-only -Wno-strict-prototypes -triple x86_64-linux -verify %s +// RUN: %clang_cc1 -DSIZE_T_64 -fsyntax-only -verify -std=c++11 -triple x86_64-linux-gnu %s +// RUN: %clang_cc1 -DSIZE_T_64 -fsyntax-only -verify -std=c++11 -triple x86_64-linux-gnu %s -fexperimental-new-constant-interpreter + int test1(int *a) { __builtin_assume_dereferenceable(a, 32); @@ -26,7 +28,7 @@ int test5(int *a, unsigned long long size) { } int test6(float a) { - __builtin_assume_dereferenceable(a, 2); // expected-error {{passing 'float' to parameter of incompatible type 'const void *'}} + __builtin_assume_dereferenceable(a, 2); // expected-error {{cannot initialize a parameter of type 'const void *' with an lvalue of type 'float'}} return 0;; } @@ -39,3 +41,15 @@ int test8(int *a) { __builtin_assume_dereferenceable(a); // expected-error {{too few arguments to function call, expected 2, have 1}} return a[0]; } + +int test9(int *a) { + a[0] = __builtin_assume_dereferenceable(a, 32); // expected-error {{assigning to 'int' from incompatible type 'void'}} + return a[0]; +} + +constexpr int *p = 0; +constexpr void *l = __builtin_assume_dereferenceable(p, 4); // expected-error {{cannot initialize a variable of type 'void *const' with an rvalue of type 'void'}} + +void *foo() { + return l; +} diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 7e51a16d51632..742c16edc1c8a 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -2687,8 +2687,11 @@ class IRBuilderBase { /// Create an assume intrinsic call that represents an dereferencable /// assumption on the provided pointer. - /// CallInst *CreateDereferenceableAssumption(Value *PtrValue, Value *SizeValue); + + /// Create an assume intrinsic call that represents a nonnull assumption + /// on the provided pointer. + CallInst *CreateNonNullAssumption(Value *PtrValue); }; /// This provides a uniform API for creating instructions and inserting diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 134459265cecb..d291c351eb4f7 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -1294,6 +1294,14 @@ CallInst *IRBuilderBase::CreateDereferenceableAssumption(Value *PtrValue, {DereferenceableOpB}); } +CallInst *IRBuilderBase::CreateNonNullAssumption(Value *PtrValue) { + assert(isa<PointerType>(PtrValue->getType()) && + "trying to create an nonnull assumption on a non-pointer?"); + SmallVector<Value *, 4> Vals({PtrValue}); + OperandBundleDefT<Value *> NonNullOpB("nonnull", Vals); + return CreateAssumption(ConstantInt::getTrue(getContext()), {NonNullOpB}); +} + IRBuilderDefaultInserter::~IRBuilderDefaultInserter() = default; IRBuilderCallbackInserter::~IRBuilderCallbackInserter() = default; IRBuilderFolder::~IRBuilderFolder() = default; >From 6604a4470b9e292bea29d188ae19a20a136240aa Mon Sep 17 00:00:00 2001 From: Florian Hahn <f...@fhahn.com> Date: Wed, 8 Jan 2025 13:15:07 +0000 Subject: [PATCH 3/5] !fixup fix formatting --- clang/lib/CodeGen/CGBuiltin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 4ba1c4fb824a5..f2c7027b510e8 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3841,7 +3841,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, } case Builtin::BI__builtin_assume_dereferenceable: { const Expr *Ptr = E->getArg(0); - const Expr *Size= E->getArg(1); + const Expr *Size = E->getArg(1); Value *PtrValue = EmitScalarExpr(Ptr); Value *SizeValue = EmitScalarExpr(Size); if (SizeValue->getType() != IntPtrTy) >From b2e443c8c74346cb11885db6ae6686ad92b0b111 Mon Sep 17 00:00:00 2001 From: Florian Hahn <f...@fhahn.com> Date: Thu, 9 Jan 2025 21:59:07 +0000 Subject: [PATCH 4/5] !fixup undo nonnull assumption, clarify docs --- clang/docs/LanguageExtensions.rst | 18 ++++++++++++------ clang/lib/CodeGen/CGBuiltin.cpp | 1 - .../CodeGen/builtin-assume-dereferenceable.c | 2 -- llvm/include/llvm/IR/IRBuilder.h | 4 ---- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 3e9b9a0a3483a..7d27da2386296 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -2869,7 +2869,7 @@ Query for this feature with ``__has_builtin(__builtin_assume_separate_storage)`` ``__builtin_assume_dereferenceable`` ------------------------------------- -``__builtin_assume_derefernceable`` is used to provide the optimizer with the +``__builtin_assume_dereferenceable`` is used to provide the optimizer with the knowledge that the pointer argument P is dereferenceable up to the specified number of bytes. @@ -2884,20 +2884,26 @@ number of bytes. .. code-block:: c++ int foo(int *x, int y) { - __builtin_assume_dereferenceable(x, 4); + __builtin_assume_dereferenceable(x, sizeof(int)); int z = 0; if (y == 1) { - // The optimizer may execute the load of x unconditionally. + // The optimizer may execute the load of x unconditionally due to + // __builtin_assume_dereferenceable guaranteeing sizeof(int) bytes can + // be loaded speculatively without trapping. z = *x; - } + } return z; } **Description**: The arguments to this function provide a start pointer ``P`` and a size ``S``. -``P`` must be non-null and ``S`` at least 1. The optimizer may assume that -``S`` bytes are dereferenceable starting at ``P``. +``S`` must be at least 1 and a constant. The optimizer may assume that ``S`` +bytes are dereferenceable starting at ``P``. Note that this does not necessarily +imply that ``P`` is non-null as ``nullptr`` can be dereferenced in some cases. +The assumption also does not imply that ``P`` is not dereferenceable past ``S`` +bytes. + Query for this feature with ``__has_builtin(__builtin_assume_dereferenceable)``. diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f2c7027b510e8..61939d1f75ed0 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3848,7 +3848,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, SizeValue = Builder.CreateIntCast(SizeValue, IntPtrTy, false, "casted.size"); Builder.CreateDereferenceableAssumption(PtrValue, SizeValue); - Builder.CreateNonNullAssumption(PtrValue); return RValue::get(nullptr); } case Builtin::BI__assume: diff --git a/clang/test/CodeGen/builtin-assume-dereferenceable.c b/clang/test/CodeGen/builtin-assume-dereferenceable.c index bf632f6e10182..cadffd4a84c26 100644 --- a/clang/test/CodeGen/builtin-assume-dereferenceable.c +++ b/clang/test/CodeGen/builtin-assume-dereferenceable.c @@ -7,7 +7,6 @@ // CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0]], i64 10) ] -// CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 8 // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 0 // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 @@ -24,7 +23,6 @@ int test1(int *a) { // CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 // CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0]], i64 32) ] -// CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 8 // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 0 // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 742c16edc1c8a..933dbb306d1fc 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -2688,10 +2688,6 @@ class IRBuilderBase { /// Create an assume intrinsic call that represents an dereferencable /// assumption on the provided pointer. CallInst *CreateDereferenceableAssumption(Value *PtrValue, Value *SizeValue); - - /// Create an assume intrinsic call that represents a nonnull assumption - /// on the provided pointer. - CallInst *CreateNonNullAssumption(Value *PtrValue); }; /// This provides a uniform API for creating instructions and inserting >From 2835b3ca2bc80867ab582993c489497c2e69108f Mon Sep 17 00:00:00 2001 From: Florian Hahn <f...@fhahn.com> Date: Fri, 10 Jan 2025 14:50:05 +0000 Subject: [PATCH 5/5] !fixup address comments, fix builds --- clang/docs/LanguageExtensions.rst | 4 ++-- llvm/lib/IR/IRBuilder.cpp | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 7d27da2386296..2a956ad5b2909 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -2870,8 +2870,8 @@ Query for this feature with ``__has_builtin(__builtin_assume_separate_storage)`` ------------------------------------- ``__builtin_assume_dereferenceable`` is used to provide the optimizer with the -knowledge that the pointer argument P is dereferenceable up to the specified -number of bytes. +knowledge that the pointer argument P is dereferenceable up to at least the +specified number of bytes. **Syntax**: diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index d291c351eb4f7..134459265cecb 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -1294,14 +1294,6 @@ CallInst *IRBuilderBase::CreateDereferenceableAssumption(Value *PtrValue, {DereferenceableOpB}); } -CallInst *IRBuilderBase::CreateNonNullAssumption(Value *PtrValue) { - assert(isa<PointerType>(PtrValue->getType()) && - "trying to create an nonnull assumption on a non-pointer?"); - SmallVector<Value *, 4> Vals({PtrValue}); - OperandBundleDefT<Value *> NonNullOpB("nonnull", Vals); - return CreateAssumption(ConstantInt::getTrue(getContext()), {NonNullOpB}); -} - IRBuilderDefaultInserter::~IRBuilderDefaultInserter() = default; IRBuilderCallbackInserter::~IRBuilderCallbackInserter() = default; IRBuilderFolder::~IRBuilderFolder() = default; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits