llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Andy Kaylor (andykaylor)

<details>
<summary>Changes</summary>

We had an off-by-one error in the CIR generation for array destructor loops, 
causing us to miss destructing one element of the array. This change fixes the 
problem.

---

Patch is 140.54 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/190242.diff


14 Files Affected:

- (modified) clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp (+32-30) 
- (modified) clang/test/CIR/CodeGen/array-dtor.cpp (+14-14) 
- (modified) clang/test/CIR/CodeGen/delete-array.cpp (+8-11) 
- (modified) clang/test/CIR/CodeGen/destructors.cpp (+9-9) 
- (modified) clang/test/CIR/CodeGen/global-array-dtor.cpp (+7-7) 
- (modified) clang/test/CIR/CodeGen/global-init.cpp (+7-7) 
- (modified) 
clang/test/CIR/CodeGenOpenACC/combined-reduction-clause-inline-ops.cpp (+18-18) 
- (modified) 
clang/test/CIR/CodeGenOpenACC/combined-reduction-clause-outline-ops.cpp 
(+18-18) 
- (modified) 
clang/test/CIR/CodeGenOpenACC/compute-reduction-clause-inline-ops.cpp (+18-18) 
- (modified) 
clang/test/CIR/CodeGenOpenACC/compute-reduction-clause-outline-ops.cpp (+18-18) 
- (modified) clang/test/CIR/CodeGenOpenACC/loop-reduction-clause-inline-ops.cpp 
(+18-18) 
- (modified) 
clang/test/CIR/CodeGenOpenACC/loop-reduction-clause-outline-ops.cpp (+18-18) 
- (modified) 
clang/test/CIR/CodeGenOpenACC/private-clause-array-recipes-CtorDtor.cpp (+8-8) 
- (modified) 
clang/test/CIR/CodeGenOpenACC/private-clause-pointer-array-recipes-CtorDtor.cpp 
(+2-2) 


``````````diff
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp 
b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 5a8e3be51a947..a67ce9850a838 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -1385,19 +1385,17 @@ static void 
lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder,
   const unsigned sizeTypeSize =
       astCtx->getTypeSize(astCtx->getSignedSizeType());
 
+  // Both constructors and destructors use end = begin + numElements.
+  // Constructors iterate forward [begin, end).  Destructors iterate backward
+  // from end, decrementing before calling the destructor on each element.
   mlir::Value begin, end;
   if (isDynamic) {
     assert(!isCtor && "Unexpected dynamic ctor loop");
-    mlir::Value one = builder.getUnsignedInt(loc, 1, sizeTypeSize);
-    mlir::Value endOffsetVal = builder.createSub(loc, numElements, one);
     begin = addr;
-    end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, endOffsetVal);
+    end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, numElements);
   } else {
-    // Static: emit endOffset const first, then array_to_ptrdecay, matching
-    // the expected IR ordering.
-    uint64_t endOffset = isCtor ? arrayLen : arrayLen - 1;
     mlir::Value endOffsetVal =
-        builder.getUnsignedInt(loc, endOffset, sizeTypeSize);
+        builder.getUnsignedInt(loc, arrayLen, sizeTypeSize);
     begin = cir::CastOp::create(builder, loc, eltTy,
                                 cir::CastKind::array_to_ptrdecay, addr);
     end = cir::PtrStrideOp::create(builder, loc, eltTy, begin, endOffsetVal);
@@ -1423,6 +1421,21 @@ static void 
lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder,
       /*var type*/ eltTy, "__array_idx", builder.getAlignmentAttr(1));
   builder.createStore(loc, start, tmpAddr);
 
