https://github.com/andykaylor updated 
https://github.com/llvm/llvm-project/pull/171897

>From a858a130a933db2753b7f678c5d0893e8d09efed Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Tue, 9 Dec 2025 14:45:09 -0800
Subject: [PATCH 1/2] [CIR] Add support for data member comparison

This adds support for handling data member pointer comparisons in CIR.
---
 .../Transforms/TargetLowering/CIRCXXABI.h     |  4 ++
 .../TargetLowering/LowerItaniumCXXABI.cpp     | 12 ++++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 11 +++-
 .../CodeGen/pointer-to-data-member-cmp.cpp    | 58 +++++++++++++++++++
 4 files changed, 84 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CIR/CodeGen/pointer-to-data-member-cmp.cpp

diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
index 90f0ac3478f9d..a2439f1c24f10 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h
@@ -53,6 +53,10 @@ class CIRCXXABI {
   lowerGetRuntimeMember(cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
                         mlir::Value loweredAddr, mlir::Value loweredMember,
                         mlir::OpBuilder &builder) const = 0;
+
+  virtual mlir::Value lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
+                                         mlir::Value loweredRhs,
+                                         mlir::OpBuilder &builder) const = 0;
 };
 
 /// Creates an Itanium-family ABI.
diff --git 
a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
index ce4b0c7e92d09..abffb193798cc 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
@@ -47,6 +47,10 @@ class LowerItaniumCXXABI : public CIRCXXABI {
   lowerGetRuntimeMember(cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
                         mlir::Value loweredAddr, mlir::Value loweredMember,
                         mlir::OpBuilder &builder) const override;
+
+  mlir::Value lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
+                                 mlir::Value loweredRhs,
+                                 mlir::OpBuilder &builder) const override;
 };
 
 } // namespace
@@ -108,4 +112,12 @@ mlir::Operation *LowerItaniumCXXABI::lowerGetRuntimeMember(
                              cir::CastKind::bitcast, memberBytesPtr);
 }
 
