[Openmp-commits] [openmp] [OpenMP] Simplify generic microtask dispatch (PR #214004)

via Openmp-commits openmp-commits at lists.llvm.org
Tue Aug 4 09:56:28 PDT 2026


https://github.com/arsnyder16 created https://github.com/llvm/llvm-project/pull/214004

Replace the generic microtask dispatcher's handwritten function-pointer types and calls with a variadic-template helper and a macro for each supported argument count.

The dispatcher still casts each microtask to the exact fixed-arity signature required by platforms such as WebAssembly. This is intended as a refactor only: the existing limit of 15 microtask arguments and the diagnostic for larger argument counts remain unchanged.

This reduces the repetitive code and makes future changes to the supported argument range easier to review.

#211071 

>From e4b2bc24ec37e31d230ed13f9e60ed06b032b672 Mon Sep 17 00:00:00 2001
From: Andrew Snyder <asnyder at minitab.com>
Date: Tue, 4 Aug 2026 12:53:56 -0400
Subject: [PATCH] [OpenMP] Simplify generic microtask dispatch

---
 openmp/runtime/src/kmp_invoke_microtask.cpp | 149 +++++---------------
 1 file changed, 39 insertions(+), 110 deletions(-)

diff --git a/openmp/runtime/src/kmp_invoke_microtask.cpp b/openmp/runtime/src/kmp_invoke_microtask.cpp
index f14f27cc06ee3..e3cae9938bcd3 100644
--- a/openmp/runtime/src/kmp_invoke_microtask.cpp
+++ b/openmp/runtime/src/kmp_invoke_microtask.cpp
@@ -1,49 +1,27 @@
 #include "kmp.h"
 
+#include <utility>
+
 #if !(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_MIC || KMP_ARCH_AARCH64 ||        \
       KMP_ARCH_PPC64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 ||            \
       KMP_ARCH_ARM || KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_PPC_XCOFF ||   \
       KMP_ARCH_AARCH64_32)
 
-// Because WebAssembly will use `call_indirect` to invoke the microtask and
-// WebAssembly indirect calls check that the called signature is a precise
-// match, we need to cast each microtask function pointer back from `void *` to
-// its original type.
-typedef void (*microtask_t0)(int *, int *);
-typedef void (*microtask_t1)(int *, int *, void *);
-typedef void (*microtask_t2)(int *, int *, void *, void *);
-typedef void (*microtask_t3)(int *, int *, void *, void *, void *);
-typedef void (*microtask_t4)(int *, int *, void *, void *, void *, void *);
-typedef void (*microtask_t5)(int *, int *, void *, void *, void *, void *,
-                             void *);
-typedef void (*microtask_t6)(int *, int *, void *, void *, void *, void *,
-                             void *, void *);
-typedef void (*microtask_t7)(int *, int *, void *, void *, void *, void *,
-                             void *, void *, void *);
-typedef void (*microtask_t8)(int *, int *, void *, void *, void *, void *,
-                             void *, void *, void *, void *);
-typedef void (*microtask_t9)(int *, int *, void *, void *, void *, void *,
-                             void *, void *, void *, void *, void *);
-typedef void (*microtask_t10)(int *, int *, void *, void *, void *, void *,
-                              void *, void *, void *, void *, void *, void *);
-typedef void (*microtask_t11)(int *, int *, void *, void *, void *, void *,
-                              void *, void *, void *, void *, void *, void *,
-                              void *);
-typedef void (*microtask_t12)(int *, int *, void *, void *, void *, void *,
-                              void *, void *, void *, void *, void *, void *,
-                              void *, void *);
-typedef void (*microtask_t13)(int *, int *, void *, void *, void *, void *,
-                              void *, void *, void *, void *, void *, void *,
-                              void *, void *, void *);
-typedef void (*microtask_t14)(int *, int *, void *, void *, void *, void *,
-                              void *, void *, void *, void *, void *, void *,
-                              void *, void *, void *, void *);
-typedef void (*microtask_t15)(int *, int *, void *, void *, void *, void *,
-                              void *, void *, void *, void *, void *, void *,
-                              void *, void *, void *, void *, void *);
+template <size_t> using microtask_argument_t = void *;
+
+template <size_t... Indices>
+static void invokeMicrotask(microtask_t pkfn, int *gtid, int *tid,
+                            void *p_argv[], std::index_sequence<Indices...>) {
+  // WebAssembly's `call_indirect` requires the callee type to exactly match the
+  // call site. Cast the variadic microtask_t to the fixed-arity signature that
+  // matches argc before invoking it.
+  using typed_microtask_t =
+      void (*)(int *, int *, microtask_argument_t<Indices>...);
+  (*(typed_microtask_t)pkfn)(gtid, tid, p_argv[Indices]...);
+}
 
