Skip to content

Commit f2d76b5

Browse files
authored
[CIR] Use a loop for array initialization (llvm#153499)
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.
1 parent 9f953fa commit f2d76b5

File tree

4 files changed

+327
-113
lines changed

4 files changed

+327
-113
lines changed

clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
124124
const QualType elementType =
125125
cgf.getContext().getAsArrayType(arrayQTy)->getElementType();
126126

127-
if (elementType.isDestructedType()) {
128-
cgf.cgm.errorNYI(loc, "dtorKind NYI");
127+
if (elementType.isDestructedType() && cgf.cgm.getLangOpts().Exceptions) {
128+
cgf.cgm.errorNYI(loc, "initialized array requires destruction");
129129
return;
130130
}
131131

@@ -135,9 +135,9 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
135135
const cir::PointerType cirElementPtrType =
136136
builder.getPointerTo(cirElementType);
137137

138-
auto begin = builder.create<cir::CastOp>(loc, cirElementPtrType,
139-
cir::CastKind::array_to_ptrdecay,
140-
destPtr.getPointer());
138+
auto begin = cir::CastOp::create(builder, loc, cirElementPtrType,
139+
cir::CastKind::array_to_ptrdecay,
140+
destPtr.getPointer());
141141

142142
const CharUnits elementSize =
143143
cgf.getContext().getTypeSizeInChars(elementType);
@@ -182,8 +182,8 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
182182
// Advance to the start of the rest of the array.
183183
if (numInitElements) {
184184
one = builder.getConstantInt(loc, cgf.PtrDiffTy, 1);
185-
element = builder.create<cir::PtrStrideOp>(loc, cirElementPtrType,
186-
element, one);
185+
element = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
186+
element, one);
187187
}
188188

189189
// Allocate the temporary variable
@@ -193,25 +193,52 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
193193
LValue tmpLV = cgf.makeAddrLValue(tmpAddr, elementPtrType);
194194
cgf.emitStoreThroughLValue(RValue::get(element), tmpLV);
195195

196-
// TODO(CIR): Replace this part later with cir::DoWhileOp
197-
for (unsigned i = numInitElements; i != numArrayElements; ++i) {
198-
cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);
199-
200-
// Emit the actual filler expression.
201-
const LValue elementLV = cgf.makeAddrLValue(
202-
Address(currentElement, cirElementType, elementAlign), elementType);
203-
204-
if (arrayFiller)
205-
emitInitializationToLValue(arrayFiller, elementLV);
206-
else
207-
emitNullInitializationToLValue(loc, elementLV);
208-
209-
// Advance pointer and store them to temporary variable
210-
one = builder.getConstantInt(loc, cgf.PtrDiffTy, 1);
211-
cir::PtrStrideOp nextElement =
212-
builder.createPtrStride(loc, currentElement, one);
213-
cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV);
214-
}
196+
// Compute the end of array
197+
cir::ConstantOp numArrayElementsConst = builder.getConstInt(
198+
loc, mlir::cast<cir::IntType>(cgf.PtrDiffTy), numArrayElements);
199+
mlir::Value end = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
200+
begin, numArrayElementsConst);
201+
202+
builder.createDoWhile(
203+
loc,
204+
/*condBuilder=*/
205+
[&](mlir::OpBuilder &b, mlir::Location loc) {
206+
cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);
207+
mlir::Type boolTy = cgf.convertType(cgf.getContext().BoolTy);
208+
cir::CmpOp cmp = cir::CmpOp::create(
209+
builder, loc, boolTy, cir::CmpOpKind::ne, currentElement, end);
210+
builder.createCondition(cmp);
211+
},
212+
/*bodyBuilder=*/
213+
[&](mlir::OpBuilder &b, mlir::Location loc) {
214+
cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);
215+
216+
assert(!cir::MissingFeatures::requiresCleanups());
217+
218+
// Emit the actual filler expression.
219+
LValue elementLV = cgf.makeAddrLValue(
220+
Address(currentElement, cirElementType, elementAlign),
221+
elementType);
222+
if (arrayFiller)
223+
emitInitializationToLValue(arrayFiller, elementLV);
224+
else
225+
emitNullInitializationToLValue(loc, elementLV);
226+
227+
// Tell the EH cleanup that we finished with the last element.
228+
if (cgf.cgm.getLangOpts().Exceptions) {
229+
cgf.cgm.errorNYI(loc, "update destructed array element for EH");
230+
return;
231+
}
232+
233+
// Advance pointer and store them to temporary variable
234+
cir::ConstantOp one = builder.getConstInt(
235+
loc, mlir::cast<cir::IntType>(cgf.PtrDiffTy), 1);
236+
auto nextElement = cir::PtrStrideOp::create(
237+
builder, loc, cirElementPtrType, currentElement, one);
238+
cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV);
239+
240+
builder.createYield(loc);
241+
});
215242
}
216243
}
217244

