https://github.com/andykaylor created 
https://github.com/llvm/llvm-project/pull/172133

This moves the code that handles CXXABI-specific lowering in 
ConvertCIRToLLVMPass into a standlone CIR-to-CIR transform pass. The handling 
of these operations was already performing a CIR-to-CIR transformation, with 
the CIR operations being further lowered to the LLVM dialect. This change makes 
that transformation a separate pass.

The LowerModule object in ConvertCIRToLLVMPass will be unused after this 
change, but removal of that object is being deferred to a follow-up PR to keep 
this change isolated to a single purpose.

---------

>From e3c6b5d8fe0c00f44718f8218c7925ffe50b1f22 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Fri, 12 Dec 2025 22:13:11 -0800
Subject: [PATCH] [CIR] Move CIR CXXABI lowering to a standlone pass

This moves the code that handles CXXABI-specific lowering in
ConvertCIRToLLVMPass into a standlone CIR-to-CIR transform pass. The
handling of these operations was already performing a CIR-to-CIR
transformation, with the CIR operations being further lowered to the LLVM
dialect. This change makes that transformation a separate pass.

The LowerModule object in ConvertCIRToLLVMPass will be unused after this
change, but removal of that object is being deferred to a follow-up PR
to keep this change isolated to a single purpose.

---------

Co-authored-by: Sirui Mu <[email protected]>
---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |   2 +
 clang/include/clang/CIR/Dialect/Passes.h      |   1 +
 clang/include/clang/CIR/Dialect/Passes.td     |  11 +
 .../lib/CIR/Dialect/Transforms/CMakeLists.txt |   1 +
 .../CIR/Dialect/Transforms/CXXABILowering.cpp | 346 ++++++++++++++++++
 clang/lib/CIR/Lowering/CIRPasses.cpp          |   1 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  57 +--
 .../CIR/CodeGen/pointer-to-data-member.cpp    | 199 ++++++----
 8 files changed, 509 insertions(+), 109 deletions(-)
 create mode 100644 clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 4922f83df0efb..ddb5bfc5a23cd 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3614,6 +3614,8 @@ def CIR_GetRuntimeMemberOp : CIR_Op<"get_runtime_member"> 
{
   }];
 
   let hasVerifier = 1;
+
+  let hasLLVMLowering = false;
 }
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/Passes.h 
b/clang/include/clang/CIR/Dialect/Passes.h
index 32c3e27d07dfb..98eaf884347ed 100644
--- a/clang/include/clang/CIR/Dialect/Passes.h
+++ b/clang/include/clang/CIR/Dialect/Passes.h
@@ -23,6 +23,7 @@ namespace mlir {
 std::unique_ptr<Pass> createCIRCanonicalizePass();
 std::unique_ptr<Pass> createCIRFlattenCFGPass();
 std::unique_ptr<Pass> createCIRSimplifyPass();
+std::unique_ptr<Pass> createCXXABILoweringPass();
 std::unique_ptr<Pass> createHoistAllocasPass();
 std::unique_ptr<Pass> createLoweringPreparePass();
 std::unique_ptr<Pass> createLoweringPreparePass(clang::ASTContext *astCtx);
diff --git a/clang/include/clang/CIR/Dialect/Passes.td 
b/clang/include/clang/CIR/Dialect/Passes.td
index 0f5783945f8ae..55007adf6ffb3 100644
--- a/clang/include/clang/CIR/Dialect/Passes.td
+++ b/clang/include/clang/CIR/Dialect/Passes.td
@@ -82,6 +82,17 @@ def GotoSolver : Pass<"cir-goto-solver"> {
   let dependentDialects = ["cir::CIRDialect"];
 }
 
+def CXXABILowering : Pass<"cir-cxxabi-lowering"> {
+  let summary = "Lower abstract C++ operations to target-specific ABI form";
+  let description = [{
+    This pass lowers high-level operations that represent C++ constructs in a
+    target-independent way to concrete, target specific operations.
+  }];
+  let constructor = "mlir::createCXXABILoweringPass()";
+  let dependentDialects = ["cir::CIRDialect"];
+}
+
+
 def LoweringPrepare : Pass<"cir-lowering-prepare"> {
   let summary = "Lower to more fine-grained CIR operations before lowering to "
     "other dialects";
diff --git a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt 
b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
index e3b7106c1d6b9..2a0d791edd22c 100644
--- a/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
@@ -3,6 +3,7 @@ add_subdirectory(TargetLowering)
 add_clang_library(MLIRCIRTransforms
   CIRCanonicalize.cpp
   CIRSimplify.cpp
+  CXXABILowering.cpp
   FlattenCFG.cpp
   HoistAllocas.cpp
   LoweringPrepare.cpp
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp 
b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
new file mode 100644
index 0000000000000..c81e69ff334da
--- /dev/null
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -0,0 +1,346 @@
+//==- CXXABILowering.cpp - lower C++ operations to target-specific ABI form 
-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PassDetail.h"
+#include "TargetLowering/LowerModule.h"
+
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/Interfaces/DataLayoutInterfaces.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
+#include "clang/CIR/Dialect/IR/CIRAttrs.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
+#include "clang/CIR/Dialect/Passes.h"
+#include "clang/CIR/MissingFeatures.h"
+
+using namespace mlir;
+using namespace cir;
+
+namespace mlir {
+#define GEN_PASS_DEF_CXXABILOWERING
+#include "clang/CIR/Dialect/Passes.h.inc"
+} // namespace mlir
+
+namespace {
+
+template <typename Op>
+class CIROpCXXABILoweringPattern : public mlir::OpConversionPattern<Op> {
+protected:
+  mlir::DataLayout *dataLayout;
+  cir::LowerModule *lowerModule;
+
+public:
+  CIROpCXXABILoweringPattern(mlir::MLIRContext *context,
+                             const mlir::TypeConverter &typeConverter,
+                             mlir::DataLayout &dataLayout,
+                             cir::LowerModule &lowerModule)
+      : mlir::OpConversionPattern<Op>(typeConverter, context),
+        dataLayout(&dataLayout), lowerModule(&lowerModule) {}
+};
+
+#define CIR_CXXABI_LOWERING_PATTERN(name, operation)                           
\
+  struct name : CIROpCXXABILoweringPattern<operation> {                        
\
+    using CIROpCXXABILoweringPattern<operation>::CIROpCXXABILoweringPattern;   
\
+                                                                               
\
+    mlir::LogicalResult                                                        
\
+    matchAndRewrite(operation op, OpAdaptor adaptor,                           
\
+                    mlir::ConversionPatternRewriter &rewriter) const override; 
\
+  }
+
+CIR_CXXABI_LOWERING_PATTERN(CIRAllocaOpABILowering, cir::AllocaOp);
+CIR_CXXABI_LOWERING_PATTERN(CIRConstantOpABILowering, cir::ConstantOp);
+CIR_CXXABI_LOWERING_PATTERN(CIRFuncOpABILowering, cir::FuncOp);
+CIR_CXXABI_LOWERING_PATTERN(CIRGetRuntimeMemberOpABILowering,
+                            cir::GetRuntimeMemberOp);
+CIR_CXXABI_LOWERING_PATTERN(CIRGlobalOpABILowering, cir::GlobalOp);
+#undef CIR_CXXABI_LOWERING_PATTERN
+
+struct CXXABILoweringPass
+    : public impl::CXXABILoweringBase<CXXABILoweringPass> {
+  CXXABILoweringPass() = default;
+  void runOnOperation() override;
+};
+
+/// A generic ABI lowering rewrite pattern. This conversion pattern matches any
+/// CIR dialect operations with at least one operand or result of an
+/// ABI-dependent type. This conversion pattern rewrites the matched operation
+/// by replacing all its ABI-dependent operands and results with their
+/// lowered counterparts.
+class CIRGenericCXXABILoweringPattern : public mlir::ConversionPattern {
+public:
+  CIRGenericCXXABILoweringPattern(mlir::MLIRContext *context,
+                                  const mlir::TypeConverter &typeConverter)
+      : mlir::ConversionPattern(typeConverter, MatchAnyOpTypeTag(),
+                                /*benefit=*/1, context) {}
+
+  mlir::LogicalResult
+  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,
+                  cir::GetRuntimeMemberOp, cir::GlobalOp>(op))
+      return mlir::failure();
+
+    const mlir::TypeConverter *typeConverter = getTypeConverter();
+    assert(typeConverter &&
+           "CIRGenericCXXABILoweringPattern requires a type converter");
+    if (typeConverter->isLegal(op)) {
+      // The operation does not have any CXXABI-dependent operands or results,
+      // the match fails.
+      return mlir::failure();
+    }
+
+    assert(op->getNumRegions() == 0 && "CIRGenericCXXABILoweringPattern cannot 
"
+                                       "deal with operations with regions");
+
+    mlir::OperationState loweredOpState(op->getLoc(), op->getName());
+    loweredOpState.addOperands(operands);
+    loweredOpState.addAttributes(op->getAttrs());
+    loweredOpState.addSuccessors(op->getSuccessors());
+
+    // Lower all result types
+    llvm::SmallVector<mlir::Type> loweredResultTypes;
+    loweredResultTypes.reserve(op->getNumResults());
+    for (mlir::Type result : op->getResultTypes())
+      loweredResultTypes.push_back(typeConverter->convertType(result));
+    loweredOpState.addTypes(loweredResultTypes);
+
+    // Clone the operation with lowered operand types and result types
+    mlir::Operation *loweredOp = rewriter.create(loweredOpState);
+
+    rewriter.replaceOp(op, loweredOp);
+    return mlir::success();
+  }
+};
+
+} // namespace
+
+mlir::LogicalResult CIRAllocaOpABILowering::matchAndRewrite(
+    cir::AllocaOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type allocaPtrTy = op.getType();
+  mlir::Type allocaTy = op.getAllocaType();
+  mlir::Type loweredAllocaPtrTy = getTypeConverter()->convertType(allocaPtrTy);
+  mlir::Type loweredAllocaTy = getTypeConverter()->convertType(allocaTy);
+
+  cir::AllocaOp loweredOp = cir::AllocaOp::create(
+      rewriter, op.getLoc(), loweredAllocaPtrTy, loweredAllocaTy, op.getName(),
+      op.getAlignmentAttr(), /*dynAllocSize=*/adaptor.getDynAllocSize());
+  loweredOp.setInit(op.getInit());
+  loweredOp.setConstant(op.getConstant());
+  loweredOp.setAnnotationsAttr(op.getAnnotationsAttr());
+
+  rewriter.replaceOp(op, loweredOp);
+  return mlir::success();
+}
+
+mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite(
+    cir::ConstantOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+
+  if (mlir::isa<cir::DataMemberType>(op.getType())) {
+    auto dataMember = mlir::cast<cir::DataMemberAttr>(op.getValue());
+    mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
+    mlir::TypedAttr abiValue = 
lowerModule->getCXXABI().lowerDataMemberConstant(
+        dataMember, layout, *getTypeConverter());
+    rewriter.replaceOpWithNewOp<ConstantOp>(op, abiValue);
+    return mlir::success();
+  }
+
+  llvm_unreachable("constant operand is not an CXXABI-dependent type");
+}
+
+mlir::LogicalResult CIRFuncOpABILowering::matchAndRewrite(
+    cir::FuncOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  cir::FuncType opFuncType = op.getFunctionType();
+  mlir::TypeConverter::SignatureConversion signatureConversion(
+      opFuncType.getNumInputs());
+
+  for (const auto &[i, argType] : llvm::enumerate(opFuncType.getInputs())) {
+    mlir::Type loweredArgType = getTypeConverter()->convertType(argType);
+    if (!loweredArgType)
+      return mlir::failure();
+    signatureConversion.addInputs(i, loweredArgType);
+  }
+
+  mlir::Type loweredResultType =
+      getTypeConverter()->convertType(opFuncType.getReturnType());
+  if (!loweredResultType)
+    return mlir::failure();
+
+  auto loweredFuncType =
+      cir::FuncType::get(signatureConversion.getConvertedTypes(),
+                         loweredResultType, 
/*isVarArg=*/opFuncType.isVarArg());
+
+  // Create a new cir.func operation for the CXXABI-lowered function.
+  cir::FuncOp loweredFuncOp = rewriter.cloneWithoutRegions(op);
+  loweredFuncOp.setFunctionType(loweredFuncType);
+  rewriter.inlineRegionBefore(op.getBody(), loweredFuncOp.getBody(),
+                              loweredFuncOp.end());
+  if (mlir::failed(rewriter.convertRegionTypes(
+          &loweredFuncOp.getBody(), *getTypeConverter(), 
&signatureConversion)))
+    return mlir::failure();
+
+  rewriter.eraseOp(op);
+  return mlir::success();
+}
+
+mlir::LogicalResult CIRGlobalOpABILowering::matchAndRewrite(
+    cir::GlobalOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type ty = op.getSymType();
+  mlir::Type loweredTy = getTypeConverter()->convertType(ty);
+  if (!loweredTy)
+    return mlir::failure();
+
+  mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
+
+  mlir::Attribute loweredInit;
+  if (mlir::isa<cir::DataMemberType>(ty)) {
+    cir::DataMemberAttr init =
+        mlir::cast_if_present<cir::DataMemberAttr>(op.getInitialValueAttr());
+    loweredInit = lowerModule->getCXXABI().lowerDataMemberConstant(
+        init, layout, *getTypeConverter());
+  } else {
+    llvm_unreachable(
+        "inputs to cir.global in ABI lowering must be data member or method");
+  }
+
+  auto newOp = mlir::cast<cir::GlobalOp>(rewriter.clone(*op.getOperation()));
+  newOp.setInitialValueAttr(loweredInit);
+  newOp.setSymType(loweredTy);
+  rewriter.replaceOp(op, newOp);
+  return mlir::success();
+}
+
+mlir::LogicalResult CIRGetRuntimeMemberOpABILowering::matchAndRewrite(
+    cir::GetRuntimeMemberOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type resTy = getTypeConverter()->convertType(op.getType());
+  mlir::Operation *newOp = lowerModule->getCXXABI().lowerGetRuntimeMember(
+      op, resTy, adaptor.getAddr(), adaptor.getMember(), rewriter);
+  rewriter.replaceOp(op, newOp);
+  return mlir::success();
+}
+
+// Prepare the type converter for the CXXABI lowering pass.
+// Even though this is a CIR-to-CIR pass, we are eliminating some CIR types.
+static void prepareCXXABITypeConverter(mlir::TypeConverter &converter,
+                                       mlir::DataLayout &dataLayout,
+                                       cir::LowerModule &lowerModule) {
+  converter.addConversion([&](mlir::Type type) -> mlir::Type { return type; });
+  // This is necessary in order to convert CIR pointer types that are pointing
+  // to CIR types that we are lowering in this pass.
+  converter.addConversion([&](cir::PointerType type) -> mlir::Type {
+    mlir::Type loweredPointeeType = converter.convertType(type.getPointee());
+    if (!loweredPointeeType)
+      return {};
+    return cir::PointerType::get(type.getContext(), loweredPointeeType,
+                                 type.getAddrSpace());
+  });
+  converter.addConversion([&](cir::DataMemberType type) -> mlir::Type {
+    mlir::Type abiType =
+        lowerModule.getCXXABI().lowerDataMemberType(type, converter);
+    return converter.convertType(abiType);
+  });
+  // This is necessary in order to convert CIR function types that have 
argument
+  // or return types that use CIR types that we are lowering in this pass.
+  converter.addConversion([&](cir::FuncType type) -> mlir::Type {
+    llvm::SmallVector<mlir::Type> loweredInputTypes;
+    loweredInputTypes.reserve(type.getNumInputs());
+    if (mlir::failed(
+            converter.convertTypes(type.getInputs(), loweredInputTypes)))
+      return {};
+
+    mlir::Type loweredReturnType = converter.convertType(type.getReturnType());
+    if (!loweredReturnType)
+      return {};
+
+    return cir::FuncType::get(loweredInputTypes, loweredReturnType,
+                              /*isVarArg=*/type.getVarArg());
+  });
+}
+
+static void
+populateCXXABIConversionTarget(mlir::ConversionTarget &target,
+                               const mlir::TypeConverter &typeConverter) {
+  target.addLegalOp<mlir::ModuleOp>();
+
+  // The ABI lowering pass is interested in CIR operations with operands or
+  // results of CXXABI-dependent types, or CIR operations with regions whose
+  // block arguments are of CXXABI-dependent types.
+  target.addDynamicallyLegalDialect<cir::CIRDialect>(
+      [&typeConverter](mlir::Operation *op) {
+        if (!typeConverter.isLegal(op))
+          return false;
+        return std::all_of(op->getRegions().begin(), op->getRegions().end(),
+                           [&typeConverter](mlir::Region &region) {
+                             return typeConverter.isLegal(&region);
+                           });
+      });
+
+  // Some CIR ops needs special checking for legality
+  target.addDynamicallyLegalOp<cir::FuncOp>([&typeConverter](cir::FuncOp op) {
+    return typeConverter.isLegal(op.getFunctionType());
+  });
+  target.addDynamicallyLegalOp<cir::GlobalOp>(
+      [&typeConverter](cir::GlobalOp op) {
+        return typeConverter.isLegal(op.getSymType());
+      });
+}
+
+//===----------------------------------------------------------------------===//
+// The Pass
+//===----------------------------------------------------------------------===//
+
+void CXXABILoweringPass::runOnOperation() {
+  auto module = mlir::cast<mlir::ModuleOp>(getOperation());
+  mlir::MLIRContext *ctx = module.getContext();
+
+  // If the triple is not present, e.g. CIR modules parsed from text, we
+  // cannot init LowerModule properly.
+  assert(!cir::MissingFeatures::makeTripleAlwaysPresent());
+  // If no target triple is available, skip the ABI lowering pass.
+  if (!module->hasAttr(cir::CIRDialect::getTripleAttrName()))
+    return;
+
+  mlir::PatternRewriter rewriter(ctx);
+  std::unique_ptr<cir::LowerModule> lowerModule =
+      cir::createLowerModule(module, rewriter);
+
+  mlir::DataLayout dataLayout(module);
+  mlir::TypeConverter typeConverter;
+  prepareCXXABITypeConverter(typeConverter, dataLayout, *lowerModule);
+
+  mlir::RewritePatternSet patterns(ctx);
+  patterns.add<CIRGenericCXXABILoweringPattern>(patterns.getContext(),
+                                                typeConverter);
+  patterns.add<
+      // clang-format off
+      CIRAllocaOpABILowering,
+      CIRConstantOpABILowering,
+      CIRFuncOpABILowering,
+      CIRGetRuntimeMemberOpABILowering,
+      CIRGlobalOpABILowering
+      // clang-format on
+      >(patterns.getContext(), typeConverter, dataLayout, *lowerModule);
+
+  mlir::ConversionTarget target(*ctx);
+  populateCXXABIConversionTarget(target, typeConverter);
+
+  if (failed(mlir::applyPartialConversion(module, target, 
std::move(patterns))))
+    signalPassFailure();
+}
+
+std::unique_ptr<Pass> mlir::createCXXABILoweringPass() {
+  return std::make_unique<CXXABILoweringPass>();
+}
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp 
b/clang/lib/CIR/Lowering/CIRPasses.cpp
index ccc838717e421..72348ff6287b4 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -31,6 +31,7 @@ mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp 
theModule,
   if (enableCIRSimplify)
     pm.addPass(mlir::createCIRSimplifyPass());
 
+  pm.addPass(mlir::createCXXABILoweringPass());
   pm.addPass(mlir::createLoweringPreparePass(&astContext));
 
   pm.enableVerifier(enableVerifier);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index c01b2c1487709..507c5596471ad 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -258,9 +258,9 @@ class CIRAttrToValue {
     return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
         .Case<cir::IntAttr, cir::FPAttr, cir::ConstComplexAttr,
               cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
-              cir::ConstPtrAttr, cir::DataMemberAttr, cir::GlobalViewAttr,
-              cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
-              cir::ZeroAttr>([&](auto attrT) { return visitCirAttr(attrT); })
+              cir::ConstPtrAttr, cir::GlobalViewAttr, cir::TypeInfoAttr,
+              cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
+            [&](auto attrT) { return visitCirAttr(attrT); })
         .Default([&](auto attrT) { return mlir::Value(); });
   }
 
@@ -271,7 +271,6 @@ class CIRAttrToValue {
   mlir::Value visitCirAttr(cir::ConstArrayAttr attr);
   mlir::Value visitCirAttr(cir::ConstRecordAttr attr);
   mlir::Value visitCirAttr(cir::ConstVectorAttr attr);
-  mlir::Value visitCirAttr(cir::DataMemberAttr attr);
   mlir::Value visitCirAttr(cir::GlobalViewAttr attr);
   mlir::Value visitCirAttr(cir::TypeInfoAttr attr);
   mlir::Value visitCirAttr(cir::UndefAttr attr);
@@ -526,15 +525,6 @@ mlir::Value 
CIRAttrToValue::visitCirAttr(cir::ConstVectorAttr attr) {
                                    mlirValues));
 }
 
-mlir::Value CIRAttrToValue::visitCirAttr(cir::DataMemberAttr attr) {
-  assert(lowerMod && "lower module is not available");
-  mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>());
-  mlir::TypedAttr init =
-      lowerMod->getCXXABI().lowerDataMemberConstant(attr, layout, *converter);
-  // Recursively lower the CIR attribute produced by the C++ ABI.
-  return visit(init);
-}
-
 // GlobalViewAttr visitor.
 mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
   auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
@@ -1776,14 +1766,6 @@ mlir::LogicalResult 
CIRToLLVMConstantOpLowering::matchAndRewrite(
       return mlir::success();
     }
     attr = op.getValue();
-  } else if (mlir::isa<cir::DataMemberType>(op.getType())) {
-    assert(lowerMod && "lower module is not available");
-    auto dataMember = mlir::cast<cir::DataMemberAttr>(op.getValue());
-    mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
-    mlir::TypedAttr abiValue = lowerMod->getCXXABI().lowerDataMemberConstant(
-        dataMember, layout, *typeConverter);
-    rewriter.replaceOpWithNewOp<ConstantOp>(op, abiValue);
-    return mlir::success();
   } else if (const auto arrTy = mlir::dyn_cast<cir::ArrayType>(op.getType())) {
     const auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(op.getValue());
     if (!constArr && !isa<cir::ZeroAttr, cir::UndefAttr>(op.getValue()))
@@ -2125,10 +2107,11 @@ 
CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
     cir::GlobalOp op, mlir::Attribute init,
     mlir::ConversionPatternRewriter &rewriter) const {
   // TODO: Generalize this handling when more types are needed here.
-  assert((isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
-              cir::ConstPtrAttr, cir::ConstComplexAttr, cir::DataMemberAttr,
-              cir::GlobalViewAttr, cir::TypeInfoAttr, cir::UndefAttr,
-              cir::VTableAttr, cir::ZeroAttr>(init)));
+  assert(
+      (isa<cir::ConstArrayAttr, cir::ConstRecordAttr, cir::ConstVectorAttr,
+           cir::ConstPtrAttr, cir::ConstComplexAttr, cir::GlobalViewAttr,
+           cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr, cir::ZeroAttr>(
+          init)));
 
   // TODO(cir): once LLVM's dialect has proper equivalent attributes this
   // should be updated. For now, we use a custom op to initialize globals
@@ -2184,9 +2167,9 @@ mlir::LogicalResult 
CIRToLLVMGlobalOpLowering::matchAndRewrite(
       }
     } else if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
                          cir::ConstRecordAttr, cir::ConstPtrAttr,
-                         cir::ConstComplexAttr, cir::DataMemberAttr,
-                         cir::GlobalViewAttr, cir::TypeInfoAttr, 
cir::UndefAttr,
-                         cir::VTableAttr, cir::ZeroAttr>(init.value())) {
+                         cir::ConstComplexAttr, cir::GlobalViewAttr,
+                         cir::TypeInfoAttr, cir::UndefAttr, cir::VTableAttr,
+                         cir::ZeroAttr>(init.value())) {
       // TODO(cir): once LLVM's dialect has proper equivalent attributes this
       // should be updated. For now, we use a custom op to initialize globals
       // to the appropriate value.
@@ -2893,13 +2876,6 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter 
&converter,
     assert(!cir::MissingFeatures::addressSpace());
     return mlir::LLVM::LLVMPointerType::get(type.getContext());
   });
-  converter.addConversion(
-      [&, lowerModule](cir::DataMemberType type) -> mlir::Type {
-        assert(lowerModule && "CXXABI is not available");
-        mlir::Type abiType =
-            lowerModule->getCXXABI().lowerDataMemberType(type, converter);
-        return converter.convertType(abiType);
-      });
   converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
     mlir::Type ty =
         convertTypeForMemory(converter, dataLayout, type.getElementType());
@@ -3246,17 +3222,6 @@ mlir::LogicalResult 
CIRToLLVMGetMemberOpLowering::matchAndRewrite(
   }
 }
 
