constant folding for cnst[i] and cnst.attr

This commit is contained in:
Araq 2011-10-29 23:54:50 +02:00
commit 299390a585
5 changed files with 78 additions and 49 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 =