Skip to content

Commit f4860fa

Browse files
committed
[CIR][CIRGen] Update C++ codegen to use #cir.zero on structs
This small improvement allows for a more compact representation of structs with zero-initialized fields in the C++ codegen. ghstack-source-id: a3fe0dc Pull Request resolved: #217
1 parent e9380e0 commit f4860fa

File tree

3 files changed

+40
-14
lines changed

3 files changed

+40
-14
lines changed

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,35 @@ class CIRGenBuilderTy : public mlir::OpBuilder {
144144
return mlir::cir::ConstArrayAttr::get(arrayTy, attrs);
145145
}
146146

147+
mlir::Attribute getConstStructOrZeroAttr(mlir::ArrayAttr arrayAttr,
148+
bool packed = false,
149+
mlir::Type type = {}) {
150+
llvm::SmallVector<mlir::Type, 8> members;
151+
auto structTy = type.dyn_cast<mlir::cir::StructType>();
152+
assert(structTy && "expected cir.struct");
153+
assert(!packed && "unpacked struct is NYI");
154+
155+
// Collect members and check if they are all zero.
156+
bool isZero = true;
157+
for (auto &attr : arrayAttr) {
158+
const auto typedAttr = attr.dyn_cast<mlir::TypedAttr>();
159+
members.push_back(typedAttr.getType());
160+
isZero &= isNullValue(typedAttr);
161+
}
162+
163+
// Struct type not specified: create type from members.
164+
if (!structTy)
165+
structTy = getType<mlir::cir::StructType>(
166+
members, mlir::StringAttr::get(getContext()),
167+
/*body=*/true, packed,
168+
/*ast=*/std::nullopt);
169+
170+
// Return zero or anonymous constant struct.
171+
if (isZero)
172+
return mlir::cir::ZeroAttr::get(getContext(), structTy);
173+
return mlir::cir::ConstStructAttr::get(structTy, arrayAttr);
174+
}
175+
147176
mlir::cir::ConstStructAttr getAnonConstStruct(mlir::ArrayAttr arrayAttr,
148177
bool packed = false,
149178
mlir::Type ty = {}) {
@@ -186,7 +215,7 @@ class CIRGenBuilderTy : public mlir::OpBuilder {
186215
// TODO(cir): Once we have CIR float types, replace this by something like a
187216
// NullableValueInterface to allow for type-independent queries.
188217
bool isNullValue(mlir::Attribute attr) const {
189-
if (attr.isa<mlir::cir::ZeroAttr>())
218+
if (attr.isa<mlir::cir::ZeroAttr, mlir::cir::NullAttr>())
190219
return true;
191220

192221
// TODO(cir): introduce char type in CIR and check for that instead.

clang/lib/CIR/CodeGen/CIRGenExprConst.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,9 @@ mlir::Attribute ConstantAggregateBuilder::buildFrom(
281281

282282
// TODO(cir): emit a #cir.zero if all elements are null values.
283283
auto &builder = CGM.getBuilder();
284-
return builder.getAnonConstStruct(
285-
mlir::ArrayAttr::get(builder.getContext(),
286-
Packed ? PackedElems : UnpackedElems),
287-
Packed, DesiredTy);
284+
auto arrAttr = mlir::ArrayAttr::get(builder.getContext(),
285+
Packed ? PackedElems : UnpackedElems);
286+
return builder.getConstStructOrZeroAttr(arrAttr, Packed, DesiredTy);
288287
}
289288

290289
void ConstantAggregateBuilder::condense(CharUnits Offset,
@@ -1461,14 +1460,6 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &Value,
14611460
const ArrayType *ArrayTy = CGM.getASTContext().getAsArrayType(DestType);
14621461
unsigned NumElements = Value.getArraySize();
14631462
unsigned NumInitElts = Value.getArrayInitializedElts();
1464-
auto isNullValue = [&](mlir::Attribute f) {
1465-
// TODO(cir): introduce char type in CIR and check for that instead.
1466-
auto intVal = f.dyn_cast_or_null<mlir::cir::IntAttr>();
1467-
assert(intVal && "not implemented");
1468-
if (intVal.getValue() == 0)
1469-
return true;
1470-
return false;
1471-
};
14721463

14731464
// Emit array filler, if there is one.
14741465
mlir::Attribute Filler;
@@ -1481,7 +1472,7 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &Value,
14811472

14821473
// Emit initializer elements.
14831474
SmallVector<mlir::TypedAttr, 16> Elts;
1484-
if (Filler && isNullValue(Filler))
1475+
if (Filler && builder.isNullValue(Filler))
14851476
Elts.reserve(NumInitElts + 1);
14861477
else
14871478
Elts.reserve(NumElements);

clang/test/CIR/CodeGen/array.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,9 @@ int multidim(int i, int j) {
6565
// Should globally zero-initialize null arrays.
6666
int globalNullArr[] = {0, 0};
6767
// CHECK: cir.global external @globalNullArr = #cir.zero : !cir.array<!s32i x 2>
68+
69+
// Should implicitly zero-initialize global array elements.
70+
struct S {
71+
int i;
72+
} arr[3] = {{1}};
73+
// CHECK: cir.global external @arr = #cir.const_array<[#cir.const_struct<{#cir.int<1> : !s32i}> : !ty_22struct2ES22, #cir.zero : !ty_22struct2ES22, #cir.zero : !ty_22struct2ES22]> : !cir.array<!ty_22struct2ES22 x 3>

0 commit comments

Comments
 (0)