-mlir::LogicalResult CIRToLLVMGetRuntimeMemberOpLowering::matchAndRewrite(
-    cir::GetRuntimeMemberOp op, OpAdaptor adaptor,
-    mlir::ConversionPatternRewriter &rewriter) const {
-  assert(lowerMod && "lowering module is not available");
-  mlir::Type llvmResTy = getTypeConverter()->convertType(op.getType());
-  mlir::Operation *llvmOp = lowerMod->getCXXABI().lowerGetRuntimeMember(
-      op, llvmResTy, adaptor.getAddr(), adaptor.getMember(), rewriter);
-  rewriter.replaceOp(op, llvmOp);
-  return mlir::success();
-}
-
 mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
     cir::UnreachableOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp 
b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
index bee6562e59b8e..5ecf94293fd5e 100644
--- a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir 
-Wno-unused-value -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 -std=c++17 -fclangir 
-Wno-unused-value -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 
-Wno-unused-value -emit-llvm %s -o %t-cir.ll
 // RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 
-Wno-unused-value -emit-llvm %s -o %t.ll
@@ -12,7 +13,8 @@ struct Point {
 };
 
 int Point::*pt_member = &Point::z;
-// CIR: cir.global external @pt_member = #cir.data_member<2> : 
!cir.data_member<!s32i in !rec_Point>
+// CIR-BEFORE: cir.global external @pt_member = #cir.data_member<2> : 
!cir.data_member<!s32i in !rec_Point>
+// CIR-AFTER: cir.global external @pt_member = #cir.int<8> : !s64i
 // LLVM: @pt_member = global i64 8
 // OGCG: @pt_member = global i64 8
 
@@ -20,12 +22,19 @@ auto test1() -> int Point::* {
   return &Point::y;
 }
 
-// CIR: cir.func {{.*}} @_Z5test1v() -> !cir.data_member<!s32i in !rec_Point> {
-// CIR:   %[[RETVAL:.*]] = cir.alloca !cir.data_member<!s32i in !rec_Point>, 
!cir.ptr<!cir.data_member<!s32i in !rec_Point>>, ["__retval"]
-// CIR:   %[[MEMBER:.*]] = cir.const #cir.data_member<1> : 
!cir.data_member<!s32i in !rec_Point>
-// CIR:   cir.store %[[MEMBER]], %[[RETVAL]] : !cir.data_member<!s32i in 
!rec_Point>, !cir.ptr<!cir.data_member<!s32i in !rec_Point>>
-// CIR:   %[[RET:.*]] = cir.load %[[RETVAL]] : !cir.ptr<!cir.data_member<!s32i 
in !rec_Point>>, !cir.data_member<!s32i in !rec_Point>
-// CIR:   cir.return %[[RET]] : !cir.data_member<!s32i in !rec_Point>
+// CIR-BEFORE: cir.func {{.*}} @_Z5test1v() -> !cir.data_member<!s32i in 
!rec_Point> {
+// CIR-BEFORE:   %[[RETVAL:.*]] = cir.alloca !cir.data_member<!s32i in 
!rec_Point>, !cir.ptr<!cir.data_member<!s32i in !rec_Point>>, ["__retval"]
+// CIR-BEFORE:   %[[MEMBER:.*]] = cir.const #cir.data_member<1> : 
!cir.data_member<!s32i in !rec_Point>
+// CIR-BEFORE:   cir.store %[[MEMBER]], %[[RETVAL]] : !cir.data_member<!s32i 
in !rec_Point>, !cir.ptr<!cir.data_member<!s32i in !rec_Point>>
+// CIR-BEFORE:   %[[RET:.*]] = cir.load %[[RETVAL]] : 
!cir.ptr<!cir.data_member<!s32i in !rec_Point>>, !cir.data_member<!s32i in 
!rec_Point>
+// CIR-BEFORE:   cir.return %[[RET]] : !cir.data_member<!s32i in !rec_Point>
+
+// CIR-AFTER: cir.func {{.*}} @_Z5test1v() -> !s64i {
+// CIR-AFTER:   %[[RETVAL:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, 
["__retval"]
+// CIR-AFTER:   %[[OFFSET:.*]] = cir.const #cir.int<4> : !s64i
+// CIR-AFTER:   cir.store %[[OFFSET]], %[[RETVAL]] : !s64i, !cir.ptr<!s64i>
+// CIR-AFTER:   %[[RET:.*]] = cir.load %[[RETVAL]] : !cir.ptr<!s64i>, !s64i
+// CIR-AFTER:   cir.return %[[RET]] : !s64i
 
 // LLVM: define {{.*}} i64 @_Z5test1v()
 // LLVM:   %[[RETVAL:.*]] = alloca i64
@@ -40,21 +49,39 @@ int test2(const Point &pt, int Point::*member) {
   return pt.*member;
 }
 
-// CIR:       cir.func {{.*}} @_Z5test2RK5PointMS_i(
-// CIR-SAME:        %[[PT_ARG:.*]]: !cir.ptr<!rec_Point>
-// CIR-SAME:        %[[MEMBER_ARG:.*]]: !cir.data_member<!s32i in !rec_Point>
-// CIR:         %[[PT_ADDR:.*]] = cir.alloca {{.*}} ["pt", init, const]
-// CIR:         %[[MEMBER_ADDR:.*]] = cir.alloca {{.*}} ["member", init]
-// CIR:         %[[RETVAL_ADDR:.*]] = cir.alloca {{.*}} ["__retval"]
-// CIR:         cir.store %[[PT_ARG]], %[[PT_ADDR]]
-// CIR:         cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]]
-// CIR:         %[[PT:.*]] = cir.load %[[PT_ADDR]]
-// CIR:         %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]]
-// CIR:         %[[RT_MEMBER:.*]] = cir.get_runtime_member %[[PT]][%[[MEMBER]] 
: !cir.data_member<!s32i in !rec_Point>] : !cir.ptr<!rec_Point> -> 
!cir.ptr<!s32i>
-// CIR:         %[[VAL:.*]] = cir.load{{.*}} %[[RT_MEMBER]]
-// CIR:         cir.store %[[VAL]], %[[RETVAL_ADDR]]
-// CIR:         %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]]
-// CIR:         cir.return %[[RET]]
+// CIR-BEFORE:       cir.func {{.*}} @_Z5test2RK5PointMS_i(
+// CIR-BEFORE-SAME:        %[[PT_ARG:.*]]: !cir.ptr<!rec_Point>
+// CIR-BEFORE-SAME:        %[[MEMBER_ARG:.*]]: !cir.data_member<!s32i in 
!rec_Point>
+// CIR-BEFORE:         %[[PT_ADDR:.*]] = cir.alloca {{.*}} ["pt", init, const]
+// CIR-BEFORE:         %[[MEMBER_ADDR:.*]] = cir.alloca {{.*}} ["member", init]
+// CIR-BEFORE:         %[[RETVAL_ADDR:.*]] = cir.alloca {{.*}} ["__retval"]
+// CIR-BEFORE:         cir.store %[[PT_ARG]], %[[PT_ADDR]]
+// CIR-BEFORE:         cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]]
+// CIR-BEFORE:         %[[PT:.*]] = cir.load %[[PT_ADDR]]
+// CIR-BEFORE:         %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]]
+// CIR-BEFORE:         %[[RT_MEMBER:.*]] = cir.get_runtime_member 
%[[PT]][%[[MEMBER]] : !cir.data_member<!s32i in !rec_Point>] : 
!cir.ptr<!rec_Point> -> !cir.ptr<!s32i>
+// CIR-BEFORE:         %[[VAL:.*]] = cir.load{{.*}} %[[RT_MEMBER]]
+// CIR-BEFORE:         cir.store %[[VAL]], %[[RETVAL_ADDR]]
+// CIR-BEFORE:         %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]]
+// CIR-BEFORE:         cir.return %[[RET]]
+
+// CIR-AFTER:      cir.func {{.*}} @_Z5test2RK5PointMS_i(
+// CIR-AFTER-SAME:        %[[PT_ARG:.*]]: !cir.ptr<!rec_Point>
+// CIR-AFTER-SAME:        %[[MEMBER_ARG:.*]]: !s64i
+// CIR-AFTER:        %[[PT_ADDR:.*]] = cir.alloca !cir.ptr<!rec_Point>, 
!cir.ptr<!cir.ptr<!rec_Point>>, ["pt", init, const]
+// CIR-AFTER:        %[[MEMBER_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, 
["member", init]
+// CIR-AFTER:        %[[RETVAL_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, 
["__retval"]
+// CIR-AFTER:        cir.store %[[PT_ARG]], %[[PT_ADDR]] : 
!cir.ptr<!rec_Point>, !cir.ptr<!cir.ptr<!rec_Point>>
+// CIR-AFTER:        cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]] : !s64i, 
!cir.ptr<!s64i>
+// CIR-AFTER:        %[[PT:.*]] = cir.load %[[PT_ADDR]] : 
!cir.ptr<!cir.ptr<!rec_Point>>, !cir.ptr<!rec_Point>
+// CIR-AFTER:        %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]] : 
!cir.ptr<!s64i>, !s64i
+// CIR-AFTER:        %[[BYTE_PTR:.*]] = cir.cast bitcast %[[PT]] : 
!cir.ptr<!rec_Point> -> !cir.ptr<!s8i>
+// CIR-AFTER:        %[[BYTE_PTR_STRIDE:.*]] = cir.ptr_stride %[[BYTE_PTR]], 
%[[MEMBER]] : (!cir.ptr<!s8i>, !s64i) -> !cir.ptr<!s8i>
+// CIR-AFTER:        %[[VAL_ADDR:.*]] = cir.cast bitcast %[[BYTE_PTR_STRIDE]] 
: !cir.ptr<!s8i> -> !cir.ptr<!s32i>
+// CIR-AFTER:        %[[VAL:.*]] = cir.load{{.*}} %[[VAL_ADDR]] : 
!cir.ptr<!s32i>, !s32i
+// CIR-AFTER:        cir.store %[[VAL]], %[[RETVAL_ADDR]] : !s32i, 
!cir.ptr<!s32i>
+// CIR-AFTER:        %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]] : 
!cir.ptr<!s32i>, !s32i
+// CIR-AFTER:        cir.return %[[RET]] : !s32i
 
 // LLVM: define {{.*}} i32 @_Z5test2RK5PointMS_i(ptr %[[PT_ARG:.*]], i64 
