[clang] [llvm] [Clang][OpenMP] Support for dispatch construct (Sema & Codegen) support (PR #131838)
Deepak Eachempati via cfe-commits
cfe-commits at lists.llvm.org
Tue May 6 18:12:13 PDT 2025
================
@@ -4529,6 +4529,191 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
emitMaster(*this, S);
}
+static Expr *replaceWithNewTraitsOrDirectCall(CapturedDecl *CDecl,
+ Expr *NewExpr) {
+ Expr *CurrentCallExpr = nullptr;
+ Stmt *CallExprStmt = CDecl->getBody();
+
+ if (BinaryOperator *BinaryCopyOpr = dyn_cast<BinaryOperator>(CallExprStmt)) {
+ CurrentCallExpr = BinaryCopyOpr->getRHS();
+ BinaryCopyOpr->setRHS(NewExpr);
+ } else {
+ CurrentCallExpr = dyn_cast<Expr>(CallExprStmt);
+ CDecl->setBody(NewExpr);
+ }
+
+ return CurrentCallExpr;
+}
+
+static Expr *transformCallInStmt(Stmt *StmtP, bool NoContext = false) {
+ Expr *CurrentExpr = nullptr;
+ if (auto *CptStmt = dyn_cast<CapturedStmt>(StmtP)) {
+ CapturedDecl *CDecl = CptStmt->getCapturedDecl();
+
+ CallExpr *NewCallExpr = nullptr;
+ for (const auto *attr : CDecl->attrs()) {
+ if (NoContext) {
+ if (const auto *annotateAttr =
+ llvm::dyn_cast<clang::AnnotateAttr>(attr);
+ annotateAttr && annotateAttr->getAnnotation() == "NoContextAttr") {
+ NewCallExpr = llvm::dyn_cast<CallExpr>(*annotateAttr->args_begin());
+ }
+ } else {
+ if (const auto *annotateAttr =
+ llvm::dyn_cast<clang::AnnotateAttr>(attr);
+ annotateAttr && annotateAttr->getAnnotation() == "NoVariantsAttr") {
+ NewCallExpr = llvm::dyn_cast<CallExpr>(*annotateAttr->args_begin());
+ }
+ }
+ }
+
+ CurrentExpr = replaceWithNewTraitsOrDirectCall(CDecl, NewCallExpr);
+ }
+ return CurrentExpr;
+}
+
+// emitIfElse is used for the following conditions:
+//
+// NoVariants = 0 && NoContext = 1
+// if (Condition_NoContext) {
+// foo_variant2(); // Present in AnnotationAttr
+// } else {
+// foo_variant();
+// }
+//
+// NoVariants = 1 && NoContext = 0
+// if (Condition_NoVariants) {
+// foo();
+// } else {
+// foo_variant();
+// }
+//
+// NoVariants = 1 && NoContext = 1
+// if (Condition_NoVariants) { // ==> label if.then.NoVariants
+// foo();
+// } else { // ==> label else.NoVariants
+// if (Condition_NoContext) { // ==> label if.then.NoContext
+// foo_variant2(); // Present in AnnotationAttr
+// } else { // ==> label else
+// foo_variant();
+// }
+// }
+//
+static void emitIfElse(CodeGenFunction *CGF, Stmt *AssociatedStmt,
----------------
dreachem wrote:
Thanks for the clarification. So something like this?
```c++
#include <iostream>
int main()
{
class IsPositive {
public:
IsPositive(int x) : _x(x) {
std::cout << "constructing IsPositive(" << x << ") object\n";
}
~IsPositive() {
std::cout << "destructing IsPositive(" << _x << ") object\n";
}
operator bool() const { return _x > 0; }
private:
int _x;
};
// case 1
#pragma omp parallel if(IsPositive(10))
{
std::cout << "[1] in parallel\n";
}
// case 2
auto cond1 = IsPositive(5);
#pragma omp parallel if(cond1)
{
std::cout << "[2] in parallel\n";
}
// case 3
#pragma omp parallel if(IsPositive(-10))
{
std::cout << "[3] in parallel\n";
}
// case 4
auto cond2 = IsPositive(-5);
#pragma omp parallel if(cond2)
{
std::cout << "[4] in parallel\n";
}
```
The output for the above with `OMP_NUM_THREADS=2` is:
```
constructing IsPositive(10) object
[1] in parallel
[1] in parallel
destructing IsPositive(10) object
constructing IsPositive(5) object
[2] in parallel
[2] in parallel
constructing IsPositive(-10) object
[3] in parallel
destructing IsPositive(-10) object
constructing IsPositive(-5) object
[4] in parallel
destructing IsPositive(-5) object
destructing IsPositive(5) object
```
So, the destructor for the instantiated class object used in the `if` condition is called upon completing each `parallel` region. On the other hand, if I move the condition expression outside the directive (as for cases 2 and 4), then the destructor for the instantiated class is called at the end of the function.
Does this match the expected behavior?
https://github.com/llvm/llvm-project/pull/131838
More information about the cfe-commits
mailing list