clang/test/CIR/CodeGen/array.cpp

Lines changed: 115 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -129,31 +129,50 @@ void func2() {
129129
}
130130

131131
// CIR: %[[ARR2:.*]] = cir.alloca !cir.array<!s32i x 2>, !cir.ptr<!cir.array<!s32i x 2>>, ["arr", init]
132-
// CIR: %[[ELE_ALLOCA:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arrayinit.temp", init]
133-
// CIR: %[[ARR_2_PTR:.*]] = cir.cast(array_to_ptrdecay, %[[ARR2]] : !cir.ptr<!cir.array<!s32i x 2>>), !cir.ptr<!s32i>
134-
// CIR: %[[V1:.*]] = cir.const #cir.int<5> : !s32i
135-
// CIR: cir.store{{.*}} %[[V1]], %[[ARR_2_PTR]] : !s32i, !cir.ptr<!s32i>
132+
// CIR: %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arrayinit.temp", init]
133+
// CIR: %[[ARR_0:.*]] = cir.cast(array_to_ptrdecay, %[[ARR2]] : !cir.ptr<!cir.array<!s32i x 2>>), !cir.ptr<!s32i>
134+
// CIR: %[[FIVE:.*]] = cir.const #cir.int<5> : !s32i
135+
// CIR: cir.store{{.*}} %[[FIVE]], %[[ARR_0]] : !s32i, !cir.ptr<!s32i>
136136
// CIR: %[[OFFSET_0:.*]] = cir.const #cir.int<1> : !s64i
137-
// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride(%[[ARR_2_PTR]] : !cir.ptr<!s32i>, %[[OFFSET_0]] : !s64i), !cir.ptr<!s32i>
138-
// CIR: cir.store{{.*}} %[[ELE_PTR]], %[[ELE_ALLOCA]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
139-
// CIR: %[[LOAD_1:.*]] = cir.load{{.*}} %[[ELE_ALLOCA]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
140-
// CIR: %[[V2:.*]] = cir.const #cir.int<0> : !s32i
141-
// CIR: cir.store{{.*}} %[[V2]], %[[LOAD_1]] : !s32i, !cir.ptr<!s32i>
142-
// CIR: %[[OFFSET_1:.*]] = cir.const #cir.int<1> : !s64i
143-
// CIR: %[[ELE_1_PTR:.*]] = cir.ptr_stride(%[[LOAD_1]] : !cir.ptr<!s32i>, %[[OFFSET_1]] : !s64i), !cir.ptr<!s32i>
144-
// CIR: cir.store{{.*}} %[[ELE_1_PTR]], %[[ELE_ALLOCA]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
137+
// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!s32i>, %[[OFFSET_0]] : !s64i), !cir.ptr<!s32i>
138+
// CIR: cir.store{{.*}} %[[ELE_PTR]], %[[ARR_PTR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
139+
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s64i
140+
// CIR: %[[ARR_END:.*]] = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!s32i>, %[[TWO]] : !s64i), !cir.ptr<!s32i>
141+
// CIR: cir.do {
142+
// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
143+
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
144+
// CIR: cir.store{{.*}} %[[ZERO]], %[[ARR_CUR]] : !s32i, !cir.ptr<!s32i>
145+
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
146+
// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride(%[[ARR_CUR]] : !cir.ptr<!s32i>, %[[ONE]] : !s64i), !cir.ptr<!s32i>
147+
// CIR: cir.store{{.*}} %[[ARR_NEXT]], %[[ARR_PTR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
148+
// CIR: cir.yield
149+
// CIR: } while {
150+
// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
151+
// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[ARR_END]]) : !cir.ptr<!s32i>, !cir.bool
152+
// CIR: cir.condition(%[[CMP]])
153+
// CIR: }
145154

146155
// LLVM: define{{.*}} void @_Z5func2v()
147-
// LLVM: %[[ARR:.*]] = alloca [2 x i32], i64 1, align 4
148-
// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8
149-
// LLVM: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR]], i32 0
150-
// LLVM: store i32 5, ptr %[[ARR_PTR]], align 4
151-
// LLVM: %[[ELE_1_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 1
152-
// LLVM: store ptr %[[ELE_1_PTR]], ptr %[[TMP]], align 8
153-
// LLVM: %[[TMP2:.*]] = load ptr, ptr %[[TMP]], align 8
154-
// LLVM: store i32 0, ptr %[[TMP2]], align 4
155-
// LLVM: %[[ELE_1:.*]] = getelementptr i32, ptr %[[TMP2]], i64 1
156-
// LLVM: store ptr %[[ELE_1]], ptr %[[TMP]], align 8
156+
// LLVM: %[[ARR:.*]] = alloca [2 x i32], i64 1, align 4
157+
// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8
158+
// LLVM: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR]], i32 0
159+
// LLVM: store i32 5, ptr %[[ARR_PTR]], align 4
160+
// LLVM: %[[ELE_1_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 1
161+
// LLVM: store ptr %[[ELE_1_PTR]], ptr %[[TMP]], align 8
162+
// LLVM: %[[END_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 2
163+
// LLVM: br label %[[LOOP_BODY:.*]]
164+
// LLVM: [[LOOP_NEXT:.*]]:
165+
// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
166+
// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[END_PTR]]
167+
// LLVM: br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]]
168+
// LLVM: [[LOOP_BODY]]:
169+
// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
170+
// LLVM: store i32 0, ptr %[[CUR]], align 4
171+
// LLVM: %[[NEXT:.*]] = getelementptr i32, ptr %[[CUR]], i64 1
172+
// LLVM: store ptr %[[NEXT]], ptr %[[TMP]], align 8
173+
// LLVM: br label %[[LOOP_NEXT:.*]]
174+
// LLVM: [[LOOP_END]]:
175+
// LLVM: ret void
157176

158177
// OGCG: %[[ARR:.*]] = alloca [2 x i32], align 4
159178
// 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() {
270289
// CIR: %[[V_0_0:.*]] = cir.const #cir.int<5> : !s32i
271290
// CIR: cir.store{{.*}} %[[V_0_0]], %[[ARR_0_PTR]] : !s32i, !cir.ptr<!s32i>
272291
// CIR: %[[OFFSET:.*]] = cir.const #cir.int<1> : !s64i
273-
// CIR: %6 = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!cir.array<!s32i x 1>>, %[[OFFSET]] : !s64i), !cir.ptr<!cir.array<!s32i x 1>>
274-
// CIR: cir.store{{.*}} %6, %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>
275-
// CIR: %7 = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>, !cir.ptr<!cir.array<!s32i x 1>>
276-
// CIR: %8 = cir.const #cir.zero : !cir.array<!s32i x 1>
277-
// CIR: cir.store{{.*}} %8, %7 : !cir.array<!s32i x 1>, !cir.ptr<!cir.array<!s32i x 1>>
278-
// CIR: %[[OFFSET_1:.*]] = cir.const #cir.int<1> : !s64i
279-
// CIR: %10 = cir.ptr_stride(%7 : !cir.ptr<!cir.array<!s32i x 1>>, %[[OFFSET_1]] : !s64i), !cir.ptr<!cir.array<!s32i x 1>>
280-
// CIR: cir.store{{.*}} %10, %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>
292+
// CIR: %[[ARR_1:.*]] = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!cir.array<!s32i x 1>>, %[[OFFSET]] : !s64i), !cir.ptr<!cir.array<!s32i x 1>>
293+
// CIR: cir.store{{.*}} %[[ARR_1]], %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>
294+
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s64i
295+
// CIR: %[[ARR_END:.*]] = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!cir.array<!s32i x 1>>, %[[TWO]] : !s64i), !cir.ptr<!cir.array<!s32i x 1>>
296+
// CIR: cir.do {
297+
// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>, !cir.ptr<!cir.array<!s32i x 1>>
298+
// CIR: %[[ZERO:.*]] = cir.const #cir.zero : !cir.array<!s32i x 1>
299+
// CIR: cir.store{{.*}} %[[ZERO]], %[[ARR_CUR]] : !cir.array<!s32i x 1>, !cir.ptr<!cir.array<!s32i x 1>>
300+
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
301+
// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride(%[[ARR_CUR]] : !cir.ptr<!cir.array<!s32i x 1>>, %[[ONE]] : !s64i), !cir.ptr<!cir.array<!s32i x 1>>
302+
// CIR: cir.store{{.*}} %[[ARR_NEXT]], %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>
303+
// CIR: cir.yield
304+
// CIR: } while {
305+
// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>, !cir.ptr<!cir.array<!s32i x 1>>
306+
// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[ARR_END]]) : !cir.ptr<!cir.array<!s32i x 1>>, !cir.bool
307+
// CIR: cir.condition(%[[CMP]])
308+
// CIR: }
281309

