Changeset 101
- Timestamp:
- 04/23/07 22:53:16 (1 year ago)
- Files:
-
- trunk/blade/Blade.d (modified) (7 diffs)
- trunk/blade/BladeParse.d (modified) (1 diff)
- trunk/blade/CodegenX87.d (modified) (27 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/blade/Blade.d
r100 r101 205 205 ReturnType performOperation(ReturnType, char [] operations, char [] finaloperation, int knownlength, X...)(X expr) 206 206 { 207 const char [] tuplestr = vectorTupleToString!(X);207 const char [][] tuplestr = splitTuple(vectorTupleToString!(X)); 208 208 const char [] rettypestr="real"; 209 209 static if (is(RetType: ireal)){ rettypestr="ireal";} … … 213 213 214 214 version(BladeDebug) { 215 pragma(msg, finaloperation ~ " " ~ operations ~ "\nTuple: " ~ tuplestr);215 pragma(msg, finaloperation ~ " " ~ operations ~ "\nTuple: " ~ vectorTupleToString!(X)); 216 216 static if (knownlength!=0) pragma(msg, "Length is known!"); 217 217 pragma(msg, "Generated Code: "\n ~ generateCode(rettypestr, tuplestr, operations, finaloperation, knownlength)); … … 220 220 } 221 221 222 char [] generateCode(char [] rettypestr, char [] tuplestr, char [] operations, char [] finaloperation, int knownlength)222 char [] generateCode(char [] rettypestr, char [][] tuplestr, char [] operations, char [] finaloperation, int knownlength) 223 223 { 224 224 char [] a=""; 225 // char [][] tuplestr = splitTuple(rawtuplestr); 225 226 // Decide which code generator to use, based on expression complexity and 226 227 // assembler availability. … … 242 243 // of the types in the tuple. 243 244 244 // Create a s ingle-character string representing the type A.245 // Create a string representing the type A. 245 246 // Pure imaginary types are treated identically to pure reals, since they result in the 246 247 // same asm code. … … 263 264 template vectorTupleToString(X...) 264 265 { 265 static if (X.length==1) const char [] vectorTupleToString = singleTypeToString!(X[0]); 266 else const char [] vectorTupleToString = singleTypeToString!(X[0]) ~ vectorTupleToString!(X[1..$]); 266 // static if (X.length==1) const char [] vectorTupleToString = singleTypeToString!(X[0])~\0; 267 // else const char [] vectorTupleToString = singleTypeToString!(X[0]) ~ \0 ~ vectorTupleToString!(X[1..$]); 268 static if (X.length==1) const char [] vectorTupleToString = X[0].stringof ~\0; 269 else const char [] vectorTupleToString = X[0].stringof ~ \0 ~ vectorTupleToString!(X[1..$]); 270 } 271 272 // Encode the types in the array. For each entry, format is: 273 // first char = category. V for real/imag vector, Z for complex vector, S for scalar. 274 // second char = size. F for float, D for double, R for real. 275 char[][] splitTuple(char [] raw) 276 { 277 char [][] s; 278 int start=0; 279 for(int i=0;i<raw.length;++i) { 280 if (raw[i]=='\0') { 281 char [] a; 282 switch(raw[start..i]) { 283 case (ifloat[]).stringof: 284 case (float[]).stringof: a="VF"; break; 285 case (idouble[]).stringof: 286 case (double[]).stringof: a="VD"; break; 287 case (ireal[]).stringof: 288 case (real[]).stringof: a="VR"; break; 289 case ireal.stringof: 290 case real.stringof: a="SR"; break; 291 case idouble.stringof: 292 case double.stringof: a="SD"; break; 293 case ifloat.stringof: 294 case float.stringof: a="SF"; break; 295 case cfloat.stringof: 296 case cdouble.stringof: 297 case creal.stringof: a="SZ"; break; 298 case (cfloat[]).stringof: a="ZF"; break; 299 case (cdouble[]).stringof: a="ZD"; break; 300 case (creal[]).stringof: a="ZZ"; break; 301 // default: 302 // a = "??" ~ raw[start..i]; break; 303 } 304 s~=a; start=i+1; } 305 } 306 return s; 267 307 } 268 308 … … 273 313 // Return a string to mixed in, which asserts that all vectors are of 274 314 // equal length. 275 char [] generateVectorLengthChecks(char [] typelist)315 char [] generateVectorLengthChecks(char [][] typelist) 276 316 { 277 317 int firstvec = findFirstVector(typelist); … … 289 329 * 290 330 */ 291 char [] generateCodeForD(char [] rettypestr, int knownlength, char [] typelist, char [] finalop, char [] operation)331 char [] generateCodeForD(char [] rettypestr, int knownlength, char [][] typelist, char [] finalop, char [] operation) 292 332 { 293 333 char [] iter=""; trunk/blade/BladeParse.d
r100 r101 22 22 23 23 // Return the first index in the tuple which is of vector type 24 int findFirstVector(char [] typelist)24 int findFirstVector(char [][] typelist) 25 25 { 26 26 for (int i=0; i< typelist.length;++i) { 27 27 if (isVector(typelist[i])) return i; 28 28 } 29 assert(0, typelist);30 29 } 31 30 32 bool isVector(char var)31 bool isVector(char [] typestr) 33 32 { 34 return ( var=='R' || var=='D' || var=='F' || var=='Z');33 return (typestr[0]=='V' || typestr[0]=='Z'); 35 34 } 35 36 // Count the number of vectors in the typestring 37 int countVectors(char [][] typelist) 38 { 39 int numVecs=0; 40 for (int i=0; i<typelist.length; ++i) { 41 if (isVector(typelist[i])) ++numVecs; 42 } 43 return numVecs; 44 } 45 trunk/blade/CodegenX87.d
r100 r101 22 22 // Converts an infix string into postfix. Also strips off the # symbols. 23 23 // Apply x87-specific optimisations during the conversion. 24 char [] makePostfixForX87(char [] operations, char [] typelist)24 char [] makePostfixForX87(char [] operations, char [][] typelist) 25 25 { 26 26 // if (operations.length==1) return operations; … … 31 31 char [] second = operations[x+2..$]; 32 32 if (first[0]=='(') { 33 first = makePostfixForX87(first[1.. $-1], typelist);33 first = makePostfixForX87(first[1..first.length-1], typelist); 34 34 } else if (first[0]=='#') first = operations[1..x+1]; 35 35 if (second[0]=='(') { 36 second = makePostfixForX87(second[1.. $-1], typelist);36 second = makePostfixForX87(second[1..second.length-1], typelist); 37 37 } else if (second[0]=='#') second = operations[x+3..$]; 38 38 … … 47 47 // complexity of the mini-compiler.). 48 48 if (operations[x+1]=='+') { 49 if (second[ $-1]=='*' && first[$-1]!='*') {49 if (second[second.length-1]=='*'&& first[first.length-1]!='*') { 50 50 return second ~ first ~ operations[x+1..x+2]; 51 51 } … … 54 54 // instead of fsub. We use _ to mean reversed subtraction. 55 55 if (operations[x+1]=='-') { 56 if (second[ $-1]=='*' && first[$-1]!='*') {56 if (second[second.length-1]=='*' && first[first.length-1]!='*') { 57 57 return second ~ first ~ "_"; 58 58 } … … 61 61 // When an operation is performed between a real[] and a non-real[], 62 62 // we want to have the real[] being the one which is loaded first. 63 if (second.length==1 && typelist[second[0]-'a']== 'R'&& operations[x+1]=='+') {63 if (second.length==1 && typelist[second[0]-'a']=="VR" && operations[x+1]=='+') { 64 64 return second ~ first ~ "+"; 65 65 } 66 if (second.length==1 && typelist[second[0]-'a']== 'R'&& operations[x+1]=='-') {66 if (second.length==1 && typelist[second[0]-'a']=="VR" && operations[x+1]=='-') { 67 67 return second ~ first ~ "_"; 68 68 } … … 77 77 { 78 78 return (op=='+' || op=='*' || op=='-'|| op=='.'|| op=='_'); 79 }80 81 // Count the number of vectors in the typestring82 int countVectors(char [] typelist)83 {84 int numVecs=0;85 for (int i=0; i<typelist.length; ++i) {86 if (typelist[i]=='R' || typelist[i]=='D' || typelist[i]=='F' || typelist[i]=='Z') ++numVecs;87 }88 return numVecs;89 79 } 90 80 … … 115 105 } 116 106 117 int vectorNum(char [] typelist, char var)107 int vectorNum(char [][] typelist, char var) 118 108 { 119 109 int numVecs=0; 120 110 for (int i=0; i<var-'a'; ++i) { 121 if (typelist[i]== 'R' || typelist[i]=='D' || typelist[i]=='F' || typelist[i]=='Z') ++numVecs;111 if (typelist[i]=="VR" || typelist[i]=="VD" || typelist[i]=="VF") ++numVecs; 122 112 } 123 113 return numVecs; 124 114 } 125 115 126 int realScalarNum(char [] typelist, char var)116 int realScalarNum(char [][] typelist, char var) 127 117 { 128 118 int k=0; 129 119 for (int i=0; i<var-'a'; ++i) { 130 if (typelist[i]== 'r') ++k;120 if (typelist[i]=="SR") ++k; 131 121 } 132 122 return k; … … 134 124 135 125 136 char [] operandSize(char var)137 { 138 switch( var) {139 case 'r':140 case 'R': return "real ptr ";141 case 'd':142 case 'D': return "double ptr ";143 case 'f':144 case 'F': return "float ptr ";126 char [] operandSize(char [] typestr) 127 { 128 switch(typestr) { 129 case "SR": 130 case "VR": return "real ptr "; 131 case "SD": 132 case "VD": return "double ptr "; 133 case "SF": 134 case "VF": return "float ptr "; 145 135 } 146 136 } … … 161 151 else static if (real.sizeof==16) const char [] REALSIZE = "16"; 162 152 163 char [] vectorSize(char vartype)164 { 165 switch ( vartype) {166 case 'D': return "8";167 case 'F': return "4";168 case 'R': return REALSIZE;153 char [] vectorSize(char [] typestr) 154 { 155 switch (typestr) { 156 case "VD": return "8"; 157 case "VF": return "4"; 158 case "VR": return REALSIZE; 169 159 } 170 160 } … … 175 165 176 166 // Is this expression simple enough for the x87 code generator? 177 bool isX87AsmPossible(char [] typelist, char [] operations) {167 bool isX87AsmPossible(char [][] typelist, char [] operations) { 178 168 version (D_InlineAsm_X86) { 179 169 // Are there enough index registers? … … 182 172 foreach(ch; typelist) { 183 173 // can only do float, double, and 80-bit vectors, and scalars. 184 if (ch!= 'R' && ch!='D' && ch!='F' && ch!='r' && ch!='d' && ch!='s') return false;174 if (ch!="VR" && ch!="VD" && ch!="VF" && ch!="SR" && ch!="SD" && ch!="SF") return false; 185 175 } 186 176 // BUG: should also check if it will overflow the FPU stack … … 193 183 194 184 // Is this expression simple enough for the SSE2 code generator? 195 bool isSSE2AsmPossible(char [] typelist, char [] operations)185 bool isSSE2AsmPossible(char [][] typelist, char [] operations) 196 186 { 197 187 version (D_InlineAsm_X86) { … … 199 189 foreach(ch; typelist) { 200 190 // can only do double vectors and double scalars. 201 if (ch!= 'D' && ch!='d') return false;191 if (ch!="VD" && ch!="SD") return false; 202 192 } 203 193 return false; // not yet implemented … … 224 214 } 225 215 226 char [] indexedVector(char [] typelist, char var)227 { 228 if (typelist[var-'a']== 'R') return " real ptr [" ~ vectorRegister[vectorNum(typelist, var)] ~ "]";216 char [] indexedVector(char [][] typelist, char var) 217 { 218 if (typelist[var-'a']=="VR") return " real ptr [" ~ vectorRegister[vectorNum(typelist, var)] ~ "]"; 229 219 return operandSize(typelist[var-'a']) ~ "[" ~ 230 220 vectorRegister[vectorNum(typelist, var)] ~ " + " ~ vectorSize(typelist[var-'a']) ~ "*ESI]"; 231 221 } 232 222 233 char [] storeVector(char type, int vecnum)234 { 235 char [] stride = " - " ~ vectorSize(type );236 if (type =='R') {223 char [] storeVector(char [] typestr, int vecnum) 224 { 225 char [] stride = " - " ~ vectorSize(typestr); 226 if (typestr=="VR") { 237 227 return " fstp real ptr [" ~ vectorRegister[vecnum] ~ stride ~ "];"\n; 238 228 } else { 239 return " fstp " ~ operandSize(type ) ~ " [" ~ vectorRegister[vecnum] ~ " + " ~ vectorSize(type)~ "*ESI" ~ stride ~ "];"\n;229 return " fstp " ~ operandSize(typestr) ~ " [" ~ vectorRegister[vecnum] ~ " + " ~ vectorSize(typestr)~ "*ESI" ~ stride ~ "];"\n; 240 230 } 241 231 } … … 248 238 case '+': return "addpd"; 249 239 case '-': return "subpd"; 250 case '_': return "**BUG**"; // Non-existent!240 // case '_': return "**BUG**"; // Non-existent! 251 241 } 252 242 } … … 259 249 case '+': return "addps"; 260 250 case '-': return "subps"; 261 case '_': return "**BUG**"; // Non-existent!262 } 263 } 264 265 266 char [] generateCodeForAsmSSE2(int knownlength, char [] typelist, char [] infixOperations, char [] finaloperation)251 // case '_': return "**BUG**"; // Non-existent! 252 } 253 } 254 255 256 char [] generateCodeForAsmSSE2(int knownlength, char [][] typelist, char [] infixOperations, char [] finaloperation) 267 257 { 268 258 // Use ESI as the index register. … … 312 302 313 303 */ 314 char [] generateCodeForAsmX87(int knownlength, char [] typelist, char [] infixOperations, char [] finaloperation)304 char [] generateCodeForAsmX87(int knownlength, char [][] typelist, char [] infixOperations, char [] finaloperation) 315 305 { 316 306 char [] operations = makePostfixForX87(infixOperations, typelist); … … 323 313 if (isVector(typelist[i])){ 324 314 result~= " auto vec" ~ itoa(i) ~ " = expr[" ~itoa(i) ~"].ptr;\n"; 325 if (typelist[i]== 'R') {315 if (typelist[i]=="VR") { 326 316 incrementRealVectors ~= " add " ~ vectorRegister[vecnum] ~ ", " ~ REALSIZE ~ ";\n"; 327 317 } … … 333 323 } 334 324 335 bool isDotProduct = (operations[ $-1]=='.');325 bool isDotProduct = (operations[operations.length-1]=='.'); 336 326 int numScalarsOnStack=0; 337 327 … … 347 337 for (int i=0; i<typelist.length; ++i) { 348 338 if (isVector(typelist[i])) { 349 if (typelist[i]== 'R') {339 if (typelist[i]=="VR") { 350 340 result ~= " mov " ~ vectorRegister[numvecs] ~ ", vec" ~ itoa(i) ~ ";"\n; 351 341 } else { … … 355 345 } 356 346 ++numvecs; 357 } else if (typelist[i]== 'r') {347 } else if (typelist[i]=="SR") { 358 348 result ~= " fld real ptr expr["~ itoa(i) ~"];\n"; 359 349 ++numconsts; … … 405 395 // If it's a float or double, we can combine the load+arithmetic op 406 396 // into a single instruction. 407 if (typelist[operations[done]-'a']== 'R') {397 if (typelist[operations[done]-'a']=="VR") { 408 398 // 80-bit vectors must be loaded onto the FPU stack first 409 399 next = " fld real ptr [" ~ vectorRegister[vectorNum(typelist, operations[done])] ~ "];\n" … … 416 406 done +=2; 417 407 } else { // multiply by scalar. 418 if (typelist[operations[done]-'a']== 'r') {408 if (typelist[operations[done]-'a']=="SR") { 419 409 // Multiply by real scalar, which is already on the stack. Note that there's an extra item on the stack when we're in the body of the loop. 420 410 firstbody ~= " fmul ST, ST(" ~ itoa(numOnStack + numScalarsOnStack - realScalarNum(typelist, operations[done]-'a')) ~ "); //var" ~ itoa(operations[done]-'a') ~ \n; … … 428 418 } 429 419 } 430 } else { // length = 1420 } else { // operations.length = 1 431 421 char [] next; 432 if (typelist[ $-1]=='R')422 if (typelist[typelist.length-1]=="VR") 433 423 next = " fld real ptr [" ~ vectorRegister[0] ~ "];\n"; 434 else next = " fld "~ operandSize(typelist[ $-1]) ~ " ["435 ~ vectorRegister[0] ~ " + " ~ vectorSize(typelist[ $-1]) ~ "*ESI];\n";424 else next = " fld "~ operandSize(typelist[typelist.length-1]) ~ " [" 425 ~ vectorRegister[0] ~ " + " ~ vectorSize(typelist[typelist.length-1]) ~ "*ESI];\n"; 436 426 mainbody ~=next; firstbody~=next; 437 427 ++numOnStack; … … 448 438 if (finaloperation[0]=='-') finalop="fsubr"; 449 439 char [] next; 450 if (typelist[ $-1]=='R') {440 if (typelist[typelist.length-1]=="VR") { 451 441 // 80-bit vectors must be loaded onto the FPU stack first 452 442 next = " fld real ptr [" ~ vectorRegister[numvecs-1] ~ "];"\n; 453 443 next ~= " " ~ finalop ~ "p ST(1), ST;\n"; 454 444 } else { 455 next = " " ~ finalop ~ " " ~ operandSize(typelist[ $-1]) ~ " [" ~ vectorRegister[numvecs-1] ~ " + "456 ~ vectorSize(typelist[ $-1]) ~ "*ESI];"\n;445 next = " " ~ finalop ~ " " ~ operandSize(typelist[typelist.length-1]) ~ " [" ~ vectorRegister[numvecs-1] ~ " + " 446 ~ vectorSize(typelist[typelist.length-1]) ~ "*ESI];"\n; 457 447 } 458 448 mainbody ~=next; firstbody~=next; … … 465 455 if (isDotProduct) result ~= " faddp ST(2), ST;"\n; 466 456 else { 467 result ~= storeVector(typelist[ $-1], numvecs-1);457 result ~= storeVector(typelist[typelist.length-1], numvecs-1); 468 458 } 469 459 … … 475 465 // Store the result from the final iteration 476 466 if (isDotProduct) result ~= " faddp ST(1), ST;"\n; 477 else result ~= storeVector(typelist[ $-1], numvecs-1);467 else result ~= storeVector(typelist[typelist.length-1], numvecs-1); 478 468 479 469 // Discard any scalars that are left on the stack
