digitalmars.D - Possilbe stub func backend related optimization
- davidl (102/102) Mar 13 2008 for stub funcs:
for stub funcs: void error(char[] string) { realerror(1,string); } void realerror(int errortype, char[] string); { // do some thing } while this case inline realerror introduce size bloat. the best optimization is binding these two functions together func_error: push 1; func_realerror: func "error" only pushes the args missing, and it doesn't get any ret code, it returns directly by func_realerror. how semantic analyze work and detect this kind of things? I propose a possible algo. if func.complicateness < MAX_BIND_COMPLICATE then for each callee in func try bind callee with func the try bind callee works in the way of trying nest the callee in the caller. that is it trying to do the following void error(char[] string) { void realerror(int errortype, char[] string); { // do some thing } realerror(1,string); } now we notice the realerror in nested func can be rewritten as void error(char[] stirng) { void realerror(int errortype) { } realerror(1); } there we go, we get the optimized func "error", all we need to do is exposing the nested func as normal func "realerror". why the "realerror" func in such rewritten form is still working? there the realerror accesses parent char[]string in the stack, and it requires the parent func to push errortype to call it, the sequence of pushing params is right in the right-to-left form. So, calling directly to realerror address with original "realerror" params. //psuedo asm code: push string push 3 call realerror it gets the same effect as calling inside the func of "error" Now the algo is almost clear. 1. we try to figure out right-to-left common params with callee and caller. 2. rewrite them in nested func syntax. 3. caller would be naturally optimized by the original flow optimizer the compiler would analyze the flow of func "error". compilers finds out realerror would be called and directly exit after calling realerror(1); so the optimal flow optimizer would optimize the nested func to the optimal assembly. for a more complicated case, error func works in the way like: void error(char[]string) { if (string == "abc") realerror(1, string); else realerror(2, string); another_func(); } if we rewrite it then something goes clearer, and it's possible to reuse current exist optimizer: void error(char[]string) { void realerror(int errortype) { } if (string == "abc") realerror(1); // from code flow analyze we know we can exit directly at this point. so inlining realerror here would optimize out call/retn instructions. else realerror(2); } there the optimal solution is inlining the realerror func in the place of first realerror(1) psuedo codegen would be: if (string == "abc") push 1 realerror_func_entry_point: inlined realerror native code // this inlining doesn't consider any cost. because realerror func would always require some place to store it. else push 2 call realerror_func_entry_point retn From this case, we see in the rewriten nested func form , we get the chance of inlining the "realerror" freely for the very first time. This optimization still applies for real nested func optimization. so if we really gets the nested func, this optimization applies to the real nested func case. -- 使用 Opera 革命性的电子邮件客户程序: http://www.opera.com/mail/
Mar 13 2008