https://github.com/eleviant updated 
https://github.com/llvm/llvm-project/pull/196392

>From eaea2cd767cefec9da55c4645920cac051f3b0be Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <[email protected]>
Date: Tue, 14 Apr 2026 16:17:11 +0200
Subject: [PATCH 1/4] [clang] Introduce -fstable-pointer-subtraction flag

The C and C++ standards require both operands of a pointer subtraction to
refer to elements of the same array object. Clang/LLVM currently relies on
this rule in several optimizations:

* `inbounds` GEP introduces UB-based assumptions once the computed address
  escapes the bounds of the originating object.

* `sdiv exact` assumes that the byte offset between two pointers is an exact
  multiple of the pointee size when lowering pointer subtraction.

While `-fwrapv-pointer` allows Clang to emit regular GEPs instead of
`inbounds` GEPs, there is currently no equivalent mechanism to avoid
generating `sdiv exact` for pointer subtraction operations.

This becomes an issue for low-level code such as kernels and boot loaders,
where pointer arithmetic is often performed over externally defined memory
layouts rather than well-typed C objects. In such cases, the assumptions
required by `sdiv exact` may not hold, causing the result to become poison
and enabling incorrect optimizations.

Introduce `-fstable-pointer-subtraction` to suppress these assumptions and
preserve stable pointer subtraction semantics in the generated IR.
---
 clang/include/clang/Basic/LangOptions.def |  2 ++
 clang/include/clang/Options/Options.td    |  7 +++++++
 clang/lib/CodeGen/CGExprScalar.cpp        |  2 ++
 clang/test/CodeGen/ptr-subtract-stable.c  | 15 +++++++++++++++
 4 files changed, 26 insertions(+)
 create mode 100644 clang/test/CodeGen/ptr-subtract-stable.c

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 3bbb40ba09f05..c7fcc6939e3cb 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -530,6 +530,8 @@ LANGOPT(EnableLifetimeSafetyTUAnalysis, 1, 0, 
NotCompatible, "Lifetime safety at
 LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector 
type")
 LANGOPT(Reflection      , 1, 0, NotCompatible, "C++26 Reflection")
 
+LANGOPT(StablePointerSubtraction, 1, 0, NotCompatible, "Make unaligned pointer 
subtraction stable")
+
 #undef LANGOPT
 #undef ENUM_LANGOPT
 #undef VALUE_LANGOPT
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 025e8e7d7d761..3ab7701cb7bdb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4819,6 +4819,13 @@ def fno_wrapv : Flag<["-"], "fno-wrapv">, Group<f_Group>,
 def fwrapv_pointer : Flag<["-"], "fwrapv-pointer">, Group<f_Group>,
   Visibility<[ClangOption, CLOption, CC1Option, FlangOption, FC1Option]>,
   HelpText<"Treat pointer overflow as two's complement">;
+def fstable_pointer_subtraction :
+  Flag<["-"], "fstable-pointer-subtraction">, Group<f_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<
+    "Allow stable subtraction of pointers not aligned to object boundaries"
+  >,
+  MarshallingInfoFlag<LangOpts<"StablePointerSubtraction">>;
 def fno_wrapv_pointer : Flag<["-"], "fno-wrapv-pointer">, Group<f_Group>,
   Visibility<[ClangOption, CLOption, FlangOption]>;
 def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>,
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index c8a8ec7b6d928..fad45dd7ebed8 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4990,6 +4990,8 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
     divisor = CGF.CGM.getSize(elementSize);
   }
 
+  if (CGF.getLangOpts().StablePointerSubtraction)
+    return Builder.CreateSDiv(diffInChars, divisor, "sub.ptr.div");
   // Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since
   // pointer difference in C is only defined in the case where both operands
   // are pointing to elements of an array.
diff --git a/clang/test/CodeGen/ptr-subtract-stable.c 
b/clang/test/CodeGen/ptr-subtract-stable.c
new file mode 100644
index 0000000000000..d18dd16cb4982
--- /dev/null
+++ b/clang/test/CodeGen/ptr-subtract-stable.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -emit-llvm -O2 -triple x86_64-windows-msvc 
-fstable-pointer-subtraction -fms-extensions %s -o - | FileCheck %s
+
+// Check that pointer subtraction isn't nuw/nsv and sdiv isn't exact
+// CHECK-LABEL: i64 @sub(ptr noundef %p, ptr noundef %q)
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %sub.ptr.lhs.cast = ptrtoint ptr %p to i64
+// CHECK-NEXT:    %sub.ptr.rhs.cast = ptrtoint ptr %q to i64
+// CHECK-NEXT:    %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+// CHECK-NEXT:    %sub.ptr.div = sdiv i64 %sub.ptr.sub, 4
+// CHECK-NEXT:    ret i64 %sub.ptr.div
+
+__declspec(noinline) long long sub(long* p, long* q) {
+  return p - q;
+}
+

>From d05cd0dc549519f726027de2a14525dce8deb48e Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <[email protected]>
Date: Wed, 27 May 2026 13:30:22 +0200
Subject: [PATCH 2/4] Add DocBrief

---
 clang/include/clang/Options/Options.td | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 3ab7701cb7bdb..284148e221115 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4825,6 +4825,12 @@ def fstable_pointer_subtraction :
   HelpText<
     "Allow stable subtraction of pointers not aligned to object boundaries"
   >,
+  DocBrief<
+    "When subtracting two pointers, do not assume that the byte difference is 
an "
+    "exact multiple of the pointee type size. The computed result is rounded "
+    "toward zero instead of producing a poison value. Users should prefer 
casting "
+    "pointers to ``char *`` before subtracting instead of relying on this 
flag."
+  >,
   MarshallingInfoFlag<LangOpts<"StablePointerSubtraction">>;
 def fno_wrapv_pointer : Flag<["-"], "fno-wrapv-pointer">, Group<f_Group>,
   Visibility<[ClangOption, CLOption, FlangOption]>;

>From 639588083e8c8c2e19b02ba15e4cd7f2b8e1d9b8 Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <[email protected]>
Date: Tue, 2 Jun 2026 13:19:54 +0200
Subject: [PATCH 3/4] Added documentation

---
 clang/docs/UsersManual.rst | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 3392a210f0bb0..dc175d49dea6e 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -2755,6 +2755,20 @@ are listed below.
    If ``-falign-functions`` is specified, or if the function has an
    ``aligned`` attribute, this option is ignored.
 
+.. option:: -fstable-pointer-subtraction
+
+  The C and C++ standards require both operands of a pointer subtraction to
+  refer to elements of the same array object. Clang normally exploits this
+  rule when lowering pointer subtraction operations, for example by emitting
+  IR constructs such as ``sdiv exact`` that rely on the computed byte offset
+  being an exact multiple of the pointee size.
+
+  ``-fstable-pointer-subtraction`` disables these assumptions and emits IR
+  that preserves the behavior of pointer subtraction even when the standard
+  requirements are violated. This is primarily intended for low-level code,
+  such as kernels and boot loaders, that performs pointer arithmetic over
+  externally defined memory layouts rather than ordinary C or C++ objects.
+
 .. _strict_aliasing:
 
 Strict Aliasing

>From e9948395488144ef46bd034ad85e9ee378bf25ef Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <[email protected]>
Date: Tue, 2 Jun 2026 13:33:23 +0200
Subject: [PATCH 4/4] Added release notes

---
 clang/docs/ReleaseNotes.rst | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c302a121457b5..9e579b17d0cdf 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -354,6 +354,11 @@ New Compiler Flags
   that ``bool`` values loaded from memory cannot have a bit pattern other
   than 0 or 1.
 
+- New option `-fstable-pointer-subtraction` added to disable optimizations
+  that assume both operands of a pointer subtraction refer to elements of the
+  same array object, preserving stable semantics for pointer subtraction in
+  low-level code that operates on externally defined memory layouts.
+
 Deprecated Compiler Flags
 -------------------------
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to