llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-codegen

Author: eleviant

<details>
<summary>Changes</summary>

The C and C++ standards require both operands of 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 assumptions once the computed address escapes 
the originating object bounds.

- `sdiv exact` assumes perfectly aligned offsets for pointer difference 
computations.

- `sdiv exact` may be folded into `ashr` for power-of-two element sizes, 
changing rounding semantics.

Under `-fms-kernel`, these assumptions are too strict and may break valid 
kernel-style code patterns.

Mitigate the issue by applying `-fwrapv-pointer` semantics and replacing `sdiv 
exact` with regular `sdiv` when `-fms-kernel` is enabled.

---
Full diff: https://github.com/llvm/llvm-project/pull/196392.diff


3 Files Affected:

- (modified) clang/lib/CodeGen/CGExprScalar.cpp (+3) 
- (modified) clang/lib/Frontend/CompilerInvocation.cpp (+1-1) 
- (added) clang/test/CodeGen/MSKernel/subptr.c (+43) 


``````````diff
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index d60f1b37be50e..e090e815c956a 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4982,6 +4982,9 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
     divisor = CGF.CGM.getSize(elementSize);
   }
 
+  // With -fms-kernel we emit normal sdiv to mitigate UB.
+  if (CGF.getLangOpts().Kernel)
+    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/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index c6e8644905964..4ed068a0481b8 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4215,7 +4215,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, 
ArgList &Args,
   }
   else if (Args.hasArg(OPT_fwrapv))
     Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
-  if (Args.hasArg(OPT_fwrapv_pointer))
+  if (Args.hasArg(OPT_fwrapv_pointer) || Opts.Kernel)
     Opts.PointerOverflowDefined = true;
 
   Opts.MSCompatibilityVersion = 0;
diff --git a/clang/test/CodeGen/MSKernel/subptr.c 
b/clang/test/CodeGen/MSKernel/subptr.c
new file mode 100644
index 0000000000000..20d6bbb5024b5
--- /dev/null
+++ b/clang/test/CodeGen/MSKernel/subptr.c
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -emit-llvm -O2 -triple x86_64-windows-msvc -fms-kernel 
-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
+
+// The getelementptr instructions using indexes which can't be statically
+// evaluated must not be inbounds
+// CHECK-LABEL: i32 @weird_func(ptr noundef %mem, i32 noundef %i, i32 noundef 
%j)
+// CHECK-NOT:   getelementptr inbounds
+
+// The value of x can be negative, so compiler can't prove we
+// always stay inbounds, even though max possible value of x
+// is less than the size of array
+// CHECK-LABEL: i32 @foo(i8 noundef %x)
+// CHECK-NOT:   getelementptr inbounds
+
+typedef struct S {
+  long a,b;
+  long v[2];
+} S;
+
+__declspec(noinline) long long sub(long* p, long* q) {
+  return p - q;
+}
+
+int weird_func(void* mem, long i, long j) {
+  S* ps = (S*)mem;
+  long* q = &ps->v[i];
+  long* p = &ps->v[j];
+  return sub(p, q);
+}
+
+long _g[256];
+long foo(char x) {
+  return _g[x];
+}
+

``````````

</details>


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

Reply via email to