Skip to content

Commit e846fd2

Browse files
YazZz1klanza
authored andcommitted
[CIR][CIRGen] Support for zero initialization of arrays (#468)
As in original codegen this PR uses the do-while loop to initialize the array elements with the filler expression. But unlike the original codegen we allocates the temporary variable on stack. Allocation is necessary to store the pointer to the first uniinitialized element.
1 parent 321ca2b commit e846fd2

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ void AggExprEmitter::buildArrayInit(Address DestPtr, mlir::cir::ArrayType AType,
433433

434434
QualType elementType =
435435
CGF.getContext().getAsArrayType(ArrayQTy)->getElementType();
436+
QualType elementPtrType = CGF.getContext().getPointerType(elementType);
436437

437438
auto cirElementType = CGF.convertType(elementType);
438439
auto cirElementPtrType = mlir::cir::PointerType::get(
@@ -498,7 +499,73 @@ void AggExprEmitter::buildArrayInit(Address DestPtr, mlir::cir::ArrayType AType,
498499
if (NumInitElements != NumArrayElements &&
499500
!(Dest.isZeroed() && hasTrivialFiller &&
500501
CGF.getTypes().isZeroInitializable(elementType))) {
501-
llvm_unreachable("zero-initialization of arrays NIY");
502+
503+
// Use an actual loop. This is basically
504+
// do { *array++ = filler; } while (array != end);
505+
506+
auto &builder = CGF.getBuilder();
507+
508+
// Advance to the start of the rest of the array.
509+
if (NumInitElements) {
510+
auto one =
511+
builder.getConstInt(loc, CGF.PtrDiffTy.cast<mlir::cir::IntType>(), 1);
512+
element = builder.create<mlir::cir::PtrStrideOp>(loc, cirElementPtrType,
513+
element, one);
514+
515+
assert(!endOfInit.isValid() && "destructed types NIY");
516+
}
517+
518+
// Allocate the temporary variable
519+
// to store the pointer to first unitialized element
520+
auto tmpAddr = CGF.CreateTempAlloca(
521+
cirElementPtrType, CGF.getPointerAlign(), loc, "arrayinit.temp");
522+
LValue tmpLV = CGF.makeAddrLValue(tmpAddr, elementPtrType);
523+
CGF.buildStoreThroughLValue(RValue::get(element), tmpLV);
524+
525+
// Compute the end of array
526+
auto numArrayElementsConst = builder.getConstInt(
527+
loc, CGF.PtrDiffTy.cast<mlir::cir::IntType>(), NumArrayElements);
528+
mlir::Value end = builder.create<mlir::cir::PtrStrideOp>(
529+
loc, cirElementPtrType, begin, numArrayElementsConst);
530+
531+
builder.createDoWhile(
532+
loc,
533+
/*condBuilder=*/
534+
[&](mlir::OpBuilder &b, mlir::Location loc) {
535+
auto currentElement = builder.createLoad(loc, tmpAddr);
536+
mlir::Type boolTy = CGF.getCIRType(CGF.getContext().BoolTy);
537+
auto cmp = builder.create<mlir::cir::CmpOp>(
538+
loc, boolTy, mlir::cir::CmpOpKind::ne, currentElement, end);
539+
builder.createCondition(cmp);
540+
},
541+
/*bodyBuilder=*/
542+
[&](mlir::OpBuilder &b, mlir::Location loc) {
543+
auto currentElement = builder.createLoad(loc, tmpAddr);
544+
545+
if (UnimplementedFeature::cleanups())
546+
llvm_unreachable("NYI");
547+
548+
// Emit the actual filler expression.
549+
LValue elementLV = CGF.makeAddrLValue(
550+
Address(currentElement, cirElementType, elementAlign),
551+
elementType);
552+
if (ArrayFiller)
553+
buildInitializationToLValue(ArrayFiller, elementLV);
554+
else
555+
buildNullInitializationToLValue(loc, elementLV);
556+
557+
// Tell the EH cleanup that we finished with the last element.
558+
assert(!endOfInit.isValid() && "destructed types NIY");
559+
560+
// Advance pointer and store them to temporary variable
561+
auto one = builder.getConstInt(
562+
loc, CGF.PtrDiffTy.cast<mlir::cir::IntType>(), 1);
563+
auto nextElement = builder.create<mlir::cir::PtrStrideOp>(
564+
loc, cirElementPtrType, currentElement, one);
565+
CGF.buildStoreThroughLValue(RValue::get(nextElement), tmpLV);
566+
567+
builder.createYield(loc);
568+
});
502569
}
503570

504571
// Leave the partial-array cleanup if we entered one.

clang/test/CIR/CodeGen/array-init.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,35 @@ void bar(int a, int b, int c) {
5353
// CHECK-NEXT: [[TH_EL:%.*]] = cir.ptr_stride(%7 : !cir.ptr<!s32i>, [[ONE]] : !s64i), !cir.ptr<!s32i>
5454
// CHECK-NEXT: [[LOAD_C:%.*]] = cir.load [[C]] : cir.ptr <!s32i>, !s32i
5555
// CHECK-NEXT: cir.store [[LOAD_C]], [[TH_EL]] : !s32i, cir.ptr <!s32i>
56+
57+
void zero_init(int x) {
58+
int arr[3] = {x};
59+
}
60+
61+
// CHECK: cir.func @zero_init
62+
// CHECK: [[VAR_ALLOC:%.*]] = cir.alloca !s32i, cir.ptr <!s32i>, ["x", init] {alignment = 4 : i64}
63+
// CHECK: %1 = cir.alloca !cir.array<!s32i x 3>, cir.ptr <!cir.array<!s32i x 3>>, ["arr", init] {alignment = 4 : i64}
64+
// CHECK: [[TEMP:%.*]] = cir.alloca !cir.ptr<!s32i>, cir.ptr <!cir.ptr<!s32i>>, ["arrayinit.temp", init] {alignment = 8 : i64}
65+
// CHECK: cir.store %arg0, [[VAR_ALLOC]] : !s32i, cir.ptr <!s32i>
66+
// CHECK: [[BEGIN:%.*]] = cir.cast(array_to_ptrdecay, %1 : !cir.ptr<!cir.array<!s32i x 3>>), !cir.ptr<!s32i>
67+
// CHECK: [[VAR:%.*]] = cir.load [[VAR_ALLOC]] : cir.ptr <!s32i>, !s32i
68+
// CHECK: cir.store [[VAR]], [[BEGIN]] : !s32i, cir.ptr <!s32i>
69+
// CHECK: [[ONE:%.*]] = cir.const(#cir.int<1> : !s64i) : !s64i
70+
// CHECK: [[ZERO_INIT_START:%.*]] = cir.ptr_stride([[BEGIN]] : !cir.ptr<!s32i>, [[ONE]] : !s64i), !cir.ptr<!s32i>
71+
// CHECK: cir.store [[ZERO_INIT_START]], [[TEMP]] : !cir.ptr<!s32i>, cir.ptr <!cir.ptr<!s32i>>
72+
// CHECK: [[SIZE:%.*]] = cir.const(#cir.int<3> : !s64i) : !s64i
73+
// CHECK: [[END:%.*]] = cir.ptr_stride([[BEGIN]] : !cir.ptr<!s32i>, [[SIZE]] : !s64i), !cir.ptr<!s32i>
74+
// CHECK: cir.do {
75+
// CHECK: [[CUR:%.*]] = cir.load [[TEMP]] : cir.ptr <!cir.ptr<!s32i>>, !cir.ptr<!s32i>
76+
// CHECK: [[FILLER:%.*]] = cir.const(#cir.int<0> : !s32i) : !s32i
77+
// CHECK: cir.store [[FILLER]], [[CUR]] : !s32i, cir.ptr <!s32i>
78+
// CHECK: [[ONE:%.*]] = cir.const(#cir.int<1> : !s64i) : !s64i
79+
// CHECK: [[NEXT:%.*]] = cir.ptr_stride([[CUR]] : !cir.ptr<!s32i>, [[ONE]] : !s64i), !cir.ptr<!s32i>
80+
// CHECK: cir.store [[NEXT]], [[TEMP]] : !cir.ptr<!s32i>, cir.ptr <!cir.ptr<!s32i>>
81+
// CHECK: cir.yield
82+
// CHECK: } while {
83+
// CHECK: [[CUR:%.*]] = cir.load [[TEMP]] : cir.ptr <!cir.ptr<!s32i>>, !cir.ptr<!s32i>
84+
// CHECK: [[CMP:%.*]] = cir.cmp(ne, [[CUR]], [[END]]) : !cir.ptr<!s32i>, !cir.bool
85+
// CHECK: cir.condition([[CMP]])
86+
// CHECK: }
87+
// CHECK: cir.return

0 commit comments

Comments
 (0)