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
