linearScanEnd pragma; string case statement optimization
This commit is contained in:
parent
6850fb73c1
commit
8d734244b1
26 changed files with 537 additions and 252 deletions
|
|
@ -2646,6 +2646,53 @@ hint pragma
|
|||
-----------
|
||||
The `hint`:idx: pragma is used to make the compiler output a hint message with
|
||||
the given content. Compilation continues after the hint.
|
||||
|
||||
|
||||
linearScanEnd pragma
|
||||
--------------------
|
||||
The `linearScanEnd`:idx: pragma can be used to tell the compiler how to
|
||||
compile a Nimrod `case`:idx: statement. Syntactially it has to be used as a
|
||||
statement:
|
||||
|
||||
.. code-block:: nimrod
|
||||
case myInt
|
||||
of 0:
|
||||
echo "most common case"
|
||||
of 1:
|
||||
{.linearScanEnd.}
|
||||
echo "second most common case"
|
||||
of 2: echo "unlikely: use branch table"
|
||||
else: echo "unlikely too: use branch table for ", myInt
|
||||
|
||||
In the example, the case branches ``0`` and ``1`` are much more common than
|
||||
the other cases. Therefore the generated assembler code should test for these
|
||||
values first, so that the CPU's branch predictor has a good chance to succeed
|
||||
(avoiding an expensive CPU pipeline stall). The other cases might be put into a
|
||||
jump table for O(1) overhead, but at the cost of a (very likely) pipeline
|
||||
stall.
|
||||
|
||||
The ``linearScanEnd`` pragma should be put into the last branch that should be
|
||||
tested against via linear scanning. If put into the last branch of the
|
||||
whole ``case`` statement, the whole ``case`` statement uses linear scanning.
|
||||
|
||||
|
||||
unroll pragma
|
||||
-------------
|
||||
The `unroll`:idx: pragma can be used to tell the compiler that it should unroll
|
||||
a `for`:idx: or `while`:idx: loop for runtime efficiency:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc searchChar(s: string, c: char): int =
|
||||
for i in 0 .. s.high:
|
||||
{.unroll: 4.}
|
||||
if s[i] == c: return i
|
||||
result = -1
|
||||
|
||||
In the above example, the search loop is unrolled by a factor 4. The unroll
|
||||
factor can be left out too; the compiler then chooses an appropriate unroll
|
||||
factor.
|
||||
|
||||
**Note**: Currently the compiler recognizes but ignores this pragma.
|
||||
|
||||
|
||||
compilation option pragmas
|
||||
|
|
|
|||
|
|
@ -293,10 +293,26 @@ However it is not efficient to do:
|
|||
.. code-block:: Nimrod
|
||||
var s = varA # assignment has to copy the whole string into a new buffer!
|
||||
|
||||
..
|
||||
String case statements are optimized too. A hashing scheme is used for them
|
||||
if several different string constants are used. This is likely to be more
|
||||
efficient than any hand-coded scheme.
|
||||
The compiler optimizes string case statements: A hashing scheme is used for them
|
||||
if several different string constants are used. So code like this is reasonably
|
||||
efficient:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
case normalize(k.key)
|
||||
of "name": c.name = v
|
||||
of "displayname": c.displayName = v
|
||||
of "version": c.version = v
|
||||
of "os": c.oses = split(v, {';'})
|
||||
of "cpu": c.cpus = split(v, {';'})
|
||||
of "authors": c.authors = split(v, {';'})
|
||||
of "description": c.description = v
|
||||
of "app":
|
||||
case normalize(v)
|
||||
of "console": c.app = appConsole
|
||||
of "gui": c.app = appGUI
|
||||
else: quit(errorStr(p, "expected: console or gui"))
|
||||
of "license": c.license = UnixToNativePath(k.value)
|
||||
else: quit(errorStr(p, "unknown variable: " & k.key))
|
||||
|
||||
|
||||
..
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue