mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-26 09:14:00 +00:00
constant folding for cnst[i] and cnst.attr
This commit is contained in:
@@ -281,7 +281,9 @@ type
|
||||
nfBase2, # nfBase10 is default, so not needed
|
||||
nfBase8,
|
||||
nfBase16,
|
||||
nfAllConst, # used to mark complex expressions constant
|
||||
nfAllConst, # used to mark complex expressions constant; easy to get rid of
|
||||
# but unfortunately it has measurable impact for compilation
|
||||
# efficiency
|
||||
nfTransf, # node has been transformed
|
||||
nfSem # node has been checked for semantics
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import
|
||||
options, intsets,
|
||||
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
|
||||
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
||||
rodutils, renderer, idgen, cgendata, ccgmerge
|
||||
rodutils, renderer, idgen, cgendata, ccgmerge, semfold
|
||||
|
||||
when options.hasTinyCBackend:
|
||||
import tccgen
|
||||
|
||||
@@ -155,9 +155,9 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||
result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n)
|
||||
of mLeU, mLeU64:
|
||||
result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n)
|
||||
of mBitandI, mBitandI64, mAnd: result = newIntNodeT(getInt(a) and getInt(b), n)
|
||||
of mBitandI, mBitandI64, mAnd: result = newIntNodeT(a.getInt and b.getInt, n)
|
||||
of mBitorI, mBitorI64, mOr: result = newIntNodeT(getInt(a) or getInt(b), n)
|
||||
of mBitxorI, mBitxorI64, mXor: result = newIntNodeT(getInt(a) xor getInt(b), n)
|
||||
of mBitxorI, mBitxorI64, mXor: result = newIntNodeT(a.getInt xor b.getInt, n)
|
||||
of mAddU, mAddU64: result = newIntNodeT(`+%`(getInt(a), getInt(b)), n)
|
||||
of mSubU, mSubU64: result = newIntNodeT(`-%`(getInt(a), getInt(b)), n)
|
||||
of mMulU, mMulU64: result = newIntNodeT(`*%`(getInt(a), getInt(b)), n)
|
||||
@@ -199,7 +199,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||
result = copyTree(a)
|
||||
result.typ = n.typ
|
||||
of mCompileOption:
|
||||
result = newIntNodeT(Ord(commands.testCompileOption(getStr(a), n.info)), n)
|
||||
result = newIntNodeT(Ord(commands.testCompileOption(a.getStr, n.info)), n)
|
||||
of mCompileOptionArg:
|
||||
result = newIntNodeT(Ord(
|
||||
testCompileOptionArg(getStr(a), getStr(b), n.info)), n)
|
||||
@@ -315,6 +315,59 @@ proc foldConv*(n, a: PNode): PNode =
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
|
||||
proc getArrayConstr(m: PSym, n: PNode): PNode =
|
||||
if n.kind == nkBracket:
|
||||
result = n
|
||||
else:
|
||||
result = getConstExpr(m, n)
|
||||
if result == nil: result = n
|
||||
|
||||
proc foldArrayAccess(m: PSym, n: PNode): PNode =
|
||||
var x = getConstExpr(m, n.sons[0])
|
||||
if x == nil: return
|
||||
|
||||
var y = getConstExpr(m, n.sons[1])
|
||||
if y == nil: return
|
||||
|
||||
var idx = getOrdValue(y)
|
||||
case x.kind
|
||||
of nkPar:
|
||||
if (idx >= 0) and (idx < sonsLen(x)):
|
||||
result = x.sons[int(idx)]
|
||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||
else:
|
||||
LocalError(n.info, errIndexOutOfBounds)
|
||||
of nkBracket, nkMetaNode:
|
||||
if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)]
|
||||
else: LocalError(n.info, errIndexOutOfBounds)
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
result = newNodeIT(nkCharLit, x.info, n.typ)
|
||||
if (idx >= 0) and (idx < len(x.strVal)):
|
||||
result.intVal = ord(x.strVal[int(idx)])
|
||||
elif idx == len(x.strVal):
|
||||
nil
|
||||
else:
|
||||
LocalError(n.info, errIndexOutOfBounds)
|
||||
else: nil
|
||||
|
||||
proc foldFieldAccess(m: PSym, n: PNode): PNode =
|
||||
# a real field access; proc calls have already been transformed
|
||||
var x = getConstExpr(m, n.sons[0])
|
||||
if x == nil or x.kind != nkPar: return
|
||||
|
||||
var field = n.sons[1].sym
|
||||
for i in countup(0, sonsLen(x) - 1):
|
||||
var it = x.sons[i]
|
||||
if it.kind != nkExprColonExpr:
|
||||
# lookup per index:
|
||||
result = x.sons[field.position]
|
||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||
return
|
||||
if it.sons[0].sym.name.id == field.name.id:
|
||||
result = x.sons[i].sons[1]
|
||||
return
|
||||
localError(n.info, errFieldXNotFound, field.name.s)
|
||||
|
||||
proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
result = nil
|
||||
case n.kind
|
||||
@@ -333,7 +386,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
of mNimrodPatch: result = newIntNodeT(VersionPatch, n)
|
||||
of mCpuEndian: result = newIntNodeT(ord(CPU[targetCPU].endian), n)
|
||||
of mHostOS: result = newStrNodeT(toLower(platform.OS[targetOS].name), n)
|
||||
of mHostCPU: result = newStrNodeT(toLower(platform.CPU[targetCPU].name), n)
|
||||
of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLower, n)
|
||||
of mAppType: result = getAppType(n)
|
||||
of mNaN: result = newFloatNodeT(NaN, n)
|
||||
of mInf: result = newFloatNodeT(Inf, n)
|
||||
@@ -346,7 +399,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
of nkIfExpr:
|
||||
result = getConstIfExpr(m, n)
|
||||
of nkCall, nkCommand, nkCallStrLit:
|
||||
of nkCall, nkCommand, nkCallStrLit, nkPrefix, nkInfix:
|
||||
if n.sons[0].kind != nkSym: return
|
||||
var s = n.sons[0].sym
|
||||
if s.kind != skProc: return
|
||||
@@ -372,13 +425,13 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
{tyOpenArray, tySequence, tyString}:
|
||||
result = newIntNodeT(lastOrd(skipTypes(n[1].typ, abstractVar)), n)
|
||||
else:
|
||||
var a = n.sons[1]
|
||||
var a = getArrayConstr(m, n.sons[1])
|
||||
if a.kind == nkBracket:
|
||||
# we can optimize it away:
|
||||
result = newIntNodeT(sonsLen(a)-1, n)
|
||||
of mLengthOpenArray:
|
||||
var a = n.sons[1]
|
||||
if a.kind == nkBracket:
|
||||
var a = getArrayConstr(m, n.sons[1])
|
||||
if a.kind == nkBracket:
|
||||
# we can optimize it away! This fixes the bug ``len(134)``.
|
||||
result = newIntNodeT(sonsLen(a), n)
|
||||
else:
|
||||
@@ -449,5 +502,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
var a = getConstExpr(m, n.sons[1])
|
||||
if a == nil: return
|
||||
result = foldConv(n, a)
|
||||
else:
|
||||
of nkBracketExpr: result = foldArrayAccess(m, n)
|
||||
of nkDotExpr: result = foldFieldAccess(m, n)
|
||||
else:
|
||||
nil
|
||||
|
||||
@@ -719,7 +719,9 @@ proc transform(c: PTransf, n: PNode): PTransNode =
|
||||
else:
|
||||
result = transformSons(c, n)
|
||||
var cnst = getConstExpr(c.module, PNode(result))
|
||||
if cnst != nil and (cnst.kind != nkBracket or cnst.len == 0):
|
||||
# we inline constants if they are not complex constants:
|
||||
if cnst != nil and (cnst.kind notin {nkCurly, nkPar, nkBracket} or
|
||||
cnst.len == 0):
|
||||
result = PTransNode(cnst) # do not miss an optimization
|
||||
|
||||
proc processTransf(context: PPassContext, n: PNode): PNode =
|
||||
|
||||
44
todo.txt
44
todo.txt
@@ -1,10 +1,8 @@
|
||||
Version 0.8.14
|
||||
==============
|
||||
|
||||
- optimize unused constants away (affected by HLO); get rid of nfAllConst
|
||||
- 'let x = y'
|
||||
- fix actors.nim
|
||||
- make threadvar efficient again on linux after testing
|
||||
- optimize unused constants away (affected by HLO)
|
||||
- fix actors.nim; test with different thread var implementations
|
||||
- dead code elim for JS backend
|
||||
|
||||
|
||||
@@ -16,42 +14,14 @@ incremental compilation
|
||||
- implement lib/pure/memfiles properly
|
||||
|
||||
|
||||
Destructors
|
||||
-----------
|
||||
|
||||
A destructor is bound to a proc instead of a type. The proc is then called
|
||||
an *init proc*. A destructor is called at
|
||||
scope exit for the local variables (declared with ``var`` or ``let``)
|
||||
that are initialized with its corresponding init proc:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc autoOpen(filename: string): TFile {.destructor: close.} =
|
||||
result = open(filename)
|
||||
|
||||
var f = autoOpen("abc.txt")
|
||||
|
||||
A template ``atScopeExit`` can easily be defined with this mechanism. However
|
||||
unfortunately the regex problem is not solved at all:
|
||||
|
||||
.. code-block:: nimrod
|
||||
if x =~ re"abc":
|
||||
...
|
||||
|
||||
We really need some form of escape analysis; ``var`` or ``let`` is not enough!
|
||||
Hm, but what if the procs declare that property:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc `=~` (s: string, pattern: TRegex{.noEscape.}): bool
|
||||
|
||||
So it's bound to a type again?
|
||||
|
||||
|
||||
version 0.9.0
|
||||
=============
|
||||
|
||||
- test the sort implementation again
|
||||
- 'let x = y'
|
||||
- const ptr/ref
|
||||
- unsigned ints and bignums; requires abstract integer literal type
|
||||
- unsigned ints and bignums; requires abstract integer literal type:
|
||||
use tyInt+node for that
|
||||
- implement the high level optimizer
|
||||
- warning for implicit openArray -> varargs convention
|
||||
- implement explicit varargs; **but** ``len(varargs)`` problem remains!
|
||||
@@ -64,7 +34,6 @@ version 0.9.0
|
||||
- 'const' objects including case objects
|
||||
- os module should use Windows Unicode versions
|
||||
- 64bit build for Windows
|
||||
- codegen should use "NIM_CAST" macro and respect aliasing rules for GCC
|
||||
- optional indentation for 'case' statement
|
||||
|
||||
Bugs
|
||||
@@ -83,7 +52,7 @@ Bugs
|
||||
|
||||
- bug: DLL generation is broken; write at least a basic test
|
||||
- bug: stress testing basic method example (eval example)
|
||||
without ``-d:relase`` leaks memory; good way to figure out how a
|
||||
without ``-d:release`` leaks memory; good way to figure out how a
|
||||
fixed amount of stack can hold an arbitrary number of GC roots!
|
||||
|
||||
|
||||
@@ -149,6 +118,7 @@ Low priority
|
||||
is allocated
|
||||
- timeout for locks
|
||||
- adapt thread var emulation to care about the new merge operation
|
||||
- codegen should use "NIM_CAST" macro and respect aliasing rules for GCC
|
||||
|
||||
|
||||
Version 2
|
||||
|
||||
Reference in New Issue
Block a user