items, pairs and friends now use unCheckedInc (#22729)

`{.push overflowChecks: off.}` works in backends. Though it could be
implemented as a magic function.

By inspecting the generated C code, the overflow check is eliminated in
the debug or release mode.

![image](https://github.com/nim-lang/Nim/assets/43030857/49c3dbf4-675e-414a-b972-b91cf218c9f8)

Likewise, the index checking is probably not needed.

(cherry picked from commit d82bc0a29f)
This commit is contained in:
ringabout
2023-09-20 18:50:23 +08:00
committed by narimiran
parent e918a762f7
commit 577ffbc57c
2 changed files with 35 additions and 26 deletions

View File

@@ -8,12 +8,17 @@ when not defined(nimNoLentIterators):
else:
template lent2(T): untyped = T
template unCheckedInc(x) =
{.push overflowChecks: off.}
inc(x)
{.pop.}
iterator items*[T: not char](a: openArray[T]): lent2 T {.inline.} =
## Iterates over each item of `a`.
var i = 0
while i < len(a):
yield a[i]
inc(i)
unCheckedInc(i)
iterator items*[T: char](a: openArray[T]): T {.inline.} =
## Iterates over each item of `a`.
@@ -23,14 +28,14 @@ iterator items*[T: char](a: openArray[T]): T {.inline.} =
var i = 0
while i < len(a):
yield a[i]
inc(i)
unCheckedInc(i)
iterator mitems*[T](a: var openArray[T]): var T {.inline.} =
## Iterates over each item of `a` so that you can modify the yielded value.
var i = 0
while i < len(a):
yield a[i]
inc(i)
unCheckedInc(i)
iterator items*[IX, T](a: array[IX, T]): T {.inline.} =
## Iterates over each item of `a`.
@@ -39,7 +44,7 @@ iterator items*[IX, T](a: array[IX, T]): T {.inline.} =
while true:
yield a[i]
if i >= high(IX): break
inc(i)
unCheckedInc(i)
iterator mitems*[IX, T](a: var array[IX, T]): var T {.inline.} =
## Iterates over each item of `a` so that you can modify the yielded value.
@@ -48,7 +53,7 @@ iterator mitems*[IX, T](a: var array[IX, T]): var T {.inline.} =
while true:
yield a[i]
if i >= high(IX): break
inc(i)
unCheckedInc(i)
iterator items*[T](a: set[T]): T {.inline.} =
## Iterates over each element of `a`. `items` iterates only over the
@@ -57,7 +62,7 @@ iterator items*[T](a: set[T]): T {.inline.} =
var i = low(T).int
while i <= high(T).int:
if T(i) in a: yield T(i)
inc(i)
unCheckedInc(i)
iterator items*(a: cstring): char {.inline.} =
## Iterates over each item of `a`.
@@ -76,7 +81,7 @@ iterator items*(a: cstring): char {.inline.} =
let n = len(a)
while i < n:
yield a[i]
inc(i)
unCheckedInc(i)
when defined(js): impl()
else:
when nimvm:
@@ -86,7 +91,7 @@ iterator items*(a: cstring): char {.inline.} =
var i = 0
while a[i] != '\0':
yield a[i]
inc(i)
unCheckedInc(i)
iterator mitems*(a: var cstring): var char {.inline.} =
## Iterates over each item of `a` so that you can modify the yielded value.
@@ -109,7 +114,7 @@ iterator mitems*(a: var cstring): var char {.inline.} =
let n = len(a)
while i < n:
yield a[i]
inc(i)
unCheckedInc(i)
when defined(js): impl()
else:
when nimvm: impl()
@@ -117,7 +122,7 @@ iterator mitems*(a: var cstring): var char {.inline.} =
var i = 0
while a[i] != '\0':
yield a[i]
inc(i)
unCheckedInc(i)
iterator items*[T: enum and Ordinal](E: typedesc[T]): T =
## Iterates over the values of `E`.
@@ -140,7 +145,7 @@ iterator pairs*[T](a: openArray[T]): tuple[key: int, val: T] {.inline.} =
var i = 0
while i < len(a):
yield (i, a[i])
inc(i)
unCheckedInc(i)
iterator mpairs*[T](a: var openArray[T]): tuple[key: int, val: var T]{.inline.} =
## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
@@ -148,7 +153,7 @@ iterator mpairs*[T](a: var openArray[T]): tuple[key: int, val: var T]{.inline.}
var i = 0
while i < len(a):
yield (i, a[i])
inc(i)
unCheckedInc(i)
iterator pairs*[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.} =
## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
@@ -157,7 +162,7 @@ iterator pairs*[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.} =
while true:
yield (i, a[i])
if i >= high(IX): break
inc(i)
unCheckedInc(i)
iterator mpairs*[IX, T](a: var array[IX, T]): tuple[key: IX, val: var T] {.inline.} =
## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
@@ -167,7 +172,7 @@ iterator mpairs*[IX, T](a: var array[IX, T]): tuple[key: IX, val: var T] {.inlin
while true:
yield (i, a[i])
if i >= high(IX): break
inc(i)
unCheckedInc(i)
iterator pairs*[T](a: seq[T]): tuple[key: int, val: T] {.inline.} =
## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
@@ -175,7 +180,7 @@ iterator pairs*[T](a: seq[T]): tuple[key: int, val: T] {.inline.} =
let L = len(a)
while i < L:
yield (i, a[i])
inc(i)
unCheckedInc(i)
assert(len(a) == L, "the length of the seq changed while iterating over it")
iterator mpairs*[T](a: var seq[T]): tuple[key: int, val: var T] {.inline.} =
@@ -185,7 +190,7 @@ iterator mpairs*[T](a: var seq[T]): tuple[key: int, val: var T] {.inline.} =
let L = len(a)
while i < L:
yield (i, a[i])
inc(i)
unCheckedInc(i)
assert(len(a) == L, "the length of the seq changed while iterating over it")
iterator pairs*(a: string): tuple[key: int, val: char] {.inline.} =
@@ -194,7 +199,7 @@ iterator pairs*(a: string): tuple[key: int, val: char] {.inline.} =
let L = len(a)
while i < L:
yield (i, a[i])
inc(i)
unCheckedInc(i)
assert(len(a) == L, "the length of the string changed while iterating over it")
iterator mpairs*(a: var string): tuple[key: int, val: var char] {.inline.} =
@@ -204,7 +209,7 @@ iterator mpairs*(a: var string): tuple[key: int, val: var char] {.inline.} =
let L = len(a)
while i < L:
yield (i, a[i])
inc(i)
unCheckedInc(i)
assert(len(a) == L, "the length of the string changed while iterating over it")
iterator pairs*(a: cstring): tuple[key: int, val: char] {.inline.} =
@@ -214,12 +219,12 @@ iterator pairs*(a: cstring): tuple[key: int, val: char] {.inline.} =
var L = len(a)
while i < L:
yield (i, a[i])
inc(i)
unCheckedInc(i)
else:
var i = 0
while a[i] != '\0':
yield (i, a[i])
inc(i)
unCheckedInc(i)
iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} =
## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
@@ -229,12 +234,12 @@ iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} =
var L = len(a)
while i < L:
yield (i, a[i])
inc(i)
unCheckedInc(i)
else:
var i = 0
while a[i] != '\0':
yield (i, a[i])
inc(i)
unCheckedInc(i)
iterator items*[T](a: seq[T]): lent2 T {.inline.} =
## Iterates over each item of `a`.
@@ -242,7 +247,7 @@ iterator items*[T](a: seq[T]): lent2 T {.inline.} =
let L = len(a)
while i < L:
yield a[i]
inc(i)
unCheckedInc(i)
assert(len(a) == L, "the length of the seq changed while iterating over it")
iterator mitems*[T](a: var seq[T]): var T {.inline.} =
@@ -251,7 +256,7 @@ iterator mitems*[T](a: var seq[T]): var T {.inline.} =
let L = len(a)
while i < L:
yield a[i]
inc(i)
unCheckedInc(i)
assert(len(a) == L, "the length of the seq changed while iterating over it")
iterator items*(a: string): char {.inline.} =
@@ -260,7 +265,7 @@ iterator items*(a: string): char {.inline.} =
let L = len(a)
while i < L:
yield a[i]
inc(i)
unCheckedInc(i)
assert(len(a) == L, "the length of the string changed while iterating over it")
iterator mitems*(a: var string): var char {.inline.} =
@@ -269,7 +274,7 @@ iterator mitems*(a: var string): var char {.inline.} =
let L = len(a)
while i < L:
yield a[i]
inc(i)
unCheckedInc(i)
assert(len(a) == L, "the length of the string changed while iterating over it")

View File

@@ -91,7 +91,9 @@ try:
`=copy`(lan_ip, splitted[1])
echo [lan_ip]
echo [splitted[1]]
{.push, overflowChecks: false.}
inc(i, 1)
{.pop.}
finally:
`=destroy`(splitted)
finally:
@@ -113,7 +115,9 @@ block :tmp:
addInterfaceDecl(c):
:tmpD = `=dup`(sym)
:tmpD
{.push, overflowChecks: false.}
inc(i, 1)
{.pop.}
`=destroy`(shadowScope)
-- end of expandArc ------------------------
--expandArc: check