https://github.com/bcardosolopes updated 
https://github.com/llvm/llvm-project/pull/232880

>From c14553b1d0bf41482c5b568de327b83ef9652de4 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <[email protected]>
Date: Thu, 15 Oct 2026 14:25:37 -0700
Subject: [PATCH 1/2] [CIR] Skip record rebuilds for unchanging types in CXXABI
 lowering

CIRABITypeConverter only rewrites data-member and method types, but it
did not override typeMayChange, so every named record converted to a
renamed copy and every op touching one was illegal, forcing the generic
pattern to rebuild them all. Override it to report only those two types
as possibly changing, letting records that reach neither convert to
themselves and stay legal.

One behavior guard: no-op casts that always fold (same-type bitcast,
address_space, complex) must stay illegal so the driver's BeforePatterns
fold still removes them; without this carve-out the dead casts that
TargetLowering leaves behind would survive into later passes (caught by
cxx-this-lvalue.hlsl). Same-type casts on non-record types now fold in
this pass too, which shows in -emit-cir output; -emit-llvm is unchanged.

CXXABILowering on SemaExpr CIR: 2.42s->0.90s (-63%). 3-rep medians on the
five slowest -fclangir translation units: Registry 36.7->35.8,
ASTImporterTest 64.4->63.7, SLPVectorizer 93.6->91.9, OpenMPDecomp
39.5->38.1, SemaExpr 59.3->57.5. Total 67.9s->61.6s (-6.3s). .text
bit-identical on all five. check-clang-cir green, 1250 passed with
0 unexpected failures.

Assisted-by: Muse Code (Muse).
---
 .../CIR/Dialect/Transforms/CXXABILowering.cpp | 28 ++++++++++++
 .../cxx-abi-lowering-same-type-cast-fold.cir  | 45 +++++++++++++++++++
 2 files changed, 73 insertions(+)
 create mode 100644 
clang/test/CIR/Transforms/cxx-abi-lowering-same-type-cast-fold.cir

diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp 
b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index 86c74ce14842b9..2bf8bf1677912b 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -846,6 +846,13 @@ class CIRABITypeConverter : public 
cir::RecordRewritingTypeConverter {
       return convertType(abiType);
     });
   }
+
+protected:
+  // Only member pointer types are rewritten. Records that reach none of them
+  // are left alone.
+  bool typeMayChange(mlir::Type type) const override {
+    return mlir::isa<cir::DataMemberType, cir::MethodType>(type);
+  }
 };
 } // namespace
 
@@ -885,6 +892,27 @@ populateCXXABIConversionTarget(mlir::ConversionTarget 
&target,
                            });
       });
 
+  // TargetLowering leaves same-type casts behind. Keep them illegal so the
+  // conversion driver folds them away.
+  target.addDynamicallyLegalOp<cir::CastOp>([&typeConverter](cir::CastOp op) {
+    if (op.getSrc().getType() == op.getType()) {
+      switch (op.getKind()) {
+      case cir::CastKind::bitcast:
+      case cir::CastKind::address_space:
+      case cir::CastKind::float_complex:
+      case cir::CastKind::int_complex:
+        return false;
+      default:
+        break;
+      }
+    }
+    if (!typeConverter.isLegal(op.getOperation()))
+      return false;
+    // CastOp has no regions, so operand/result types and inherent
+    // attributes are the whole legality check.
+    return areCXXABIInherentAttrsLegal(op, typeConverter);
+  });
+
   // Some CIR ops needs special checking for legality
   target.addDynamicallyLegalOp<cir::FuncOp>([&typeConverter](cir::FuncOp op) {
     bool attrs = areCXXABIInherentAttrsLegal(op, typeConverter);
diff --git a/clang/test/CIR/Transforms/cxx-abi-lowering-same-type-cast-fold.cir 
b/clang/test/CIR/Transforms/cxx-abi-lowering-same-type-cast-fold.cir
new file mode 100644
index 00000000000000..c0ee9a9b611a43
--- /dev/null
+++ b/clang/test/CIR/Transforms/cxx-abi-lowering-same-type-cast-fold.cir
@@ -0,0 +1,45 @@
+// RUN: cir-opt %s -cir-cxxabi-lowering -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+
+!u8i = !cir.int<u, 8>
+!s32i = !cir.int<s, 32>
+!rec_S = !cir.struct<"S" {data !s32i}>
+!rec_Other = !cir.struct<"Other" {pad !u8i}>
+!rec_Dmp = !cir.struct<"Dmp" {data !cir.data_member<!s32i in !rec_Other>}>
+// CHECK: !rec_Dmp = !cir.struct<"Dmp" {data !s64i}>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  // Same-type no-op casts stay illegal so the driver folds them away,
+  // on plain ...
+  cir.func @cast_plain(%p: !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {
+    %c = cir.cast bitcast %p : !cir.ptr<!s32i> -> !cir.ptr<!s32i>
+    cir.return %c : !cir.ptr<!s32i>
+  }
+  // CHECK-LABEL: cir.func @cast_plain
+  // CHECK-NEXT: cir.return %{{.*}} : !cir.ptr<!s32i>
+
+  // ... and record pointers.
+  cir.func @cast_record(%p: !cir.ptr<!rec_S>) -> !cir.ptr<!rec_S> {
+    %c = cir.cast bitcast %p : !cir.ptr<!rec_S> -> !cir.ptr<!rec_S>
+    cir.return %c : !cir.ptr<!rec_S>
+  }
+  // CHECK-LABEL: cir.func @cast_record
+  // CHECK-NEXT: cir.return %{{.*}} : !cir.ptr<!rec_S>
+
+  // Same for the address_space casts TargetLowering leaves behind.
+  cir.func @cast_addrspace(%p: !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {
+    %c = cir.cast address_space %p : !cir.ptr<!s32i> -> !cir.ptr<!s32i>
+    cir.return %c : !cir.ptr<!s32i>
+  }
+  // CHECK-LABEL: cir.func @cast_addrspace
+  // CHECK-NEXT: cir.return %{{.*}} : !cir.ptr<!s32i>
+
+  // Records that reach member pointers are still rewritten.
+  cir.func @dmp_rewritten() {
+    %r = cir.const #cir.zero : !rec_Dmp
+    cir.return
+  }
+  // CHECK-LABEL: cir.func @dmp_rewritten
+  // CHECK-NEXT: %{{.*}} = cir.const #cir.zero : !rec_Dmp
+  // CHECK-NEXT: cir.return
+}

>From 6ef66f677eec156a08e74b439b35d237a96f03d2 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <[email protected]>
Date: Fri, 16 Oct 2026 19:04:24 -0700
Subject: [PATCH 2/2] Add member-record lowering coverage for typeMayChange

---
 .../cxx-abi-lowering-member-record.cir        | 26 +++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 clang/test/CIR/Transforms/cxx-abi-lowering-member-record.cir

diff --git a/clang/test/CIR/Transforms/cxx-abi-lowering-member-record.cir 
b/clang/test/CIR/Transforms/cxx-abi-lowering-member-record.cir
new file mode 100644
index 00000000000000..ee5a0ede7b0bff
--- /dev/null
+++ b/clang/test/CIR/Transforms/cxx-abi-lowering-member-record.cir
@@ -0,0 +1,26 @@
+// RUN: cir-opt %s -cir-cxxabi-lowering -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+
+!s32i = !cir.int<s, 32>
+!rec_Foo = !cir.struct<"Foo" {data !s32i}>
+!method = !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i)> in !rec_Foo>
+!rec_HasMethod = !cir.struct<"HasMethod" {data !method}>
+!rec_Plain = !cir.struct<"Plain" {data !s32i}>
+
+// A record reaching a method type is rebuilt with the Itanium lowered form,
+// a {ptrdiff_t, ptrdiff_t} pair. Dropping MethodType from typeMayChange
+// leaves the member unlowered and this check fails.
+// CHECK-DAG: !rec_HasMethod = !cir.struct<"HasMethod" {data !rec_anon_struct}>
+// CHECK-DAG: !rec_anon_struct = !cir.struct<{data !s64i, data !s64i}>
+
+// A record reaching no member pointer type converts to itself and passes
+// through with its name and members untouched.
+// CHECK-DAG: !rec_Plain = !cir.struct<"Plain" {data !s32i}>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @method_record() {
+    %m = cir.const #cir.zero : !rec_HasMethod
+    %p = cir.const #cir.zero : !rec_Plain
+    cir.return
+  }
+}

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

Reply via email to