Skip to content

Commit

Permalink
[CIR][CIRGen] Support for zero initialization of arrays (#468)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
YazZz1k authored Feb 20, 2024
1 parent 364812d commit 0c140c2
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 1 deletion.
69 changes: 68 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ void AggExprEmitter::buildArrayInit(Address DestPtr, mlir::cir::ArrayType AType,

QualType elementType =
CGF.getContext().getAsArrayType(ArrayQTy)->getElementType();
QualType elementPtrType = CGF.getContext().getPointerType(elementType);

auto cirElementType = CGF.convertType(elementType);
auto cirElementPtrType = mlir::cir::PointerType::get(
Expand Down Expand Up @@ -498,7 +499,73 @@ void AggExprEmitter::buildArrayInit(Address DestPtr, mlir::cir::ArrayType AType,
if (NumInitElements != NumArrayElements &&
!(Dest.isZeroed() && hasTrivialFiller &&
CGF.getTypes().isZeroInitializable(elementType))) {
llvm_unreachable("zero-initialization of arrays NIY");

// Use an actual loop. This is basically
// do { *array++ = filler; } while (array != end);

auto &builder = CGF.getBuilder();

// Advance to the start of the rest of the array.
if (NumInitElements) {
auto one =
builder.getConstInt(loc, CGF.PtrDiffTy.cast<mlir::cir::IntType>(), 1);
element = builder.create<mlir::cir::PtrStrideOp>(loc, cirElementPtrType,
element, one);

assert(!endOfInit.isValid() && "destructed types NIY");
}

// Allocate the temporary variable
// to store the pointer to first unitialized element
auto tmpAddr = CGF.CreateTempAlloca(
cirElementPtrType, CGF.getPointerAlign(), loc, "arrayinit.temp");
LValue tmpLV = CGF.makeAddrLValue(tmpAddr, elementPtrType);
CGF.buildStoreThroughLValue(RValue::get(element), tmpLV);

// Compute the end of array
auto numArrayElementsConst = builder.getConstInt(
loc, CGF.PtrDiffTy.cast<mlir::cir::IntType>(), NumArrayElements);
mlir::Value end = builder.create<mlir::cir::PtrStrideOp>(
loc, cirElementPtrType, begin, numArrayElementsConst);

builder.createDoWhile(
loc,
/*condBuilder=*/
[&](mlir::OpBuilder &b, mlir::Location loc) {
auto currentElement = builder.createLoad(loc, tmpAddr);
mlir::Type boolTy = CGF.getCIRType(CGF.getContext().BoolTy);
auto cmp = builder.create<mlir::cir::CmpOp>(
loc, boolTy, mlir::cir::CmpOpKind::ne, currentElement, end);
builder.createCondition(cmp);
},
/*bodyBuilder=*/
[&](mlir::OpBuilder &b, mlir::Location loc) {
auto currentElement = builder.createLoad(loc, tmpAddr);

if (UnimplementedFeature::cleanups())
llvm_unreachable("NYI");

// Emit the actual filler expression.
LValue elementLV = CGF.makeAddrLValue(
Address(currentElement, cirElementType, elementAlign),
elementType);
if (ArrayFiller)
buildInitializationToLValue(ArrayFiller, elementLV);
else
buildNullInitializationToLValue(loc, elementLV);

// Tell the EH cleanup that we finished with the last element.
assert(!endOfInit.isValid() && "destructed types NIY");

// Advance pointer and store them to temporary variable
auto one = builder.getConstInt(
loc, CGF.PtrDiffTy.cast<mlir::cir::IntType>(), 1);
auto nextElement = builder.create<mlir::cir::PtrStrideOp>(
loc, cirElementPtrType, currentElement, one);
CGF.buildStoreThroughLValue(RValue::get(nextElement), tmpLV);

builder.createYield(loc);
});
}

// Leave the partial-array cleanup if we entered one.
Expand Down
32 changes: 32 additions & 0 deletions clang/test/CIR/CodeGen/array-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,35 @@ void bar(int a, int b, int c) {
// CHECK-NEXT: [[TH_EL:%.*]] = cir.ptr_stride(%7 : !cir.ptr<!s32i>, [[ONE]] : !s64i), !cir.ptr<!s32i>
// CHECK-NEXT: [[LOAD_C:%.*]] = cir.load [[C]] : cir.ptr <!s32i>, !s32i
// CHECK-NEXT: cir.store [[LOAD_C]], [[TH_EL]] : !s32i, cir.ptr <!s32i>

void zero_init(int x) {
int arr[3] = {x};
}

// CHECK: cir.func @zero_init
// CHECK: [[VAR_ALLOC:%.*]] = cir.alloca !s32i, cir.ptr <!s32i>, ["x", init] {alignment = 4 : i64}
// CHECK: %1 = cir.alloca !cir.array<!s32i x 3>, cir.ptr <!cir.array<!s32i x 3>>, ["arr", init] {alignment = 4 : i64}
// CHECK: [[TEMP:%.*]] = cir.alloca !cir.ptr<!s32i>, cir.ptr <!cir.ptr<!s32i>>, ["arrayinit.temp", init] {alignment = 8 : i64}
// CHECK: cir.store %arg0, [[VAR_ALLOC]] : !s32i, cir.ptr <!s32i>
// CHECK: [[BEGIN:%.*]] = cir.cast(array_to_ptrdecay, %1 : !cir.ptr<!cir.array<!s32i x 3>>), !cir.ptr<!s32i>
// CHECK: [[VAR:%.*]] = cir.load [[VAR_ALLOC]] : cir.ptr <!s32i>, !s32i
// CHECK: cir.store [[VAR]], [[BEGIN]] : !s32i, cir.ptr <!s32i>
// CHECK: [[ONE:%.*]] = cir.const(#cir.int<1> : !s64i) : !s64i
// CHECK: [[ZERO_INIT_START:%.*]] = cir.ptr_stride([[BEGIN]] : !cir.ptr<!s32i>, [[ONE]] : !s64i), !cir.ptr<!s32i>
// CHECK: cir.store [[ZERO_INIT_START]], [[TEMP]] : !cir.ptr<!s32i>, cir.ptr <!cir.ptr<!s32i>>
// CHECK: [[SIZE:%.*]] = cir.const(#cir.int<3> : !s64i) : !s64i
// CHECK: [[END:%.*]] = cir.ptr_stride([[BEGIN]] : !cir.ptr<!s32i>, [[SIZE]] : !s64i), !cir.ptr<!s32i>
// CHECK: cir.do {
// CHECK: [[CUR:%.*]] = cir.load [[TEMP]] : cir.ptr <!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CHECK: [[FILLER:%.*]] = cir.const(#cir.int<0> : !s32i) : !s32i
// CHECK: cir.store [[FILLER]], [[CUR]] : !s32i, cir.ptr <!s32i>
// CHECK: [[ONE:%.*]] = cir.const(#cir.int<1> : !s64i) : !s64i
// CHECK: [[NEXT:%.*]] = cir.ptr_stride([[CUR]] : !cir.ptr<!s32i>, [[ONE]] : !s64i), !cir.ptr<!s32i>
// CHECK: cir.store [[NEXT]], [[TEMP]] : !cir.ptr<!s32i>, cir.ptr <!cir.ptr<!s32i>>
// CHECK: cir.yield
// CHECK: } while {
// CHECK: [[CUR:%.*]] = cir.load [[TEMP]] : cir.ptr <!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CHECK: [[CMP:%.*]] = cir.cmp(ne, [[CUR]], [[END]]) : !cir.ptr<!s32i>, !cir.bool
// CHECK: cir.condition([[CMP]])
// CHECK: }
// CHECK: cir.return

0 comments on commit 0c140c2

Please sign in to comment.