JS Optimizations - how much does the code generator assume?

瀏覽次數:12 次
跳到第一則未讀訊息

J Decker

未讀,
2020年3月25日 凌晨1:47:122020/3/25
收件者:v8-users
Say I have this snippet of code.... 

{
var no_overlap = true;//( pd.algorithm == match_types.TwoGroupsNoOver )
//|| ( pd.algorithm == match_types.TwoGroupsPrimeNoOver );
//var prime = ( pd.algorithm == match_types.TwoGroupsPrime )
// || ( pd.algorithm == match_types.TwoGroupsPrimeNoOver );
var g;
var masks = []
var index = [];
var n = 0;
var m = 0;

for( g = 0; g < pd.groups.length; g++ ) {
simple_masks.push( ExpandMods( pd.groups[g].mode_mod, pd.groups[g].masks ) )
index.push(0);
}
do {
var composite = 0;
for( g = 0; g < pd.groups.length; g++ ) {
masks[g] = simple_masks[g][index[g]];
if( no_overlap )
if( composite & masks[g] ) {
break;
}
composite |= masks[g];
}
if( g < pd.groups.length ) {
g++;  // add 1 to g... so 'this' gets incremented
// this faulted, so next iterate.
for( var h = g; h < pd.groups.length; h++ ){
index[h] = 0; // reset all the following counters
}
}
else
composite_masks.push(composite);
// iterate combination set.
index[g-1]++; 
while( g > 0 && ( index[g-1] >= simple_masks[g-1].length ) ) {
if( g > 1 )  // don't reset 0.
index[g-1] = 0;
if( --g > 0 )
index[g-1]++; 
}
if( !g ){
if( index[0] >= simple_masks[0].length )
break;
}
}while(1);
}


This is all algorithmic; no expression calls a function, so a lot of things should be easiliy identifiable as unchanging.

pd.groups.length

for instance comes from 'pd.groups' which will never change during the duration of the above code, and that array within it also would not change, would the length for that be read once at the start?
I've seen compiled code from C (where many compilers apparently assume that everything is at least somewhat volatile (apparently) and reload values of partial expressions even though that same value was just computed in the previous section.  Especially where the number of available scratch registers is plentiful (as opposed to only 4-6) ?

I would hope that I could write visually appealing code like the above and have the guts of the actual code generation do all the clever work; maybe it is a lot of work to do a pattern match in an AST and find all sub-expressions that are exactly the same to coalesce into a single access...



Jakob Kummerow

未讀,
2020年3月25日 清晨5:54:252020/3/25
收件者:v8-users
Yes, V8's optimizing compiler performs "Common Subexpression Elimination".

The number of available registers does matter a lot. We've seen cases where recomputing values when they are needed (somewhat counter-intuitively) yielded better performance than computing them once and keeping them around. In particular, loading a property from an object is not necessarily more expensive than loading it from a spill slot. So when a given compiler's output doesn't match your intuition, it's hard to be sure whether that indicates untapped optimization potential, or whether it actually turns out to be faster that way.

回覆所有人
回覆作者
轉寄
0 則新訊息