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
