llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clangir
Author: Andy Kaylor (andykaylor)
<details>
<summary>Changes</summary>
This fixes a problem with scope termination when a cleanup scope appears as the
last operation within a region that is nested inside another operation, such as
within the body region of a cir.for operaiton. When the cleanup is popped, we
set the insertion point to just past the cleanup operation, which is what we
need if there are going to be more operations emitted, but the
LexicalScope::cleanup function, which intends to add a terminator to its
ScopeOp region, was not working correctly because it expected the insert
location to be at the end of the scope.
In the problematic case, we had something like this:
cir.scope {
...
cir.for : cond {
...
} body {
...
cir.cleanup.scope {
...
} cleanup normal {
...
}
< insert location was set here >
}
< no terminator here>
}
We have another function (terminateStructuredRegionBody) that fills in the
terminator in the cir.for body, but we need LexicalScope::cleanup to insert the
terminator for the cir.scope.
This change updates the insert location in LexicalScope::cleanup, if necessary,
to the end of the scope region.
Assisted-by: Cursor / claude-opus-4.7-thinking-xhigh
---
Full diff: https://github.com/llvm/llvm-project/pull/197780.diff
2 Files Affected:
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+16)
- (modified) clang/test/CIR/CodeGen/forrange.cpp (+36)
``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index cda37513a4feb..4be91b1bef935 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -274,6 +274,22 @@ void CIRGenFunction::LexicalScope::cleanup() {
if (curBlock->mightHaveTerminator() && curBlock->getTerminator())
return;
+ // If the builder's current block lives in a region nested below this
+ // lexical scope's region, popCleanup has left the insertion point past
+ // a cir.cleanup.scope inside that nested region (for example, inside a
+ // cir.for body when the body cleanup was registered there). Emitting a
+ // cir.yield at the current position would terminate the nested region
+ // instead of this scope's region. Reposition to the back block of this
+ // scope's region so the terminator below lands in the correct place.
+ if (mlir::Region *scopeRegion = entryBlock->getParent();
+ scopeRegion && !scopeRegion->empty() &&
+ curBlock->getParent() != scopeRegion) {
+ builder.setInsertionPointToEnd(&scopeRegion->back());
+ curBlock = builder.getBlock();
+ if (curBlock->mightHaveTerminator() && curBlock->getTerminator())
+ return;
+ }
+
// Get rid of any empty block at the end of the scope. An empty non-entry
// block is created when a terminator (return/break/continue) is followed
// by unreachable code.
diff --git a/clang/test/CIR/CodeGen/forrange.cpp
b/clang/test/CIR/CodeGen/forrange.cpp
index 0ffe4e2f29743..f31c2fe0e37b5 100644
--- a/clang/test/CIR/CodeGen/forrange.cpp
+++ b/clang/test/CIR/CodeGen/forrange.cpp
@@ -131,3 +131,39 @@ void for_range3() {
// CIR: cir.yield
// CIR: }
// CIR: }
+
+struct HasDtor { ~HasDtor(); };
+
+void for_range4() {
+ C3 c;
+ for (Element &e : c) {
+ HasDtor hd;
+ }
+}
+
+// CIR: cir.func{{.*}} @_Z10for_range4v()
+// CIR: cir.scope {
+// CIR: %[[RANGE_ADDR:.*]] = cir.alloca !cir.ptr<!rec_C3>{{.*}}
["__range1", init, const]
+// CIR: %[[BEGIN_ADDR:.*]] = cir.alloca !rec_Iterator,
!cir.ptr<!rec_Iterator>{{.*}} ["__begin1", init]
+// CIR: %[[END_ADDR:.*]] = cir.alloca !rec_Iterator,
!cir.ptr<!rec_Iterator>{{.*}} ["__end1", init]
+// CIR: %[[E_ADDR:.*]] = cir.alloca !cir.ptr<!rec_Element>{{.*}} ["e",
init, const]
+// CIR: %[[HD:.*]] = cir.alloca !rec_HasDtor, !cir.ptr<!rec_HasDtor>,
["hd"]
+// CIR: cir.store{{.*}} %[[C_ADDR]], %[[RANGE_ADDR]]
+// CIR: cir.for : cond {
+// CIR: %[[ITER_NE:.*]] = cir.call
@_ZNK8IteratorneERKS_(%[[BEGIN_ADDR]], %[[END_ADDR]])
+// CIR: cir.condition(%[[ITER_NE]])
+// CIR: } body {
+// CIR: %[[E:.*]] = cir.call @_ZN8IteratordeEv(%[[BEGIN_ADDR]])
+// CIR: cir.store{{.*}} %[[E]], %[[E_ADDR]]
+// CIR: cir.cleanup.scope {
+// CIR: cir.yield
+// CIR: } cleanup normal {
+// CIR: cir.call @_ZN7HasDtorD1Ev(%[[HD]]) nothrow
+// CIR: cir.yield
+// CIR: }
+// CIR: cir.yield
+// CIR: } step {
+// CIR: %[[ITER_NEXT:.*]] = cir.call @_ZN8IteratorppEv(%[[BEGIN_ADDR]])
+// CIR: cir.yield
+// CIR: }
+// CIR: }
``````````
</details>
https://github.com/llvm/llvm-project/pull/197780
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits