Changeset 171

Show
Ignore:
Timestamp:
01/08/08 07:11:22 (8 months ago)
Author:
Don Clugston
Message:

Added abs() intrinsic. Added codegen for unary minus. Bugfix for rank error messages. Bugfix for A=A.

Files:

Legend:

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

    r170 r171  
    1313* 
    1414* FEATURES: 
    15 *  - Supports any mix of vector addition, subtraction, dot product, slicing, and 
    16 *    multiplication by a scalar
     15*  - Supports any mix of vector addition, subtraction, dot product, unary minus, 
     16*    multiplication by a scalar, sum(), abs(), and multidimensional slicing
    1717*  - Generates either x87 asm code, SSE or SSE2 asm code or pure D, depending on 
    1818*    the complexity of the expression, and the availability of inline asm. 
     
    143143} 
    144144 
     145private: 
     146// Masks for setting or clearing the signbit in SSE registers. 
     147static ulong[2] SSE_SIGNMASKpd = [0x7FFF_FFFF_FFFF_FFFFL, 0x7FFF_FFFF_FFFF_FFFFL]; 
     148static uint[4] SSE_SIGNMASKps = [0x7FFF_FFFF, 0x7FFF_FFFF, 0x7FFF_FFFF, 0x7FFF_FFFF]; 
     149static ulong[2] SSE_SIGNBITpd = [0x8000_0000_0000_0000L, 0x8000_0000_0000_0000L]; 
     150static uint[4] SSE_SIGNBITps = [0x8000_0000,0x8000_0000,0x8000_0000, 0x8000_0000]; 
    145151 
    146152private: 
  • trunk/blade/BladeDemo.d

    r169 r171  
    4242    mixin(vectorize("a+=6*another[1,0..$]")); 
    4343    mixin(vectorize("a+=6*(another[1,0..$]+another[1,0..$])")); 
     44   
    4445 
    4546    mixin(vectorize("a+=6*another[1][0..$]")); 
     
    5253    mixin(vectorize("another[0..$,1]=6*a[0..2]")); 
    5354 
    54 // Simplifies to q*= 2*dot(q,q)*dot(q*q). 
     55// Simplifies to q*= 2*dot(q,q)*dot(q,q). 
    5556   mixin(vectorize("q *=dot(q,q*dot(2*q,q))")); 
    5657   double u; 
    5758   mixin(vectorize("u = dot(q,q*dot(q,q))")); 
    5859   mixin(vectorize("u = dot(a, q)")); 
    59    mixin(vectorize("u = sum(a)")); 
     60   mixin(vectorize("u = sum(abs(-p))")); 
     61   mixin(vectorize("a = -a")); 
    6062 
    6163    writefln("a=", a); 
  • trunk/blade/BladeRank.d

    r169 r171  
    9393    RankMismatchDotProduct = -10, 
    9494    ExtraCharsAfterArrayLiteral = -11, 
    95     ArrayLiteralRankMismatch = -12 
     95    ArrayLiteralRankMismatch = -12, 
     96    AbsDimensionality = -13 
    9697} 
    9798 
     
    107108            "Dimensionality mismatch (addition or subtraction)", 
    108109            "Dimensionality mismatch in concatenation", 
    109             "Dimenionality error in dot product" 
    110             "Extra characters after array literal" 
    111             "Rank mismatch in array literal" 
     110            "Dimenionality error in dot product", 
     111            "Extra characters after array literal", 
     112            "Rank mismatch in array literal", 
     113            "Can only use abs with scalar or vector" 
    112114            ][-err-1]; 
    113115} 
     
    135137            if (lrank<0) return lrank; // propagate errors 
    136138            return 0; 
    137         } 
     139        } else if (func=="abs") { 
     140            auto lrank = doVisit(this_,args[0]); 
     141            if (lrank>1) return RankError.AbsDimensionality; 
     142            return 0; 
     143        }         
    138144        assert(0, "BLADE ICE: Unsupported function:" ~ func); 
    139145        return 0; 
  • trunk/blade/BladeSimplify.d

    r169 r171  
    5151bool isBladeIntrinsic(char [] str) 
    5252{ 
    53     return str=="dot" || str=="sum"
     53    return str=="dot" || str=="sum" || str=="abs"
    5454} 
    5555 
     
    9090    int numdups=0; 
    9191    char [] mapping = ""; // The new letter which this symbol should become, 
    92                          // or '!' if it is an intrinsic 
     92                          // or '!' if it is an intrinsic 
    9393    for (int i=0; i<tree.symbolTable.length; ++i) { 
    9494        char c = 'A'+i; 
     
    112112        char c = tree.expression[i]; 
    113113        if (c>='A' && c<='Z') { 
    114            if (mapping[c-'A']=='!') e~=tree.symbolTable[c-'A'].value; 
    115            else e~= mapping[c-'A']; 
     114            if (mapping[c-'A']=='!') e~=tree.symbolTable[c-'A'].value; 
     115            else e~= mapping[c-'A']; 
    116116        } else e~=c; 
    117117    } 
     
    281281       } 
    282282    } 
    283     ReturnType onVisitFunction(This this_, char [] func, char [][] args) {         
    284         if (func=="dot") { // dot product. 
    285             // Each element is reduced seperately 
    286             char [] left = wrapInParens(doVisit(this_,args[0])); 
    287             char [] right = wrapInParens(doVisit(this_, args[1])); 
    288             return func ~ "(" ~ left ~ "," ~ right ~ ")"; 
    289         } else if (func=="sum") { 
    290             char [] left = wrapInParens(doVisit(this_,args[0])); 
    291             return func ~ "(" ~ left ~ ")"; 
    292         } 
    293         assert(0, "BLADE ICE: Unsupported function"); 
    294         return ""; 
     283    ReturnType onVisitFunction(This this_, char [] func, char [][] args) { 
     284        switch (func) { 
     285            case "dot": 
     286                // Each element is reduced seperately 
     287                char [] left = wrapInParens(doVisit(this_,args[0])); 
     288                char [] right = wrapInParens(doVisit(this_, args[1])); 
     289                return func ~ "(" ~ left ~ "," ~ right ~ ")"; 
     290            case "sum": 
     291            case "abs": 
     292                char [] left = wrapInParens(doVisit(this_,args[0])); 
     293                return func ~ "(" ~ left ~ ")";             
     294            default: 
     295                assert(0, "BLADE ICE: Unsupported function"); 
     296                return ""; 
     297        } 
    295298    } 
    296299    ReturnType onVisitPrefix(This this_, char [] op, char [] expr) { 
    297300        assert(this_.slicing.length==0, "BLADE ICE"); 
    298         return op ~ doVisit(this_, expr);         
     301        return op ~ wrapInParens(doVisit(this_, expr)); 
    299302    } 
    300303    ReturnType onVisitPostfix(This this_, char [] op, char [] expr) { 
    301304        assert(this_.slicing.length==0, "BLADE ICE"); 
    302         return doVisit(this_, expr) ~ op; 
     305        return wrapInParens(doVisit(this_, expr)) ~ op; 
    303306    } 
    304307    // Includes multi-dimensional slicing and indexing.     
     
    459462        else return ScalarFold(sym, ""); 
    460463    } 
    461     ReturnType onVisitFunction(This this_, char [] func, char [][] args) {         
    462         if (func=="dot") { // dot product. 
     464    ReturnType onVisitFunction(This this_, char [] func, char [][] args) { 
     465        switch(func) { 
     466        case "dot": 
    463467            ScalarFold left = doVisit(this_,args[0]); 
    464468            ScalarFold right = doVisit(this_, args[1]); 
    465469            return ScalarFold("", combineMul(combineMul(left.multiplier, right.multiplier), "{" ~ func ~ "(" ~ wrapInParens(left.expr) ~ "," ~ wrapInParens(right.expr) ~ ")}")); 
    466         } else if (func=="sum") { 
     470        case "sum":  
    467471            ScalarFold left = doVisit(this_,args[0]); 
    468472            return ScalarFold("", combineMul(left.multiplier, "{" ~ func ~ "(" ~ wrapInParens(left.expr) ~ ")}")); 
    469         } else { 
     473        case "abs": 
     474            ScalarFold left = doVisit(this_,args[0]); 
     475            return ScalarFold((left.expr!="" ? func ~ "(" ~ wrapInParens(left.expr) ~ ")" : ""), (left.multiplier.length>0 && left.multiplier!="-")? func ~ "(" ~ wrapInParens(left.multiplier) ~ ")":""); 
     476        default: 
    470477            assert(0, "BLADE: Unsupported function"); 
    471478            return ScalarFold("",""); 
     
    483490        } else { 
    484491            ScalarFold f = doVisit(this_, expr); 
    485             assert(f.expr==""); 
     492            assert(f.expr=="", "BLADE ICE: Prefix error" ~ op ~ " " ~ expr); 
    486493            return ScalarFold("", op ~ wrapInParens(f.multiplier)); 
    487494        } 
  • trunk/blade/CodegenX86.d

    r170 r171  
    3838* This string is converted to postfix. The postfix string is converted to 
    3939* a string containing x87 asm, which is then mixed into a function which accepts the tuple. 
    40 * 
    4140*/ 
    4241 
     
    4443 * POTENTIAL FROM RECENT INSTRUCTION SETS: 
    4544 * SSE5(AMD): fmaddpd can dramatically improve both performance and accuracy. 
    46  * SSE4(Intel): dppd has limited use. 
     45 * SSE4(Intel): dppd has some limited use. 
    4746 */ 
    4847 
     
    399398            ++done; 
    400399            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; 
    401406      } else if (!isInstruction(operations[done+1])){ 
    402407            // load a vector onto the FPU stack, to begin a new subexpression. 
     
    498503 
    499504private: 
     505 
    500506// split off from the template to make code coverage work 
    501507char [] generateCodeForSSEImpl(bool usingDoubles, char [] ranklist, char [] operations, char cumulatingOp=0) 
     
    564570            ++done; 
    565571            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; 
    566580      } else if (!isInstruction(operations[done+1])){ 
    567581            // load a vector onto the FPU stack, to begin a new subexpression. 
     
    571585            ++done; 
    572586            numOnStack++; 
     587      } else if (operations[done]==',') { 
     588                // operation on self, eg XX+ --> don't need to load it again. 
     589                comment = ";  // " ~ operations[done..done+2] ~ \n; 
     590                mainbody ~= "  " ~ opToSSE[operations[done+1]] ~ suffix ~ " " ~ XMM(numOnStack-1) ~ ", " 
     591                     ~ XMM(numOnStack-1) ~ comment; 
     592                extra ~= "  " ~ opToSSESingle[operations[done+1]] ~ suffix ~ " " ~ XMM(numOnStack-1) ~ ", " 
     593                    ~ XMM(numOnStack-1) ~ comment; 
     594                done +=2;           
    573595      } else if (ranklist[operations[done]-'A']=='1') { 
    574596             // An operation will be performed between the stack top and a vector. 
     
    577599                 mainbody ~= "  movap" ~ suffix ~ indexedSSEVector(ranklist, operations[$-2], vectorsize) ~ ", XMM" ~ itoa(numOnStack-1) ~ comment; 
    578600                 extra ~= "  movs" ~ suffix ~ indexedSSENext(ranklist, operations[$-2], vectorsize) ~ ", XMM" ~ itoa(numOnStack-1) ~ comment; 
    579             } else  
    580             if (operations[done-1]==operations[done]) { 
    581                 // operation on self, eg XX+ --> don't need to load it again. 
    582                 int cumvector = (operations[done-1]=='0')? numScalarsOnStack : numOnStack-1; 
    583                 mainbody ~= "  " ~ opToSSE[operations[done+1]] ~ suffix ~ " " ~ XMM(numOnStack-1) ~ ", " 
    584                      ~ XMM(numOnStack-1) ~ comment; 
    585                 extra ~= "  " ~ opToSSESingle[operations[done+1]] ~ suffix ~ " " ~ XMM(numOnStack-1) ~ ", " 
    586                     ~ XMM(numOnStack-1) ~ comment;             
    587601            } else { 
    588602                mainbody ~= "  " ~ opToSSE[operations[done+1]] ~ suffix ~ " " ~ XMM(numOnStack-1) ~ ", " 
  • trunk/blade/PostfixX86.d

    r170 r171  
    1414*  _            ST(1)-ST(0) and pop stack 
    1515*  =            store stack top and pop stack 
     16*  ,            duplicate stack top (so ,* means ST=ST*ST, ,+ means ST*=2) 
     17*  a            abs 
     18*  n            unary negation 
    1619* 
    1720*  NOT YET IMPLEMENTED: 
    1821*  1            the literal one (used to initialize a product, for example) 
    19 *  sc           ST(0) = sine(ST(0)) ST(0) = cos(ST(0)) 
    20 *  q            ST(0) = sqrt(ST(0)) 
     22*  sc           sin, cos 
     23*  q            sqrt 
    2124*/ 
    2225 
     
    5760            return "0" ~ doVisit(this_,args[0]) ~ doVisit(this_, args[1]) ~ "*+"; 
    5861        } 
     62        if (func=="sum") return "0" ~ doVisit(this_, args[0]) ~ "+"; 
     63        if (func=="abs") return doVisit(this_,args[0]) ~ "a"; 
    5964        assert(0, "BLADE ICE: Unsupported"); 
    6065    } 
    6166    ReturnType onVisitPrefix(This this_, char [] op, char [] expr) { 
     67        if (op=="-") return doVisit(this_, expr) ~ "n"; // unary minus 
    6268        assert(0, "BLADE ICE: Unsupported"); 
    6369    } 
     
    134140        } 
    135141        if (func=="sum") return "0" ~ doVisit(this_, args[0]) ~ "+"; 
     142        if (func=="abs") return doVisit(this_,args[0]) ~ "a"; 
    136143        assert(0, "BLADE ICE: Unsupported"); 
    137144    } 
    138145    ReturnType onVisitPrefix(This this_, char [] op, char [] expr) { 
     146        if (op=="-") return doVisit(this_, expr) ~ "n"; // unary minus 
    139147        assert(0, "BLADE ICE: Unsupported"); 
    140148    } 
     
    157165            return second ~ first ~ "="; 
    158166        } 
     167        if (second == first) return first ~ "," ~ op; 
    159168         
    160169        // SSE OPTIMISATION #1 
  • trunk/blade/SyntaxTree.d

    r157 r171  
    178178            } 
    179179            if (symbol.length>0) { 
    180                 // Find it, and add it to the symbol table if not already present. 
    181                 int k=0; 
    182                 while(k < symbols.length && symbol!=symbols[k]) ++k; 
    183                 code ~= cast(char)('A' + k); 
    184                 if (k==symbols.length) { 
    185                    symbols ~= symbol; 
    186                 } 
    187                symbol=""; 
     180               // Add the new symbol to the symbol table 
     181               code ~= cast(char)('A' + symbols.length); 
     182               symbols ~= symbol;                
     183               symbol = ""; 
    188184           } 
    189185           if (c=='.') { // it was opSlice. Skip the next . as well. 
     
    217213    return symbols; 
    218214} 
    219  
    220215 
    221216//  ==== SYNTAX PASS ====