[clang] 07ef7b1 - [Builtins] Add __builtin_assume_separate_storage

Bruno Cardoso Lopes via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 23 16:35:38 PDT 2023


Author: Bruno Cardoso Lopes
Date: 2023-03-23T16:35:30-07:00
New Revision: 07ef7b1ff21e8e3faaf8279b8ec6a7f0ac252fad

URL: https://github.com/llvm/llvm-project/commit/07ef7b1ff21e8e3faaf8279b8ec6a7f0ac252fad
DIFF: https://github.com/llvm/llvm-project/commit/07ef7b1ff21e8e3faaf8279b8ec6a7f0ac252fad.diff

LOG: [Builtins] Add __builtin_assume_separate_storage

Plumbing from the language level to the assume intrinsics with
separate_storage operand bundles.

Patch by David Goldblatt (davidtgoldblatt)

Differential Revision: https://reviews.llvm.org/D136515

Added: 
    clang/test/CodeGen/builtin-assume-separate-storage.c
    clang/test/Sema/builtin-assume-separate-storage.c

Modified: 
    clang/docs/LanguageExtensions.rst
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/Builtins.def
    clang/lib/CodeGen/CGBuiltin.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index f8c83d4d6d162..a9bdc83c53e7a 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2358,6 +2358,46 @@ evaluated, so any side effects of the expression will be discarded.
 
 Query for this feature with ``__has_builtin(__builtin_assume)``.
 
+.. _langext-__builtin_assume_separate_storage:
+
+``__builtin_assume_separate_storage``
+--------------------
+
+``__builtin_assume_separate_storage`` is used to provide the optimizer with the
+knowledge that its two arguments point to separately allocated objects.
+
+**Syntax**:
+
+.. code-block:: c++
+
+    __builtin_assume_separate_storage(const volatile void *, const volatile void *)
+
+**Example of Use**:
+
+.. code-block:: c++
+
+  int foo(int *x, int *y) {
+      __builtin_assume_separate_storage(x, y);
+      *x = 0;
+      *y = 1;
+      // The optimizer may optimize this to return 0 without reloading from *x.
+      return *x;
+  }
+
+**Description**:
+
+The arguments to this function are assumed to point into separately allocated
+storage (either 
diff erent variable definitions or 
diff erent dynamic storage
+allocations). The optimizer may use this fact to aid in alias analysis. If the
+arguments point into the same storage, the behavior is undefined. Note that the
+definition of "storage" here refers to the outermost enclosing allocation of any
+particular object (so for example, it's never correct to call this function
+passing the addresses of fields in the same struct, elements of the same array,
+etc.).
+
+Query for this feature with ``__has_builtin(__builtin_assume_separate_storage)``.
+
+
 ``__builtin_offsetof``
 ----------------------
 

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index faac3b17b223f..29e3f516c06e5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -124,6 +124,8 @@ Non-comprehensive list of changes in this release
 - Clang now supports ``__builtin_FILE_NAME()`` which returns the same
   information as the ``__FILE_NAME__`` macro (the presumed file name
   from the invocation point, with no path components included).
+- Clang now supports ``__builtin_assume_separate_storage`` that indicates that
+  its arguments point to objects in separate storage allocations.
 
 New Compiler Flags
 ------------------

diff  --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index 957375eccb84a..dea806099efbf 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -1591,6 +1591,7 @@ BUILTIN(__builtin_annotation, "v.", "tn")
 
 // Invariants
 BUILTIN(__builtin_assume, "vb", "nE")
+BUILTIN(__builtin_assume_separate_storage, "vvCD*vCD*", "nE")
 
 // Multiprecision Arithmetic Builtins.
 BUILTIN(__builtin_addcb, "UcUcCUcCUcCUc*", "n")

diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 6381d68c161c6..b3aea13878c1c 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2856,6 +2856,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     Builder.CreateCall(FnAssume, ArgValue);
     return RValue::get(nullptr);
   }
+  case Builtin::BI__builtin_assume_separate_storage: {
+    const Expr *Arg0 = E->getArg(0);
+    const Expr *Arg1 = E->getArg(1);
+
+    Value *Value0 = EmitScalarExpr(Arg0);
+    Value *Value1 = EmitScalarExpr(Arg1);
+
+    Value *Values[] = {Value0, Value1};
+    OperandBundleDefT<Value *> OBD("separate_storage", Values);
+    Builder.CreateAssumption(ConstantInt::getTrue(getLLVMContext()), {OBD});
+    return RValue::get(nullptr);
+  }
   case Builtin::BI__arithmetic_fence: {
     // Create the builtin call if FastMath is selected, and the target
     // supports the builtin, otherwise just return the argument.

diff  --git a/clang/test/CodeGen/builtin-assume-separate-storage.c b/clang/test/CodeGen/builtin-assume-separate-storage.c
new file mode 100644
index 0000000000000..ac82f27b3e720
--- /dev/null
+++ b/clang/test/CodeGen/builtin-assume-separate-storage.c
@@ -0,0 +1,36 @@
+// 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
+void *nonconst(void);
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    store ptr [[A:%.*]], ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    store ptr [[B:%.*]], ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[TMP0]], ptr [[TMP1]]) ]
+// CHECK-NEXT:    ret void
+//
+void test1(int *a, int *b) {
+
+  __builtin_assume_separate_storage(a, b);
+}
+
+// Separate storage assumptions evaluate their arguments unconditionally, like
+// assume_aligned but *unlike* assume. Check that we actually do so.
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    store ptr [[A:%.*]], ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    store ptr [[B:%.*]], ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[CALL:%.*]] = call ptr @nonconst()
+// CHECK-NEXT:    call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[TMP0]], ptr [[CALL]]) ]
+// CHECK-NEXT:    ret void
+//
+void test2(int *a, int *b) {
+  __builtin_assume_separate_storage(a, nonconst());
+}

diff  --git a/clang/test/Sema/builtin-assume-separate-storage.c b/clang/test/Sema/builtin-assume-separate-storage.c
new file mode 100644
index 0000000000000..f27d0b821d5ab
--- /dev/null
+++ b/clang/test/Sema/builtin-assume-separate-storage.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
+
+void *nonconst(void);
+
+void test1(int *a, int *b) {
+  __builtin_assume_separate_storage(a, b);
+  // Separate storage assumptions evaluate their arguments unconditionally, like
+  // assume_aligned but *unlike* assume. Check that we don't warn on it.
+  __builtin_assume_separate_storage(a, nonconst());
+  __builtin_assume_separate_storage(nonconst(), a);
+  __builtin_assume_separate_storage(a, 3); // expected-error {{incompatible integer to pointer conversion}}
+  __builtin_assume_separate_storage(3, a); // expected-error {{incompatible integer to pointer conversion}}
+}


        


More information about the cfe-commits mailing list