ABataev marked an inline comment as done.
ABataev added a comment.

Thanks for the review!


================
Comment at: test/Analysis/cfg-openmp.cpp:58-67
 #pragma omp distribute simd
   for (int i = 0; i < 10; ++i)
     argc = x;
-// CHECK-NEXT:  27: x
-// CHECK-NEXT:  28: [B1.27] (ImplicitCastExpr, LValueToRValue, int)
-// CHECK-NEXT:  29: argc
-// CHECK-NEXT:  30: [B1.29] = [B1.28]
-// CHECK-NEXT:  31: #pragma omp for
+// CHECK-NEXT:  [[#FOR:]]: x
+// CHECK-NEXT:  [[#FOR+1]]: [B1.[[#FOR]]] (ImplicitCastExpr, LValueToRValue, 
int)
+// CHECK-NEXT:  [[#FOR+2]]: argc
+// CHECK-NEXT:  [[#FOR+3]]: [B1.[[#FOR+2]]] = [B1.[[#FOR+1]]]
----------------
NoQ wrote:
> I'm slowly updating my mental model of these CFGs. Just to confirm my 
> understanding - tried the following example:
> 
> ```lang=c++
> 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?
`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".
you can consider this code as something like this:
```
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?
`OMPCapturedExprDecl` is used only in some rare cases, only for the complex 
combined constructs (which consists of several simple constructs) and only for 
the clauses, which require expression evaluation before entering the construct.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64646/new/

https://reviews.llvm.org/D64646



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to