+mlir::Value
+LowerItaniumCXXABI::lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
+                                       mlir::Value loweredRhs,
+                                       mlir::OpBuilder &builder) const {
+  return cir::CmpOp::create(builder, op.getLoc(), op.getKind(), loweredLhs,
+                            loweredRhs);
+}
+
 } // namespace cir
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6d01964ebac41..66a875810aa5c 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2569,8 +2569,17 @@ mlir::LogicalResult 
CIRToLLVMCmpOpLowering::matchAndRewrite(
     mlir::ConversionPatternRewriter &rewriter) const {
   mlir::Type type = cmpOp.getLhs().getType();
 
-  assert(!cir::MissingFeatures::dataMemberType());
   assert(!cir::MissingFeatures::methodType());
+  if (mlir::isa<cir::DataMemberType>(type)) {
+    assert(lowerMod && "lowering module is not available");
+
+    mlir::Value loweredResult;
+    loweredResult = lowerMod->getCXXABI().lowerDataMemberCmp(
+        cmpOp, adaptor.getLhs(), adaptor.getRhs(), rewriter);
+
+    rewriter.replaceOp(cmpOp, loweredResult);
+    return mlir::success();
+  }
 
   if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
     bool isSigned = mlir::isa<cir::IntType>(type)
diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member-cmp.cpp 
b/clang/test/CIR/CodeGen/pointer-to-data-member-cmp.cpp
new file mode 100644
index 0000000000000..fa3491252cb5f
--- /dev/null
+++ b/clang/test/CIR/CodeGen/pointer-to-data-member-cmp.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir 
-emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir --check-prefix=CIR %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir 
-emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll --check-prefix=LLVM %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -emit-llvm %s 
-o %t.ll
+// RUN: FileCheck --input-file=%t.ll --check-prefix=OGCG %s
+
+struct Foo {
+  int a;
+};
+
+struct Bar {
+  int a;
+};
+
+bool eq(int Foo::*x, int Foo::*y) {
+  return x == y;
+}
+
+// CIR-LABEL: @_Z2eqM3FooiS0_
+//      CIR:   %[[#x:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
+// CIR-NEXT:   %[[#y:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
+// CIR-NEXT:   %{{.+}} = cir.cmp(eq, %[[#x]], %[[#y]]) : 
!cir.data_member<!s32i in !rec_Foo>, !cir.bool
+//      CIR: }
+
+// LLVM-LABEL: @_Z2eqM3FooiS0_
+//      LLVM:   %[[#x:]] = load i64, ptr %{{.+}}, align 8
+// LLVM-NEXT:   %[[#y:]] = load i64, ptr %{{.+}}, align 8
+// LLVM-NEXT:   %{{.+}} = icmp eq i64 %[[#x]], %[[#y]]
+//      LLVM: }
+
+// OGCG-LABEL: @_Z2eqM3FooiS0_
+//      OGCG:   %[[#x:]] = load i64, ptr %{{.+}}, align 8
+// OGCG-NEXT:   %[[#y:]] = load i64, ptr %{{.+}}, align 8
+// OGCG-NEXT:   %{{.+}} = icmp eq i64 %[[#x]], %[[#y]]
+//      OGCG: }
+
+bool ne(int Foo::*x, int Foo::*y) {
+  return x != y;
+}
+
+// CIR-LABEL: @_Z2neM3FooiS0_
+//      CIR:   %[[#x:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
+// CIR-NEXT:   %[[#y:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
+// CIR-NEXT:   %{{.+}} = cir.cmp(ne, %[[#x]], %[[#y]]) : 
!cir.data_member<!s32i in !rec_Foo>, !cir.bool
+//      CIR: }
+
+// LLVM-LABEL: @_Z2neM3FooiS0_
+//      LLVM:   %[[#x:]] = load i64, ptr %{{.+}}, align 8
+// LLVM-NEXT:   %[[#y:]] = load i64, ptr %{{.+}}, align 8
+// LLVM-NEXT:   %{{.+}} = icmp ne i64 %[[#x]], %[[#y]]
+//      LLVM: }
+
+// OGCG-LABEL: @_Z2neM3FooiS0_
+//      OGCG:   %[[#x:]] = load i64, ptr %{{.+}}, align 8
+// OGCG-NEXT:   %[[#y:]] = load i64, ptr %{{.+}}, align 8
+// OGCG-NEXT:   %{{.+}} = icmp ne i64 %[[#x]], %[[#y]]
+//      OGCG: }

>From c925f7b9bf512910546703bdb8984767dbe85039 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Thu, 18 Dec 2025 16:53:12 -0800
Subject: [PATCH 2/2] Move lowering to cxxabi pass

---
 .../CIR/Dialect/Transforms/CXXABILowering.cpp | 19 +++++++++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 12 -------
 .../CodeGen/pointer-to-data-member-cmp.cpp    | 35 ++++++++++++-------
 3 files changed, 41 insertions(+), 25 deletions(-)

diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp 
b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index bcd9147b130e5..3ac171d060ca6 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -58,6 +58,7 @@ class CIROpCXXABILoweringPattern : public 
mlir::OpConversionPattern<Op> {
 
 CIR_CXXABI_LOWERING_PATTERN(CIRAllocaOpABILowering, cir::AllocaOp);
 CIR_CXXABI_LOWERING_PATTERN(CIRConstantOpABILowering, cir::ConstantOp);
+CIR_CXXABI_LOWERING_PATTERN(CIRCmpOpABILowering, cir::CmpOp);
 CIR_CXXABI_LOWERING_PATTERN(CIRFuncOpABILowering, cir::FuncOp);
 CIR_CXXABI_LOWERING_PATTERN(CIRGetRuntimeMemberOpABILowering,
                             cir::GetRuntimeMemberOp);
@@ -86,7 +87,7 @@ class CIRGenericCXXABILoweringPattern : public 
mlir::ConversionPattern {
   matchAndRewrite(mlir::Operation *op, llvm::ArrayRef<mlir::Value> operands,
                   mlir::ConversionPatternRewriter &rewriter) const override {
     // Do not match on operations that have dedicated ABI lowering rewrite 
rules
-    if (llvm::isa<cir::AllocaOp, cir::ConstantOp, cir::FuncOp,
+    if (llvm::isa<cir::AllocaOp, cir::ConstantOp, cir::CmpOp, cir::FuncOp,
                   cir::GetRuntimeMemberOp, cir::GlobalOp>(op))
       return mlir::failure();
 
@@ -174,6 +175,21 @@ mlir::LogicalResult 
CIRConstantOpABILowering::matchAndRewrite(
   llvm_unreachable("constant operand is not an CXXABI-dependent type");
 }
 
+mlir::LogicalResult CIRCmpOpABILowering::matchAndRewrite(
+    cir::CmpOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type type = op.getLhs().getType();
+  assert((mlir::isa<cir::DataMemberType>(type)) &&
+         "input to cmp in ABI lowering must be a data member");
+
+  assert(!cir::MissingFeatures::methodType());
+  mlir::Value loweredResult = lowerModule->getCXXABI().lowerDataMemberCmp(
+      op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
+
+  rewriter.replaceOp(op, loweredResult);
+  return mlir::success();
+}
+
 mlir::LogicalResult CIRFuncOpABILowering::matchAndRewrite(
     cir::FuncOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
@@ -344,6 +360,7 @@ void CXXABILoweringPass::runOnOperation() {
       // clang-format off
       CIRAllocaOpABILowering,
       CIRConstantOpABILowering,
+      CIRCmpOpABILowering,
       CIRFuncOpABILowering,
       CIRGetRuntimeMemberOpABILowering,
       CIRGlobalOpABILowering
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 66a875810aa5c..7aebc7effc4d1 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2569,18 +2569,6 @@ mlir::LogicalResult 
CIRToLLVMCmpOpLowering::matchAndRewrite(
     mlir::ConversionPatternRewriter &rewriter) const {
   mlir::Type type = cmpOp.getLhs().getType();
 
-  assert(!cir::MissingFeatures::methodType());
-  if (mlir::isa<cir::DataMemberType>(type)) {
-    assert(lowerMod && "lowering module is not available");
-
-    mlir::Value loweredResult;
-    loweredResult = lowerMod->getCXXABI().lowerDataMemberCmp(
-        cmpOp, adaptor.getLhs(), adaptor.getRhs(), rewriter);
-
-    rewriter.replaceOp(cmpOp, loweredResult);
-    return mlir::success();
-  }
-
   if (mlir::isa<cir::IntType, mlir::IntegerType>(type)) {
     bool isSigned = mlir::isa<cir::IntType>(type)
                         ? mlir::cast<cir::IntType>(type).isSigned()
diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member-cmp.cpp 
b/clang/test/CIR/CodeGen/pointer-to-data-member-cmp.cpp
index fa3491252cb5f..482a1aa3938d4 100644
--- a/clang/test/CIR/CodeGen/pointer-to-data-member-cmp.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-data-member-cmp.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir 
-emit-cir %s -o %t.cir
-// RUN: FileCheck --input-file=%t.cir --check-prefix=CIR %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir 
-emit-cir -mmlir -mlir-print-ir-before=cir-cxxabi-lowering %s -o %t.cir 2> 
%t-before.cir
+// RUN: FileCheck --check-prefix=CIR-BEFORE --input-file=%t-before.cir %s
+// RUN: FileCheck --check-prefix=CIR-AFTER --input-file=%t.cir %s
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir 
-emit-llvm %s -o %t-cir.ll
 // RUN: FileCheck --input-file=%t-cir.ll --check-prefix=LLVM %s
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -emit-llvm %s 
-o %t.ll
@@ -17,11 +18,16 @@ bool eq(int Foo::*x, int Foo::*y) {
   return x == y;
 }
 
-// CIR-LABEL: @_Z2eqM3FooiS0_
-//      CIR:   %[[#x:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
-// CIR-NEXT:   %[[#y:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
-// CIR-NEXT:   %{{.+}} = cir.cmp(eq, %[[#x]], %[[#y]]) : 
!cir.data_member<!s32i in !rec_Foo>, !cir.bool
-//      CIR: }
+// CIR-BEFORE-LABEL: @_Z2eqM3FooiS0_
+//      CIR-BEFORE:   %[[#x:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
+// CIR-BEFORE-NEXT:   %[[#y:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
+// CIR-BEFORE-NEXT:   %{{.+}} = cir.cmp(eq, %[[#x]], %[[#y]]) : 
!cir.data_member<!s32i in !rec_Foo>, !cir.bool
+//      CIR-BEFORE: }
+
+// CIR-AFTER-LABEL: @_Z2eqM3FooiS0_
+// CIR-AFTER:   %[[#x:]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i
+// CIR-AFTER:   %[[#y:]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i
+// CIR-AFTER:   %{{.*}} = cir.cmp(eq, %[[#x]], %[[#y]]) : !s64i, !cir.bool
 
 // LLVM-LABEL: @_Z2eqM3FooiS0_
 //      LLVM:   %[[#x:]] = load i64, ptr %{{.+}}, align 8
@@ -39,11 +45,16 @@ bool ne(int Foo::*x, int Foo::*y) {
   return x != y;
 }
 
-// CIR-LABEL: @_Z2neM3FooiS0_
-//      CIR:   %[[#x:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
-// CIR-NEXT:   %[[#y:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
-// CIR-NEXT:   %{{.+}} = cir.cmp(ne, %[[#x]], %[[#y]]) : 
!cir.data_member<!s32i in !rec_Foo>, !cir.bool
-//      CIR: }
+// CIR-BEFORE-LABEL: @_Z2neM3FooiS0_
+//      CIR-BEFORE:   %[[#x:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
+// CIR-BEFORE-NEXT:   %[[#y:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.data_member<!s32i in !rec_Foo>>, !cir.data_member<!s32i in 
!rec_Foo>
+// CIR-BEFORE-NEXT:   %{{.+}} = cir.cmp(ne, %[[#x]], %[[#y]]) : 
!cir.data_member<!s32i in !rec_Foo>, !cir.bool
+//      CIR-BEFORE: }
+
+// CIR-AFTER-LABEL: @_Z2neM3FooiS0_
+// CIR-AFTER:   %[[#x:]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i
+// CIR-AFTER:   %[[#y:]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i
+// CIR-AFTER:   %{{.*}} = cir.cmp(ne, %[[#x]], %[[#y]]) : !s64i, !cir.bool
 
 // LLVM-LABEL: @_Z2neM3FooiS0_
 //      LLVM:   %[[#x:]] = load i64, ptr %{{.+}}, align 8

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

Reply via email to