Changeset 172
- Timestamp:
- 01/10/08 02:48:44 (8 months ago)
- Files:
-
- trunk/blade/BladeDemo.d (modified) (1 diff)
- trunk/blade/BladeRank.d (modified) (3 diffs)
- trunk/blade/BladeSimplify.d (modified) (4 diffs)
- trunk/blade/CodegenX86.d (modified) (12 diffs)
- trunk/blade/PostfixX86.d (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/blade/BladeDemo.d
r171 r172 60 60 mixin(vectorize("u = sum(abs(-p))")); 61 61 mixin(vectorize("a = -a")); 62 mixin(vectorize("u = sum(sqrt(abs(p))) + sum(sqrt(abs(q)))")); 62 63 63 64 writefln("a=", a); trunk/blade/BladeRank.d
r171 r172 111 111 "Extra characters after array literal", 112 112 "Rank mismatch in array literal", 113 "Can only use abs with scalar or vector"113 "Can only use abs, sqrt with scalar or vector" 114 114 ][-err-1]; 115 115 } … … 125 125 } 126 126 ReturnType onVisitFunction(This this_, char [] func, char [][] args) { 127 if (func=="dot") { // dot product 127 switch(func) { 128 case "dot": 128 129 if (args.length!=2) return RankError.CommaExpected; 129 130 auto lrank = doVisit(this_,args[0]); … … 133 134 if (lrank!=1 || rrank!=1) return RankError.RankMismatchDotProduct; 134 135 return 0; 135 } else if (func=="sum") {136 case "sum": 136 137 auto lrank = doVisit(this_,args[0]); 137 138 if (lrank<0) return lrank; // propagate errors 138 139 return 0; 139 } else if (func=="abs") { 140 case "abs": 141 case "sqrt": 140 142 auto lrank = doVisit(this_,args[0]); 141 143 if (lrank>1) return RankError.AbsDimensionality; 142 144 return 0; 145 default: 146 assert(0, "BLADE ICE: Unsupported function:" ~ func); 147 return 0; 143 148 } 144 assert(0, "BLADE ICE: Unsupported function:" ~ func);145 return 0;146 149 } 147 150 ReturnType onVisitPrefix(This this_, char [] op, char [] expr) { trunk/blade/BladeSimplify.d
r171 r172 51 51 bool isBladeIntrinsic(char [] str) 52 52 { 53 return str=="dot" || str=="sum" || str=="abs" ;53 return str=="dot" || str=="sum" || str=="abs" || str=="sqrt"; 54 54 } 55 55 … … 284 284 switch (func) { 285 285 case "dot": 286 // Each element is reduced seperately286 // 2-argument functions 287 287 char [] left = wrapInParens(doVisit(this_,args[0])); 288 288 char [] right = wrapInParens(doVisit(this_, args[1])); 289 289 return func ~ "(" ~ left ~ "," ~ right ~ ")"; 290 290 case "sum": 291 case "sqrt": 291 292 case "abs": 293 // 1-argument functions 292 294 char [] left = wrapInParens(doVisit(this_,args[0])); 293 295 return func ~ "(" ~ left ~ ")"; … … 465 467 switch(func) { 466 468 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 467 471 ScalarFold left = doVisit(this_,args[0]); 468 472 ScalarFold right = doVisit(this_, args[1]); 469 473 return ScalarFold("", combineMul(combineMul(left.multiplier, right.multiplier), "{" ~ func ~ "(" ~ wrapInParens(left.expr) ~ "," ~ wrapInParens(right.expr) ~ ")}")); 470 474 case "sum": 475 // Functions where f(v) is a scalar. 471 476 ScalarFold left = doVisit(this_,args[0]); 472 477 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) 474 480 ScalarFold left = doVisit(this_,args[0]); 475 481 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) ~ ")":""); 476 487 default: 477 488 assert(0, "BLADE: Unsupported function"); … … 600 611 assert(foldScalars("A*=-(-B)", "10")=="A*={(-(-B))}"); 601 612 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 308 308 ranklist~="1"; 309 309 typelist ~= typeof(T.data[0]).stringof; 310 } else {310 } else { 311 311 stridelist~="0"; 312 312 ranklist~="0"; … … 392 392 while(done<operations.length) { 393 393 char [] next; 394 if (isInstruction(operations[done])) {394 if (isInstruction(operations[done])) { 395 395 // Perform an arithmetic operation on the top two FPU stack items. 396 396 next = " " ~ opToX87[operations[done]] ~ "p ST(1), ST; //" ~ operations[done] ~ \n; … … 398 398 ++done; 399 399 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])){ 407 410 // load a vector onto the FPU stack, to begin a new subexpression. 408 411 int u = operations[done]-'A'; … … 415 418 ++done; 416 419 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') { 421 424 // An operation will be performed between the stack top and a vector. 422 425 // If it's a float or double, we can combine the load+arithmetic op … … 432 435 next = " fld real ptr [" ~ vectorRegister[vectorNum(ranklist, operations[done])] ~ "]; //" ~ operations[done] ~ \n 433 436 ~ " " ~ opToX87[operations[done+1]] ~ "p ST(1), ST; //" ~ operations[done+1] ~\n; 434 } else { // floats and doubles can be used directly437 } else { // floats and doubles can be used directly 435 438 next = " " ~ opToX87[operations[done+1]] ~ " " 436 439 ~ indexedVector(typelist, ranklist, stridelist, operations[done] ) ~ comment; … … 438 441 mainbody ~= next; 439 442 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 { 446 449 // For scalar float or double values, we can multiply directly, saving one slot on the FP stack. 447 450 next = " fmul " ~ operandSize(typelist[operations[done]-'A']) ~ "values[" ~ itoa(operations[done]-'A') ~"]; // * " ~ operations[done..done+1] ~ "\n"; 448 451 mainbody ~= next; //firstbody ~= next; 449 }450 done +=2;451 }452 } 453 done +=2; 454 } 452 455 } 453 456 … … 562 565 " jz short L2; // test for length==0"\n; 563 566 while(done<operations.length) { 564 char [] comment;565 if (isInstruction(operations[done])) {567 char [] comment; 568 if (isInstruction(operations[done])) { 566 569 // Perform an arithmetic operation on the top two items. 567 570 comment = "; //" ~ operations[done] ~ \n; … … 570 573 ++done; 571 574 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])){ 581 588 // load a vector onto the FPU stack, to begin a new subexpression. 582 589 comment = "; // " ~ operations[done] ~ \n; … … 585 592 ++done; 586 593 numOnStack++; 587 } else if (operations[done]==',') {594 } else if (operations[done]==',') { 588 595 // operation on self, eg XX+ --> don't need to load it again. 589 596 comment = "; // " ~ operations[done..done+2] ~ \n; … … 593 600 ~ XMM(numOnStack-1) ~ comment; 594 601 done +=2; 595 } else if (ranklist[operations[done]-'A']=='1') {602 } else if (ranklist[operations[done]-'A']=='1') { 596 603 // An operation will be performed between the stack top and a vector. 597 604 comment = "; // " ~ operations[done..done+2] ~ \n; … … 606 613 } 607 614 done+=2; 608 } else { // multiply by scalar.615 } else { // multiply by scalar. 609 616 comment = "; // " ~operations[done..done+2] ~ \n; 610 617 int u = scalarNum(ranklist, operations[done]-'A'); … … 612 619 extra ~= " " ~ opToSSESingle[operations[done+1]] ~ suffix ~ XMM(numOnStack-1) ~ ", " ~ XMM(u) ~ comment; 613 620 done +=2; 614 }621 } 615 622 } 616 623 trunk/blade/PostfixX86.d
r171 r172 57 57 } 58 58 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 } 65 71 } 66 72 ReturnType onVisitPrefix(This this_, char [] op, char [] expr) { … … 136 142 } 137 143 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 } 144 156 } 145 157 ReturnType onVisitPrefix(This this_, char [] op, char [] expr) {
