NoQ added inline comments.
================ 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]]] ---------------- ABataev wrote: > 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. I think i managed to consume this, thanks!! I'll ask more questions when i have them. Repository: rL LLVM 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