From e8f8f4d97cb555b2143b7427dc7d8d5a1c30f119 Mon Sep 17 00:00:00 2001 From: FeepingCreature Date: Wed, 14 Aug 2013 23:25:40 +0200 Subject: [PATCH] Tiny speed improvements, Windows native compilation support --- ast/aliasing.d | 8 ++++--- ast/arrays.d | 1 + ast/base.d | 35 ++++++++++++++--------------- ast/math.d | 2 +- ast/modules.d | 30 +++++++++++++++---------- ast/pointer.d | 7 +++++- cache.d | 11 +++++++++- casts.d | 51 +++++++++++++++++++++++++++---------------- fcc.d | 41 ++++++++++++++++++++++++---------- hello.nt | 3 +++ llvmtype.d | 17 ++++++++++----- memconserve_stdfile.d | 1 + std/parser.nt | 18 ++++++++------- 13 files changed, 145 insertions(+), 80 deletions(-) diff --git a/ast/aliasing.d b/ast/aliasing.d index 28498343..cd641a82 100644 --- a/ast/aliasing.d +++ b/ast/aliasing.d @@ -75,14 +75,16 @@ class CValueAlias : ExprAlias, CValue { override CValueAlias dup() { return fastalloc!(CValueAlias)(base.dup, name); } } -class LValueAlias : CValueAlias, LValue { +final class LValueAlias : CValueAlias, LValue { + static const isFinal = true; mixin MyThis!("super(base, name)"[]); override LValueAlias dup() { return fastalloc!(LValueAlias)(base.dup, name); } } -class MValueAlias : ExprAlias, MValue { +final class MValueAlias : ExprAlias, MValue { + static const isFinal = true; mixin MyThis!("super(base, name)"[]); - override void emitAssignment(LLVMFile lf) { (fastcast!(MValue)~ base).emitAssignment(lf); } + void emitAssignment(LLVMFile lf) { (fastcast!(MValue)~ base).emitAssignment(lf); } override MValueAlias dup() { return fastalloc!(MValueAlias)(base.dup, name); } } diff --git a/ast/arrays.d b/ast/arrays.d index 7e64281b..fbf3813b 100644 --- a/ast/arrays.d +++ b/ast/arrays.d @@ -84,6 +84,7 @@ class Array_ : Type, RelNamespace, Dwarf2Encodable, ReferenceType { } final class Array : Array_ { + static const isFinal = true; this() { super(); } this(IType it) { super(it); } } diff --git a/ast/base.d b/ast/base.d index b2447fb5..e0c6864d 100644 --- a/ast/base.d +++ b/ast/base.d @@ -662,9 +662,20 @@ interface Dependency { } extern(C) int atoi(char*); -int my_atoi(string s) { - auto mew = qformat(s, "\x00"[]); - return atoi(mew.ptr); +bool my_atoi(string s, out int i) { + s = s.mystripl(); + if (!s.length) return false; + if (s == "0") return true; + bool neg; + if (s[0] == '-') { s = s[1..$]; neg = true; } + if (!s.length) return false; + foreach (ch; s) { + if (ch < '0' || ch > '9') return false; + byte b = ch - '0'; + i = i * 10 + b; + } + if (neg) i = -i; + return true; } class NamedNull : NoOp, Named, SelfAdding { @@ -740,11 +751,7 @@ interface ModifiesName { bool readIndexShorthand(string name, ref int i) { auto idxstr = name.startsWith("_"[]); - if (!idxstr) return false; - auto idx = my_atoi(idxstr); - if (idxstr != Format(idx)) - return false; - i = idx; + if (!idxstr || !my_atoi(idxstr, i)) return false; return true; } @@ -896,14 +903,7 @@ Expr llvmval(T...)(T t) { return llvmvalstr(qformat(t)); } -bool isnum(string s, out int i) { - auto var = s.my_atoi(); - if (qformat(var) == s) { - i = var; - return true; - } - return false; -} +bool isnum(string s, out int i) { return my_atoi(s, i); } string lladd(string a, string b) { int k, l; @@ -927,7 +927,8 @@ string lldiv(string a, string b) { } bool llmax_decompose_first(string s, out int i, out string k) { if (auto rest = s.startsWith("select(i1 icmp sgt(i32 ")) { - auto num = rest.slice(" ").my_atoi(); + int num; + my_atoi(rest.slice(" "), num); auto reconstruct_a = qformat(num); auto start = qformat("select(i1 icmp sgt(i32 ", reconstruct_a, ", i32 "); if (auto rest2 = s.startsWith(start)) { diff --git a/ast/math.d b/ast/math.d index 34eaab96..33af2289 100644 --- a/ast/math.d +++ b/ast/math.d @@ -73,7 +73,7 @@ static this() { return null; }; foldopt ~= delegate Itr(Itr it) { - if (auto fc = fastcast!(FunCall) (it)) { + if (auto fc = fastcast_direct!(FunCall)(it)) { if (fc.fun.extern_c && fc.fun.name == "sqrtf"[]) { assert(fc.params.length == 1); auto fe = fc.params[0]; diff --git a/ast/modules.d b/ast/modules.d index ea917b0c..a9bd8106 100644 --- a/ast/modules.d +++ b/ast/modules.d @@ -39,17 +39,21 @@ class Module : NamespaceImporter, IModule, Tree, Named, StoresDebugState, Emitti scope(exit) current_module.set(backup); current_module.set(this); - if (sourcefile) if (auto cache = read_cache("module imports", sourcefile)) { - Module[] res; - bool failed; - while (cache) { - auto entry = slice(cache, ","); - try res ~= lookupMod(entry); - catch (Exception ex) { failed = true; break; } // don't use cache if it leads to errors - } - if (!failed) { - imports_cache = res; - return res; + if (sourcefile) { + string relevant_file = sourcefile; + if (sourcefile == "sys.nt") relevant_file = "fcc.exe"; + if (auto cache = read_cache("module imports", relevant_file)) { + Module[] res; + bool failed; + while (cache) { + auto entry = slice(cache, ","); + try res ~= lookupMod(entry); + catch (Exception ex) { failed = true; break; } // don't use cache if it leads to errors + } + if (!failed) { + imports_cache = res; + return res; + } } } @@ -72,7 +76,9 @@ class Module : NamespaceImporter, IModule, Tree, Named, StoresDebugState, Emitti if (sourcefile) { string[] names; foreach (entry; res) names ~= entry.name; - write_cache("module imports", sourcefile, names.join(",")); + string relevant_file = sourcefile; + if (sourcefile == "sys.nt") relevant_file = "fcc.exe"; + write_cache("module imports", relevant_file, names.join(",")); } imports_cache = res; diff --git a/ast/pointer.d b/ast/pointer.d index b36df215..51850ffb 100644 --- a/ast/pointer.d +++ b/ast/pointer.d @@ -85,7 +85,7 @@ final class RefExpr : RefExpr_ { } // *foo -class DerefExpr : LValue, HasInfo { +class DerefExpr_ : LValue, HasInfo { Expr src; int count; static int de_count; @@ -117,6 +117,11 @@ class DerefExpr : LValue, HasInfo { string toString() { return Format("*"[], src); } } +final class DerefExpr : DerefExpr_ { + static const isFinal = true; + this(Expr ex) { super(ex); } +} + bool isVoidP(IType it) { if (!it) return false; auto p = fastcast!(Pointer)~ it; diff --git a/cache.d b/cache.d index f93335ff..f9746e5a 100644 --- a/cache.d +++ b/cache.d @@ -41,7 +41,12 @@ long atol(string s) { string[string] findfile_cache; string findfile(string file) { - if (auto p = file in findfile_cache) return *p; + if (auto p = file in findfile_cache) { + if (!*p) { + fail(qformat("lookup for ", file, " returned in null from cache")); + } + return *p; + } string res; if (file.exists()) res = file; else { @@ -50,8 +55,12 @@ string findfile(string file) { res = entry.qsub(file); break; } + if (!res) { + fail(qformat("File not found: ", file, ", in path ", include_path)); + } } findfile_cache[file] = res; + if (!res) fail(qformat("lookup for ", file, " returned in uncached null")); return res; } diff --git a/casts.d b/casts.d index cb0bd4ae..dedd03e0 100644 --- a/casts.d +++ b/casts.d @@ -101,7 +101,7 @@ const string[] quicklist = [ Stuple!(void*, int)[] idtable; -int xor; +int xor, idmask; const uint knuthMagic = 2654435761; const cachesize = 1; // tested and best .. 0 is way slower, 2 is slightly slower. @@ -139,7 +139,7 @@ void initCastTable() { } ci ~= cl; } - int bestXOR, bestXORSize = int.max; + int bestXOR, bestXORSize = int.max, bestMask; auto rng = fastalloc!(Mersenne)(23); auto backing_pretable = new bool[1024]; bool[] pretable; @@ -151,36 +151,35 @@ void initCastTable() { for (int i = 0; i < 512; ++i) { // lol xor = rng(); - auto cursize = quicklist.length; + // auto cursize = quicklist.length; + int cursize = 2, curmask = 1; outer: resize_pretable(cursize); resetHash(); foreach (int id, entry; ci) { auto pos = hash(cast(void*) entry) % pretable.length; if (pretable[pos]) { - cursize ++; + // cursize ++; + cursize *= 2; curmask = (curmask << 1) | 1; if (cursize >= bestXORSize) break; goto outer; } pretable[pos] = true; } if (cursize < bestXORSize) { - bestXORSize = cursize; bestXOR = xor; + bestXORSize = cursize; + bestMask = curmask; } } xor = bestXOR; idtable.length = bestXORSize; - if (PredictedTableLength != -1 && idtable.length != PredictedTableLength) { - logln("please update pred const to "[], idtable.length); - asm { int 3; } - } + idmask = bestMask; + memset(idtable.ptr, 0, idtable.length * typeof(idtable[0]).sizeof); resetHash(); foreach (int i, entry; ci) { - static if (PredictedTableLength == -1) int len = idtable.length; - else const len = PredictedTableLength; - idtable[hash(cast(void*) entry) % len] = stuple(cast(void*) entry, i); + idtable[hash(cast(void*) entry) & idmask] = stuple(cast(void*) entry, i); } } @@ -195,9 +194,7 @@ int getId(ClassInfo ci) { if (getIdCache[idx]._0 == cp) return getIdCache[idx]._1; } - static if (PredictedTableLength == -1) int len = idtable.length; - else const len = PredictedTableLength; - auto entry = idtable.ptr[hash(cp) % len]; + auto entry = idtable.ptr[hash(cp) & idmask]; int res = (entry._0 == cp)?entry._1:-1; static if (getIdCacheSize) { auto p = &getIdCache[getIdLoopPtr]; @@ -210,10 +207,26 @@ int getId(ClassInfo ci) { return res; } -const PredictedTableLength = -1; - extern(C) void fastcast_marker() { } +template fastcast_direct(T) { + T fastcast_direct(U)(U u) { + Object obj = void; + // stolen from fastcast + static if (!is(U: Object)) { // interface + auto ptr = **cast(Interface***) u; + void* vp = cast(void*) u - ptr.offset; + obj = *cast(Object*) &vp; + } else { + void* vp = cast(void*) u; + obj = *cast(Object*) &vp; + } + + if (obj.classinfo !is typeid(T)) return null; + return *cast(T*) &obj; // prevent a redundant D cast + } +} + struct _fastcast(T) { const ptrdiff_t INVALID = 0xffff; // magic numbah static ptrdiff_t[quicklist.length] offsets; @@ -229,10 +242,10 @@ struct _fastcast(T) { const string fillObj = ` {static if (!is(U: Object)) { // interface auto ptr = **cast(Interface***) u; - void* vp = *cast(void**) &u - ptr.offset; + void* vp = cast(void*) u - ptr.offset; obj = *cast(Object*) &vp; } else { - void* vp = *cast(void**) &u; + void* vp = cast(void*) u; obj = *cast(Object*) &vp; // prevent a redundant D cast }}`; static if (is(typeof(T.isFinal)) && T.isFinal) { diff --git a/fcc.d b/fcc.d index 0a743294..78392eb3 100644 --- a/fcc.d +++ b/fcc.d @@ -345,7 +345,7 @@ void ast_math_constr() { return fastalloc!(FAbsFExpr)(arg); };*/ Itr substfun(int arity, bool delegate(Function, Module) dg, Expr delegate(Expr[]) dgex, Itr it) { - auto fc = fastcast!(FunCall)(it); + auto fc = fastcast_direct!(FunCall)(it); if (!fc) return null; if (fc.getParams().length != arity) return null; auto mod = fastcast!(Module)(fc.fun.sup); @@ -1130,14 +1130,17 @@ string cpumode() { return ""; } -string get_llc_cmd(bool optimize, bool debugmode, bool saveTemps, ref string fullcommand) { +string get_llc_cmd(bool optimize, bool debugmode, bool saveTemps, ref string fullcommand, ref string tempfile) { string llc_optflags; if (optimize) { void optrun(string flags, string marker = null) { if (marker) marker ~= "."; string optfile = ".obj/"~output~".opt."~marker~"bc"; - fullcommand ~= " |opt "~flags~"-lint -"; - if (saveTemps) fullcommand ~= " |tee "~optfile; + string tempfile2 = ".obj/_all3.bc"; + assert(tempfile != tempfile2); + fullcommand ~= " opt "~flags~"-lint "~tempfile~" -o "~tempfile2~"&&"; + tempfile = tempfile2; + // if (saveTemps) fullcommand ~= " |tee "~optfile; } string fpmathopts = "-enable-fp-mad -enable-no-infs-fp-math -enable-no-nans-fp-math -enable-unsafe-fp-math " "-fp-contract=fast "/*-vectorize */"-vectorize-loops "; @@ -1159,7 +1162,8 @@ string get_llc_cmd(bool optimize, bool debugmode, bool saveTemps, ref string ful } int bashsystem(string s) { - s = "/bin/bash -c \""~s.replace("\"", "\\\"")~"\""; + if (!isWindoze()) + s = "/bin/bash -c \"set -o pipefail; " ~ s.replace("\"", "\\\"")~"\""; return system(s.toStringz()); } @@ -1232,7 +1236,7 @@ string delegate() compile(string file, CompileSettings cs, bool force = false) { if (false && cs.preopt) flags = "-O3 -lint "; // if (platform_prefix.startsWith("arm-")) flags = "-meabi=5"; // auto cmdline = Format(my_prefix(), "as ", flags, " -o ", objname, " ", srcname, " 2>&1"); - string cmdline = "set -o pipefail; "; + string cmdline; if (cs.preopt && !cs.optimize) { cmdline ~= Format("opt ", flags); } else { @@ -1246,7 +1250,7 @@ string delegate() compile(string file, CompileSettings cs, bool force = false) { if (llvmver() == "3.1") { } else if (isARM) march="-march=arm "; else march = "-mattr=-avx,-avx2,-sse41 -march=x86 "; - cmdline ~= Format("-o - ", srcname, " |opt "~march~" - "~get_llc_cmd(cs.optimize, cs.debugMode, cs.saveTemps, bogus)~" |llc "~march~cpumode()~"- -filetype=obj -o ", objname); + cmdline ~= Format("-o - ", srcname, " |opt "~march~" - "~get_llc_cmd(cs.optimize, cs.debugMode, cs.saveTemps, bogus, bogus)~" |llc "~march~cpumode()~"- -filetype=obj -o ", objname); } logSmart!(false)("> (", len_parse, "s,", len_gen, "s,", len_emit, "s) ", cmdline); @@ -1359,14 +1363,16 @@ void link(string[] objects, bool optimize, bool debugmode, bool saveTemps = fals if (!isWindoze && !optimize) { objfile = objlist; } else { - string fullcommand = "set -o pipefail; llvm-link "~objlist; + string fullcommand = "llvm-link "~objlist~" -o .obj/_all.bc && "; - fullcommand ~= " |llvm-dis - |sed -e s/^define\\ weak_odr\\ /define\\ /g -e s/=\\ weak_odr\\ /=\\ /g |llvm-as"; - if (saveTemps) fullcommand ~= " |tee "~linkedfile; + string curtemp = ".obj/_all2.bc"; + fullcommand ~= "llvm-dis .obj/_all.bc -o - |sed -e \"s/^define weak_odr /define /g\" -e \"s/= weak_odr /= /g\" |llvm-as - -o "~curtemp~"&&"; + // if (saveTemps) fullcommand ~= " |tee "~linkedfile; objfile = ".obj/"~output~".o"; // -mattr=-avx,-sse41 - fullcommand ~= " |llc - -mattr=-avx,-avx2,-sse41 "~get_llc_cmd(optimize, debugmode, saveTemps, fullcommand)~"-filetype=obj -o "~objfile; + auto llc_cmd = get_llc_cmd(optimize, debugmode, saveTemps, fullcommand, curtemp); + fullcommand ~= "llc "~curtemp~" -mattr=-avx,-avx2,-sse41 "~llc_cmd~"-filetype=obj -o "~objfile; logSmart!(false)("> ", fullcommand); if (bashsystem(fullcommand)) throw new Exception("link failed"); @@ -1421,12 +1427,15 @@ void incbuild(string start, bool[string] neededRebuild; // prevent issue where we rebuild a mod, after which // it obviously needs no further rebuild, preventing // another module from realizing that it needs to be rebuilt also - bool needsRebuild(Module mod) { + bool[string] needsRebuildCache; + bool delegate(Module) needsRebuild; + bool _needsRebuild(Module mod) { if (mod.dontEmit) return false; auto file = mod.name.undo(); string obj, asmf; file.translate(obj, asmf); + if (file == "sys.nt") file = "fcc.exe"; // contained within file = findfile(file); auto start2 = findfile(start); @@ -1448,9 +1457,17 @@ void incbuild(string start, } return false; } + needsRebuild = delegate bool(Module mod) { + if (auto p = mod.name in needsRebuildCache) return *p; + auto res = _needsRebuild(mod); + needsRebuildCache[mod.name] = res; + return res; + }; + auto drbackup = dontReemit; dontReemit = delegate bool(Module mod) { return !needsRebuild(mod); }; + scope(exit) dontReemit = drbackup; lazySysmod(); try { string[] objs = start.compileWithDepends(cs); diff --git a/hello.nt b/hello.nt index be0332e7..6437191f 100644 --- a/hello.nt +++ b/hello.nt @@ -33,4 +33,7 @@ void main(string[] args) { // import std.process; // writeln readback("cat", ["6"]); int a = -360 % 360; + auto qq = (2, 3, 4); + qq[0..2] = (4, 5); + writeln "$qq"; } diff --git a/llvmtype.d b/llvmtype.d index 5b31d203..cc5040d0 100644 --- a/llvmtype.d +++ b/llvmtype.d @@ -43,8 +43,8 @@ extern(C) int guessSize(IType it) { pragma(set_attribute, llvmvalstr, externally_visible); extern(C) Expr llvmvalstr(string s) { - auto val = my_atoi(s); - if (qformat(val) == s) return mkInt(val); + int val; + if (my_atoi(s, val)) return mkInt(val); return fastalloc!(LLVMValue)(s); } @@ -67,7 +67,8 @@ string eatType(ref string s) { } if (eat("<")) { auto t = s; - auto num = t.slice("x").my_atoi(); + int num; + my_atoi(t.slice("x"), num); if (!eat(qformat(num)) || !eat("x")) { logln("weird vector ", first_s, " at ", s); fail; @@ -81,7 +82,8 @@ string eatType(ref string s) { } if (eat("[")) { auto t = s; - auto num = t.slice("x").my_atoi(); + int num; + my_atoi(t.slice("x"), num); if (!eat(qformat(num)) || !eat("x")) { logln("weird SA ", first_s, " at ", s); fail; @@ -113,7 +115,8 @@ string eatType(ref string s) { string[] getVecTypes(string str) { if (auto rest = str.startsWith("<")) str = rest; else fail; - int len = str.slice("x").my_atoi(); + int len; + my_atoi(str.slice("x"), len); auto type = str.endsWith(">").strip(); if (!type) fail; string[] res = new string[len]; @@ -219,7 +222,9 @@ string eat_canonify(ref string s) { string str = s; if (s1 && s1.length < str.length) str = s1; if (s2 && s2.length < str.length) str = s2; - auto testnum = str.my_atoi(), test = qformat(testnum); + int testnum; + my_atoi(str, testnum); + auto test = qformat(testnum); if (auto rest = s.startsWith(test)) { s = rest; return test; diff --git a/memconserve_stdfile.d b/memconserve_stdfile.d index af8d5485..579842a1 100644 --- a/memconserve_stdfile.d +++ b/memconserve_stdfile.d @@ -6,6 +6,7 @@ import quickformat, std.file, std.date, std.string; version(Win32) { import std.c.windows.windows; + extern(C) void abort(); void getTimes(char[] name, out d_time ftc, out d_time fta, out d_time ftm) { HANDLE findhndl; diff --git a/std/parser.nt b/std/parser.nt index b9ededfc..de78f2e9 100644 --- a/std/parser.nt +++ b/std/parser.nt @@ -31,15 +31,17 @@ context parser { } string gotIdentifier() { cleanup; - string eatAlpha() { - if (!text.length) return null; - string res; - if ("a" <= text[0] <= "z" || "A" <= text[0] <= "Z") (res, text) = text[(0..1, 1..$)]; - return res; + int len; + bool checkAlpha() { + if (len >= text.length) return false; + if ("a" <= text[len] <= "z" || "A" <= text[len] <= "Z") return true; + return false; } - char[auto~] res; - while auto ch = eatAlpha() res ~= ch; - return res[]; + while checkAlpha() len ++; + if (!len) return null; + auto res = text[0 .. len]; + text = text[len .. $]; + return res; } bool gotNumber(int* ip) { cleanup;