+  mlir::Block *bodyBlock = &op->getRegion(0).front();
+
+  // Clone the region body (ctor/dtor call and any setup ops like per-element
+  // zero-init) into the loop, remapping the block argument to the current
+  // element pointer.
+  auto cloneRegionBodyInto = [&](mlir::Block *srcBlock,
+                                 mlir::Value replacement) {
+    mlir::IRMapping map;
+    map.map(srcBlock->getArgument(0), replacement);
+    for (mlir::Operation &regionOp : *srcBlock) {
+      if (!mlir::isa<cir::YieldOp>(&regionOp))
+        builder.clone(regionOp, map);
+    }
+  };
+
   builder.createDoWhile(
       loc,
       /*condBuilder=*/
@@ -1435,31 +1448,20 @@ static void 
lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder,
       /*bodyBuilder=*/
       [&](mlir::OpBuilder &b, mlir::Location loc) {
         auto currentElement = cir::LoadOp::create(b, loc, eltTy, tmpAddr);
-
-        // Clone the region body (ctor/dtor call and any setup ops like
-        // per-element zero-init) into the loop, remapping the block argument
-        // to the current element pointer.
-        mlir::Block *oldBlock = &op->getRegion(0).front();
-        mlir::BlockArgument oldArg = oldBlock->getArgument(0);
-        mlir::IRMapping map;
-        map.map(oldArg, currentElement);
-        for (mlir::Operation &regionOp : *oldBlock) {
-          if (!mlir::isa<cir::YieldOp>(&regionOp))
-            builder.clone(regionOp, map);
+        if (isCtor) {
+          cloneRegionBodyInto(bodyBlock, currentElement);
+          mlir::Value stride = builder.getUnsignedInt(loc, 1, sizeTypeSize);
+          auto nextElement = cir::PtrStrideOp::create(builder, loc, eltTy,
+                                                      currentElement, stride);
+          builder.createStore(loc, nextElement, tmpAddr);
+        } else {
+          mlir::Value stride = builder.getSignedInt(loc, -1, sizeTypeSize);
+          auto prevElement = cir::PtrStrideOp::create(builder, loc, eltTy,
+                                                      currentElement, stride);
+          builder.createStore(loc, prevElement, tmpAddr);
+          cloneRegionBodyInto(bodyBlock, prevElement);
         }
 
-        // Array elements get constructed in order but destructed in reverse.
-        mlir::Value stride;
-        if (isCtor)
-          stride = builder.getUnsignedInt(loc, 1, sizeTypeSize);
-        else
-          stride = builder.getSignedInt(loc, -1, sizeTypeSize);
-
-        auto nextElement = cir::PtrStrideOp::create(builder, loc, eltTy,
-                                                    currentElement, stride);
-
-        // Store the element pointer to the temporary variable
-        builder.createStore(loc, nextElement, tmpAddr);
         builder.createYield(loc);
       });
 
diff --git a/clang/test/CIR/CodeGen/array-dtor.cpp 
b/clang/test/CIR/CodeGen/array-dtor.cpp
index f5d1c7ebbd7fd..d37b6323575d6 100644
--- a/clang/test/CIR/CodeGen/array-dtor.cpp
+++ b/clang/test/CIR/CodeGen/array-dtor.cpp
@@ -25,17 +25,17 @@ void test_cleanup_array() {
 
 // CIR: cir.func{{.*}} @_Z18test_cleanup_arrayv()
 // CIR:   %[[S:.*]] = cir.alloca !cir.array<!rec_S x 42>, 
!cir.ptr<!cir.array<!rec_S x 42>>, ["s"]
-// CIR:   %[[CONST41:.*]] = cir.const #cir.int<41> : !u64i
+// CIR:   %[[CONST42:.*]] = cir.const #cir.int<42> : !u64i
 // CIR:   %[[DECAY:.*]] = cir.cast array_to_ptrdecay %[[S]] : 
!cir.ptr<!cir.array<!rec_S x 42>> -> !cir.ptr<!rec_S>
-// CIR:   %[[END_PTR:.*]] = cir.ptr_stride %[[DECAY]], %[[CONST41]] : 
(!cir.ptr<!rec_S>, !u64i) -> !cir.ptr<!rec_S>
+// CIR:   %[[END_PTR:.*]] = cir.ptr_stride %[[DECAY]], %[[CONST42]] : 
(!cir.ptr<!rec_S>, !u64i) -> !cir.ptr<!rec_S>
 // CIR:   %[[ITER:.*]] = cir.alloca !cir.ptr<!rec_S>, 
!cir.ptr<!cir.ptr<!rec_S>>, ["__array_idx"]
 // CIR:   cir.store %[[END_PTR]], %[[ITER]] : !cir.ptr<!rec_S>, 
!cir.ptr<!cir.ptr<!rec_S>>
 // CIR:   cir.do {
 // CIR:     %[[CURRENT:.*]] = cir.load %[[ITER]] : !cir.ptr<!cir.ptr<!rec_S>>, 
!cir.ptr<!rec_S>
-// CIR:     cir.call @_ZN1SD1Ev(%[[CURRENT]]) nothrow : 
(!cir.ptr<!rec_S>{{.*}}) -> ()
 // CIR:     %[[CONST_MINUS1:.*]] = cir.const #cir.int<-1> : !s64i
-// CIR:     %[[NEXT:.*]] = cir.ptr_stride %[[CURRENT]], %[[CONST_MINUS1]] : 
(!cir.ptr<!rec_S>, !s64i) -> !cir.ptr<!rec_S>
-// CIR:     cir.store %[[NEXT]], %[[ITER]] : !cir.ptr<!rec_S>, 
!cir.ptr<!cir.ptr<!rec_S>>
+// CIR:     %[[PREV:.*]] = cir.ptr_stride %[[CURRENT]], %[[CONST_MINUS1]] : 
(!cir.ptr<!rec_S>, !s64i) -> !cir.ptr<!rec_S>
+// CIR:     cir.store %[[PREV]], %[[ITER]] : !cir.ptr<!rec_S>, 
!cir.ptr<!cir.ptr<!rec_S>>
+// CIR:     cir.call @_ZN1SD1Ev(%[[PREV]]) nothrow : (!cir.ptr<!rec_S>{{.*}}) 
-> ()
 // CIR:     cir.yield
 // CIR:   } while {
 // CIR:     %[[CURRENT2:.*]] = cir.load %[[ITER]] : 
!cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
@@ -48,7 +48,7 @@ void test_cleanup_array() {
 // LLVM:   %[[ITER:.*]] = alloca ptr
 // LLVM:   %[[ARRAY:.*]] = alloca [42 x %struct.S]
 // LLVM:   %[[START:.*]] = getelementptr %struct.S, ptr %[[ARRAY]], i32 0
-// LLVM:   %[[END:.*]] = getelementptr %struct.S, ptr %[[START]], i64 41
+// LLVM:   %[[END:.*]] = getelementptr %struct.S, ptr %[[START]], i64 42
 // LLVM:   store ptr %[[END]], ptr %[[ITER]]
 // LLVM:   br label %[[LOOP:.*]]
 // LLVM: [[COND:.*]]:
@@ -57,9 +57,9 @@ void test_cleanup_array() {
 // LLVM:   br i1 %[[DONE]], label %[[LOOP]], label %[[EXIT:.*]]
 // LLVM: [[LOOP]]:
 // LLVM:   %[[CURRENT:.*]] = load ptr, ptr %[[ITER]]
-// LLVM:   call void @_ZN1SD1Ev(ptr{{.*}} %[[CURRENT]])
-// LLVM:   %[[NEXT:.*]] = getelementptr %struct.S, ptr %[[CURRENT]], i64 -1
-// LLVM:   store ptr %[[NEXT]], ptr %[[ITER]]
+// LLVM:   %[[PREV:.*]] = getelementptr %struct.S, ptr %[[CURRENT]], i64 -1
+// LLVM:   store ptr %[[PREV]], ptr %[[ITER]]
+// LLVM:   call void @_ZN1SD1Ev(ptr{{.*}} %[[PREV]])
 // LLVM:   br label %[[COND]]
 // LLVM: [[EXIT]]:
 // LLVM:   ret void
@@ -120,17 +120,17 @@ void multi_dimensional() {
 // CIR:     cir.func{{.*}} @_Z17multi_dimensionalv()
 // CIR:       %[[S:.*]] = cir.alloca !cir.array<!cir.array<!rec_S x 5> x 3>, 
!cir.ptr<!cir.array<!cir.array<!rec_S x 5> x 3>>, ["s"]
 // CIR:       %[[FLAT:.*]] = cir.cast bitcast %[[S]] : 
!cir.ptr<!cir.array<!cir.array<!rec_S x 5> x 3>> -> !cir.ptr<!cir.array<!rec_S 
x 15>>
-// CIR:       %[[CONST14:.*]] = cir.const #cir.int<14> : !u64i
+// CIR:       %[[CONST15:.*]] = cir.const #cir.int<15> : !u64i
 // CIR:       %[[DECAY:.*]] = cir.cast array_to_ptrdecay %[[FLAT]] : 
!cir.ptr<!cir.array<!rec_S x 15>> -> !cir.ptr<!rec_S>
-// CIR:       %[[END_PTR:.*]] = cir.ptr_stride %[[DECAY]], %[[CONST14]] : 
(!cir.ptr<!rec_S>, !u64i) -> !cir.ptr<!rec_S>
+// CIR:       %[[END_PTR:.*]] = cir.ptr_stride %[[DECAY]], %[[CONST15]] : 
(!cir.ptr<!rec_S>, !u64i) -> !cir.ptr<!rec_S>
 // CIR:       %[[ITER:.*]] = cir.alloca !cir.ptr<!rec_S>, 
!cir.ptr<!cir.ptr<!rec_S>>, ["__array_idx"]
 // CIR:       cir.store %[[END_PTR]], %[[ITER]] : !cir.ptr<!rec_S>, 
!cir.ptr<!cir.ptr<!rec_S>>
 // CIR:       cir.do {
 // CIR:         %[[CUR:.*]] = cir.load %[[ITER]] : !cir.ptr<!cir.ptr<!rec_S>>, 
!cir.ptr<!rec_S>
-// CIR:         cir.call @_ZN1SD1Ev(%[[CUR]]) nothrow : 
(!cir.ptr<!rec_S>{{.*}}) -> ()
 // CIR:         %[[NEG1:.*]] = cir.const #cir.int<-1> : !s64i
 // CIR:         %[[PREV:.*]] = cir.ptr_stride %[[CUR]], %[[NEG1]] : 
(!cir.ptr<!rec_S>, !s64i) -> !cir.ptr<!rec_S>
 // CIR:         cir.store %[[PREV]], %[[ITER]] : !cir.ptr<!rec_S>, 
!cir.ptr<!cir.ptr<!rec_S>>
+// CIR:         cir.call @_ZN1SD1Ev(%[[PREV]]) nothrow : 
(!cir.ptr<!rec_S>{{.*}}) -> ()
 // CIR:         cir.yield
 // CIR:       } while {
 // CIR:         %[[CHK:.*]] = cir.load %[[ITER]] : !cir.ptr<!cir.ptr<!rec_S>>, 
!cir.ptr<!rec_S>
@@ -143,7 +143,7 @@ void multi_dimensional() {
 // LLVM:       %[[ITER:.*]] = alloca ptr
 // LLVM:       %[[S:.*]] = alloca [3 x [5 x %struct.S]]
 // LLVM:       %[[START:.*]] = getelementptr %struct.S, ptr %[[S]], i32 0
-// LLVM:       %[[END:.*]] = getelementptr %struct.S, ptr %[[START]], i64 14
+// LLVM:       %[[END:.*]] = getelementptr %struct.S, ptr %[[START]], i64 15
 // LLVM:       store ptr %[[END]], ptr %[[ITER]]
 // LLVM:       br label %[[LOOP:.*]]
 // LLVM: [[COND:.*]]:
@@ -152,9 +152,9 @@ void multi_dimensional() {
 // LLVM:       br i1 %[[DONE]], label %[[LOOP]], label %[[EXIT:.*]]
 // LLVM: [[LOOP]]:
 // LLVM:       %[[CUR:.*]] = load ptr, ptr %[[ITER]]
-// LLVM:       call void @_ZN1SD1Ev(ptr{{.*}} %[[CUR]])
 // LLVM:       %[[PREV:.*]] = getelementptr %struct.S, ptr %[[CUR]], i64 -1
 // LLVM:       store ptr %[[PREV]], ptr %[[ITER]]
+// LLVM:       call void @_ZN1SD1Ev(ptr{{.*}} %[[PREV]])
 // LLVM:       br label %[[COND]]
 // LLVM: [[EXIT]]:
 // LLVM:       ret void
diff --git a/clang/test/CIR/CodeGen/delete-array.cpp 
b/clang/test/CIR/CodeGen/delete-array.cpp
index 2ce2880b9d464..25a49cf668978 100644
--- a/clang/test/CIR/CodeGen/delete-array.cpp
+++ b/clang/test/CIR/CodeGen/delete-array.cpp
@@ -188,19 +188,17 @@ void test_delete_array_destructed(Destructed *ptr) {
 // CIR:     %[[NUM_ELEM:.*]] = cir.load{{.*}} %[[COOKIE_PTR]] : 
!cir.ptr<!u64i>, !u64i
 //
 // Destruct elements in reverse order.
-// CIR:     %[[ONE:.*]] = cir.const #cir.int<1> : !u64i
-// CIR:     %[[NUM_ELEM_MINUS_ONE:.*]] = cir.sub %[[NUM_ELEM]], %[[ONE]] : 
!u64i
-// CIR:     %[[END:.*]] = cir.ptr_stride %[[PTR]], %[[NUM_ELEM_MINUS_ONE]] : 
(!cir.ptr<!rec_Destructed>, !u64i) -> !cir.ptr<!rec_Destructed>
+// CIR:     %[[END:.*]] = cir.ptr_stride %[[PTR]], %[[NUM_ELEM]] : 
(!cir.ptr<!rec_Destructed>, !u64i) -> !cir.ptr<!rec_Destructed>
 // CIR:     %[[NOT_EMPTY:.*]] = cir.cmp ne %[[END]], %[[PTR]] : 
!cir.ptr<!rec_Destructed>
 // CIR:     cir.if %[[NOT_EMPTY]] {
 // CIR:       %[[ARR_IDX:.*]] = cir.alloca !cir.ptr<!rec_Destructed>, 
!cir.ptr<!cir.ptr<!rec_Destructed>>, ["__array_idx"] {alignment = 1 : i64}
 // CIR:       cir.store %[[END]], %[[ARR_IDX]] : !cir.ptr<!rec_Destructed>, 
!cir.ptr<!cir.ptr<!rec_Destructed>>
 // CIR:       cir.do {
 // CIR:         %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_IDX]] : 
!cir.ptr<!cir.ptr<!rec_Destructed>>, !cir.ptr<!rec_Destructed>
-// CIR:         cir.call @_ZN10DestructedD1Ev(%[[ARR_CUR]]) : 
(!cir.ptr<!rec_Destructed>) -> ()
 // CIR:         %[[NEG_ONE:.*]] = cir.const #cir.int<-1> : !s64i
-// CIR:         %[[ARR_NEXT:.*]] = cir.ptr_stride %[[ARR_CUR]], %[[NEG_ONE]] : 
(!cir.ptr<!rec_Destructed>, !s64i) -> !cir.ptr<!rec_Destructed>
-// CIR:         cir.store %[[ARR_NEXT]], %[[ARR_IDX]] : 
!cir.ptr<!rec_Destructed>, !cir.ptr<!cir.ptr<!rec_Destructed>>
+// CIR:         %[[ARR_PREV:.*]] = cir.ptr_stride %[[ARR_CUR]], %[[NEG_ONE]] : 
(!cir.ptr<!rec_Destructed>, !s64i) -> !cir.ptr<!rec_Destructed>
+// CIR:         cir.store %[[ARR_PREV]], %[[ARR_IDX]] : 
!cir.ptr<!rec_Destructed>, !cir.ptr<!cir.ptr<!rec_Destructed>>
+// CIR:         cir.call @_ZN10DestructedD1Ev(%[[ARR_PREV]]) : 
(!cir.ptr<!rec_Destructed>) -> ()
 // CIR:         cir.yield
 // CIR:       } while {
 // CIR:         %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_IDX]] : 
!cir.ptr<!cir.ptr<!rec_Destructed>>, !cir.ptr<!rec_Destructed>
@@ -224,8 +222,7 @@ void test_delete_array_destructed(Destructed *ptr) {
 // LLVM: [[DELETE_NOTNULL]]:
 // LLVM:   %[[ALLOC_PTR:.*]] = getelementptr i8, ptr %[[PTR]], i64 -8
 // LLVM:   %[[NUM_ELEM:.*]] = load i64, ptr %[[ALLOC_PTR]], align 4
-// LLVM:   %[[NUM_ELEM_MINUS_ONE:.*]] = sub i64 %[[NUM_ELEM]], 1
-// LLVM:   %[[ARR_END:.*]] = getelementptr %struct.Destructed, ptr %[[PTR]], 
i64 %[[NUM_ELEM_MINUS_ONE]]
+// LLVM:   %[[ARR_END:.*]] = getelementptr %struct.Destructed, ptr %[[PTR]], 
i64 %[[NUM_ELEM]]
 // LLVM:   %[[NOT_EMPTY:.*]] = icmp ne ptr %[[ARR_END]], %[[PTR]]
 // LLVM:   br i1 %[[NOT_EMPTY]], label %[[DESTROY_ELEMENTS:.*]], label 
%[[CALL_DELETE:.*]]
 // LLVM: [[DESTROY_ELEMENTS:.*]]:
@@ -237,9 +234,9 @@ void test_delete_array_destructed(Destructed *ptr) {
 // LLVM:   br i1 %[[CMP]], label %[[DELETE_ELEMENT:.*]], label %[[LOOP_END:.*]]
 // LLVM: [[DELETE_ELEMENT]]:
 // LLVM:   %[[ELEM:.*]] = load ptr, ptr %[[ARR_IDX]]
-// LLVM:   call void @_ZN10DestructedD1Ev(ptr %[[ELEM]])
-// LLVM:   %[[NEXT:.*]] = getelementptr %struct.Destructed, ptr %[[ELEM]], i64 
-1
-// LLVM:   store ptr %[[NEXT]], ptr %[[ARR_IDX]]
+// LLVM:   %[[PREV:.*]] = getelementptr %struct.Destructed, ptr %[[ELEM]], i64 
-1
+// LLVM:   store ptr %[[PREV]], ptr %[[ARR_IDX]]
+// LLVM:   call void @_ZN10DestructedD1Ev(ptr %[[PREV]])
 // LLVM:   br label %[[LOOP_CONDITION]]
 // LLVM: [[LOOP_END]]:
 // LLVM:   br label %[[CALL_DELETE]]
diff --git a/clang/test/CIR/CodeGen/destructors.cpp 
b/clang/test/CIR/CodeGen/destructors.cpp
index e58a61b9fc2f9..75d490498b34b 100644
--- a/clang/test/CIR/CodeGen/destructors.cpp
+++ b/clang/test/CIR/CodeGen/destructors.cpp
@@ -82,17 +82,17 @@ void test_array_destructor() {
 // CIR:   cir.cleanup.scope {
 // CIR:      cir.yield
 // CIR:   } cleanup normal {
-// CIR:     %[[FOUR:.*]] = cir.const #cir.int<4> : !u64i
+// CIR:     %[[FIVE:.*]] = cir.const #cir.int<5> : !u64i
 // CIR:     %[[BEGIN:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : 
!cir.ptr<!cir.array<!rec_array_element x 5>>
-// CIR:     %[[END:.*]] = cir.ptr_stride %[[BEGIN]], %[[FOUR]] : 
(!cir.ptr<!rec_array_element>, !u64i)
+// CIR:     %[[END:.*]] = cir.ptr_stride %[[BEGIN]], %[[FIVE]] : 
(!cir.ptr<!rec_array_element>, !u64i)
 // CIR:     %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!rec_array_element>, 
!cir.ptr<!cir.ptr<!rec_array_element>>, ["__array_idx"]
 // CIR:     cir.store %[[END]], %[[ARR_PTR]]
 // CIR:     cir.do {
 // CIR:       %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]]
-// CIR:       cir.call @_ZN13array_elementD1Ev(%[[ARR_CUR]]) nothrow : 
(!cir.ptr<!rec_array_element> {{.*}}) -> ()
 // CIR:       %[[NEG_ONE:.*]] = cir.const #cir.int<-1> : !s64i
-// CIR:       %[[ARR_NEXT:.*]] = cir.ptr_stride %[[ARR_CUR]], %[[NEG_ONE]] : 
(!cir.ptr<!rec_array_element>, !s64i)
-// CIR:       cir.store %[[ARR_NEXT]], %[[ARR_PTR]]
+// CIR:       %[[ARR_PREV:.*]] = cir.ptr_stride %[[ARR_CUR]], %[[NEG_ONE]] : 
(!cir.ptr<!rec_array_element>, !s64i)
+// CIR:       cir.store %[[ARR_PREV]], %[[ARR_PTR]]
+// CIR:       cir.call @_ZN13array_elementD1Ev(%[[ARR_PREV]]) nothrow : 
(!cir.ptr<!rec_array_element> {{.*}}) -> ()
 // CIR:       cir.yield
 // CIR:     } while {
 // CIR:       %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]]
@@ -122,7 +122,7 @@ void test_array_destructor() {
 // LLVM:   br label %[[INIT_LOOP_NEXT:.*]]
 // LLVM: [[INIT_LOOP_END]]:
 // LLVM:   %[[ARR_BEGIN:.*]] = getelementptr %struct.array_element, ptr 
%[[ARR]], i32 0
-// LLVM:   %[[ARR_END:.*]] = getelementptr %struct.array_element, ptr 
%[[ARR_BEGIN]], i64 4
+// LLVM:   %[[ARR_END:.*]] = getelementptr %struct.array_element, ptr 
%[[ARR_BEGIN]], i64 5
 // LLVM:   store ptr %[[ARR_END]], ptr %[[ARR_CUR]]
 // LLVM:   br label %[[DESTROY_LOOP_BODY:.*]]
 // LLVM: [[DESTROY_LOOP_NEXT:.*]]:
@@ -130,10 +130,10 @@ void test_array_destructor() {
 // LLVM:   %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[ARR_BEGIN]]
 // LLVM:   br i1 %[[CMP]], label %[[DESTROY_LOOP_BODY]], label 
%[[DESTROY_LOOP_END:.*]]
 // LLVM: [[DESTROY_LOOP_BODY]]:
-// LLVM:   %[[CUR:.*]] = load ptr, ptr %[[ARR_CUR]]
-// LLVM:   call void @_ZN13array_elementD1Ev(ptr {{.*}} %[[CUR]])
-// LLVM:   %[[PREV:.*]] = getelementptr %struct.array_element, ptr %[[CUR]], 
i64 -1
+// LLVM:   %[[CUR2:.*]] = load ptr, ptr %[[ARR_CUR]]
+// LLVM:   %[[PREV:.*]] = getelementptr %struct.array_element, ptr %[[CUR2]], 
i64 -1
 // LLVM:   store ptr %[[PREV]], ptr %[[ARR_CUR]]
+// LLVM:   call void @_ZN13array_elementD1Ev(ptr {{.*}} %[[PREV]])
 // LLVM:   br label %[[DESTROY_LOOP_NEXT]]
 // LLVM: [[DESTROY_LOOP_END]]:
 // LLVM:   ret void
diff --git a/clang/test/CIR/CodeGen/global-array-dtor.cpp 
b/clang/test/CIR/CodeGen/global-array-dtor.cpp
index 0b9552561a756..61b1717b156fb 100644
--- a/clang/test/CIR/CodeGen/global-array-dtor.cpp
+++ b/clang/test/CIR/CodeGen/global-array-dtor.cpp
@@ -28,17 +28,17 @@ ArrayDtor arrDtor[16];
 
 // CIR: cir.global external @arrDtor = #cir.zero : !cir.array<!rec_ArrayDtor x 
16>
 // CIR: cir.func internal private @__cxx_global_array_dtor(%[[ARR_ARG:.*]]: 
!cir.ptr<!void> {{.*}}) {
-// CIR:   %[[CONST15:.*]] = cir.const #cir.int<15> : !u64i
+// CIR:   %[[CONST16:.*]] = cir.const #cir.int<16> : !u64i
 // CIR:   %[[BEGIN:.*]] = cir.cast array_to_ptrdecay %[[ARR_ARG]] : 
!cir.ptr<!void> -> !cir.ptr<!rec_ArrayDtor>
-// CIR:   %[[END:.*]] = cir.ptr_stride %[[BEGIN]], %[[CONST15]] : 
(!cir.ptr<!rec_ArrayDtor>, !u64i) -> !cir.ptr<!rec_ArrayDtor>
+// CIR:   %[[END:.*]] = cir.ptr_stride %[[BEGIN]], %[[CONST16]] : 
(!cir.ptr<!rec_ArrayDtor>, !u64i) -> !cir.ptr<!rec_ArrayDtor>
 // CIR:   %[[CUR_ADDR:.*]] = cir.alloca !cir.ptr<!rec_ArrayDtor>, 
!cir.ptr<!cir.ptr<!rec_ArrayDtor>>, ["__array_idx"]
 // CIR:   cir.store %[[END]], %[[CUR_ADDR]] : !cir.ptr<!rec_ArrayDtor>, 
!cir.ptr<!cir.ptr<!rec_ArrayDtor>>
 // CIR:   cir.do {
 // CIR:     %[[CUR:.*]] = cir.load %[[CUR_ADDR]] : 
!cir.ptr<!cir.ptr<!rec_ArrayDtor>>, !cir.ptr<!rec_ArrayDtor>
-// CIR:     cir.call @_ZN9ArrayDtorD1Ev(%[[CUR]]) nothrow : 
(!cir.ptr<!rec_ArrayDtor> {{.*}}) -> ()
 // CIR:     %[[NEG_ONE:.*]] = cir.const #cir.int<-1> : !s64i
-// CIR:     %[[NEXT:.*]] = cir.ptr_stride %[[CUR]], %[[NEG_ONE]] : 
(!cir.ptr<!rec_ArrayDtor>, !s64i) -> !cir.ptr<!rec_ArrayDtor>
-// CIR:     cir.store %[[NEXT]], %[[CUR_ADDR]] : !cir.ptr<!rec_ArrayDtor>, 
!cir.ptr<!cir.ptr<!rec_ArrayDtor>>
+// CIR:     %[[PREV:.*]] = cir.ptr_stride %[[CUR]], %[[NEG_ONE]] : 
(!cir.ptr<!rec_ArrayDtor>, !s64i) -> !cir.ptr<!rec_ArrayDtor>
+// CIR:     cir.store %[[PREV]], %[[CUR_ADDR]] : !cir.ptr<!rec_ArrayDtor>, 
!cir.ptr<!cir.ptr<!rec_ArrayDtor>>
+// CIR:     cir.call @_ZN9ArrayDtorD1Ev(%[[PREV]]) nothrow : 
(!cir.ptr<!rec_ArrayDtor> {{.*}}) -> ()
 // CIR:     cir.yield
 // CIR:   } while {
 // CIR:     %[[CUR:.*]] = cir.load %[[CUR_ADDR]] : 
!cir.ptr<!cir.ptr<!rec_ArrayDtor>>, !cir.ptr<!rec_ArrayDtor>
@@ -58,7 +58,7 @@ ArrayDtor arrDtor[16];
 
 // LLVM: define internal void @__cxx_global_array_dtor(ptr %[[ARR_ARG:.*]]) {
 // LLVM:   %[[BEGIN:.*]] = getelementptr %struct.ArrayDtor, ptr %[[ARR_ARG]], 
i32 0
-// LLVM:   %[[END:.*]] = getelementptr %struct.ArrayDtor, ptr %[[BEGIN]], i64 
15
+// LLVM:   %[[END:.*]] = getelementptr %struct.ArrayDtor, ptr %[[BEGIN]], i64 
16
 // LLVM:   %[[CUR_ADDR:.*]] = alloca ptr
 // LLVM:   store ptr %[[END]], ptr %[[CUR_ADDR]]
 // LLVM:   br label %[[LOOP_BODY:.*]]
@@ -68,9 +68,9 @@ ArrayDtor arrDtor[16];
 // LLVM:   br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]]
 // LLVM: [[LOOP_BODY]]:
 // LLVM:   %[[CUR:.*]] = load ptr, ptr %[[CUR_ADDR]]
-// LLVM:   call void @_ZN9ArrayDtorD1Ev(ptr noundef nonnull align 1 
dereferenceabl...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/190242
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to