%[[MEMBER_ARG:.*]])
 // LLVM:   %[[PT_ADDR:.*]] = alloca ptr
@@ -85,21 +112,39 @@ int test3(const Point *pt, int Point::*member) {
   return pt->*member;
 }
 
-// CIR:       cir.func {{.*}} @_Z5test3PK5PointMS_i(
-// CIR-SAME:        %[[PT_ARG:.*]]: !cir.ptr<!rec_Point>
-// CIR-SAME:        %[[MEMBER_ARG:.*]]: !cir.data_member<!s32i in !rec_Point>
-// CIR:         %[[PT_ADDR:.*]] = cir.alloca {{.*}} ["pt", init]
-// CIR:         %[[MEMBER_ADDR:.*]] = cir.alloca {{.*}} ["member", init]
-// CIR:         %[[RETVAL_ADDR:.*]] = cir.alloca {{.*}} ["__retval"]
-// CIR:         cir.store %[[PT_ARG]], %[[PT_ADDR]]
-// CIR:         cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]]
-// CIR:         %[[PT:.*]] = cir.load{{.*}} %[[PT_ADDR]]
-// CIR:         %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]]
-// CIR:         %[[RT_MEMBER:.*]] = cir.get_runtime_member %[[PT]][%[[MEMBER]] 
: !cir.data_member<!s32i in !rec_Point>] : !cir.ptr<!rec_Point> -> 
!cir.ptr<!s32i>
-// CIR:         %[[VAL:.*]] = cir.load{{.*}} %[[RT_MEMBER]]
-// CIR:         cir.store %[[VAL]], %[[RETVAL_ADDR]]
-// CIR:         %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]]
-// CIR:         cir.return %[[RET]]
+// CIR-BEFORE:       cir.func {{.*}} @_Z5test3PK5PointMS_i(
+// CIR-BEFORE-SAME:        %[[PT_ARG:.*]]: !cir.ptr<!rec_Point>
+// CIR-BEFORE-SAME:        %[[MEMBER_ARG:.*]]: !cir.data_member<!s32i in 
!rec_Point>
+// CIR-BEFORE:         %[[PT_ADDR:.*]] = cir.alloca {{.*}} ["pt", init]
+// CIR-BEFORE:         %[[MEMBER_ADDR:.*]] = cir.alloca {{.*}} ["member", init]
+// CIR-BEFORE:         %[[RETVAL_ADDR:.*]] = cir.alloca {{.*}} ["__retval"]
+// CIR-BEFORE:         cir.store %[[PT_ARG]], %[[PT_ADDR]]
+// CIR-BEFORE:         cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]]
+// CIR-BEFORE:         %[[PT:.*]] = cir.load{{.*}} %[[PT_ADDR]]
+// CIR-BEFORE:         %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]]
+// CIR-BEFORE:         %[[RT_MEMBER:.*]] = cir.get_runtime_member 
%[[PT]][%[[MEMBER]] : !cir.data_member<!s32i in !rec_Point>] : 
!cir.ptr<!rec_Point> -> !cir.ptr<!s32i>
+// CIR-BEFORE:         %[[VAL:.*]] = cir.load{{.*}} %[[RT_MEMBER]]
+// CIR-BEFORE:         cir.store %[[VAL]], %[[RETVAL_ADDR]]
+// CIR-BEFORE:         %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]]
+// CIR-BEFORE:         cir.return %[[RET]]
+
+// CIR-AFTER:      cir.func {{.*}} @_Z5test3PK5PointMS_i(
+// CIR-AFTER-SAME:        %[[PT_ARG:.*]]: !cir.ptr<!rec_Point>
+// CIR-AFTER-SAME:        %[[MEMBER_ARG:.*]]: !s64i
+// CIR-AFTER:        %[[PT_ADDR:.*]] = cir.alloca !cir.ptr<!rec_Point>, 
!cir.ptr<!cir.ptr<!rec_Point>>, ["pt", init]
+// CIR-AFTER:        %[[MEMBER_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, 
["member", init]
+// CIR-AFTER:        %[[RETVAL_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, 
["__retval"]
+// CIR-AFTER:        cir.store %[[PT_ARG]], %[[PT_ADDR]] : 
!cir.ptr<!rec_Point>, !cir.ptr<!cir.ptr<!rec_Point>>
+// CIR-AFTER:        cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]] : !s64i, 
!cir.ptr<!s64i>
+// CIR-AFTER:        %[[PT:.*]] = cir.load{{.*}} %[[PT_ADDR]] : 
!cir.ptr<!cir.ptr<!rec_Point>>, !cir.ptr<!rec_Point>
+// CIR-AFTER:        %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]] : 
!cir.ptr<!s64i>, !s64i
+// CIR-AFTER:        %[[BYTE_PTR:.*]] = cir.cast bitcast %[[PT]] : 
!cir.ptr<!rec_Point> -> !cir.ptr<!s8i>
+// CIR-AFTER:        %[[BYTE_PTR_STRIDE:.*]] = cir.ptr_stride %[[BYTE_PTR]], 
%[[MEMBER]] : (!cir.ptr<!s8i>, !s64i) -> !cir.ptr<!s8i>
+// CIR-AFTER:        %[[VAL_ADDR:.*]] = cir.cast bitcast %[[BYTE_PTR_STRIDE]] 
: !cir.ptr<!s8i> -> !cir.ptr<!s32i>
+// CIR-AFTER:        %[[VAL:.*]] = cir.load{{.*}} %[[VAL_ADDR]] : 
!cir.ptr<!s32i>, !s32i
+// CIR-AFTER:        cir.store %[[VAL]], %[[RETVAL_ADDR]] : !s32i, 
!cir.ptr<!s32i>
+// CIR-AFTER:        %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]] : 
!cir.ptr<!s32i>, !s32i
+// CIR-AFTER:        cir.return %[[RET]] : !s32i
 
 // LLVM: define {{.*}} i32 @_Z5test3PK5PointMS_i(ptr %[[PT_ARG:.*]], i64 
%[[MEMBER_ARG:.*]])
 // LLVM:   %[[PT_ADDR:.*]] = alloca ptr
@@ -132,15 +177,25 @@ auto test4(int Incomplete::*member) -> int Incomplete::* {
   return member;
 }
 
-// CIR:       cir.func {{.*}} @_Z5test4M10Incompletei(
-// CIR-SAME:        %[[MEMBER_ARG:.*]]: !cir.data_member<!s32i in 
!rec_Incomplete>
-// CIR:         %[[MEMBER_ADDR:.*]] = cir.alloca {{.*}} ["member", init]
-// CIR:         %[[RETVAL_ADDR:.*]] = cir.alloca {{.*}} ["__retval"]
-// CIR:         cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]]
-// CIR:         %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]]
-// CIR:         cir.store %[[MEMBER]], %[[RETVAL_ADDR]]
-// CIR:         %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]]
-// CIR:         cir.return %[[RET]]
+// CIR-BEFORE:       cir.func {{.*}} @_Z5test4M10Incompletei(
+// CIR-BEFORE-SAME:        %[[MEMBER_ARG:.*]]: !cir.data_member<!s32i in 
!rec_Incomplete>
+// CIR-BEFORE:         %[[MEMBER_ADDR:.*]] = cir.alloca {{.*}} ["member", init]
+// CIR-BEFORE:         %[[RETVAL_ADDR:.*]] = cir.alloca {{.*}} ["__retval"]
+// CIR-BEFORE:         cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]]
+// CIR-BEFORE:         %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]]
+// CIR-BEFORE:         cir.store %[[MEMBER]], %[[RETVAL_ADDR]]
+// CIR-BEFORE:         %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]]
+// CIR-BEFORE:         cir.return %[[RET]]
+
+// CIR-AFTER:      cir.func {{.*}} @_Z5test4M10Incompletei(
+// CIR-AFTER-SAME:       %[[MEMBER_ARG:.*]]: !s64i
+// CIR-AFTER:        %[[MEMBER_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, 
["member", init]
+// CIR-AFTER:        %[[RETVAL_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, 
["__retval"]
+// CIR-AFTER:        cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]] : !s64i, 
!cir.ptr<!s64i>
+// CIR-AFTER:        %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]] : 
!cir.ptr<!s64i>, !s64i
+// CIR-AFTER:        cir.store %[[MEMBER]], %[[RETVAL_ADDR]] : !s64i, 
!cir.ptr<!s64i>
+// CIR-AFTER:        %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]] : 
!cir.ptr<!s64i>, !s64i
+// CIR-AFTER:        cir.return %[[RET]] : !s64i
 
 // LLVM: define {{.*}} i64 @_Z5test4M10Incompletei(i64 %[[MEMBER_ARG:.*]])
 // LLVM:   %[[MEMBER_ADDR:.*]] = alloca i64
@@ -161,21 +216,39 @@ int test5(Incomplete *ic, int Incomplete::*member) {
   return ic->*member;
 }
 
-// CIR:       cir.func {{.*}} @_Z5test5P10IncompleteMS_i(
-// CIR-SAME:        %[[IC_ARG:.*]]: !cir.ptr<!rec_Incomplete>
-// CIR-SAME:        %[[MEMBER_ARG:.*]]: !cir.data_member<!s32i in 
!rec_Incomplete>
-// CIR:         %[[IC_ADDR:.*]] = cir.alloca {{.*}} ["ic", init]
-// CIR:         %[[MEMBER_ADDR:.*]] = cir.alloca {{.*}} ["member", init]
-// CIR:         %[[RETVAL_ADDR:.*]] = cir.alloca {{.*}} ["__retval"]
-// CIR:         cir.store %[[IC_ARG]], %[[IC_ADDR]]
-// CIR:         cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]]
-// CIR:         %[[IC:.*]] = cir.load{{.*}} %[[IC_ADDR]]
-// CIR:         %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]]
-// CIR:         %[[RT_MEMBER:.*]] = cir.get_runtime_member %[[IC]][%[[MEMBER]] 
: !cir.data_member<!s32i in !rec_Incomplete>] : !cir.ptr<!rec_Incomplete> -> 
!cir.ptr<!s32i>
-// CIR:         %[[VAL:.*]] = cir.load{{.*}} %[[RT_MEMBER]]
-// CIR:         cir.store %[[VAL]], %[[RETVAL_ADDR]]
-// CIR:         %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]]
-// CIR:         cir.return %[[RET]]
+// CIR-BEFORE:       cir.func {{.*}} @_Z5test5P10IncompleteMS_i(
+// CIR-BEFORE-SAME:        %[[IC_ARG:.*]]: !cir.ptr<!rec_Incomplete>
+// CIR-BEFORE-SAME:        %[[MEMBER_ARG:.*]]: !cir.data_member<!s32i in 
!rec_Incomplete>
+// CIR-BEFORE:         %[[IC_ADDR:.*]] = cir.alloca {{.*}} ["ic", init]
+// CIR-BEFORE:         %[[MEMBER_ADDR:.*]] = cir.alloca {{.*}} ["member", init]
+// CIR-BEFORE:         %[[RETVAL_ADDR:.*]] = cir.alloca {{.*}} ["__retval"]
+// CIR-BEFORE:         cir.store %[[IC_ARG]], %[[IC_ADDR]]
+// CIR-BEFORE:         cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]]
+// CIR-BEFORE:         %[[IC:.*]] = cir.load{{.*}} %[[IC_ADDR]]
+// CIR-BEFORE:         %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]]
+// CIR-BEFORE:         %[[RT_MEMBER:.*]] = cir.get_runtime_member 
%[[IC]][%[[MEMBER]] : !cir.data_member<!s32i in !rec_Incomplete>] : 
!cir.ptr<!rec_Incomplete> -> !cir.ptr<!s32i>
+// CIR-BEFORE:         %[[VAL:.*]] = cir.load{{.*}} %[[RT_MEMBER]]
+// CIR-BEFORE:         cir.store %[[VAL]], %[[RETVAL_ADDR]]
+// CIR-BEFORE:         %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]]
+// CIR-BEFORE:         cir.return %[[RET]]
+
+// CIR-AFTER:      cir.func {{.*}} @_Z5test5P10IncompleteMS_i(
+// CIR-AFTER-SAME:       %[[IC_ARG:.*]]: !cir.ptr<!rec_Incomplete>
+// CIR-AFTER-SAME:       %[[MEMBER_ARG:.*]]: !s64i
+// CIR-AFTER:        %[[IC_ADDR:.*]] = cir.alloca !cir.ptr<!rec_Incomplete>, 
!cir.ptr<!cir.ptr<!rec_Incomplete>>, ["ic", init]
+// CIR-AFTER:        %[[MEMBER_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, 
["member", init]
+// CIR-AFTER:        %[[RETVAL_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, 
["__retval"]
+// CIR-AFTER:        cir.store %[[IC_ARG]], %[[IC_ADDR]] : 
!cir.ptr<!rec_Incomplete>, !cir.ptr<!cir.ptr<!rec_Incomplete>>
+// CIR-AFTER:        cir.store %[[MEMBER_ARG]], %[[MEMBER_ADDR]] : !s64i, 
!cir.ptr<!s64i>
+// CIR-AFTER:        %[[IC:.*]] = cir.load{{.*}} %[[IC_ADDR]] : 
!cir.ptr<!cir.ptr<!rec_Incomplete>>, !cir.ptr<!rec_Incomplete>
+// CIR-AFTER:        %[[MEMBER:.*]] = cir.load{{.*}} %[[MEMBER_ADDR]] : 
!cir.ptr<!s64i>, !s64i
+// CIR-AFTER:        %[[BYTE_PTR:.*]] = cir.cast bitcast %[[IC]] : 
!cir.ptr<!rec_Incomplete> -> !cir.ptr<!s8i>
+// CIR-AFTER:        %[[BYTE_PTR_STRIDE:.*]] = cir.ptr_stride %[[BYTE_PTR]], 
%[[MEMBER]] : (!cir.ptr<!s8i>, !s64i) -> !cir.ptr<!s8i>
+// CIR-AFTER:        %[[VAL_ADDR:.*]] = cir.cast bitcast %[[BYTE_PTR_STRIDE]] 
: !cir.ptr<!s8i> -> !cir.ptr<!s32i>
+// CIR-AFTER:        %[[VAL:.*]] = cir.load{{.*}} %[[VAL_ADDR]] : 
!cir.ptr<!s32i>, !s32i
+// CIR-AFTER:        cir.store %[[VAL]], %[[RETVAL_ADDR]] : !s32i, 
!cir.ptr<!s32i>
+// CIR-AFTER:        %[[RET:.*]] = cir.load{{.*}} %[[RETVAL_ADDR]] : 
!cir.ptr<!s32i>, !s32i
+// CIR-AFTER:        cir.return %[[RET]] : !s32i
 
 // LLVM: define {{.*}} i32 @_Z5test5P10IncompleteMS_i(ptr %[[IC_ARG:.*]], i64 
%[[MEMBER_ARG:.*]])
 // LLVM:   %[[IC_ADDR:.*]] = alloca ptr

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

Reply via email to