summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorMamy Ratsimbazafy <mratsim@users.noreply.github.com>2019-03-22 23:38:43 +0100
committerAndreas Rumpf <rumpf_a@web.de>2019-03-22 23:38:43 +0100
commit25649616ea5b6aba575149df3f9943f48a5ece31 (patch)
tree30da754b1ec901a7fe6f0b7894789ee61d9fc52e
parent04ad200b403f1c4908a1a043e1f27b111298e1f3 (diff)
downloadNim-25649616ea5b6aba575149df3f9943f48a5ece31.tar.gz
Add OpenMP overload with stepping (#10891)
-rw-r--r--changelog.md2
-rw-r--r--compiler/ccgstmts.nim20
-rw-r--r--lib/system.nim18
3 files changed, 35 insertions, 5 deletions
diff --git a/changelog.md b/changelog.md
index 6e3872219..975c71ca2 100644
--- a/changelog.md
+++ b/changelog.md
@@ -20,6 +20,8 @@
   the change is transparent, if you used annotations you will have to prefix
   your previous annotations with `parallel for`.
 
+  Furthermore, an overload with positive stepping is available.
+
 - The `unchecked` pragma was removed, instead use `system.UncheckedArray`.
 
 - The undocumented ``#? strongSpaces`` parsing mode has been removed.
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 1e6e04458..2b1cb404d 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -622,15 +622,25 @@ proc genParForStmt(p: BProc, t: PNode) =
     #initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack)
     #discard mangleName(forLoopVar)
     let call = t.sons[1]
+    assert(sonsLen(call) in {4, 5})
     initLocExpr(p, call.sons[1], rangeA)
     initLocExpr(p, call.sons[2], rangeB)
 
     # $n at the beginning because of #9710
-    lineF(p, cpsStmts, "$n#pragma omp $4$n" &
-                        "for ($1 = $2; $1 <= $3; ++$1)",
-                        [forLoopVar.loc.rdLoc,
-                        rangeA.rdLoc, rangeB.rdLoc,
-                        call.sons[3].getStr.rope])
+    if call.sonsLen == 4: # `||`(a, b, annotation)
+      lineF(p, cpsStmts, "$n#pragma omp $4$n" &
+                          "for ($1 = $2; $1 <= $3; ++$1)",
+                          [forLoopVar.loc.rdLoc,
+                          rangeA.rdLoc, rangeB.rdLoc,
+                          call.sons[3].getStr.rope])
+    else: # `||`(a, b, step, annotation)
+      var step: TLoc
+      initLocExpr(p, call.sons[3], step)
+      lineF(p, cpsStmts, "$n#pragma omp $5$n" &
+                    "for ($1 = $2; $1 <= $3; $1 += $4)",
+                    [forLoopVar.loc.rdLoc,
+                    rangeA.rdLoc, rangeB.rdLoc, step.rdLoc,
+                    call.sons[4].getStr.rope])
 
     p.breakIdx = startBlock(p)
     p.blocks[p.breakIdx].isLoop = true
diff --git a/lib/system.nim b/lib/system.nim
index 090c6359c..016675d55 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2681,6 +2681,24 @@ iterator `||`*[S, T](a: S, b: T, annotation: static string = "parallel for"): T
   ## and GC.
   discard
 
+iterator `||`*[S, T](a: S, b: T, step: Positive, annotation: static string = "parallel for"): T {.
+  inline, magic: "OmpParFor", sideEffect.} =
+  ## OpenMP parallel loop iterator with stepping.
+  ## Same as `countup` but the loop may run in parallel.
+  ##
+  ## `annotation` is an additional annotation for the code generator to use.
+  ## The default annotation is `parallel for`.
+  ## Please refer to the `OpenMP Syntax Reference
+  ## <https://www.openmp.org/wp-content/uploads/OpenMP-4.5-1115-CPP-web.pdf>`_
+  ## for further information.
+  ##
+  ## Note that the compiler maps that to
+  ## the ``#pragma omp parallel for`` construct of `OpenMP`:idx: and as
+  ## such isn't aware of the parallelism in your code! Be careful! Later
+  ## versions of ``||`` will get proper support by Nim's code generator
+  ## and GC.
+  discard
+
 {.push stackTrace:off.}
 proc min*(x, y: int): int {.magic: "MinI", noSideEffect.} =
   if x <= y: x else: y