Changeset 144
- Timestamp:
- 11/21/07 02:11:00 (9 months ago)
- Files:
-
- trunk/blade/Blade.d (modified) (5 diffs)
- trunk/blade/BladeDemo.d (modified) (1 diff)
- trunk/blade/BladeRank.d (modified) (5 diffs)
- trunk/blade/CodegenX86.d (modified) (17 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/blade/Blade.d
r143 r144 47 47 public import blade.SyntaxTree : AbstractSyntaxTree, syntaxtreeof, AST, Symbol; 48 48 private import blade.BladeUtil : enquote; 49 private import blade.BladeRank;50 49 private import blade.BladeSimplify : simplifySyntaxTree, RevisedExpression; 51 public import blade.CodegenX86 : generateCodeForAsmX87, generateCodeForSSE, MAX_X87_VECTORS, MAX_SSE_VECTORS; 50 public import blade.CodegenX86 : generateCodeForAsmX87, MAX_X87_VECTORS, 51 generateCodeForSSE, MAX_SSE_VECTORS; 52 52 53 53 public: … … 80 80 } 81 81 82 82 83 // These functions have the complete expression encoded in the template type. 83 84 // One of these functions is instantiated for each expression. … … 90 91 */ 91 92 void SSEVECGEN(int SSEVersion, char [] expr, Values...)(int veclength, Values values) { 92 const ranklist = TupleRank!(Values);93 93 debug(BladeBackEnd) { 94 pragma(msg, generateCodeForSSE (SSEVersion, ranklist, expr));95 } 96 mixin(generateCodeForSSE (SSEVersion, ranklist, expr));97 }94 pragma(msg, generateCodeForSSE!(Values)(SSEVersion, expr)); 95 } 96 mixin(generateCodeForSSE!(Values)(SSEVersion, expr)); 97 } 98 98 99 99 /** Function to implement BLAS1 operations using X87 assembler. 100 100 * Every member of the Values tuple must only be real, float[], double [], or real[]. 101 101 */ 102 void X87VECGEN(char [] rawexpr, Values...)(int veclength, Values values) { 103 const typelist = elementTupleToString!(Values); 104 const ranklist = TupleRank!(Values); 105 const char [] expr = rawexpr; 102 void X87VECGEN(char [] expr, Values...)(int veclength, Values values) { 106 103 debug(BladeBackEnd) { 107 pragma(msg, generateCodeForAsmX87 (typelist, ranklist,expr));108 } 109 mixin(generateCodeForAsmX87 (typelist, ranklist,expr));104 pragma(msg, generateCodeForAsmX87!(Values)(expr)); 105 } 106 mixin(generateCodeForAsmX87!(Values)(expr)); 110 107 } 111 108 … … 185 182 char [] result = assertAllVectorLengthsEqual(tree, revised); 186 183 result ~= `X87VECGEN!("` ~ enquote(revised.expression) ~ `"`; 184 187 185 char [] vals; 188 186 … … 231 229 char [] result = assertAllVectorLengthsEqual(tree, revised); 232 230 result ~= assertAllVectorsAlign128(tree, revised); 231 233 232 234 233 result ~= "SSEVECGEN!(" ~ (SSE2?"2":"1") ~ `,"` ~ enquote(revised.expression) ~ `"`; trunk/blade/BladeDemo.d
r143 r144 33 33 34 34 mixin(vectorize(` a += (d[2..$-1]*2.01*a[2]-another[][1])["abc".length-3..$]`)); 35 mixin(vectorize(" a -= 2.01*( 3.04+k)*r")); 35 36 mixin(vectorize(" a-= 2.01*( 3.04+k)*r")); 36 37 mixin(vectorize("q+= q*2.01")); 37 38 writefln("a=", a); trunk/blade/BladeRank.d
r143 r144 7 7 module blade.BladeRank; 8 8 9 9 10 // ------------------------------------------------ 10 11 // Dealing with linear algebra types … … 15 16 template Rank(T) { 16 17 // If it can be indexed, it's a vector 17 static if (is(typeof(T[0]))) const intRank = 1 + Rank!(typeof(T[0]));18 else const int Rank = 0;18 static if (is(typeof(T[0]))) const char Rank = 1 + Rank!(typeof(T[0])); 19 else const char Rank = '0'; 19 20 } 20 21 … … 43 44 /// Determine the rank of every item of the tuple T. 44 45 template TupleRank(T...) { 45 static if (T.length==1) const int[] TupleRank = [ Rank!(T[0])]; 46 else const int[] TupleRank = Rank!(T[0]) ~ TupleRank!(T[1..$]); 47 } 48 46 static if (T.length==1) const char[] TupleRank = "" ~ Rank!(T[0]); 47 else const char[] TupleRank = Rank!(T[0]) ~ TupleRank!(T[1..$]); 48 } 49 50 /* 49 51 debug(UnitTest) { 50 52 private: … … 69 71 70 72 } 73 */ 71 74 72 75 … … 75 78 76 79 // Count the number of vectors 77 int countVectors( int[] ranklist)80 int countVectors(char[] ranklist) 78 81 { 79 82 int numVecs=0; 80 83 for (int i=0; i<ranklist.length; ++i) { 81 if (ranklist[i]== 1) ++numVecs;84 if (ranklist[i]=='1') ++numVecs; 82 85 } 83 86 return numVecs; 84 87 } 85 88 86 int vectorNum( int[] ranklist, char var)89 int vectorNum(char [] ranklist, char var) 87 90 { 88 91 int numVecs=0; 89 92 for (int i=0; i<var-'A'; ++i) { 90 if (ranklist[i]== 1) ++numVecs;93 if (ranklist[i]=='1') ++numVecs; 91 94 } 92 95 return numVecs; 93 96 } 94 97 95 int scalarNum( int[] ranklist, char var)98 int scalarNum(char [] ranklist, char var) 96 99 { 97 100 int k=0; 98 101 for (int i=0; i<var-'A'; ++i) { 99 if (ranklist[i]== 0) ++k;102 if (ranklist[i]=='0') ++k; 100 103 } 101 104 return k; 102 105 } 103 106 104 int realScalarNum(char [][] typelist, int[] ranklist, char var)107 int realScalarNum(char [][] typelist, char [] ranklist, char var) 105 108 { 106 109 int k=0; 107 110 for (int i=0; i<var-'A'; ++i) { 108 if (ranklist[i]== 0&& typelist[i]=="real") ++k;111 if (ranklist[i]=='0' && typelist[i]=="real") ++k; 109 112 } 110 113 return k; trunk/blade/CodegenX86.d
r143 r144 54 54 /// Converts an infix string into postfix. 55 55 /// Apply x87-specific optimisations during the conversion. 56 char [] makePostfixForX87(char [] operations, char [][] typelist, int[] ranklist)56 char [] makePostfixForX87(char [] operations, char [][] typelist, char[] ranklist) 57 57 { 58 58 if (operations.length==1) return operations; … … 93 93 // When an operation is performed between a real[] and a non-real[], 94 94 // we want to have the real[] being the one which is loaded first. 95 if (second.length==1 && typelist[second[0]-'A']=="real" && ranklist[second[0]-'A']== 1) {95 if (second.length==1 && typelist[second[0]-'A']=="real" && ranklist[second[0]-'A']=='1') { 96 96 return second ~ first ~ oprvs; 97 97 } … … 102 102 103 103 unittest { 104 assert(makePostfixForX87("A=B", elementTupleToString!(double, double),[1,1])=="BA="); 105 assert(makePostfixForX87("(B*C)+A", elementTupleToString!(double, float, float),[1,1,1])=="BC*A+"); 106 assert(makePostfixForX87("(B*C)+A", elementTupleToString!(real, float, float),[1,1,1])=="ABC*+"); 107 assert(makePostfixForX87("A-(B*C)", elementTupleToString!(double, float, float),[1,0,0])=="BC*A_"); 108 assert(makePostfixForX87("(B*C)-A", elementTupleToString!(float, float, float),[1,0,0])=="BC*A-"); 109 assert(makePostfixForX87("(B*C)-A", elementTupleToString!(real, float, float),[1,0,0])=="ABC*_"); 110 assert(makePostfixForX87("C+=((B*C)-A)", elementTupleToString!(real, float, float),[1,0,1])=="CABC*_+C="); 111 assert(makePostfixForX87("C-=((B*C)-A)", elementTupleToString!(real, float, float),[1,0,1])=="CABC*_-C="); 112 assert(makePostfixForX87("C-=(B*A)", elementTupleToString!(real, float, float),[1,0,1]) =="BA*C_C="); 113 assert(makePostfixForX87("C-=(B*A)", elementTupleToString!(real, float, real),[1,0,1]) =="BA*C_C="); 114 assert(makePostfixForX87("((A*B)+(C*D))+(E*F)", elementTupleToString!(int, int, int),[0,0,0])=="EF*AB*CD*++"); 115 116 } 117 104 assert(makePostfixForX87("A=B", elementTupleToString!(double, double),"11")=="BA="); 105 assert(makePostfixForX87("(B*C)+A", elementTupleToString!(double, float, float),"111")=="BC*A+"); 106 assert(makePostfixForX87("(B*C)+A", elementTupleToString!(real, float, float),"111")=="ABC*+"); 107 assert(makePostfixForX87("A-(B*C)", elementTupleToString!(double, float, float),"100")=="BC*A_"); 108 assert(makePostfixForX87("(B*C)-A", elementTupleToString!(float, float, float),"100")=="BC*A-"); 109 assert(makePostfixForX87("(B*C)-A", elementTupleToString!(real, float, float),"100")=="ABC*_"); 110 assert(makePostfixForX87("C+=((B*C)-A)", elementTupleToString!(real, float, float),"101")=="CABC*_+C="); 111 assert(makePostfixForX87("C-=((B*C)-A)", elementTupleToString!(real, float, float),"101")=="CABC*_-C="); 112 assert(makePostfixForX87("C-=(B*A)", elementTupleToString!(real, float, float),"101") =="BA*C_C="); 113 assert(makePostfixForX87("C-=(B*A)", elementTupleToString!(real, float, real),"101") =="BA*C_C="); 114 assert(makePostfixForX87("((A*B)+(C*D))+(E*F)", elementTupleToString!(int, int, int),"000")=="EF*AB*CD*++"); 115 116 } 118 117 119 118 // num chars before we get a comma. … … 128 127 /// Converts an infix string into postfix. 129 128 /// Apply SSE/SSE2-specific optimisations during the conversion. 130 char [] makePostfixForSSE(char [] operations, int[] ranklist)129 char [] makePostfixForSSE(char [] operations, char [] ranklist) 131 130 { 132 131 if (operations.length==1) return operations; … … 164 163 // When an operation is performed between a vector and a scalar 165 164 // we want to have the vector being the one which is loaded first. 166 if (first.length==1 && ranklist[first[0]-'A']== 0) {165 if (first.length==1 && ranklist[first[0]-'A']=='0') { 167 166 return second ~ first ~ op; 168 167 } … … 171 170 return first ~ second ~ op; 172 171 } 172 173 private: 173 174 174 175 unittest { … … 285 286 286 287 // indexed by i. 287 char [] indexedVector(char [][] typelist, int[] ranklist, char var)288 char [] indexedVector(char [][] typelist, char [] ranklist, char var) 288 289 { 289 290 if (typelist[var-'A']=="real") return " real ptr [" ~ vectorRegister[vectorNum(ranklist, var)] ~ "]"; … … 293 294 294 295 // indexed by i-1 295 char [] indexedVectorPrev(char [][] typelist, int[] ranklist, char var)296 char [] indexedVectorPrev(char [][] typelist, char [] ranklist, char var) 296 297 { 297 298 char [] stride = " - " ~ vectorSize(typelist[var-'A']); … … 301 302 } 302 303 303 char [] indexedSSEVector( int[] ranklist, char var, char [] vecsize)304 char [] indexedSSEVector(char [] ranklist, char var, char [] vecsize) 304 305 { 305 306 return "[" ~ vectorRegister[vectorNum(ranklist, var)] ~ " + " ~ vecsize ~"*EAX]"; 306 307 } 307 308 308 char [] indexedSSENext( int[] ranklist, char var, char [] vecsize)309 char [] indexedSSENext(char [] ranklist, char var, char [] vecsize) 309 310 { 310 311 return "[" ~ vectorRegister[vectorNum(ranklist, var)] ~ " + " ~ vecsize ~"*EAX+16]"; 311 312 } 312 313 313 char [] indexedVectorWithStride(char [][] typelist, int[] ranklist, char var, int stride)314 char [] indexedVectorWithStride(char [][] typelist, char [] ranklist, char var, int stride) 314 315 { 315 316 char [] stridestr = " - " ~ vectorSize(typelist[var-'A']) ~ "*" ~ itoa(stride); … … 366 367 367 368 */ 368 char [] generateCodeForAsmX87(char [][] typelist, int [] ranklist, char [] infixOperations, char cumulatingOp=0) 369 { 369 char [] generateCodeForAsmX87(Values...)(char [] infixOperations, char cumulatingOp=0) 370 { 371 char [] ranklist; 372 char [][] typelist; 373 foreach(T; Values) { 374 static if (is(typeof(T[0]))) { 375 ranklist~="1"; 376 typelist ~= typeof(T[0]).stringof; 377 } else { 378 ranklist~="0"; 379 typelist ~= T.stringof; 380 } 381 } 370 382 char [] operations = makePostfixForX87(infixOperations, typelist, ranklist); 371 383 char [] result=""; … … 377 389 int vecnum = 0; 378 390 for (int i=0; i< ranklist.length;++i) { 379 if (ranklist[i]== 1){391 if (ranklist[i]=='1'){ 380 392 if (typelist[i]=="real") { 381 393 incrementRealVectors ~= " add " ~ vectorRegister[vecnum] ~ ", " ~ REALSIZE ~ ";\n"; … … 396 408 int numconsts=0; 397 409 for (int i=0; i<ranklist.length; ++i) { 398 if (ranklist[i]== 1) {410 if (ranklist[i]=='1') { 399 411 if (typelist[i]=="real") { 400 412 result ~= " mov " ~ vectorRegister[numvecs] ~ ", values[" ~ itoa(i) ~ "];"; … … 449 461 // load a vector onto the FPU stack, to begin a new subexpression. 450 462 int u = operations[done]-'A'; 451 if (ranklist[operations[done]-'A']== 1) {463 if (ranklist[operations[done]-'A']=='1') { 452 464 next = " fld " ~ indexedVector(typelist, ranklist, operations[done] ) ~ "; //" ~ operations[done] ~\n; 453 465 } else { // load constant. Will never be a real … … 457 469 ++done; 458 470 numOnStack++; 459 } else if (ranklist[operations[done]-'A']== 1) {471 } else if (ranklist[operations[done]-'A']=='1') { 460 472 // An operation will be performed between the stack top and a vector. 461 473 // If it's a float or double, we can combine the load+arithmetic op … … 525 537 * At entry, all vector parameters are aligned. 526 538 */ 527 char [] generateCodeForSSE(int SSEVer, int [] ranklist, char [] infixOperations, char cumulatingOp=0) 528 { 539 char [] generateCodeForSSE(Values...)(int SSEVer, char [] infixOperations, char cumulatingOp=0) 540 { 541 char [] ranklist; 542 foreach(T; Values) { 543 static if (is(typeof(T[0]))) ranklist~="1"; else ranklist~="0"; 544 } 529 545 char [] operations = makePostfixForSSE(infixOperations, ranklist); 530 546 char [] result=""; … … 546 562 int numconsts=0; 547 563 for (int i=0; i<ranklist.length; ++i) { 548 if (ranklist[i]== 1) {564 if (ranklist[i]=='1') { 549 565 result ~= " lea " ~ vectorRegister[vecregnum] 550 566 ~ ", [" ~ vectorsize ~ "*EAX]; " … … 591 607 ++done; 592 608 numOnStack++; 593 } else if (ranklist[operations[done]-'A']== 1) {609 } else if (ranklist[operations[done]-'A']=='1') { 594 610 // An operation will be performed between the stack top and a vector. 595 611 comment = "; // " ~ operations[done..done+2] ~ \n;
