Author: erichkeane
Date: 2025-04-24T14:26:24-07:00
New Revision: 80182a7d5d66c8dc90bb4623c1f722aba7ebe45b

URL: 
https://github.com/llvm/llvm-project/commit/80182a7d5d66c8dc90bb4623c1f722aba7ebe45b
DIFF: 
https://github.com/llvm/llvm-project/commit/80182a7d5d66c8dc90bb4623c1f722aba7ebe45b.diff

LOG: [OpenACC][CIR] Implement 'wait' directive lowering

This construct has a couple of 'intexprs' which are lowered the same way
as clauses, plus has a pair of simple clauses that needed lowering.
This patch does all of that.

Added: 
    clang/test/CIR/CodeGenOpenACC/wait.c

Modified: 
    clang/lib/CIR/CodeGen/CIRGenFunction.h
    clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index f533d0ab53cd2..74fcd081dec18 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -626,10 +626,9 @@ class CIRGenFunction : public CIRGenTypeCache {
   
//===--------------------------------------------------------------------===//
 private:
   template <typename Op>
-  mlir::LogicalResult
-  emitOpenACCOp(mlir::Location start, OpenACCDirectiveKind dirKind,
-                SourceLocation dirLoc,
-                llvm::ArrayRef<const OpenACCClause *> clauses);
+  Op emitOpenACCOp(mlir::Location start, OpenACCDirectiveKind dirKind,
+                   SourceLocation dirLoc,
+                   llvm::ArrayRef<const OpenACCClause *> clauses);
   // Function to do the basic implementation of an operation with an Associated
   // Statement.  Models AssociatedStmtConstruct.
   template <typename Op, typename TermOp>

diff  --git a/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp 
b/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp
index 57ef06df068b7..688fca1bf2751 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmtOpenACC.cpp
@@ -317,10 +317,18 @@ class OpenACCClauseCIREmitter final
             operation.getAsyncOperandsDeviceTypeAttr(),
             createIntExpr(clause.getIntExpr()), range));
       }
+    } else if constexpr (isOneOfTypes<OpTy, WaitOp>) {
+      // Wait doesn't have a device_type, so its handling here is slightly
+      // 
diff erent.
+      if (!clause.hasIntExpr())
+        operation.setAsync(true);
+      else
+        operation.getAsyncOperandMutable().append(
+            createIntExpr(clause.getIntExpr()));
     } else {
       // TODO: When we've implemented this for everything, switch this to an
       // unreachable. Combined constructs remain. Data, enter data, exit data,
-      // update, wait, combined constructs remain.
+      // update, combined constructs remain.
       return clauseNotImplemented(clause);
     }
   }
