Changeset 172

Show
Ignore:
Timestamp:
01/10/08 02:48:44 (8 months ago)
Author:
Don Clugston
Message:

Added sqrt intrinsic, with codegen for both X87 and SSE.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/blade/BladeDemo.d

    r171 r172  
    6060   mixin(vectorize("u = sum(abs(-p))")); 
    6161   mixin(vectorize("a = -a")); 
     62   mixin(vectorize("u = sum(sqrt(abs(p))) + sum(sqrt(abs(q)))")); 
    6263 
    6364    writefln("a=", a); 
  • trunk/blade/BladeRank.d

    r171 r172  
    111111            "Extra characters after array literal", 
    112112            "Rank mismatch in array literal", 
    113             "Can only use abs with scalar or vector" 
     113            "Can only use abs, sqrt with scalar or vector" 
    114114            ][-err-1]; 
    115115} 
     
    125125    } 
    126126    ReturnType onVisitFunction(This this_, char [] func, char [][] args) { 
    127         if (func=="dot") { // dot product 
     127        switch(func) { 
     128        case "dot": 
    128129            if (args.length!=2) return RankError.CommaExpected; 
    129130            auto lrank = doVisit(this_,args[0]); 
     
    133134            if (lrank!=1 || rrank!=1) return RankError.RankMismatchDotProduct;        
    134135            return 0; 
    135         } else if (func=="sum") { 
     136        case "sum": 
    136137            auto lrank = doVisit(this_,args[0]); 
    137138            if (lrank<0) return lrank; // propagate errors 
    138139            return 0; 
    139         } else if (func=="abs") { 
     140        case "abs": 
     141        case "sqrt": 
    140142            auto lrank = doVisit(this_,args[0]); 
    141143            if (lrank>1) return RankError.AbsDimensionality; 
    142144            return 0; 
     145        default: 
     146            assert(0, "BLADE ICE: Unsupported function:" ~ func); 
     147            return 0; 
    143148        }         
    144         assert(0, "BLADE ICE: Unsupported function:" ~ func); 
    145         return 0; 
    146149    } 
    147150    ReturnType onVisitPrefix(This this_, char [] op, char [] expr) { 
  • trunk/blade/BladeSimplify.d

    r171 r172  
    5151bool isBladeIntrinsic(char [] str) 
    5252{ 
    53     return str=="dot" || str=="sum" || str=="abs"
     53    return str=="dot" || str=="sum" || str=="abs" || str=="sqrt"
    5454} 
    5555 
     
    284284        switch (func) { 
    285285            case "dot": 
    286                 // Each element is reduced seperately 
     286                // 2-argument functions 
    287287                char [] left = wrapInParens(doVisit(this_,args[0])); 
    288288                char [] right = wrapInParens(doVisit(this_, args[1])); 
    289289                return func ~ "(" ~ left ~ "," ~ right ~ ")"; 
    290290            case "sum": 
     291            case "sqrt": 
    291292            case "abs": 
     293                // 1-argument functions 
    292294                char [] left = wrapInParens(doVisit(this_,args[0])); 
    293295                return func ~ "(" ~ left ~ ")";             
     
    465467        switch(func) { 
    466468        case "dot": 
     469            // dot(a*v1, c*v2) == (a*b)*dot(v1, v2) 
     470            // this is a scalar, but the dot is a nested expression 
    467471            ScalarFold left = doVisit(this_,args[0]); 
    468472            ScalarFold right = doVisit(this_, args[1]); 
    469473            return ScalarFold("", combineMul(combineMul(left.multiplier, right.multiplier), "{" ~ func ~ "(" ~ wrapInParens(left.expr) ~ "," ~ wrapInParens(right.expr) ~ ")}")); 
    470474        case "sum":  
     475            // Functions where f(v) is a scalar. 
    471476            ScalarFold left = doVisit(this_,args[0]); 
    472477            return ScalarFold("", combineMul(left.multiplier, "{" ~ func ~ "(" ~ wrapInParens(left.expr) ~ ")}")); 
    473         case "abs": 
     478        case "abs":             
     479            // f(a*v)==f(a)*f(v), and f(-v)==f(v) 
    474480            ScalarFold left = doVisit(this_,args[0]); 
    475481            return ScalarFold((left.expr!="" ? func ~ "(" ~ wrapInParens(left.expr) ~ ")" : ""), (left.multiplier.length>0 && left.multiplier!="-")? func ~ "(" ~ wrapInParens(left.multiplier) ~ ")":""); 
     482        case "sqrt": 
     483            // There's a reduction in precision if we use f(a*v)==f(a)*f(v); also 
     484            // a and b could both be negative. 
     485            ScalarFold left = doVisit(this_,args[0]); 
     486            return ScalarFold((left.expr!="" ? func ~ "(" ~ wrapInParens(left.expr) ~ ")" : ""), (left.multiplier.length>0)? func ~ "(" ~ wrapInParens(left.multiplier) ~ ")":""); 
    476487        default: 
    477488            assert(0, "BLADE: Unsupported function"); 
     
    600611    assert(foldScalars("A*=-(-B)", "10")=="A*={(-(-B))}"); 
    601612    assert(foldScalars("sum((A*sum(A)))", "1")=="({sum(A)})*({sum(A)})"); 
    602 
     613    assert(foldScalars("abs((A*abs(B)))", "10")=="(abs(A))*{(abs((abs(B))))}"); 
     614    assert(foldScalars("abs((-A))", "1")=="abs(A)"); 
     615
  • trunk/blade/CodegenX86.d

    r171 r172  
    308308            ranklist~="1"; 
    309309            typelist ~= typeof(T.data[0]).stringof; 
    310         }else { 
     310        } else { 
    311311            stridelist~="0"; 
    312312            ranklist~="0"; 
     
    392392    while(done<operations.length) { 
    393393        char [] next; 
    394       if (isInstruction(operations[done])) { 
     394        if (isInstruction(operations[done])) { 
    395395            // Perform an arithmetic operation on the top two FPU stack items. 
    396396            next = "  " ~ opToX87[operations[done]] ~ "p ST(1), ST;  //" ~ operations[done] ~ \n; 
     
    398398            ++done; 
    399399            numOnStack--; 
    400       } else if (operations[done]=='a') { 
    401           mainbody ~= "  fabs;"\n; 
    402           ++done; 
    403       } else if (operations[done]=='n') { 
    404         mainbody ~= "  fchs;"\n; 
    405         ++done; 
    406       } else if (!isInstruction(operations[done+1])){ 
     400        } else if (operations[done]=='a') { 
     401            mainbody ~= "  fabs;"\n; 
     402            ++done; 
     403        } else if (operations[done]=='n') { 
     404            mainbody ~= "  fchs;"\n; 
     405            ++done; 
     406        } else if (operations[done]=='q') { 
     407            mainbody ~= "  fsqrt;"\n; 
     408            ++done; 
     409        } else if (!isInstruction(operations[done+1])){ 
    407410            // load a vector onto the FPU stack, to begin a new subexpression. 
    408411            int u  = operations[done]-'A'; 
     
    415418            ++done; 
    416419            numOnStack++; 
    417       } else if (operations[done]==',') { 
    418           mainbody ~= "  " ~ opToX87[operations[done+1]] ~ " ST, ST(0);    // dup " ~ operations[done+1] ~ \n; 
    419           done+=2;           
    420       } else if (ranklist[operations[done]-'A']=='1') { 
     420        } else if (operations[done]==',') { 
     421            mainbody ~= "  " ~ opToX87[operations[done+1]] ~ " ST, ST(0);    // dup " ~ operations[done+1] ~ \n; 
     422            done+=2;           
     423        } else if (ranklist[operations[done]-'A']=='1') { 
    421424             // An operation will be performed between the stack top and a vector. 
    422425             // If it's a float or double, we can combine the load+arithmetic op 
     
    432435                next = "  fld real ptr ["  ~ vectorRegister[vectorNum(ranklist, operations[done])] ~ "]; //" ~ operations[done] ~ \n 
    433436                    ~ "  " ~ opToX87[operations[done+1]] ~ "p ST(1), ST; //" ~ operations[done+1] ~\n; 
    434             } else { // floats and doubles can be used directly 
     437            } else { // floats and doubles can be used directly 
    435438                next = "  " ~ opToX87[operations[done+1]] ~ " " 
    436439                  ~ indexedVector(typelist, ranklist, stridelist, operations[done] ) ~ comment; 
     
    438441            mainbody ~= next; 
    439442            done+=2; 
    440       } else { // multiply by scalar. 
    441         if (typelist[operations[done]-'A']=="real") { 
    442             // Multiply by real scalar, which is already on the stack. 
    443             next = "  fmul ST, ST(" ~ itoa(numOnStack + numScalarsOnStack - realScalarNum(typelist, ranklist, operations[done]-'A')-1) ~ "); // * " ~ operations[done] ~ \n; 
    444             mainbody ~= next;             
    445         } else { 
     443        } else { // multiply by scalar. 
     444          if (typelist[operations[done]-'A']=="real") { 
     445            // Multiply by real scalar, which is already on the stack. 
     446            next = "  fmul ST, ST(" ~ itoa(numOnStack + numScalarsOnStack - realScalarNum(typelist, ranklist, operations[done]-'A')-1) ~ "); // * " ~ operations[done] ~ \n; 
     447            mainbody ~= next;             
     448          } else { 
    446449            // For scalar float or double values, we can multiply directly, saving one slot on the FP stack. 
    447450            next = "  fmul " ~ operandSize(typelist[operations[done]-'A']) ~ "values[" ~ itoa(operations[done]-'A') ~"]; // * " ~ operations[done..done+1] ~ "\n"; 
    448451            mainbody ~= next; //firstbody ~= next; 
    449        
    450         done +=2; 
    451       }       
     452         
     453            done +=2; 
     454        }       
    452455    } 
    453456         
     
    562565        "  jz short L2; // test for length==0"\n; 
    563566    while(done<operations.length) { 
    564       char [] comment; 
    565       if (isInstruction(operations[done])) { 
     567        char [] comment; 
     568        if (isInstruction(operations[done])) { 
    566569            // Perform an arithmetic operation on the top two items. 
    567570            comment = ";  //" ~ operations[done] ~ \n; 
     
    570573            ++done; 
    571574            numOnStack--; 
    572       } else if (operations[done]=='a') { // abs 
    573           mainbody ~= "  andp" ~ suffix ~ XMM(numOnStack-1) ~ ", SSE_SIGNMASKp" ~ suffix ~";  // abs"\n; 
    574           extra ~= "  andp" ~ suffix ~ XMM(numOnStack-1) ~ ", SSE_SIGNMASKp" ~ suffix ~ ";  // abs"\n; 
    575           ++done; 
    576       } else if (operations[done]=='n') { // neg 
    577           mainbody ~= "  xorp" ~ suffix ~ XMM(numOnStack-1) ~ ", SSE_SIGNBITp" ~ suffix ~";  // negate"\n; 
    578           extra ~= "  xorp" ~ suffix ~ XMM(numOnStack-1) ~ ", SSE_SIGNBITp" ~ suffix ~ ";  // negate"\n; 
    579           ++done; 
    580       } else if (!isInstruction(operations[done+1])){ 
     575        } else if (operations[done]=='a') { // abs 
     576            mainbody ~= "  andp" ~ suffix ~ XMM(numOnStack-1) ~ ", SSE_SIGNMASKp" ~ suffix ~";  // abs"\n; 
     577            extra ~= "  andp" ~ suffix ~ XMM(numOnStack-1) ~ ", SSE_SIGNMASKp" ~ suffix ~ ";  // abs"\n; 
     578            ++done; 
     579        } else if (operations[done]=='n') { // neg 
     580            mainbody ~= "  xorp" ~ suffix ~ XMM(numOnStack-1) ~ ", SSE_SIGNBITp" ~ suffix ~";  // negate"\n; 
     581            extra ~= "  xorp" ~ suffix ~ XMM(numOnStack-1) ~ ", SSE_SIGNBITp" ~ suffix ~ ";  // negate"\n; 
     582            ++done; 
     583        } else if (operations[done]=='q') { // sqrt 
     584            mainbody ~= "  sqrtp" ~ suffix ~ XMM(numOnStack-1) ~ "," ~ XMM(numOnStack-1) ~ "; // sqrt"\n; 
     585            extra ~= "  sqrts" ~ suffix ~ XMM(numOnStack-1) ~ "," ~ XMM(numOnStack-1) ~ "; // sqrt"\n; 
     586            ++done; 
     587        } else if (!isInstruction(operations[done+1])){ 
    581588            // load a vector onto the FPU stack, to begin a new subexpression. 
    582589            comment = ";  // " ~ operations[done] ~ \n; 
     
    585592            ++done; 
    586593            numOnStack++; 
    587       } else if (operations[done]==',') { 
     594        } else if (operations[done]==',') { 
    588595                // operation on self, eg XX+ --> don't need to load it again. 
    589596                comment = ";  // " ~ operations[done..done+2] ~ \n; 
     
    593600                    ~ XMM(numOnStack-1) ~ comment; 
    594601                done +=2;           
    595       } else if (ranklist[operations[done]-'A']=='1') { 
     602        } else if (ranklist[operations[done]-'A']=='1') { 
    596603             // An operation will be performed between the stack top and a vector. 
    597604            comment = ";  // " ~ operations[done..done+2] ~ \n; 
     
    606613            } 
    607614            done+=2; 
    608       } else { // multiply by scalar. 
     615        } else { // multiply by scalar. 
    609616            comment = "; // " ~operations[done..done+2] ~ \n; 
    610617            int u = scalarNum(ranklist, operations[done]-'A'); 
     
    612619            extra ~= "  " ~ opToSSESingle[operations[done+1]] ~ suffix ~ XMM(numOnStack-1) ~ ", " ~ XMM(u) ~ comment; 
    613620            done +=2; 
    614       }       
     621        }       
    615622    } 
    616623         
  • trunk/blade/PostfixX86.d

    r171 r172  
    5757    } 
    5858    ReturnType onVisitFunction(This this_, char [] func, char [][] args) { 
    59         if (func=="dot") { 
    60             return "0" ~ doVisit(this_,args[0]) ~ doVisit(this_, args[1]) ~ "*+"; 
    61         } 
    62         if (func=="sum") return "0" ~ doVisit(this_, args[0]) ~ "+"; 
    63         if (func=="abs") return doVisit(this_,args[0]) ~ "a"; 
    64         assert(0, "BLADE ICE: Unsupported"); 
     59        switch(func) { 
     60        case "dot": 
     61            char [] left = doVisit(this_,args[0]); 
     62            char [] right = doVisit(this_, args[1]); 
     63            if (left==right) return "0" ~ left ~ ",*+"; 
     64            return "0" ~ left ~ right ~ "*+"; 
     65        case "sum": 
     66            return "0" ~ doVisit(this_, args[0]) ~ "+"; 
     67        case "abs": return doVisit(this_,args[0]) ~ "a"; 
     68        case "sqrt": return doVisit(this_,args[0]) ~ "q"; 
     69        default:     assert(0, "BLADE ICE: Unsupported"); 
     70        } 
    6571    } 
    6672    ReturnType onVisitPrefix(This this_, char [] op, char [] expr) { 
     
    136142    } 
    137143    ReturnType onVisitFunction(This this_, char [] func, char [][] args) {       
    138         if (func=="dot") { 
    139             return "0" ~ doVisit(this_,args[0]) ~ doVisit(this_, args[1]) ~ "*+"; 
    140         } 
    141         if (func=="sum") return "0" ~ doVisit(this_, args[0]) ~ "+"; 
    142         if (func=="abs") return doVisit(this_,args[0]) ~ "a"; 
    143         assert(0, "BLADE ICE: Unsupported"); 
     144        switch(func) { 
     145        case "dot": 
     146            char [] left = doVisit(this_,args[0]); 
     147            char [] right = doVisit(this_, args[1]); 
     148            if (left==right) return "0" ~ left ~ ",*+"; 
     149            return "0" ~ left ~ right ~ "*+"; 
     150        case "sum": 
     151            return "0" ~ doVisit(this_, args[0]) ~ "+"; 
     152        case "abs": return doVisit(this_,args[0]) ~ "a"; 
     153        case "sqrt": return doVisit(this_,args[0]) ~ "q"; 
     154        default:   assert(0, "BLADE ICE: Unsupported"); 
     155        } 
    144156    } 
    145157    ReturnType onVisitPrefix(This this_, char [] op, char [] expr) {