282310
// LLVM: define{{.*}} void @_Z5func5v()
283-
// LLVM: %[[ARR:.*]] = alloca [2 x [1 x i32]], i64 1, align 4
284-
// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8
285-
// LLVM: %[[ARR_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR]], i32 0
286-
// LLVM: %[[ARR_0:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i32 0
287-
// LLVM: store i32 5, ptr %[[ARR_0]], align 4
288-
// LLVM: %[[ARR_1:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 1
289-
// LLVM: store ptr %[[ARR_1]], ptr %[[TMP]], align 8
290-
// LLVM: %[[ARR_1_VAL:.*]] = load ptr, ptr %[[TMP]], align 8
291-
// LLVM: store [1 x i32] zeroinitializer, ptr %[[ARR_1_VAL]], align 4
292-
// LLVM: %[[ARR_1_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR_1_VAL]], i64 1
293-
// LLVM: store ptr %[[ARR_1_PTR]], ptr %[[TMP]], align 8
311+
// LLVM: %[[ARR:.*]] = alloca [2 x [1 x i32]], i64 1, align 4
312+
// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8
313+
// LLVM: %[[ARR_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR]], i32 0
314+
// LLVM: %[[ARR_0:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i32 0
315+
// LLVM: store i32 5, ptr %[[ARR_0]], align 4
316+
// LLVM: %[[ARR_1:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 1
317+
// LLVM: store ptr %[[ARR_1]], ptr %[[TMP]], align 8
318+
// LLVM: %[[END_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 2
319+
// LLVM: br label %[[LOOP_BODY:.*]]
320+
// LLVM: [[LOOP_NEXT:.*]]:
321+
// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
322+
// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[END_PTR]]
323+
// LLVM: br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]]
324+
// LLVM: [[LOOP_BODY]]:
325+
// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
326+
// LLVM: store [1 x i32] zeroinitializer, ptr %[[CUR]], align 4
327+
// LLVM: %[[NEXT:.*]] = getelementptr [1 x i32], ptr %[[CUR]], i64 1
328+
// LLVM: store ptr %[[NEXT]], ptr %[[TMP]], align 8
329+
// LLVM: br label %[[LOOP_NEXT:.*]]
330+
// LLVM: [[LOOP_END]]:
331+
// LLVM: ret void
294332

295333
// ORGC: %[[ARR:.*]] = alloca [2 x [1 x i32]], align 4
296334
// 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() {
335373
}
336374

