Added support for analysis of if clauses in the OpenMP directives to be
able to check for the use of uninitialized variables.
Details
- Reviewers
NoQ - Commits
- rG655cb4a2d702: [OPENMP]Add support for analysis of if clauses.
rC366211: [OPENMP]Add support for analysis of if clauses.
rL366211: [OPENMP]Add support for analysis of if clauses.
rG63d00b19e5c4: [OPENMP]Add support for analysis of if clauses.
rC366068: [OPENMP]Add support for analysis of if clauses.
rL366068: [OPENMP]Add support for analysis of if clauses.
Diff Detail
- Repository
- rL LLVM
Event Timeline
Looks great! Thank you for improving the tests even further.
test/Analysis/cfg-openmp.cpp | ||
---|---|---|
58–67 ↗ | (On Diff #209520) | I'm slowly updating my mental model of these CFGs. Just to confirm my understanding - tried the following example: int main(int argc, char **argv) { int x = 0; #pragma omp for for (int i = 0; i < 10; ++i) x += argv[i]; } The CFG was as follows: 1: 0 2: int x = 0; 3: x 4: argv 5: [B1.4] (ImplicitCastExpr, LValueToRValue, char **) 6: i 7: [B1.6] (ImplicitCastExpr, LValueToRValue, int) 8: [B1.5][[B1.7]] 9: [B1.8] (ImplicitCastExpr, LValueToRValue, char *) 10: [B1.3] += [B1.9] 11: #pragma omp for for (int i = 0; i < 10; ++i) [B1.10]; Do i understand correctly that [B1.10] aka argv[0] is going to act like an "argument" to the "outlined function" and then it's going to be re-used (as if it was a "local" "variable") on subsequent iterations of the loop (i.e., assigned values argv[1], ..., argv[9])? I.e., the "function" is going to be responsible for computing argv[1] and storing it in the "parameter variable" (OMPCapturedExprDecl which is a sub-class of VarDecl) that previously contained argv[0], but it's not responsible for computing argv[0] itself, right? |
Thanks for the review!
test/Analysis/cfg-openmp.cpp | ||
---|---|---|
58–67 ↗ | (On Diff #209520) | argv here is the shared variable, so it is passed by reference to the "outlined function". We do not create local copy of this variable here, we use the original argv in the "outlined function". char **argv; int x = 0; outlined(x, argv); ... void outlined(char **&argv, int &x) { for(int i =0; i < 10; ++i) x += argv[i]; } This is very schematic but good enough to understand how it works. OMPCapturedExprDecl is used only in some rare cases, when we need to pass the expression to the outlined region. For example: #pragma omp target parallel if(a+b) <body> After codegen it must look like this: <OMPCapturedExprDecl> int .captured_expr. = a+b; if (.captured_expr.) { offload target_outlined(.captured_expr.) } else { call on host target_outlined(.captured_expr.) } ... void target_outlined(int .captured_expr.) { if (.captured_expr.) parallel outlined(); else serialized outlined(); } ... void outined() { <body>; } In this case if clause is applied to both, target and parallel constructs. We could capture variables a and b and calculate a+b inside of the target region but this is not effective. Instead, it is better to capture the result of a+b condition into the special variable and capture only this single variable by value (the value of clauses in most cases must be pre-evaluated before the real execution of the OpenMP construct). Does it make it a little bit clearer? |
test/Analysis/cfg-openmp.cpp | ||
---|---|---|
58–67 ↗ | (On Diff #209520) | I think i managed to consume this, thanks!! I'll ask more questions when i have them. |