@@ -345,7 +353,7 @@ class OpenACCClauseCIREmitter final
 
   void VisitIfClause(const OpenACCIfClause &clause) {
     if constexpr (isOneOfTypes<OpTy, ParallelOp, SerialOp, KernelsOp, InitOp,
-                               ShutdownOp, SetOp, DataOp>) {
+                               ShutdownOp, SetOp, DataOp, WaitOp>) {
       operation.getIfCondMutable().append(
           createCondition(clause.getConditionExpr()));
     } else {
@@ -353,7 +361,7 @@ class OpenACCClauseCIREmitter final
       // until we can write tests/know what we're doing with codegen to make
       // sure we get it right.
       // TODO: When we've implemented this for everything, switch this to an
-      // unreachable. Enter data, exit data, host_data, update, wait, combined
+      // unreachable. Enter data, exit data, host_data, update, combined 
       // constructs remain.
       return clauseNotImplemented(clause);
     }
@@ -444,11 +452,9 @@ mlir::LogicalResult 
CIRGenFunction::emitOpenACCOpAssociatedStmt(
 }
 
 template <typename Op>
-mlir::LogicalResult CIRGenFunction::emitOpenACCOp(
+Op CIRGenFunction::emitOpenACCOp(
     mlir::Location start, OpenACCDirectiveKind dirKind, SourceLocation dirLoc,
     llvm::ArrayRef<const OpenACCClause *> clauses) {
-  mlir::LogicalResult res = mlir::success();
-
   llvm::SmallVector<mlir::Type> retTy;
   llvm::SmallVector<mlir::Value> operands;
   auto op = builder.create<Op>(start, retTy, operands);
@@ -461,7 +467,7 @@ mlir::LogicalResult CIRGenFunction::emitOpenACCOp(
     makeClauseEmitter(op, *this, builder, dirKind, dirLoc)
         .VisitClauseList(clauses);
   }
-  return res;
+  return op;
 }
 
 mlir::LogicalResult
@@ -500,22 +506,61 @@ CIRGenFunction::emitOpenACCDataConstruct(const 
OpenACCDataConstruct &s) {
 mlir::LogicalResult
 CIRGenFunction::emitOpenACCInitConstruct(const OpenACCInitConstruct &s) {
   mlir::Location start = getLoc(s.getSourceRange().getBegin());
-  return emitOpenACCOp<InitOp>(start, s.getDirectiveKind(), 
s.getDirectiveLoc(),
+  emitOpenACCOp<InitOp>(start, s.getDirectiveKind(), s.getDirectiveLoc(),
                                s.clauses());
+  return mlir::success();
 }
 
 mlir::LogicalResult
 CIRGenFunction::emitOpenACCSetConstruct(const OpenACCSetConstruct &s) {
   mlir::Location start = getLoc(s.getSourceRange().getBegin());
-  return emitOpenACCOp<SetOp>(start, s.getDirectiveKind(), s.getDirectiveLoc(),
+  emitOpenACCOp<SetOp>(start, s.getDirectiveKind(), s.getDirectiveLoc(),
                               s.clauses());
+  return mlir::success();
 }
 
 mlir::LogicalResult CIRGenFunction::emitOpenACCShutdownConstruct(
     const OpenACCShutdownConstruct &s) {
   mlir::Location start = getLoc(s.getSourceRange().getBegin());
-  return emitOpenACCOp<ShutdownOp>(start, s.getDirectiveKind(),
+  emitOpenACCOp<ShutdownOp>(start, s.getDirectiveKind(),
                                    s.getDirectiveLoc(), s.clauses());
+  return mlir::success();
+}
+
+mlir::LogicalResult
+CIRGenFunction::emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s) {
+  mlir::Location start = getLoc(s.getSourceRange().getBegin());
+  auto waitOp = emitOpenACCOp<WaitOp>(start, s.getDirectiveKind(),
+                                   s.getDirectiveLoc(), s.clauses());
+
+  auto createIntExpr = [this](const Expr *intExpr) {
+    mlir::Value expr = emitScalarExpr(intExpr);
+    mlir::Location exprLoc = cgm.getLoc(intExpr->getBeginLoc());
+
+    mlir::IntegerType targetType = mlir::IntegerType::get(
+        &getMLIRContext(), getContext().getIntWidth(intExpr->getType()),
+        intExpr->getType()->isSignedIntegerOrEnumerationType()
+            ? mlir::IntegerType::SignednessSemantics::Signed
+            : mlir::IntegerType::SignednessSemantics::Unsigned);
+
+    auto conversionOp = builder.create<mlir::UnrealizedConversionCastOp>(
+        exprLoc, targetType, expr);
+    return conversionOp.getResult(0);
+  };
+
+  // Emit the correct 'wait' clauses.
+  {
+    mlir::OpBuilder::InsertionGuard guardCase(builder);
+    builder.setInsertionPoint(waitOp);
+
+    if (s.hasDevNumExpr())
+      waitOp.getWaitDevnumMutable().append(createIntExpr(s.getDevNumExpr()));
+
+    for (Expr *QueueExpr  : s.getQueueIdExprs())
+      waitOp.getWaitOperandsMutable().append(createIntExpr(QueueExpr));
+  }
+
+  return mlir::success();
 }
 
 mlir::LogicalResult
@@ -544,11 +589,6 @@ mlir::LogicalResult 
CIRGenFunction::emitOpenACCHostDataConstruct(
   return mlir::failure();
 }
 mlir::LogicalResult
-CIRGenFunction::emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s) {
-  cgm.errorNYI(s.getSourceRange(), "OpenACC Wait Construct");
-  return mlir::failure();
-}
-mlir::LogicalResult
 CIRGenFunction::emitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &s) {
   cgm.errorNYI(s.getSourceRange(), "OpenACC Update Construct");
   return mlir::failure();

diff  --git a/clang/test/CIR/CodeGenOpenACC/wait.c 
b/clang/test/CIR/CodeGenOpenACC/wait.c
new file mode 100644
index 0000000000000..569846a91ab8a
--- /dev/null
+++ b/clang/test/CIR/CodeGenOpenACC/wait.c
@@ -0,0 +1,77 @@
+// RUN: %clang_cc1 -fopenacc -emit-cir -fclangir %s -o - | FileCheck %s
+
+void acc_wait(int cond) {
+  // CHECK: cir.func @acc_wait(%[[ARG:.*]]: !s32i{{.*}}) {
+  // CHECK-NEXT: %[[COND:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["cond", 
init]
+  // CHECK-NEXT: cir.store %[[ARG]], %[[COND]] : !s32i, !cir.ptr<!s32i>
+
+#pragma acc wait
+  // CHECK-NEXT: acc.wait
+
+#pragma acc wait if (cond)
+  // CHECK-NEXT: %[[COND_LOAD:.*]] = cir.load %[[COND]] : !cir.ptr<!s32i>, 
!s32i
+  // CHECK-NEXT: %[[BOOL_CAST:.*]] = cir.cast(int_to_bool, %[[COND_LOAD]] : 
!s32i), !cir.bool
+  // CHECK-NEXT: %[[CONV_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[BOOL_CAST]] : !cir.bool to i1
+  // CHECK-NEXT: acc.wait if(%[[CONV_CAST]])
+
+#pragma acc wait async
+  // CHECK-NEXT: acc.wait attributes {async}
+
+#pragma acc wait async(cond)
+  // CHECK-NEXT: %[[COND_LOAD:.*]] = cir.load %[[COND]] : !cir.ptr<!s32i>, 
!s32i
+  // CHECK-NEXT: %[[CONV_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[COND_LOAD]] : !s32i to si32
+  // CHECK-NEXT: acc.wait async(%[[CONV_CAST]] : si32) loc
+
+#pragma acc wait(1)
+  // CHECK-NEXT: %[[ONE_LITERAL:.*]] = cir.const #cir.int<1> : !s32i
+  // CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[ONE_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: acc.wait(%[[ONE_CAST]] : si32) loc
+
+#pragma acc wait(1, 2) async
+  // CHECK-NEXT: %[[ONE_LITERAL:.*]] = cir.const #cir.int<1> : !s32i
+  // CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[ONE_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: %[[TWO_LITERAL:.*]] = cir.const #cir.int<2> : !s32i
+  // CHECK-NEXT: %[[TWO_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[TWO_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: acc.wait(%[[ONE_CAST]], %[[TWO_CAST]] : si32, si32) 
attributes {async}
+
+
+#pragma acc wait(queues:1) if (cond)
+  // CHECK-NEXT: %[[COND_LOAD:.*]] = cir.load %[[COND]] : !cir.ptr<!s32i>, 
!s32i
+  // CHECK-NEXT: %[[BOOL_CAST:.*]] = cir.cast(int_to_bool, %[[COND_LOAD]] : 
!s32i), !cir.bool
+  // CHECK-NEXT: %[[CONV_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[BOOL_CAST]] : !cir.bool to i1
+  // CHECK-NEXT: %[[ONE_LITERAL:.*]] = cir.const #cir.int<1> : !s32i
+  // CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[ONE_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: acc.wait(%[[ONE_CAST]] : si32)  if(%[[CONV_CAST]])
+
+#pragma acc wait(queues:1, 2) async(cond)
+  // CHECK-NEXT: %[[COND_LOAD:.*]] = cir.load %[[COND]] : !cir.ptr<!s32i>, 
!s32i
+  // CHECK-NEXT: %[[CONV_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[COND_LOAD]] : !s32i to si32
+  // CHECK-NEXT: %[[ONE_LITERAL:.*]] = cir.const #cir.int<1> : !s32i
+  // CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[ONE_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: %[[TWO_LITERAL:.*]] = cir.const #cir.int<2> : !s32i
+  // CHECK-NEXT: %[[TWO_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[TWO_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: acc.wait(%[[ONE_CAST]], %[[TWO_CAST]] : si32, si32) 
async(%[[CONV_CAST]] : si32) loc
+
+#pragma acc wait(devnum:1: 2, 3) if (cond)
+  // CHECK-NEXT: %[[COND_LOAD:.*]] = cir.load %[[COND]] : !cir.ptr<!s32i>, 
!s32i
+  // CHECK-NEXT: %[[BOOL_CAST:.*]] = cir.cast(int_to_bool, %[[COND_LOAD]] : 
!s32i), !cir.bool
+  // CHECK-NEXT: %[[CONV_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[BOOL_CAST]] : !cir.bool to i1
+  // CHECK-NEXT: %[[ONE_LITERAL:.*]] = cir.const #cir.int<1> : !s32i
+  // CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[ONE_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: %[[TWO_LITERAL:.*]] = cir.const #cir.int<2> : !s32i
+  // CHECK-NEXT: %[[TWO_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[TWO_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: %[[THREE_LITERAL:.*]] = cir.const #cir.int<3> : !s32i
+  // CHECK-NEXT: %[[THREE_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[THREE_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: acc.wait(%[[TWO_CAST]], %[[THREE_CAST]] : si32, si32) 
wait_devnum(%[[ONE_CAST]] : si32) if(%[[CONV_CAST]]) loc
+
+#pragma acc wait(devnum:1: queues: 2, 3) async
+  // CHECK-NEXT: %[[ONE_LITERAL:.*]] = cir.const #cir.int<1> : !s32i
+  // CHECK-NEXT: %[[ONE_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[ONE_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: %[[TWO_LITERAL:.*]] = cir.const #cir.int<2> : !s32i
+  // CHECK-NEXT: %[[TWO_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[TWO_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: %[[THREE_LITERAL:.*]] = cir.const #cir.int<3> : !s32i
+  // CHECK-NEXT: %[[THREE_CAST:.*]] = builtin.unrealized_conversion_cast 
%[[THREE_LITERAL]] : !s32i to si32
+  // CHECK-NEXT: acc.wait(%[[TWO_CAST]], %[[THREE_CAST]] : si32, si32) 
wait_devnum(%[[ONE_CAST]] : si32) attributes {async}
+
+  // CHECK-NEXT: cir.return
+}


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

Reply via email to