llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Erich Keane (erichkeane)
<details>
<summary>Changes</summary>
This patch adds support for arrays of pointer-to-member-data, just like we do
for pointer-to-member-function. This patch also does a refactor of some basic
value lowering, which both makes this apply to locals and constants, but also
unifies them in preperation of future work when it comes to record types.
Other than the otherwise-not-quite-intentional change (the recursion got
this feature, and I realized it worked while looking at other
things!), this is NFCI.
---
Full diff: https://github.com/llvm/llvm-project/pull/186887.diff
2 Files Affected:
- (modified) clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp (+47-54)
- (modified) clang/test/CIR/CodeGen/no-odr-use.cpp (+24-1)
``````````diff
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index d2c7ac37e8a96..35a841f8dbb1a 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -168,30 +168,56 @@ mlir::LogicalResult CIRCastOpABILowering::matchAndRewrite(
return mlir::failure();
}
+// Helper function to lower a value for things like an initializer.
+static mlir::TypedAttr lowerValue(const LowerModule *lowerModule,
+ const mlir::DataLayout &layout,
+ const mlir::TypeConverter &tc, mlir::Type ty,
+ mlir::Attribute initVal) {
+ if (mlir::isa<cir::DataMemberType>(ty)) {
+ auto dataMemberVal = mlir::cast_if_present<cir::DataMemberAttr>(initVal);
+ return lowerModule->getCXXABI().lowerDataMemberConstant(dataMemberVal,
+ layout, tc);
+ }
+ if (mlir::isa<cir::MethodType>(ty)) {
+ auto methodVal = mlir::cast_if_present<cir::MethodAttr>(initVal);
+ return lowerModule->getCXXABI().lowerMethodConstant(methodVal, layout, tc);
+ }
-mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite(
- cir::ConstantOp op, OpAdaptor adaptor,
- mlir::ConversionPatternRewriter &rewriter) const {
+ if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty)) {
+ auto loweredArrTy = mlir::cast<cir::ArrayType>(tc.convertType(arrTy));
+ // TODO(cir): there are other types that can appear here inside of record
+ // members that we should handle. Those will come in a follow-up patch to
+ // minimize changes here.
+ if (!initVal)
+ return {};
+ auto arrayVal = mlir::cast<cir::ConstArrayAttr>(initVal);
+ auto arrayElts = mlir::cast<ArrayAttr>(arrayVal.getElts());
+ SmallVector<mlir::Attribute> loweredElements;
+ loweredElements.reserve(arrTy.getSize());
+ for (const mlir::Attribute &attr : arrayElts) {
+ auto typedAttr = cast<mlir::TypedAttr>(attr);
+ loweredElements.push_back(
+ lowerValue(lowerModule, layout, tc, typedAttr.getType(), typedAttr));
+ }
- 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();
+ return cir::ConstArrayAttr::get(
+ loweredArrTy, mlir::ArrayAttr::get(ty.getContext(), loweredElements),
+ arrayVal.getTrailingZerosNum());
}
- if (mlir::isa<cir::MethodType>(op.getType())) {
- auto method = mlir::cast<cir::MethodAttr>(op.getValue());
- mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
- mlir::TypedAttr abiValue = lowerModule->getCXXABI().lowerMethodConstant(
- method, layout, *getTypeConverter());
- rewriter.replaceOpWithNewOp<ConstantOp>(op, abiValue);
- return mlir::success();
- }
+ llvm_unreachable("inputs to cir.global/constant in ABI lowering must be data
"
+ "member or method");
+}
- llvm_unreachable("constant operand is not an CXXABI-dependent type");
+mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite(
+ cir::ConstantOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+
+ mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
+ mlir::TypedAttr newValue = lowerValue(
+ lowerModule, layout, *getTypeConverter(), op.getType(), op.getValue());
+ rewriter.replaceOpWithNewOp<ConstantOp>(op, newValue);
+ return mlir::success();
}
mlir::LogicalResult CIRCmpOpABILowering::matchAndRewrite(
@@ -259,41 +285,8 @@ mlir::LogicalResult
CIRGlobalOpABILowering::matchAndRewrite(
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 if (mlir::isa<cir::MethodType>(ty)) {
- cir::MethodAttr init =
- mlir::cast_if_present<cir::MethodAttr>(op.getInitialValueAttr());
- loweredInit = lowerModule->getCXXABI().lowerMethodConstant(
- init, layout, *getTypeConverter());
- } else if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty)) {
- auto init = mlir::cast<cir::ConstArrayAttr>(op.getInitialValueAttr());
- auto arrayElts = mlir::cast<ArrayAttr>(init.getElts());
- SmallVector<mlir::Attribute> loweredElements;
- loweredElements.reserve(arrTy.getSize());
- for (const mlir::Attribute &attr : arrayElts) {
- if (auto methodAttr = mlir::dyn_cast<cir::MethodAttr>(attr)) {
- mlir::Attribute loweredElt =
- lowerModule->getCXXABI().lowerMethodConstant(methodAttr, layout,
- *getTypeConverter());
- loweredElements.push_back(loweredElt);
- } else {
- llvm_unreachable("array of data member lowering is NYI");
- }
- }
- auto loweredArrTy =
- mlir::cast<cir::ArrayType>(getTypeConverter()->convertType(arrTy));
- loweredInit = cir::ConstArrayAttr::get(
- loweredArrTy,
- mlir::ArrayAttr::get(rewriter.getContext(), loweredElements));
- } else {
- llvm_unreachable(
- "inputs to cir.global in ABI lowering must be data member or method");
- }
+ mlir::Attribute loweredInit = lowerValue(
+ lowerModule, layout, *getTypeConverter(), ty, op.getInitialValueAttr());
auto newOp = mlir::cast<cir::GlobalOp>(rewriter.clone(*op.getOperation()));
newOp.setInitialValueAttr(loweredInit);
diff --git a/clang/test/CIR/CodeGen/no-odr-use.cpp
b/clang/test/CIR/CodeGen/no-odr-use.cpp
index bd12c70803fc5..08d75b5e56221 100644
--- a/clang/test/CIR/CodeGen/no-odr-use.cpp
+++ b/clang/test/CIR/CodeGen/no-odr-use.cpp
@@ -15,6 +15,14 @@
// LLVM-DAG: @[[F_A:.*]] = private constant {{.*}} { i32 1, [2 x i32] [i32 2,
i32 3], [3 x i32] [i32 4, i32 5, i32 6] }
// OGCG-DAG: @__const._Z1fi.a = private unnamed_addr constant {{.*}} { i32 1,
[2 x i32] [i32 2, i32 3], [3 x i32] [i32 4, i32 5, i32 6] }
+// CIR-CXX11-DAG: cir.global "private" constant cir_private
@_ZN7PR422765State3dmsE.const = #cir.const_array<[#cir.int<0> : !s64i,
#cir.int<0> : !s64i]> : !cir.array<!s64i x 2> {alignment = 16 : i64}
+// LLVM-CXX11-DAG :@_ZN7PR422765State3dmsE.const = private constant [2 x i64]
zeroinitializer, align 16
+// OGCG-CXX11-DAG :@_ZN7PR422765State3dmsE.const = private constant [2 x i64]
zeroinitializer, align 16
+
+// CIR-CXX20-DAG: cir.global "private" constant cir_private
@_ZN7PR422765State3dmsE = #cir.const_array<[#cir.int<0> : !s64i, #cir.int<0> :
!s64i]> : !cir.array<!s64i x 2> {alignment = 16 : i64}
+// LLVM-CXX20-DAG :@_ZN7PR422765State3dmsE = private constant [2 x i64]
zeroinitializer, align 16
+// OGCG-CXX20-DAG :@_ZN7PR422765State3dmsE = private constant [2 x i64]
zeroinitializer, align 16
+
// CIR-CXX11-DAG: cir.global "private" constant cir_private
@_ZN7PR422765State1mE.const =
#cir.const_array<[#cir.const_record<{#cir.global_view<@_ZN7PR422765State2f1Ev>
: !s64i, #cir.int<0> : !s64i}> : !rec_anon_struct,
#cir.const_record<{#cir.global_view<@_ZN7PR422765State2f2Ev> : !s64i,
#cir.int<0> : !s64i}> : !rec_anon_struct]> : !cir.array<!rec_anon_struct x 2>
// LLVM-CXX11-DAG: @_ZN7PR422765State1mE.const = private constant [2 x { i64,
i64 }] [{ {{.*}} @_ZN7PR422765State2f1Ev {{.*}}, i64 0 }, { {{.*}}
@_ZN7PR422765State2f2Ev {{.*}}, i64 0 }]
// OGCG-CXX11-DAG: @_ZN7PR422765State1mE.const = private unnamed_addr constant
[2 x { i64, i64 }] [{ {{.*}} @_ZN7PR422765State2f1Ev {{.*}}, i64 0 }, { {{.*}}
@_ZN7PR422765State2f2Ev {{.*}}, i64 0 }]
@@ -93,8 +101,12 @@ namespace PR42276 {
class State {
void syncDirtyObjects();
void f1(), f2();
+ int dataMem;
using l = void (State::*)();
static constexpr l m[]{&State::f1, &State::f2};
+
+ using dmTy = int State::*;
+ static constexpr dmTy dms[]{&State::dataMem, &State::dataMem};
};
// CIR-CXX11-LABEL: cir.func {{.*}}
@_ZN7PR422765State2f1Ev(!cir.ptr<!rec_PR422763A3AState>{{.*}})
// CIR-CXX11-LABEL: cir.func {{.*}}
@_ZN7PR422765State2f2Ev(!cir.ptr<!rec_PR422763A3AState>{{.*}})
@@ -111,13 +123,24 @@ namespace PR42276 {
for (int i = 0; i < sizeof(m) / sizeof(m[0]); ++i)
// CIR-CXX11: %[[M:.*]] = cir.get_global @_ZN7PR422765State1mE.const :
!cir.ptr<!cir.array<!rec_anon_struct x 2>>
// CIR-CXX2A: %[[M:.*]] = cir.get_global @_ZN7PR422765State1mE :
!cir.ptr<!cir.array<!rec_anon_struct x 2>>
- // CIR: %[[M_I:.*]] = cir.get_element %[[M]][%{{.*}} : !s32i] :
!cir.ptr<!cir.array<!rec_anon_struct x 2>> -> !cir.ptr<!rec_anon_struct>
+ // CIR: cir.get_element %[[M]][%{{.*}} : !s32i] :
!cir.ptr<!cir.array<!rec_anon_struct x 2>> -> !cir.ptr<!rec_anon_struct>
// LLVM-CXX11: getelementptr [2 x { i64, i64 }], ptr
@_ZN7PR422765State1mE.const, i32 0, i64 %{{.*}}
// LLVM-CXX2A: getelementptr [2 x { i64, i64 }], ptr
@_ZN7PR422765State1mE, i32 0, i64 %{{.*}}
// OGCG-CXX11: getelementptr inbounds [2 x { i64, i64 }], ptr
@_ZN7PR422765State1mE.const, i64 0, i64 %{{.*}}
// OGCG-CXX2A: getelementptr inbounds [2 x { i64, i64 }], ptr
@_ZN7PR422765State1mE, i64 0, i64 %{{.*}}
(this->*m[i])();
+
+ int sum = 0;
+ for (int i = 0; i< sizeof(dms) / sizeof(dms[0]); ++i)
+ // CIR-CXX11: %[[DMS:.*]] = cir.get_global @_ZN7PR422765State3dmsE.const
: !cir.ptr<!cir.array<!s64i x 2>>
+ // CIR-CXX2A: %[[DMS:.*]] = cir.get_global @_ZN7PR422765State3dmsE :
!cir.ptr<!cir.array<!s64i x 2>>
+ // CIR: cir.get_element %[[DMS]][%{{.*}} : !s32i] :
!cir.ptr<!cir.array<!s64i x 2>> -> !cir.ptr<!s64i>
+ // LLVM-CXX11: getelementptr [2 x i64], ptr
@_ZN7PR422765State3dmsE.const, i32 0, i64 %{{.*}}
+ // LLVM-CXX2A: getelementptr [2 x i64], ptr @_ZN7PR422765State3dmsE, i32
0, i64 %{{.*}}
+ // OGCG-CXX11: getelementptr inbounds [2 x i64], ptr
@_ZN7PR422765State3dmsE.const, i64 0, i64 %{{.*}}
+ // OGCG-CXX2A: getelementptr inbounds [2 x i64], ptr
@_ZN7PR422765State3dmsE, i64 0, i64 %{{.*}}
+ sum += this->*dms[i];
}
// CIR-CXX2A-LABEL: cir.func {{.*}}
@_ZN7PR422765State2f1Ev(!cir.ptr<!rec_PR422763A3AState>{{.*}})
// CIR-CXX2A-LABEL: cir.func {{.*}}
@_ZN7PR422765State2f2Ev(!cir.ptr<!rec_PR422763A3AState>{{.*}})
``````````
</details>
https://github.com/llvm/llvm-project/pull/186887
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits