Add the checks for invalid branch to/from the OpenMP constructs with structured blocks
Resolve few related test cases marked as XFAIL.
Differential D92735
[Flang] [OpenMP] Add semantic checks for invalid branch into/from OpenMP constructs praveen on Dec 6 2020, 11:08 AM. Authored by
Details Add the checks for invalid branch to/from the OpenMP constructs with structured blocks Resolve few related test cases marked as XFAIL.
Diff Detail Event TimelineComment Actions There is a labelEnforce class (https://github.com/llvm/llvm-project/blob/a2f922140f5380571fb74179f2bf622b3b925697/flang/lib/Semantics/tools.cpp#L1338) which is used for checks in do-concurrent and co-arrays. It is used to find control flow escaping from a construct. Can that be reused?
Comment Actions @kiranchandramohan We can make use of labelEnforce class to identify the control flow escaping the construct . But it would not be useful to identify the control flow entering the OpenMP constructs and also it does not identify the transfer of control from one OpenMP construct to another such as this. !$omp parallel goto 10 a = a + b !$omp single 10 call sb() !$omp end single !$omp end parallel
Since the function CheckBranchesIntoDoBody does not follow the OpenMP constructs , I guess it would not be much useful in this case . Please suggest.
Comment Actions
Please see D93447 if it helps in this patch. Comment Actions @sameeranjoshi Yes . I had initially thought of the same change as in https://reviews.llvm.org/D93447 using the existing 'NoBranchingEnforce' as it would handle the branching out of the construct part . But since it wasnt able to identify the branching into the constructs , I made the changes in resolve-directives.cpp as part of this patch. Comment Actions
Not clear what the issue is here. Is it that it will be inefficient to call enforce for each nested construct?
The CheckBranchesIntoDoBody takes in a list of branches, labels, location of bodies of constructs. This seemed to be a generic function which can be moved to Semantics/tools.cpp and reused. void CheckBranchesIntoDoBody(const SourceStmtList &branches, const TargetStmtMap &labels, const IndexList &loopBodies, SemanticsContext &context) The reason I asked to look at reusing existing code is because labelEnforce class seems to be checking for labels arising for more statements (see below). It was not clear to me whether you were missing some or whether some are not allowed in OpenMP. void LabelEnforce::Post(const parser::GotoStmt &gotoStmt) { Comment Actions @kiranchandramohan I am trying to resuse the function CheckBranchesIntoDoBody . Will update the patch regarding the same. @sameeranjoshi Will you be merging the related changes https://reviews.llvm.org/D93447 that makes use of LabelEnforce ? Comment Actions I was waiting for action based on the approach we follow from the current patch. Comment Actions @sameeranjoshi I do not see any restrictions on not allowing the statements part of 'LabelEnforce' inside the OpenMP block as per the OpenMP 4.5 documentation. Comment Actions @kiranchandramohan @sameeranjoshi I tried to make use of the CheckBranchesIntoDoBody function, but since it involves the use of multiple functions and types defined in resolve-labels.cpp such as using ProxyForScope, LabeledStatementInfoTuplePOD, SourceStatementInfoTuplePOD and also the labels, scopes and other details are being identified as part of the walk in ParseTreeAnalyzer class, it would be more complex to reuse these functions. Hence I felt adding the logic in resolve-directives.cpp to identify the control flow to / from OpenMP structured blocks would be simple . Also handled the checks for all the statements involving labels as in 'LabelEnforce' class except AssignStmt. void LabelEnforce::Post(const parser::AssignStmt &); integer :: b !$omp parallel assign 5 to b !$omp end parallel 5 print *, 5 In the above example, we detect this as an error as part of the 'LabelEnforce' check. Can we make use of the function CheckLabelContext added as part of this change itself to check the control flow escaping the OpenMP constructs ? Comment Actions OK if it is difficult or too specialized for Do loops then no need to reuse CheckBranchesIntoDoBody.
Can we remove void LabelEnforce::Post(const parser::AssignStmt &); from LabelEnforce? Are you saying it is not applicable in this context but applicable in other contexts? You might want to do a thorough check to ensure that the branch into checks are called for all OpenMP constructs. I think it is now not called at least for Critical, Ordered constructs.
Comment Actions @kiranchandramohan We can maybe remove void LabelEnforce::Post(const parser::AssignStmt &); check from LabelEnforce as it detects the error when there is only AssignStmt. integer n !$omp parallel assign 1 to n goto n !$omp end parallel 1 print *, 1 But it does not detect the error in the following case since the AssignedGoto check does not identify the context of the variable 'n' integer n assign 1 to n !$omp parallel goto n !$omp end parallel 1 print *, 1 The assigned goto check void LabelEnforce::Post(const parser::AssignedGotoStmt &) detects the errors only when specified with the list of labels as below. integer n assign 1 to n !$omp parallel goto n (1,2) !$omp end parallel 1 print *, 1 2 print *, 2 This behaviour is same with the do concurrent and critical constructs which makes use of LabelEnforce class.
I will check all the OpenMP constructs thoroughly to see if the checks works as expected for all constructs . The branch into check for Critical construct will work if we handle Pre(const parser::OpenMPCriticalConstruct &) and invoke PushContext(). Shall I handle it as part of this patch ?
Comment Actions
I think you can handle in this patch. If your patch is able to handle all cases then may be it is better to remove the code added by @sameeranjoshi in checkNoBranching. While common code is better, in this case i believe there will be some compilation time impact due to the fact that,
@sameeranjoshi let us know if you disagree or see any issues. Thanks (as always) for your work and pro-activity.
Comment Actions Use the logic in resolve-directives.cpp instead of 'LabelEnforce' to identify control flow escaping the OpenMP constructs. Handle omp taskgroup and omp critical constructs to check the invalid entry or branch to/from these constructs. Resolve omp-taskloop01.f90 which was failing due to taskgroup not being handled. Comment Actions @kiranchandramohan I guess the checks work for all the OpenMP constructs . I have added the code for omp critical constructs to identify the invalid entry and branch to/from errors. @sameeranjoshi I have made the changes to make use of the logic in resolve-directives.cpp instead of the 'LabelEnforce' class. Please let us know if you have any other suggestions regarding this . Thanks for the changes made to make use of LabelEnforce.
Comment Actions Can the error messages be updated to check for the entire message, both the place where it is entering and leaving (or viceversa)?
Comment Actions Currently , the error message with the source of the statement causing the branch is thrown as a fatal error and the error message with source of the target label printed as part of the Attach() is not being marked as fatal . Should both the error messages be marked as fatal and the error messages be updated accordingly as separate messages ?
Comment Actions I am not familiar with that. I can look up if required. But what I am suggesting is to do what is similar to the do loop checks like the following. $ ./bin/flang ../flang/test/Semantics/doconcurrent03.f90 ../flang/test/Semantics/doconcurrent03.f90:11:9: error: Control flow escapes from DO CONCURRENT goto 20 ^^^^^^^ ../flang/test/Semantics/doconcurrent03.f90:9:3: Enclosing DO CONCURRENT statement do 10 concurrent (i = 1:10) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../flang/test/Semantics/doconcurrent03.f90:18:3: branch into loop body from outside goto 30 ^^^^^^^ ../flang/test/Semantics/doconcurrent03.f90:9:3: the loop branched into do 10 concurrent (i = 1:10) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ` BTW, for a branch leaving/entering a nested construct, how many errors are reported? Just to understand, Not requesting a change here. !$omp parallel !$omp single !$omp end single goto 10 !$omp end parallel 10 print *, "Invalid"
Comment Actions
@kiranchandramohan As per the current changes , the errors for the various cases are being displayed as follows Branch into the OpenMP Structured block !$omp parallel 10 print*, 10 !$omp end parallel goto 10 ./invalid-branching.f90:15:1: error: invalid entry to OpenMP structured block goto 10 ^^^^^^^ ./invalid-branching.f90:13:3: In the enclosing PARALLEL directive 10 print*, 10 ^^^^^^^^^^^^^ Branch out of OpenMP structured blocks !$omp parallel goto 10 !$omp end parallel 10 print*, 10 ./invalid-branching.f90:13:4: error: invalid branch to/from OpenMP structured block goto 10 ^^^^^^^ ./invalid-branching.f90:15:1: Outside the enclosing PARALLEL directive 10 print*, 10 ^^^^^^^^^^^^^ Branch among the OpenMP structured blocks !$omp parallel 10 print *, 10 !$omp end parallel !$omp parallel goto 10 !$omp end parallel ./invalid-branching.f90:17:3: error: invalid branch to/from OpenMP structured block goto 10 ^^^^^^^ ./invalid-branching.f90:13:3: Outside the enclosing PARALLEL directive 10 print *, 10 ^^^^^^^^^^^^^^ Since the second message in the above errors which indicates the label target source are not marked as error , I had not included them as plain comments in the test cases.
For the branch entering/leaving a nested construct , one error is reported by printing the innermost construct in which the error occured. !$omp parallel !$omp single goto 10 !$omp end single !$omp end parallel 10 print *, 10 ./invalid-branching.f90:14:3: error: invalid branch to/from OpenMP structured block goto 10 ^^^^^^^ ./invalid-branching.f90:17:3: Outside the enclosing SINGLE directive 10 print *, 10
Comment Actions Thanks for the detailed listing. I think the second message in the do loop checks (non-openmp) is also not listed as an error. But they still check for that in the tests.
Comment Actions Modify error messages to identify branch into or branch out of openmp structued blocks Comment Actions
@kiranchandramohan I have updated the error messages and the test cases to check for two separate messages in the tests
|
Add a few comments on what is done on seeing a statement with a label.