This is an archive of the discontinued LLVM Phabricator instance.

[flang] Fix one bug in nested branching-related constructs
AbandonedPublic

Authored by peixin on Jun 22 2022, 8:39 AM.

Details

Summary

When setting construct exit in creating PFT, it does not consider if
there is one compile-time generated statement such as memory free in the
successor. So, using nonNopSuccessor in setConstructExit is not
correct when the select case construct is perfectly nested in the if
construct and there is one temporary memory generated in the select case
construct which needs memory free when ending the select case construct.
This bug is exposed in cam4 in SPEC2017
https://github.com/llvm/llvm-project/issues/56143.

Diff Detail

Event Timeline

peixin created this revision.Jun 22 2022, 8:39 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 22 2022, 8:39 AM
peixin requested review of this revision.Jun 22 2022, 8:39 AM

@jeanPerier @schweitz This is the initial try to fix the bug. I guess https://github.com/llvm/llvm-project/issues/56143 exposes one class of bugs. Fixing it considering all kinds of nested constructs is kind of difficult for me for now. If this is not the right fix, please feel free to take up this.

Thanks @peixin for investigating this and proposing a fix.

I spent some time on this. Something that came to my mind is that ideally, it is best to have the blocks belonging to the CaseConstruct itself deal with the deallocation. So how about something like adding a block to EndSelect and then marking that as the constructExit for the CaseConstruct? Something like the following.

Otherwise, we might need to have pre-fir-tree test as well.

diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index 49ae53118473..ee7a193ef59d 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -831,6 +831,7 @@ private:
             lastConstructStmtEvaluation = &eval;
           },
           [&](const parser::EndSelectStmt &) {
+            eval.isNewBlock = true;
             eval.nonNopSuccessor().isNewBlock = true; 
             lastConstructStmtEvaluation = nullptr;
           },
@@ -927,7 +928,8 @@ private:
             eval.constructExit = &eval.evaluationList->back();
           },
           [&](const parser::CaseConstruct &) {
-            setConstructExit(eval);
+            // EndSelectCaseStmt may have code.
+            eval.constructExit = &eval.evaluationList->back();
             eval.isUnstructured = true;
           },
           [&](const parser::ChangeTeamConstruct &) {
peixin added a comment.EditedJun 28 2022, 4:21 AM

Thanks @peixin for investigating this and proposing a fix.

I spent some time on this. Something that came to my mind is that ideally, it is best to have the blocks belonging to the CaseConstruct itself deal with the deallocation. So how about something like adding a block to EndSelect and then marking that as the constructExit for the CaseConstruct? Something like the following.

Otherwise, we might need to have pre-fir-tree test as well.

diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index 49ae53118473..ee7a193ef59d 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -831,6 +831,7 @@ private:
             lastConstructStmtEvaluation = &eval;
           },
           [&](const parser::EndSelectStmt &) {
+            eval.isNewBlock = true;
             eval.nonNopSuccessor().isNewBlock = true; 
             lastConstructStmtEvaluation = nullptr;
           },
@@ -927,7 +928,8 @@ private:
             eval.constructExit = &eval.evaluationList->back();
           },
           [&](const parser::CaseConstruct &) {
-            setConstructExit(eval);
+            // EndSelectCaseStmt may have code.
+            eval.constructExit = &eval.evaluationList->back();
             eval.isUnstructured = true;
           },
           [&](const parser::ChangeTeamConstruct &) {

@kiranchandramohan This sounds one more resonable PFT to me. Are you trying this? Will this change in creating PFT affect the FIR lowering? That is, does FIR lowering also need to change something so to solve the bug you found?

Maybe trying this with some test cases is better for reviewers?

I dont think any change in lowering is required.
Yes, you are right that it will be good to test it well. I can try it later this week.

flang/test/Lower/nested-branching.f90
1

Nit: Add the flang-new driver also.

@peixin, thanks for investigating this problem. Unfortunately, because CASE code can contain arbitrary GOTOs, there is no guarantee that a construct successor or exit block will be executed. The problem can be addressed by freeing the selector temp after the places in the code where it is last used. I'm working on a fix that does that.

@peixin, thanks for investigating this problem. Unfortunately, because CASE code can contain arbitrary GOTOs, there is no guarantee that a construct successor or exit block will be executed. The problem can be addressed by freeing the selector temp after the places in the code where it is last used. I'm working on a fix that does that.

OK. Thanks for working on that.

peixin abandoned this revision.Jun 30 2022, 3:35 AM