diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 7529d4465f2c..af89b427531d 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4447,6 +4447,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/test/CodeGen/MSKernel/subptr.c b/clang/test/CodeGen/MSKernel/subptr.c new file mode 100644 index 000000000000..13079bb840a5 --- /dev/null +++ b/clang/test/CodeGen/MSKernel/subptr.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fms-kernel -triple x86_64-windows-msvc -O2 -emit-llvm %s -o - | FileCheck %s +// CHECK: define {{.*}} i64 @sub_ptrs(ptr noundef %p1, ptr noundef %p2) +// CHECK-NEXT: entry: +// CHECK-NEXT: %sub.ptr.lhs.cast = ptrtoint ptr %p1 to i64 +// CHECK-NEXT: %sub.ptr.rhs.cast = ptrtoint ptr %p2 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 + +long long sub_ptrs(int* p1, int* p2) { + return p1 - p2; +} +