-// we really only need the case with 1 argument, because CLANG always build
-// a struct of pointers to shared variables referenced in the outlined function
+// Keep a bounded set of exact signatures for targets that cannot dynamically
+// construct a variable-argument microtask call.
 int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
                            void *p_argv[]
 #if OMPT_SUPPORT
@@ -55,85 +33,36 @@ int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
   *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0);
 #endif
 
+#define KMP_INVOKE_MICROTASK_CASE(N)                                           \
+  case N:                                                                      \
+    invokeMicrotask(pkfn, &gtid, &tid, p_argv, std::make_index_sequence<N>{}); \
+    break
+
   switch (argc) {
+    KMP_INVOKE_MICROTASK_CASE(0);
+    KMP_INVOKE_MICROTASK_CASE(1);
+    KMP_INVOKE_MICROTASK_CASE(2);
+    KMP_INVOKE_MICROTASK_CASE(3);
+    KMP_INVOKE_MICROTASK_CASE(4);
+    KMP_INVOKE_MICROTASK_CASE(5);
+    KMP_INVOKE_MICROTASK_CASE(6);
+    KMP_INVOKE_MICROTASK_CASE(7);
+    KMP_INVOKE_MICROTASK_CASE(8);
+    KMP_INVOKE_MICROTASK_CASE(9);
+    KMP_INVOKE_MICROTASK_CASE(10);
+    KMP_INVOKE_MICROTASK_CASE(11);
+    KMP_INVOKE_MICROTASK_CASE(12);
+    KMP_INVOKE_MICROTASK_CASE(13);
+    KMP_INVOKE_MICROTASK_CASE(14);
+    KMP_INVOKE_MICROTASK_CASE(15);
   default:
     fprintf(stderr, "Too many args to microtask: %d!\n", argc);
     fflush(stderr);
     exit(-1);
-  case 0:
-    (*(microtask_t0)pkfn)(&gtid, &tid);
-    break;
-  case 1:
-    (*(microtask_t1)pkfn)(&gtid, &tid, p_argv[0]);
-    break;
-  case 2:
-    (*(microtask_t2)pkfn)(&gtid, &tid, p_argv[0], p_argv[1]);
-    break;
-  case 3:
-    (*(microtask_t3)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2]);
-    break;
-  case 4:
-    (*(microtask_t4)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                          p_argv[3]);
-    break;
-  case 5:
-    (*(microtask_t5)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                          p_argv[3], p_argv[4]);
-    break;
-  case 6:
-    (*(microtask_t6)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                          p_argv[3], p_argv[4], p_argv[5]);
-    break;
-  case 7:
-    (*(microtask_t7)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                          p_argv[3], p_argv[4], p_argv[5], p_argv[6]);
-    break;
-  case 8:
-    (*(microtask_t8)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                          p_argv[3], p_argv[4], p_argv[5], p_argv[6],
-                          p_argv[7]);
-    break;
-  case 9:
-    (*(microtask_t9)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                          p_argv[3], p_argv[4], p_argv[5], p_argv[6], p_argv[7],
-                          p_argv[8]);
-    break;
-  case 10:
-    (*(microtask_t10)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                           p_argv[3], p_argv[4], p_argv[5], p_argv[6],
-                           p_argv[7], p_argv[8], p_argv[9]);
-    break;
-  case 11:
-    (*(microtask_t11)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                           p_argv[3], p_argv[4], p_argv[5], p_argv[6],
-                           p_argv[7], p_argv[8], p_argv[9], p_argv[10]);
-    break;
-  case 12:
-    (*(microtask_t12)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                           p_argv[3], p_argv[4], p_argv[5], p_argv[6],
-                           p_argv[7], p_argv[8], p_argv[9], p_argv[10],
-                           p_argv[11]);
-    break;
-  case 13:
-    (*(microtask_t13)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                           p_argv[3], p_argv[4], p_argv[5], p_argv[6],
-                           p_argv[7], p_argv[8], p_argv[9], p_argv[10],
-                           p_argv[11], p_argv[12]);
-    break;
-  case 14:
-    (*(microtask_t14)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                           p_argv[3], p_argv[4], p_argv[5], p_argv[6],
-                           p_argv[7], p_argv[8], p_argv[9], p_argv[10],
-                           p_argv[11], p_argv[12], p_argv[13]);
-    break;
-  case 15:
-    (*(microtask_t15)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
-                           p_argv[3], p_argv[4], p_argv[5], p_argv[6],
-                           p_argv[7], p_argv[8], p_argv[9], p_argv[10],
-                           p_argv[11], p_argv[12], p_argv[13], p_argv[14]);
-    break;
   }
 
+#undef KMP_INVOKE_MICROTASK_CASE
+
   return 1;
 }
 



More information about the Openmp-commits mailing list