[clang] [CIR] Upstream pointer subtraction handling (PR #163306)

Shawn K via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 14 13:33:04 PDT 2025


https://github.com/kimsh02 updated https://github.com/llvm/llvm-project/pull/163306

>From 9f2ec3c40d9c4f28531e4a18f392703ca16ab2d7 Mon Sep 17 00:00:00 2001
From: kimsh02 <kimshawn02 at icloud.com>
Date: Mon, 13 Oct 2025 13:18:28 -0700
Subject: [PATCH 1/7] Copy incubator tests

---
 clang/test/CIR/CodeGen/ptrdiff.c   | 18 ++++++++++++++++++
 clang/test/CIR/CodeGen/ptrdiff.cpp | 23 +++++++++++++++++++++++
 2 files changed, 41 insertions(+)
 create mode 100644 clang/test/CIR/CodeGen/ptrdiff.c
 create mode 100644 clang/test/CIR/CodeGen/ptrdiff.cpp

diff --git a/clang/test/CIR/CodeGen/ptrdiff.c b/clang/test/CIR/CodeGen/ptrdiff.c
new file mode 100644
index 0000000000000..2ccbbb02dddaa
--- /dev/null
+++ b/clang/test/CIR/CodeGen/ptrdiff.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
+
+int addrcmp(const void* a, const void* b) {
+  // CIR-LABEL: addrcmp
+  // CIR: %[[R:.*]] = cir.ptr_diff
+  // CIR: cir.cast integral  %[[R]] : !s64i -> !s32
+
+  // LLVM-LABEL: addrcmp
+  // LLVM: %[[PTR_A:.*]] = ptrtoint ptr {{.*}} to i64
+  // LLVM: %[[PTR_B:.*]] = ptrtoint ptr {{.*}} to i64
+  // LLVM: %[[SUB:.*]] = sub i64 %[[PTR_A]], %[[PTR_B]]
+  // LLVM-NOT: sdiv
+  // LLVM: trunc i64 %[[SUB]] to i32
+  return *(const void**)a - *(const void**)b;
+}
diff --git a/clang/test/CIR/CodeGen/ptrdiff.cpp b/clang/test/CIR/CodeGen/ptrdiff.cpp
new file mode 100644
index 0000000000000..ba54b7a3b11bf
--- /dev/null
+++ b/clang/test/CIR/CodeGen/ptrdiff.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+
+typedef unsigned long size_type;
+size_type size(unsigned long *_start, unsigned long *_finish) {
+  return static_cast<size_type>(_finish - _start);
+}
+
+// CHECK: cir.func dso_local @_Z4sizePmS_(%arg0: !cir.ptr<!u64i>
+// CHECK:   %3 = cir.load{{.*}} %1 : !cir.ptr<!cir.ptr<!u64i>>, !cir.ptr<!u64i>
+// CHECK:   %4 = cir.load{{.*}} %0 : !cir.ptr<!cir.ptr<!u64i>>, !cir.ptr<!u64i>
+// CHECK:   %5 = cir.ptr_diff %3, %4 : !cir.ptr<!u64i> -> !s64i
+// CHECK:   %6 = cir.cast integral %5 : !s64i -> !u64i
+
+long add(char *a, char *b) {
+  return a - b + 1;
+}
+
+// CHECK: cir.func dso_local @_Z3addPcS_(%arg0: !cir.ptr<!s8i>
+//          %5 = cir.ptr_diff %3, %4 : !cir.ptr<!s8i> -> !s64i
+//          %6 = cir.const #cir.int<1> : !s32i
+//          %7 = cir.cast integral %6 : !s32i -> !s64i
+//          %8 = cir.binop(add, %5, %7) : !s64i

>From db85047a5f606caad31770219f468f66985b2ed1 Mon Sep 17 00:00:00 2001
From: kimsh02 <kimshawn02 at icloud.com>
Date: Mon, 13 Oct 2025 19:05:05 -0700
Subject: [PATCH 2/7] Stash

---
 clang/include/clang/CIR/MissingFeatures.h     |  2 +-
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp    |  3 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 34 +++++++++++++++++
 clang/test/CIR/CodeGen/ptrdiff.c              | 14 +++++++
 clang/test/CIR/CodeGen/ptrdiff.cpp            | 37 +++++++++++++------
 5 files changed, 75 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 4fbae150b587e..8edb4adcf48de 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -321,7 +321,7 @@ struct MissingFeatures {
   static bool ifOp() { return false; }
   static bool invokeOp() { return false; }
   static bool labelOp() { return false; }
-  static bool ptrDiffOp() { return false; }
+  static bool ptrDiffOp() { return true; }
   static bool ptrStrideOp() { return false; }
   static bool switchOp() { return false; }
   static bool throwOp() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 637f9ef65c88f..6c6e25c3f6caa 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1735,8 +1735,7 @@ mlir::Value ScalarExprEmitter::emitSub(const BinOpInfo &ops) {
   //
   // See more in `EmitSub` in CGExprScalar.cpp.
   assert(!cir::MissingFeatures::ptrDiffOp());
-  cgf.cgm.errorNYI("ptrdiff");
-  return {};
+  return builder.create<cir::PtrDiffOp>(cgf.getLoc(ops.loc), cgf.PtrDiffTy, ops.lhs, ops.rhs);
 }
 
 mlir::Value ScalarExprEmitter::emitShl(const BinOpInfo &ops) {
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index f0d73ac872386..5f4fb2aa5c09d 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1499,6 +1499,40 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
+    cir::PtrDiffOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  auto dstTy = mlir::cast<cir::IntType>(op.getType());
+  auto llvmDstTy = getTypeConverter()->convertType(dstTy);
+
+  auto lhs = rewriter.create<mlir::LLVM::PtrToIntOp>(op.getLoc(), llvmDstTy,
+                                                     adaptor.getLhs());
+  auto rhs = rewriter.create<mlir::LLVM::PtrToIntOp>(op.getLoc(), llvmDstTy,
+                                                     adaptor.getRhs());
+
+  auto diff =
+      rewriter.create<mlir::LLVM::SubOp>(op.getLoc(), llvmDstTy, lhs, rhs);
+
+  cir::PointerType ptrTy = op.getLhs().getType();
+  auto typeSize = getTypeSize(ptrTy.getPointee(), *op);
+
+  // Avoid silly division by 1.
+  auto resultVal = diff.getResult();
+  if (typeSize != 1) {
+    auto typeSizeVal = rewriter.create<mlir::LLVM::ConstantOp>(
+        op.getLoc(), llvmDstTy, typeSize);
+
+    if (dstTy.isUnsigned())
+      resultVal =
+          rewriter.create<mlir::LLVM::UDivOp>(op.getLoc(), diff, typeSizeVal);
+    else
+      resultVal =
+          rewriter.create<mlir::LLVM::SDivOp>(op.getLoc(), diff, typeSizeVal);
+  }
+  rewriter.replaceOp(op, resultVal);
+  return mlir::success();
+}
+
 mlir::LogicalResult CIRToLLVMExpectOpLowering::matchAndRewrite(
     cir::ExpectOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/test/CIR/CodeGen/ptrdiff.c b/clang/test/CIR/CodeGen/ptrdiff.c
index 2ccbbb02dddaa..ef37d4b139568 100644
--- a/clang/test/CIR/CodeGen/ptrdiff.c
+++ b/clang/test/CIR/CodeGen/ptrdiff.c
@@ -16,3 +16,17 @@ int addrcmp(const void* a, const void* b) {
   // LLVM: trunc i64 %[[SUB]] to i32
   return *(const void**)a - *(const void**)b;
 }
+
+unsigned long long test_ptr_diff(int *a, int* b) {
+  // CIR-LABEL: test_ptr_diff
+  // CIR: %[[D:.*]] = cir.ptr_diff{{.*}} : !cir.ptr<!s32i> -> !u64i
+  // CIR: cir.return %[[D]] : !u64i
+
+  // LLVM-LABEL: @_Z13test_ptr_diffPiS_
+  // LLVM: %[[IA:.*]] = ptrtoint ptr %{{.*}} to i64
+  // LLVM: %[[IB:.*]] = ptrtoint ptr %{{.*}} to i64
+  // LLVM: %[[SUB:.*]] = sub i64 %[[IA]], %[[IB]]
+  // LLVM: %[[Q:.*]] = sdiv exact i64 %[[SUB]], 4
+  // LLVM: ret i64 %[[Q]]
+  return a - b;
+}
diff --git a/clang/test/CIR/CodeGen/ptrdiff.cpp b/clang/test/CIR/CodeGen/ptrdiff.cpp
index ba54b7a3b11bf..32a3955807b8f 100644
--- a/clang/test/CIR/CodeGen/ptrdiff.cpp
+++ b/clang/test/CIR/CodeGen/ptrdiff.cpp
@@ -2,22 +2,35 @@
 // RUN: FileCheck --input-file=%t.cir %s
 
 typedef unsigned long size_type;
+
 size_type size(unsigned long *_start, unsigned long *_finish) {
+  // CIR-LABEL: cir.func dso_local @_Z4sizePmS_
+  // CIR: %[[D:.*]] = cir.ptr_diff {{.*}} : !cir.ptr<!u64i> -> !s64i
+  // CIR: %[[U:.*]] = cir.cast integral %[[D]] : !s64i -> !u64i
+  // CIR: cir.return %[[U]] : !u64i
+
+  // LLVM-LABEL: @_Z4sizePmS_
+  // LLVM: ptrtoint ptr {{.*}} to i64
+  // LLVM: ptrtoint ptr {{.*}} to i64
+  // LLVM: %[[SUB:.*]] = sub i64 {{.*}}, {{.*}}
+  // LLVM: %[[DIV:.*]] = sdiv exact i64 %[[SUB]], 8
+  // LLVM: ret i64 %[[DIV]]
   return static_cast<size_type>(_finish - _start);
 }
 
-// CHECK: cir.func dso_local @_Z4sizePmS_(%arg0: !cir.ptr<!u64i>
-// CHECK:   %3 = cir.load{{.*}} %1 : !cir.ptr<!cir.ptr<!u64i>>, !cir.ptr<!u64i>
-// CHECK:   %4 = cir.load{{.*}} %0 : !cir.ptr<!cir.ptr<!u64i>>, !cir.ptr<!u64i>
-// CHECK:   %5 = cir.ptr_diff %3, %4 : !cir.ptr<!u64i> -> !s64i
-// CHECK:   %6 = cir.cast integral %5 : !s64i -> !u64i
-
 long add(char *a, char *b) {
+  // CIR-LABEL: cir.func dso_local @_Z3addPcS_
+  // CIR: %[[D:.*]] = cir.ptr_diff {{.*}} : !cir.ptr<!s8i> -> !s64i
+  // CIR: %[[C1:.*]] = cir.const #cir.int<1> : !s32i
+  // CIR: %[[C1W:.*]] = cir.cast integral %[[C1]] : !s32i -> !s64i
+  // CIR: %[[S:.*]] = cir.binop(add, %[[D]], %[[C1W]]) : !s64i
+  // CIR: cir.return %[[S]] : !s64i
+
+  // LLVM-LABEL: @_Z3addPcS_
+  // LLVM: ptrtoint ptr {{.*}} to i64
+  // LLVM: ptrtoint ptr {{.*}} to i64
+  // LLVM: %[[SUB:.*]] = sub i64 {{.*}}, {{.*}}
+  // LLVM: %[[ADD1:.*]] = add i64 %[[SUB]], 1
+  // LLVM: ret i64 %[[ADD1]]
   return a - b + 1;
 }
-
-// CHECK: cir.func dso_local @_Z3addPcS_(%arg0: !cir.ptr<!s8i>
-//          %5 = cir.ptr_diff %3, %4 : !cir.ptr<!s8i> -> !s64i
-//          %6 = cir.const #cir.int<1> : !s32i
-//          %7 = cir.cast integral %6 : !s32i -> !s64i
-//          %8 = cir.binop(add, %5, %7) : !s64i

>From a3709f9303d2db3f07b878501bda4ba4f93722ae Mon Sep 17 00:00:00 2001
From: kimsh02 <kimshawn02 at icloud.com>
Date: Mon, 13 Oct 2025 19:06:12 -0700
Subject: [PATCH 3/7] Clang-format

---
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 6c6e25c3f6caa..ff77c0ef5a540 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1735,7 +1735,8 @@ mlir::Value ScalarExprEmitter::emitSub(const BinOpInfo &ops) {
   //
   // See more in `EmitSub` in CGExprScalar.cpp.
   assert(!cir::MissingFeatures::ptrDiffOp());
-  return builder.create<cir::PtrDiffOp>(cgf.getLoc(ops.loc), cgf.PtrDiffTy, ops.lhs, ops.rhs);
+  return builder.create<cir::PtrDiffOp>(cgf.getLoc(ops.loc), cgf.PtrDiffTy,
+                                        ops.lhs, ops.rhs);
 }
 
 mlir::Value ScalarExprEmitter::emitShl(const BinOpInfo &ops) {

>From 0ff02185f99e2047f5a73cf691876b6f48a188a5 Mon Sep 17 00:00:00 2001
From: kimsh02 <kimshawn02 at icloud.com>
Date: Tue, 14 Oct 2025 12:33:37 -0700
Subject: [PATCH 4/7] Stash

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 31 +++++++++++++++++++
 clang/include/clang/CIR/MissingFeatures.h     |  3 +-
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp    |  2 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  9 ++++++
 4 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 4c15d9ed0f834..56ff289f91a93 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4044,6 +4044,37 @@ def CIR_ExpectOp : CIR_Op<"expect", [
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// PtrDiffOp
+//===----------------------------------------------------------------------===//
+
+def CIR_PtrDiffOp : CIR_Op<"ptr_diff", [Pure, SameTypeOperands]> {
+  let summary = "Pointer subtraction arithmetic";
+  let description = [{
+    The cir.ptr_diff operation computes the difference between two pointers that
+    have the same element type
+
+    The result reflects the ABI-defined size of the pointed-to type. For example,
+    subtracting two !cir.ptr<!u64i> values may yield 1, representing an 8-byte
+    difference. In contrast, for pointers to void or function types, a result of
+    8 corresponds to an 8-byte difference.
+
+    Example:
+
+    ```mlir
+    %7 = cir.ptr_diff %0, %1 : !cir.ptr<!u64i> -> !u64i
+    ```
+  }];
+
+  let arguments = (ins CIR_PointerType:$lhs, CIR_PointerType:$rhs);
+  let results = (outs CIR_AnyFundamentalIntType:$result);
+
+  let assemblyFormat = [{
+    $lhs `,` $rhs  `:` qualified(type($lhs)) `->` qualified(type($result)) 
+    attr-dict
+  }];
+}
+
 //===----------------------------------------------------------------------===//
 // Floating Point Ops
 //===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 8edb4adcf48de..d133453c137fb 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -321,7 +321,8 @@ struct MissingFeatures {
   static bool ifOp() { return false; }
   static bool invokeOp() { return false; }
   static bool labelOp() { return false; }
-  static bool ptrDiffOp() { return true; }
+  static bool ptrDiffOp() { return false; }
+  static bool llvmLoweringPtrDiffConsidersPointee() {return false; }
   static bool ptrStrideOp() { return false; }
   static bool switchOp() { return false; }
   static bool throwOp() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index ff77c0ef5a540..8889bbeebe399 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1734,7 +1734,7 @@ mlir::Value ScalarExprEmitter::emitSub(const BinOpInfo &ops) {
   // LLVM we shall take VLA's, division by element size, etc.
   //
   // See more in `EmitSub` in CGExprScalar.cpp.
-  assert(!cir::MissingFeatures::ptrDiffOp());
+  assert(!cir::MissingFeatures::llvmLoweringPtrDiffConsidersPointee());
   return builder.create<cir::PtrDiffOp>(cgf.getLoc(ops.loc), cgf.PtrDiffTy,
                                         ops.lhs, ops.rhs);
 }
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 5f4fb2aa5c09d..19d734df42331 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1499,6 +1499,15 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+uint64_t CIRToLLVMPtrDiffOpLowering::getTypeSize(mlir::Type type,
+                                                 mlir::Operation &op) const {
+  mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
+  // For LLVM purposes we treat void as u8.
+  if (isa<cir::VoidType>(type))
+    type = cir::IntType::get(type.getContext(), 8, /*isSigned=*/false);
+  return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
+}
+
 mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
     cir::PtrDiffOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {

>From 61bc2569fc4792ddd97d81ddace687b1e10ca451 Mon Sep 17 00:00:00 2001
From: kimsh02 <kimshawn02 at icloud.com>
Date: Tue, 14 Oct 2025 13:30:34 -0700
Subject: [PATCH 5/7] Fix testcases

---
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  4 +--
 clang/test/CIR/CodeGen/ptrdiff.c              | 17 +++++++-----
 clang/test/CIR/CodeGen/ptrdiff.cpp            | 27 ++-----------------
 3 files changed, 14 insertions(+), 34 deletions(-)

diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 19d734df42331..4b8d912409a8e 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1499,8 +1499,8 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
-uint64_t CIRToLLVMPtrDiffOpLowering::getTypeSize(mlir::Type type,
-                                                 mlir::Operation &op) const {
+static uint64_t getTypeSize(mlir::Type type,
+                                                 mlir::Operation &op)  {
   mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
   // For LLVM purposes we treat void as u8.
   if (isa<cir::VoidType>(type))
diff --git a/clang/test/CIR/CodeGen/ptrdiff.c b/clang/test/CIR/CodeGen/ptrdiff.c
index ef37d4b139568..33a0c3ad4faf4 100644
--- a/clang/test/CIR/CodeGen/ptrdiff.c
+++ b/clang/test/CIR/CodeGen/ptrdiff.c
@@ -6,9 +6,9 @@
 int addrcmp(const void* a, const void* b) {
   // CIR-LABEL: addrcmp
   // CIR: %[[R:.*]] = cir.ptr_diff
-  // CIR: cir.cast integral  %[[R]] : !s64i -> !s32
+  // CIR: cir.cast integral %[[R]] : !s64i -> !s32i
 
-  // LLVM-LABEL: addrcmp
+  // LLVM-LABEL: define dso_local i32 @addrcmp(
   // LLVM: %[[PTR_A:.*]] = ptrtoint ptr {{.*}} to i64
   // LLVM: %[[PTR_B:.*]] = ptrtoint ptr {{.*}} to i64
   // LLVM: %[[SUB:.*]] = sub i64 %[[PTR_A]], %[[PTR_B]]
@@ -19,14 +19,17 @@ int addrcmp(const void* a, const void* b) {
 
 unsigned long long test_ptr_diff(int *a, int* b) {
   // CIR-LABEL: test_ptr_diff
-  // CIR: %[[D:.*]] = cir.ptr_diff{{.*}} : !cir.ptr<!s32i> -> !u64i
-  // CIR: cir.return %[[D]] : !u64i
+  // CIR: %[[D:.*]] = cir.ptr_diff {{.*}} : !cir.ptr<!s32i> -> !s64i
+  // CIR: %[[U:.*]] = cir.cast integral %[[D]] : !s64i -> !u64i
+  // CIR: cir.return {{.*}} : !u64i
 
-  // LLVM-LABEL: @_Z13test_ptr_diffPiS_
+  // LLVM-LABEL: define dso_local i64 @test_ptr_diff(
   // LLVM: %[[IA:.*]] = ptrtoint ptr %{{.*}} to i64
   // LLVM: %[[IB:.*]] = ptrtoint ptr %{{.*}} to i64
   // LLVM: %[[SUB:.*]] = sub i64 %[[IA]], %[[IB]]
-  // LLVM: %[[Q:.*]] = sdiv exact i64 %[[SUB]], 4
-  // LLVM: ret i64 %[[Q]]
+  // LLVM: %[[Q:.*]] = sdiv{{( exact)?}} i64 %[[SUB]], 4
+  // LLVM: store i64 %[[Q]], ptr %[[RETADDR:.*]], align
+  // LLVM: %[[RETLOAD:.*]] = load i64, ptr %[[RETADDR]], align
+  // LLVM: ret i64 %[[RETLOAD]]
   return a - b;
 }
diff --git a/clang/test/CIR/CodeGen/ptrdiff.cpp b/clang/test/CIR/CodeGen/ptrdiff.cpp
index 32a3955807b8f..2c0aed6089816 100644
--- a/clang/test/CIR/CodeGen/ptrdiff.cpp
+++ b/clang/test/CIR/CodeGen/ptrdiff.cpp
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
-// RUN: FileCheck --input-file=%t.cir %s
+// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
 
 typedef unsigned long size_type;
 
@@ -7,30 +7,7 @@ size_type size(unsigned long *_start, unsigned long *_finish) {
   // CIR-LABEL: cir.func dso_local @_Z4sizePmS_
   // CIR: %[[D:.*]] = cir.ptr_diff {{.*}} : !cir.ptr<!u64i> -> !s64i
   // CIR: %[[U:.*]] = cir.cast integral %[[D]] : !s64i -> !u64i
-  // CIR: cir.return %[[U]] : !u64i
+  // CIR: cir.return {{.*}} : !u64i
 
-  // LLVM-LABEL: @_Z4sizePmS_
-  // LLVM: ptrtoint ptr {{.*}} to i64
-  // LLVM: ptrtoint ptr {{.*}} to i64
-  // LLVM: %[[SUB:.*]] = sub i64 {{.*}}, {{.*}}
-  // LLVM: %[[DIV:.*]] = sdiv exact i64 %[[SUB]], 8
-  // LLVM: ret i64 %[[DIV]]
   return static_cast<size_type>(_finish - _start);
 }
-
-long add(char *a, char *b) {
-  // CIR-LABEL: cir.func dso_local @_Z3addPcS_
-  // CIR: %[[D:.*]] = cir.ptr_diff {{.*}} : !cir.ptr<!s8i> -> !s64i
-  // CIR: %[[C1:.*]] = cir.const #cir.int<1> : !s32i
-  // CIR: %[[C1W:.*]] = cir.cast integral %[[C1]] : !s32i -> !s64i
-  // CIR: %[[S:.*]] = cir.binop(add, %[[D]], %[[C1W]]) : !s64i
-  // CIR: cir.return %[[S]] : !s64i
-
-  // LLVM-LABEL: @_Z3addPcS_
-  // LLVM: ptrtoint ptr {{.*}} to i64
-  // LLVM: ptrtoint ptr {{.*}} to i64
-  // LLVM: %[[SUB:.*]] = sub i64 {{.*}}, {{.*}}
-  // LLVM: %[[ADD1:.*]] = add i64 %[[SUB]], 1
-  // LLVM: ret i64 %[[ADD1]]
-  return a - b + 1;
-}

>From 50412c36ad1c771b221d6db91fe320df5a9e5c2d Mon Sep 17 00:00:00 2001
From: kimsh02 <kimshawn02 at icloud.com>
Date: Tue, 14 Oct 2025 13:31:43 -0700
Subject: [PATCH 6/7] Clang-format

---
 clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 4b8d912409a8e..70c152f8722b0 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1499,8 +1499,7 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
-static uint64_t getTypeSize(mlir::Type type,
-                                                 mlir::Operation &op)  {
+static uint64_t getTypeSize(mlir::Type type, mlir::Operation &op) {
   mlir::DataLayout layout(op.getParentOfType<mlir::ModuleOp>());
   // For LLVM purposes we treat void as u8.
   if (isa<cir::VoidType>(type))

>From 52f0f44f5e58277335a74a6a80c20944ad824ffc Mon Sep 17 00:00:00 2001
From: kimsh02 <kimshawn02 at icloud.com>
Date: Tue, 14 Oct 2025 13:32:52 -0700
Subject: [PATCH 7/7] Clang-format

---
 clang/include/clang/CIR/MissingFeatures.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index d133453c137fb..de3bc9487bc8c 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -322,7 +322,7 @@ struct MissingFeatures {
   static bool invokeOp() { return false; }
   static bool labelOp() { return false; }
   static bool ptrDiffOp() { return false; }
-  static bool llvmLoweringPtrDiffConsidersPointee() {return false; }
+  static bool llvmLoweringPtrDiffConsidersPointee() { return false; }
   static bool ptrStrideOp() { return false; }
   static bool switchOp() { return false; }
   static bool throwOp() { return false; }



More information about the cfe-commits mailing list