-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[Clang] Allow non-constant sizes for __builtin_assume_dereferenceable. #156929
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Update Clang's __builtin_assume_dereferenceable to support non-constant lengths. The corresponding assume bundle has been updated to support non-constant sizes in cad62df. The current docs for the builtin don't mention the constant requirement for the size argument, so don't need to be updated: https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume-dereferenceable A number of patches landed recently to make the optimizer make better use of the dereferenceable assumptions, and once llvm#156730 lands, it can be used to vectorize some early-exit loops, for example std::find with std::vector::iterator: https://godbolt.org/z/qo58PKG37 #include <algorithm> #include <cstddef> #include <vector> auto find(std::vector<short>::iterator first, short s, unsigned size) { auto Addr = __builtin_assume_aligned(std::to_address(first), 2); __builtin_assume_dereferenceable(std::to_address(first), size * sizeof(short)); return std::find(first, first + size, s); }
@llvm/pr-subscribers-clang Author: Florian Hahn (fhahn) ChangesUpdate Clang's __builtin_assume_dereferenceable to support non-constant lengths. The corresponding assume bundle has been updated to support non-constant sizes in cad62df. The current docs for the builtin don't mention the constant requirement for the size argument, so don't need to be updated: https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume-dereferenceable A number of patches landed recently to make the optimizer make better use of the dereferenceable assumptions, and once #include <algorithm> auto find(std::vector<short>::iterator first, short s, unsigned size) { Full diff: https://github.com/llvm/llvm-project/pull/156929.diff 4 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bec001bf8e353..12974c128d5e7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -206,6 +206,7 @@ Non-comprehensive list of changes in this release
Currently, the use of ``__builtin_dedup_pack`` is limited to template arguments and base
specifiers, it also must be used within a template context.
+- ``__builtin_assume_dereferenceable`` now accepts non-constant size operands.
New Compiler Flags
------------------
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 27fc6f008d743..27639f06529cb 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -854,7 +854,7 @@ def BuiltinAssumeAligned : Builtin {
def BuiltinAssumeDereferenceable : Builtin {
let Spellings = ["__builtin_assume_dereferenceable"];
let Attributes = [NoThrow, Const];
- let Prototype = "void(void const*, _Constant size_t)";
+ let Prototype = "void(void const*, size_t)";
}
def BuiltinFree : Builtin {
diff --git a/clang/test/CodeGen/builtin-assume-dereferenceable.c b/clang/test/CodeGen/builtin-assume-dereferenceable.c
index cadffd4a84c26..0dc4ba089ee3a 100644
--- a/clang/test/CodeGen/builtin-assume-dereferenceable.c
+++ b/clang/test/CodeGen/builtin-assume-dereferenceable.c
@@ -32,3 +32,62 @@ int test2(int *a) {
__builtin_assume_dereferenceable(a, 32ull);
return a[0];
}
+
+// CHECK-LABEL: @test3(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8
+// CHECK-NEXT: store i32 [[N:%.*]], ptr [[N_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP1]] to i64
+// CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0]], i64 [[CONV]]) ]
+// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 0
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int test3(int *a, int n) {
+ __builtin_assume_dereferenceable(a, n);
+ return a[0];
+}
+
+// CHECK-LABEL: @test4(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i64, align 8
+// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8
+// CHECK-NEXT: store i64 [[N:%.*]], ptr [[N_ADDR]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[N_ADDR]], align 8
+// CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0]], i64 [[TMP1]]) ]
+// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 0
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int test4(int *a, unsigned long long n) {
+ __builtin_assume_dereferenceable(a, n);
+ return a[0];
+}
+
+// CHECK-LABEL: @test5(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[N_ADDR:%.*]] = alloca float, align 4
+// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8
+// CHECK-NEXT: store float [[N:%.*]], ptr [[N_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[N_ADDR]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = fptoui float [[TMP1]] to i64
+// CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0]], i64 [[CONV]]) ]
+// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 0
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT: ret i32 [[TMP3]]
+//
+int test5(int *a, float n) {
+ __builtin_assume_dereferenceable(a, n);
+ return a[0];
+}
diff --git a/clang/test/SemaCXX/builtin-assume-dereferenceable.cpp b/clang/test/SemaCXX/builtin-assume-dereferenceable.cpp
index b79b7c059567e..2cbd7ac3507bf 100644
--- a/clang/test/SemaCXX/builtin-assume-dereferenceable.cpp
+++ b/clang/test/SemaCXX/builtin-assume-dereferenceable.cpp
@@ -18,12 +18,12 @@ int test3(int *a) {
}
int test4(int *a, unsigned size) {
- a = __builtin_assume_dereferenceable(a, size); // expected-error {{argument to '__builtin_assume_dereferenceable' must be a constant integer}}
+ __builtin_assume_dereferenceable(a, size);
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}}
+ __builtin_assume_dereferenceable(a, size);
return a[0];
}
@@ -53,3 +53,8 @@ constexpr void *l = __builtin_assume_dereferenceable(p, 4); // expected-error {{
void *foo() {
return l;
}
+
+int test10(int *a) {
+ __builtin_assume_dereferenceable(a, a); // expected-error {{cannot initialize a parameter of type '__size_t' (aka 'unsigned long') with an lvalue of type 'int *'}}
+ return a[0];
+}
|
|
||
// CHECK-LABEL: @test3( | ||
// CHECK-NEXT: entry: | ||
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alignments in the tests make this a touch fragile, but I see the rest of the test does it, so YOLO.
Update Clang's __builtin_assume_dereferenceable to support non-constant lengths. The corresponding assume bundle has been updated to support non-constant sizes in cad62df.
The current docs for the builtin don't mention the constant requirement for the size argument, so don't need to be updated: https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume-dereferenceable
A number of patches landed recently to make the optimizer make better use of the dereferenceable assumptions, and once
#156730 lands, it can be used to vectorize some early-exit loops, for example std::find with std::vector::iterator: https://godbolt.org/z/qo58PKG37