337375
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!cir.ptr<!s32i> x 1>, !cir.ptr<!cir.array<!cir.ptr<!s32i> x 1>>, ["arr", init]
338-
// CIR: %[[ARR_TMP:.*]] = cir.alloca !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, ["arrayinit.temp", init]
339-
// CIR: %[[ARR_PTR:.*]] = cir.cast(array_to_ptrdecay, %[[ARR]] : !cir.ptr<!cir.array<!cir.ptr<!s32i> x 1>>), !cir.ptr<!cir.ptr<!s32i>>
340-
// CIR: cir.store{{.*}} %[[ARR_PTR]], %[[ARR_TMP]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>
341-
// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[ARR_TMP]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>>
342-
// CIR: %[[NULL_PTR:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i>
343-
// CIR: cir.store{{.*}} %[[NULL_PTR]], %[[TMP]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
344-
// CIR: %[[OFFSET:.*]] = cir.const #cir.int<1> : !s64i
345-
// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride(%[[TMP]] : !cir.ptr<!cir.ptr<!s32i>>, %[[OFFSET]] : !s64i), !cir.ptr<!cir.ptr<!s32i>>
346-
// CIR: cir.store{{.*}} %[[ELE_PTR]], %[[ARR_TMP]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>
376+
// CIR: %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, ["arrayinit.temp", init]
377+
// CIR: %[[ARR_0:.*]] = cir.cast(array_to_ptrdecay, %[[ARR]] : !cir.ptr<!cir.array<!cir.ptr<!s32i> x 1>>), !cir.ptr<!cir.ptr<!s32i>>
378+
// CIR: cir.store{{.*}} %[[ARR_0]], %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>
379+
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
380+
// CIR: %[[ARR_END:.*]] = cir.ptr_stride(%[[ARR_0]] : !cir.ptr<!cir.ptr<!s32i>>, %[[ONE]] : !s64i), !cir.ptr<!cir.ptr<!s32i>>
381+
// CIR: cir.do {
382+
// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>>
383+
// CIR: %[[NULL_PTR:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i>
384+
// CIR: cir.store{{.*}} %[[NULL_PTR]], %[[ARR_CUR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
385+
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
386+
// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride(%[[ARR_CUR]] : !cir.ptr<!cir.ptr<!s32i>>, %[[ONE]] : !s64i), !cir.ptr<!cir.ptr<!s32i>>
387+
// CIR: cir.store{{.*}} %[[ARR_NEXT]], %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>
388+
// CIR: cir.yield
389+
// CIR: } while {
390+
// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>>
391+
// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[ARR_END]]) : !cir.ptr<!cir.ptr<!s32i>>, !cir.bool
392+
// CIR: cir.condition(%[[CMP]])
393+
// CIR: }
347394

348395
// LLVM: define{{.*}} void @_Z5func7v()
349-
// LLVM: %[[ARR:.*]] = alloca [1 x ptr], i64 1, align 8
350-
// LLVM: %[[ALLOCA:.*]] = alloca ptr, i64 1, align 8
351-
// LLVM: %[[ELE_PTR:.*]] = getelementptr ptr, ptr %[[ARR]], i32 0
352-
// LLVM: store ptr %[[ELE_PTR]], ptr %[[ALLOCA]], align 8
353-
// LLVM: %[[TMP:.*]] = load ptr, ptr %[[ALLOCA]], align 8
354-
// LLVM: store ptr null, ptr %[[TMP]], align 8
355-
// LLVM: %[[ELE:.*]] = getelementptr ptr, ptr %[[TMP]], i64 1
356-
// LLVM: store ptr %[[ELE]], ptr %[[ALLOCA]], align 8
396+
// LLVM: %[[ARR:.*]] = alloca [1 x ptr], i64 1, align 8
397+
// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8
398+
// LLVM: %[[ARR_PTR:.*]] = getelementptr ptr, ptr %[[ARR]], i32 0
399+
// LLVM: store ptr %[[ARR_PTR]], ptr %[[TMP]], align 8
400+
// LLVM: %[[END_PTR:.*]] = getelementptr ptr, ptr %[[ARR_PTR]], i64 1
401+
// LLVM: br label %[[LOOP_BODY:.*]]
402+
// LLVM: [[LOOP_NEXT:.*]]:
403+
// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
404+
// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[END_PTR]]
405+
// LLVM: br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]]
406+
// LLVM: [[LOOP_BODY]]:
407+
// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
408+
// LLVM: store ptr null, ptr %[[CUR]], align 8
409+
// LLVM: %[[NEXT:.*]] = getelementptr ptr, ptr %[[CUR]], i64 1
410+
// LLVM: store ptr %[[NEXT]], ptr %[[TMP]], align 8
411+
// LLVM: br label %[[LOOP_NEXT:.*]]
412+
// LLVM: [[LOOP_END]]:
413+
// LLVM: ret void
357414

358415
// OGCG: %[[ARR:.*]] = alloca [1 x ptr], align 8
359416
// OGCG: call void @llvm.memset.p0.i64(ptr align 8 %[[ARR]], i8 0, i64 8, i1 false)

0 commit comments

Comments
 (0)