llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Andy Kaylor (andykaylor) <details> <summary>Changes</summary> This updates the array initialization loop to use a do..while loop rather than a fully serialized initialization. It also allows the initialization of destructed objects when exception handling is not enabled. Array initialization when exception handling is enabled remains unimplemented, but more precise messages are now emitted. --- Patch is 29.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/153499.diff 4 Files Affected: - (modified) clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (+53-26) - (modified) clang/test/CIR/CodeGen/array.cpp (+115-58) - (modified) clang/test/CIR/CodeGen/destructors.cpp (+99) - (modified) clang/test/CIR/Lowering/array.cpp (+60-29) ``````````diff diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp index 1fda8487796a9..6b6ac701e6867 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp @@ -124,8 +124,8 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy, const QualType elementType = cgf.getContext().getAsArrayType(arrayQTy)->getElementType(); - if (elementType.isDestructedType()) { - cgf.cgm.errorNYI(loc, "dtorKind NYI"); + if (elementType.isDestructedType() && cgf.cgm.getLangOpts().Exceptions) { + cgf.cgm.errorNYI(loc, "initialized array requires destruction"); return; } @@ -135,9 +135,9 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy, const cir::PointerType cirElementPtrType = builder.getPointerTo(cirElementType); - auto begin = builder.create<cir::CastOp>(loc, cirElementPtrType, - cir::CastKind::array_to_ptrdecay, - destPtr.getPointer()); + auto begin = cir::CastOp::create(builder, loc, cirElementPtrType, + cir::CastKind::array_to_ptrdecay, + destPtr.getPointer()); const CharUnits elementSize = cgf.getContext().getTypeSizeInChars(elementType); @@ -182,8 +182,8 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy, // Advance to the start of the rest of the array. if (numInitElements) { one = builder.getConstantInt(loc, cgf.PtrDiffTy, 1); - element = builder.create<cir::PtrStrideOp>(loc, cirElementPtrType, - element, one); + element = cir::PtrStrideOp::create(builder, loc, cirElementPtrType, + element, one); } // Allocate the temporary variable @@ -193,25 +193,52 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy, LValue tmpLV = cgf.makeAddrLValue(tmpAddr, elementPtrType); cgf.emitStoreThroughLValue(RValue::get(element), tmpLV); - // TODO(CIR): Replace this part later with cir::DoWhileOp - for (unsigned i = numInitElements; i != numArrayElements; ++i) { - cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr); - - // Emit the actual filler expression. - const LValue elementLV = cgf.makeAddrLValue( - Address(currentElement, cirElementType, elementAlign), elementType); - - if (arrayFiller) - emitInitializationToLValue(arrayFiller, elementLV); - else - emitNullInitializationToLValue(loc, elementLV); - - // Advance pointer and store them to temporary variable - one = builder.getConstantInt(loc, cgf.PtrDiffTy, 1); - cir::PtrStrideOp nextElement = - builder.createPtrStride(loc, currentElement, one); - cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV); - } + // Compute the end of array + cir::ConstantOp numArrayElementsConst = builder.getConstInt( + loc, mlir::cast<cir::IntType>(cgf.PtrDiffTy), numArrayElements); + mlir::Value end = cir::PtrStrideOp::create(builder, loc, cirElementPtrType, + begin, numArrayElementsConst); + + builder.createDoWhile( + loc, + /*condBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr); + mlir::Type boolTy = cgf.convertType(cgf.getContext().BoolTy); + cir::CmpOp cmp = cir::CmpOp::create( + builder, loc, boolTy, cir::CmpOpKind::ne, currentElement, end); + builder.createCondition(cmp); + }, + /*bodyBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr); + + assert(!cir::MissingFeatures::requiresCleanups()); + + // Emit the actual filler expression. + LValue elementLV = cgf.makeAddrLValue( + Address(currentElement, cirElementType, elementAlign), + elementType); + if (arrayFiller) + emitInitializationToLValue(arrayFiller, elementLV); + else + emitNullInitializationToLValue(loc, elementLV); + + // Tell the EH cleanup that we finished with the last element. + if (cgf.cgm.getLangOpts().Exceptions) { + cgf.cgm.errorNYI(loc, "update destructed array element for EH"); + return; + } + + // Advance pointer and store them to temporary variable + cir::ConstantOp one = builder.getConstInt( + loc, mlir::cast<cir::IntType>(cgf.PtrDiffTy), 1); + auto nextElement = cir::PtrStrideOp::create( + builder, loc, cirElementPtrType, currentElement, one); + cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV); + + builder.createYield(loc); + }); } } diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp index 141b67e0e63c7..60028af4b3161 100644 --- a/clang/test/CIR/CodeGen/array.cpp +++ b/clang/test/CIR/CodeGen/array.cpp @@ -129,31 +129,50 @@ void func2() { } // CIR: %[[ARR2:.*]] = cir.alloca !cir.array<!s32i x 2>, !cir.ptr<!cir.array<!s32i x 2>>, ["arr", init] -// CIR: %[[ELE_ALLOCA:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arrayinit.temp", init] -// CIR: %[[ARR_2_PTR:.*]] = cir.cast(array_to_ptrdecay, %[[ARR2]] : !cir.ptr<!cir.array<!s32i x 2>>), !cir.ptr<!s32i> -// CIR: %[[V1:.*]] = cir.const #cir.int<5> : !s32i -// CIR: cir.store{{.*}} %[[V1]], %[[ARR_2_PTR]] : !s32i, !cir.ptr<!s32i> +// CIR: %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arrayinit.temp", init] +// CIR: %[[ARR_0:.*]] = cir.cast(array_to_ptrdecay, %[[ARR2]] : !cir.ptr<!cir.array<!s32i x 2>>), !cir.ptr<!s32i> +// CIR: %[[FIVE:.*]] = cir.const #cir.int<5> : !s32i +// CIR: cir.store{{.*}} %[[FIVE]], %[[ARR_0]] : !s32i, !cir.ptr<!s32i> // CIR: %[[OFFSET_0:.*]] = cir.const #cir.int<1> : !s64i -// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride(%[[ARR_2_PTR]] : !cir.ptr<!s32i>, %[[OFFSET_0]] : !s64i), !cir.ptr<!s32i> -// CIR: cir.store{{.*}} %[[ELE_PTR]], %[[ELE_ALLOCA]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> -// CIR: %[[LOAD_1:.*]] = cir.load{{.*}} %[[ELE_ALLOCA]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> -// CIR: %[[V2:.*]] = cir.const #cir.int<0> : !s32i -// CIR: cir.store{{.*}} %[[V2]], %[[LOAD_1]] : !s32i, !cir.ptr<!s32i> -// CIR: %[[OFFSET_1:.*]] = cir.const #cir.int<1> : !s64i -// CIR: %[[ELE_1_PTR:.*]] = cir.ptr_stride(%[[LOAD_1]] : !cir.ptr<!s32i>, %[[OFFSET_1]] : !s64i), !cir.ptr<!s32i> -// CIR: cir.store{{.*}} %[[ELE_1_PTR]], %[[ELE_ALLOCA]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> +// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!s32i>, %[[OFFSET_0]] : !s64i), !cir.ptr<!s32i> +// CIR: cir.store{{.*}} %[[ELE_PTR]], %[[ARR_PTR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> +// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s64i +// CIR: %[[ARR_END:.*]] = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!s32i>, %[[TWO]] : !s64i), !cir.ptr<!s32i> +// CIR: cir.do { +// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> +// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i +// CIR: cir.store{{.*}} %[[ZERO]], %[[ARR_CUR]] : !s32i, !cir.ptr<!s32i> +// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i +// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride(%[[ARR_CUR]] : !cir.ptr<!s32i>, %[[ONE]] : !s64i), !cir.ptr<!s32i> +// CIR: cir.store{{.*}} %[[ARR_NEXT]], %[[ARR_PTR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> +// CIR: cir.yield +// CIR: } while { +// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> +// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[ARR_END]]) : !cir.ptr<!s32i>, !cir.bool +// CIR: cir.condition(%[[CMP]]) +// CIR: } // LLVM: define{{.*}} void @_Z5func2v() -// LLVM: %[[ARR:.*]] = alloca [2 x i32], i64 1, align 4 -// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8 -// LLVM: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR]], i32 0 -// LLVM: store i32 5, ptr %[[ARR_PTR]], align 4 -// LLVM: %[[ELE_1_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 1 -// LLVM: store ptr %[[ELE_1_PTR]], ptr %[[TMP]], align 8 -// LLVM: %[[TMP2:.*]] = load ptr, ptr %[[TMP]], align 8 -// LLVM: store i32 0, ptr %[[TMP2]], align 4 -// LLVM: %[[ELE_1:.*]] = getelementptr i32, ptr %[[TMP2]], i64 1 -// LLVM: store ptr %[[ELE_1]], ptr %[[TMP]], align 8 +// LLVM: %[[ARR:.*]] = alloca [2 x i32], i64 1, align 4 +// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8 +// LLVM: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR]], i32 0 +// LLVM: store i32 5, ptr %[[ARR_PTR]], align 4 +// LLVM: %[[ELE_1_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 1 +// LLVM: store ptr %[[ELE_1_PTR]], ptr %[[TMP]], align 8 +// LLVM: %[[END_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 2 +// LLVM: br label %[[LOOP_BODY:.*]] +// LLVM: [[LOOP_NEXT:.*]]: +// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8 +// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[END_PTR]] +// LLVM: br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]] +// LLVM: [[LOOP_BODY]]: +// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8 +// LLVM: store i32 0, ptr %[[CUR]], align 4 +// LLVM: %[[NEXT:.*]] = getelementptr i32, ptr %[[CUR]], i64 1 +// LLVM: store ptr %[[NEXT]], ptr %[[TMP]], align 8 +// LLVM: br label %[[LOOP_NEXT:.*]] +// LLVM: [[LOOP_END]]: +// LLVM: ret void // OGCG: %[[ARR:.*]] = alloca [2 x i32], align 4 // OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR]], ptr align 4 @[[FUN2_ARR]], i64 8, i1 false) @@ -270,27 +289,46 @@ void func5() { // CIR: %[[V_0_0:.*]] = cir.const #cir.int<5> : !s32i // CIR: cir.store{{.*}} %[[V_0_0]], %[[ARR_0_PTR]] : !s32i, !cir.ptr<!s32i> // CIR: %[[OFFSET:.*]] = cir.const #cir.int<1> : !s64i -// CIR: %6 = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!cir.array<!s32i x 1>>, %[[OFFSET]] : !s64i), !cir.ptr<!cir.array<!s32i x 1>> -// CIR: cir.store{{.*}} %6, %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>> -// CIR: %7 = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>, !cir.ptr<!cir.array<!s32i x 1>> -// CIR: %8 = cir.const #cir.zero : !cir.array<!s32i x 1> -// CIR: cir.store{{.*}} %8, %7 : !cir.array<!s32i x 1>, !cir.ptr<!cir.array<!s32i x 1>> -// CIR: %[[OFFSET_1:.*]] = cir.const #cir.int<1> : !s64i -// CIR: %10 = cir.ptr_stride(%7 : !cir.ptr<!cir.array<!s32i x 1>>, %[[OFFSET_1]] : !s64i), !cir.ptr<!cir.array<!s32i x 1>> -// CIR: cir.store{{.*}} %10, %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>> +// CIR: %[[ARR_1:.*]] = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!cir.array<!s32i x 1>>, %[[OFFSET]] : !s64i), !cir.ptr<!cir.array<!s32i x 1>> +// CIR: cir.store{{.*}} %[[ARR_1]], %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>> +// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s64i +// CIR: %[[ARR_END:.*]] = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!cir.array<!s32i x 1>>, %[[TWO]] : !s64i), !cir.ptr<!cir.array<!s32i x 1>> +// CIR: cir.do { +// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>, !cir.ptr<!cir.array<!s32i x 1>> +// CIR: %[[ZERO:.*]] = cir.const #cir.zero : !cir.array<!s32i x 1> +// CIR: cir.store{{.*}} %[[ZERO]], %[[ARR_CUR]] : !cir.array<!s32i x 1>, !cir.ptr<!cir.array<!s32i x 1>> +// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i +// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride(%[[ARR_CUR]] : !cir.ptr<!cir.array<!s32i x 1>>, %[[ONE]] : !s64i), !cir.ptr<!cir.array<!s32i x 1>> +// CIR: cir.store{{.*}} %[[ARR_NEXT]], %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>> +// CIR: cir.yield +// CIR: } while { +// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>, !cir.ptr<!cir.array<!s32i x 1>> +// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[ARR_END]]) : !cir.ptr<!cir.array<!s32i x 1>>, !cir.bool +// CIR: cir.condition(%[[CMP]]) +// CIR: } // LLVM: define{{.*}} void @_Z5func5v() -// LLVM: %[[ARR:.*]] = alloca [2 x [1 x i32]], i64 1, align 4 -// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8 -// LLVM: %[[ARR_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR]], i32 0 -// LLVM: %[[ARR_0:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i32 0 -// LLVM: store i32 5, ptr %[[ARR_0]], align 4 -// LLVM: %[[ARR_1:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 1 -// LLVM: store ptr %[[ARR_1]], ptr %[[TMP]], align 8 -// LLVM: %[[ARR_1_VAL:.*]] = load ptr, ptr %[[TMP]], align 8 -// LLVM: store [1 x i32] zeroinitializer, ptr %[[ARR_1_VAL]], align 4 -// LLVM: %[[ARR_1_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR_1_VAL]], i64 1 -// LLVM: store ptr %[[ARR_1_PTR]], ptr %[[TMP]], align 8 +// LLVM: %[[ARR:.*]] = alloca [2 x [1 x i32]], i64 1, align 4 +// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8 +// LLVM: %[[ARR_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR]], i32 0 +// LLVM: %[[ARR_0:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i32 0 +// LLVM: store i32 5, ptr %[[ARR_0]], align 4 +// LLVM: %[[ARR_1:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 1 +// LLVM: store ptr %[[ARR_1]], ptr %[[TMP]], align 8 +// LLVM: %[[END_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 2 +// LLVM: br label %[[LOOP_BODY:.*]] +// LLVM: [[LOOP_NEXT:.*]]: +// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8 +// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[END_PTR]] +// LLVM: br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]] +// LLVM: [[LOOP_BODY]]: +// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8 +// LLVM: store [1 x i32] zeroinitializer, ptr %[[CUR]], align 4 +// LLVM: %[[NEXT:.*]] = getelementptr [1 x i32], ptr %[[CUR]], i64 1 +// LLVM: store ptr %[[NEXT]], ptr %[[TMP]], align 8 +// LLVM: br label %[[LOOP_NEXT:.*]] +// LLVM: [[LOOP_END]]: +// LLVM: ret void // ORGC: %[[ARR:.*]] = alloca [2 x [1 x i32]], align 4 // ORGC: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR]], ptr align 4 @[[FUN5_ARR]], i64 8, i1 false) @@ -335,25 +373,44 @@ void func7() { } // CIR: %[[ARR:.*]] = cir.alloca !cir.array<!cir.ptr<!s32i> x 1>, !cir.ptr<!cir.array<!cir.ptr<!s32i> x 1>>, ["arr", init] -// CIR: %[[ARR_TMP:.*]] = cir.alloca !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, ["arrayinit.temp", init] -// CIR: %[[ARR_PTR:.*]] = cir.cast(array_to_ptrdecay, %[[ARR]] : !cir.ptr<!cir.array<!cir.ptr<!s32i> x 1>>), !cir.ptr<!cir.ptr<!s32i>> -// CIR: cir.store{{.*}} %[[ARR_PTR]], %[[ARR_TMP]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>> -// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[ARR_TMP]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>> -// CIR: %[[NULL_PTR:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i> -// CIR: cir.store{{.*}} %[[NULL_PTR]], %[[TMP]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> -// CIR: %[[OFFSET:.*]] = cir.const #cir.int<1> : !s64i -// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride(%[[TMP]] : !cir.ptr<!cir.ptr<!s32i>>, %[[OFFSET]] : !s64i), !cir.ptr<!cir.ptr<!s32i>> -// CIR: cir.store{{.*}} %[[ELE_PTR]], %[[ARR_TMP]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>> +// CIR: %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, ["arrayinit.temp", init] +// CIR: %[[ARR_0:.*]] = cir.cast(array_to_ptrdecay, %[[ARR]] : !cir.ptr<!cir.array<!cir.ptr<!s32i> x 1>>), !cir.ptr<!cir.ptr<!s32i>> +// CIR: cir.store{{.*}} %[[ARR_0]], %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>> +// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i +// CIR: %[[ARR_END:.*]] = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!cir.ptr<!s32i>>, %[[ONE]] : !s64i), !cir.ptr<!cir.ptr<!s32i>> +// CIR: cir.do { +// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>> +// CIR: %[[NULL_PTR:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i> +// CIR: cir.store{{.*}} %[[NULL_PTR]], %[[ARR_CUR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> +// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i +// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride(%[[ARR_CUR]] : !cir.ptr<!cir.ptr<!s32i>>, %[[ONE]] : !s64i), !cir.ptr<!cir.ptr<!s32i>> +// CIR: cir.store{{.*}} %[[ARR_NEXT]], %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>> +// CIR: cir.yield +// CIR: } while { +// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>> +// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[ARR_END]]) : !cir.ptr<!cir.ptr<!s32i>>, !cir.bool +// CIR: cir.condition(%[[CMP]]) +// CIR: } // LLVM: define{{.*}} void @_Z5func7v() -// LLVM: %[[ARR:.*]] = alloca [1 x ptr], i64 1, align 8 -// LLVM: %[[ALLOCA:.*]] = alloca ptr, i64 1, align 8 -// LLVM: %[[ELE_PTR:.*]] = getelementptr ptr, ptr %[[ARR]], i32 0 -// LLVM: store ptr %[[ELE_PTR]], ptr %[[ALLOCA]], align 8 -// LLVM: %[[TMP:.*]] = load ptr, ptr %[[ALLOCA]], align 8 -// LLVM: store ptr null, ptr %[[TMP]], align 8 -// LLVM: %[[ELE:.*]] = getelementptr ptr, ptr %[[TMP]], i64 1 -// LLVM: store ptr %[[ELE]], ptr %[[ALLOCA]], align 8 +// LLVM: %[[ARR:.*]] = alloca [1 x ptr], i64 1, align 8 +// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8 +// LLVM: %[[ARR_PTR:.*]] = getelementptr ptr, ptr %[[ARR]], i32 0 +// LLVM: store ptr %[[ARR_PTR]], ptr %[[TMP]], align 8 +// LLVM: %[[END_PTR:.*]] = getelementptr ptr, ptr %[[ARR_PTR]], i64 1 +// LLVM: br label %[[LOOP_BODY:.*]] +// LLVM: [[LOOP_NEXT:.*]]: +// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8 +// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[END_PTR]] +// LLVM: br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]] +// LLVM: [[LOOP_BODY]]: +// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8 +// LLVM: store ptr null, ptr %[[CUR]], align 8 +// LLVM: %[[NEXT:.*]] = getelementptr ptr, ptr %[[CUR]], i64 1 +// LLVM: store ptr %[[NEXT]], ptr %[[TMP]], align 8 +// LLVM: br label %[[LOOP_NEXT:.*]] +// LLVM: [[LOOP_END]]: +// LLVM: ret void // OGCG: %[[ARR:.*]] = alloca [1 x ptr], align 8 // OGCG: call void @llvm.memset.p0.i64(ptr align 8 %[[ARR]], i8 0, i64 8, i1 false) diff --git a/clang/test/CIR/CodeGen/destructors.cpp b/clang/test/CIR/CodeGen/destructors.cpp index de7718f0998fc..fde0732a4352f 100644 --- a/clang/test/CIR/CodeGen/destructors.cpp +++ b/clang/test/CIR/CodeGen/destructors.cpp @@ -55,3 +55,102 @@ struct inline_destructor { // CIR-NOT: cir.func {{.*}}inline_destructor{{.*}} // LLVM-NOT: define {{.*}}inline_destructor{{.*}} // OGCG-NOT: define {{.*}}inline_destructor{{.*}} + +struct array_element {~array_element();}; +void test_array_destructor() { + array_element arr[5]{}; +} + +// CIR: cir.func dso_local @_Z21test_array_destructorv() +// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!rec_array_element x 5>, !cir.ptr<!cir.array<!rec_array_element x 5>>, ["arr", init] +// CIR: %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!rec_array_element>, !cir.ptr<!cir.ptr<!rec_array_element>>, ["arrayinit.temp", init] +// CIR: %[[BEGIN:.*]] = cir.cast(array_to_ptrdecay, %[[ARR]] : !cir.ptr<!cir.array<!rec_array_element x 5>>) +// CIR: cir.store{{.*}} %[[BEGIN]], %[[ARR_PTR]] +// CIR: %[[FIVE:.*]] = cir.const #cir.int<5> : !s64i +// CIR: %[[ARR_END:.*]] = cir.ptr_stride(%[[BEGIN]] : !cir.ptr<!rec_array_element>, %[[FIVE]] : !s64i) +// CIR: cir.do { +// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] +// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i +// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride(%[[ARR_CUR]] : !cir.ptr<!rec_array_element>, %[[ONE]] : !s64i) +// CIR: cir.store{{.*}} %[[ARR_NEXT]], %[[ARR_PTR]] : !cir.ptr<!rec_array_element>, !cir.ptr<!cir.ptr<!rec_array_element>> +// CIR: cir.yield +// CIR: } while { +// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] +// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[ARR_END]]) +// CIR: cir.condition(%[[CMP]]) +// CIR: } +// CIR: %[[FOUR:.*]] = cir.const #cir.int<4> : !u64i +// CIR... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/153499 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits