comparison mc-nop-386.c @ 56:5aa4528b6983 parallel-assign-c

A little optimized parallel assignment
author kono
date Wed, 19 Feb 2003 12:15:05 +0900
parents 94564b45c4f3
children 3d7f199e99d0
comparison
equal deleted inserted replaced
55:94564b45c4f3 56:5aa4528b6983
1036 /* target list4(list2(tag,disp),cdr,ty,source_expr) */ 1036 /* target list4(list2(tag,disp),cdr,ty,source_expr) */
1037 /* source expr=listn(tag,...) */ 1037 /* source expr=listn(tag,...) */
1038 /* source (after) list2(tag,disp) */ 1038 /* source (after) list2(tag,disp) */
1039 /* source list list3(e,cdr,sz) */ 1039 /* source list list3(e,cdr,sz) */
1040 1040
1041 #define DEBUG_PARALLEL_ASSIGN 0
1042
1041 int 1043 int
1042 overrap(int t,int sz,int source) 1044 overrap(int t,int sz,int source)
1043 { 1045 {
1044 int s,s0,s1; 1046 int s,s0,s1;
1045 int t0=cadr(t); 1047 int t0=cadr(t);
1046 int t1=t0+sz; 1048 int t1=t0+sz;
1047 for(;source;source=cadr(source)) { 1049 for(;source;source=cadr(source)) {
1048 s=car(source); s0=cadr(s); 1050 s=car(source); s0=cadr(s);
1049 if(car(s)==REGISTER && car(t)==REGISTER) { 1051 if(car(s)==REGISTER && car(t)==REGISTER) {
1050 if(s0==t0) return 1; 1052 if(s0==t0) return s;
1051 } else if (is_same_type(s,t)) { 1053 } else if (is_same_type(s,t)) {
1052 s1=s0+caddr(source); 1054 s1=s0+caddr(source);
1053 #if 0 1055 #if DEBUG_PARALLEL_ASSIGN>1
1054 printf("# ovedrrap source %d t0 %d t1 %d\n",car(car(t)),t0,t1); 1056 printf("# ovedrrap source %d t0 %d t1 %d\n",car(car(t)),t0,t1);
1055 printf("# ovedrrap target %d s0 %d s1 %d\n",car(car(source)),s0,s1); 1057 printf("# ovedrrap target %d s0 %d s1 %d\n",car(car(source)),s0,s1);
1056 printf("# ovedrrap equal = %d\n",((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1))); 1058 printf("# ovedrrap equal = %d\n",((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1)));
1057 #endif 1059 #endif
1058 if((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1)) return s; 1060 if((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1)) return s;
1090 g_expr(assign_expr0((e1=list2(LVAR,disp)),s,ty,ty)); 1092 g_expr(assign_expr0((e1=list2(LVAR,disp)),s,ty,ty));
1091 *target = append4(*target,t,ty,e1); 1093 *target = append4(*target,t,ty,e1);
1092 } 1094 }
1093 } 1095 }
1094 1096
1097 int
1098 circular_dependency(int t,int s,int *target,int *source)
1099 {
1100 int target0=*target;
1101 int t1,sz,ty,s1;
1102 while(target0) {
1103 if (cadddr(target0)==s) {
1104 t1=car(target0);
1105 s=cadddr(target0);
1106 sz=size(ty=caddr(target0));
1107 if(t==t1) {
1108 #if DEBUG_PARALLEL_ASSIGN
1109 printf("# circular dependency %d ty %d+%d sz %d\n",car(t1),ty,cadr(t1),sz);
1110 #endif
1111 return 1;
1112 }
1113 if ((s1=overrap(t1,sz,*source))) {
1114 /* another overrap start over */
1115 return circular_dependency(t,s1,target,source);
1116 }
1117 }
1118 target0=cadr(target0);
1119 }
1120 return 0;
1121 }
1122
1095 void 1123 void
1096 parallel_assign(int *target,int *source,int *processing,int *use) 1124 parallel_assign(int *target,int *source,int *processing,int *use)
1097 { 1125 {
1098 int t,s,e1,p,sz,ty; 1126 int t,s,sz,ty,target0,s1;
1099 while(*target) { 1127 while(*target) {
1100 t=car(*target); s=cadddr(*target); 1128 target0=*target;
1101 sz=size(ty=caddr(*target)); 1129 while(target0) {
1102 if(car(t)==car(s) && cadr(t)==cadr(s)) { 1130 t=car(target0); s=cadddr(target0);
1103 #if 1 1131 sz=size(ty=caddr(target0));
1104 printf("# duplicate same target check (you shouldn't see this) \n# %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); 1132 if(car(t)==car(s) && cadr(t)==cadr(s)) {
1133 /*書き込み先が自分自身*/
1134 #if DEBUG_PARALLEL_ASSIGN
1135 printf("# remove same %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz);
1105 #endif 1136 #endif
1106 /*書き込み先が自分自身*/ 1137 remove_target(target,t,use);
1107 remove_target(target,t,use); 1138 /* 破壊されては困るので、source listからは除かない */
1108 /* 破壊されては困るので、source listからは除かない */ 1139 } else if (!(s1=overrap(t,sz,*source))) {
1109 } else if (!(overrap(t,sz,*source))) { 1140 /* 重なってないので安心して書き込める */
1110 /* 重なってないので安心して書き込める */ 1141 #if DEBUG_PARALLEL_ASSIGN
1111 #if 1
1112 printf("# normal assign %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); 1142 printf("# normal assign %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz);
1113 #endif 1143 #endif
1114 g_expr(assign_expr0(t,s,ty,ty)); 1144 g_expr(assign_expr0(t,s,ty,ty));
1115 remove_target(target,t,use); remove0(source,s); 1145 remove_target(target,t,use); remove0(source,s);
1116 } else { 1146 } else {
1117 #if 1 1147 if(circular_dependency(t,s1,target,source)) {
1118 printf("# circular dependcy %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); 1148 #if DEBUG_PARALLEL_ASSIGN
1149 printf("# saving %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz);
1119 #endif 1150 #endif
1120 remove_target(target,t,use); remove0(source,s); 1151 remove_target(target,t,use); remove0(source,s);
1121 save_target(t,s,target,use,sz,ty); 1152 save_target(t,s,target,use,sz,ty);
1153 }
1154 }
1155 target0=cadr(target0);
1122 } 1156 }
1123 } 1157 }
1124 } 1158 }
1125 1159
1126 void 1160 void
1204 } else { 1238 } else {
1205 target=list4(list2(LVAR,0), 1239 target=list4(list2(LVAR,0),
1206 target,ty,e2); 1240 target,ty,e2);
1207 arg_size += sz; 1241 arg_size += sz;
1208 } 1242 }
1209 #if 1 1243 #if DEBUG_PARALLEL_ASSIGN
1210 printf("# target %d ty %d+%d sz %d\n",car(car(target)),ty,cadr(car(target)),sz); 1244 printf("# target %d ty %d+%d sz %d\n",car(car(target)),ty,cadr(car(target)),sz);
1211 #endif 1245 #endif
1212 } 1246 }
1213 1247
1214 /* disp を飛び先似合わせて修正 */ 1248 /* disp を飛び先似合わせて修正 */
1237 g_expr(assign_expr0((e4=list2(LVAR,disp)),s0,ty,ty)); 1271 g_expr(assign_expr0((e4=list2(LVAR,disp)),s0,ty,ty));
1238 cadddr(e2)=e4; 1272 cadddr(e2)=e4;
1239 s0=e4; 1273 s0=e4;
1240 } else if (is_same_type(t0,s0)) { 1274 } else if (is_same_type(t0,s0)) {
1241 if(cadr(t0)==cadr(s0)) { 1275 if(cadr(t0)==cadr(s0)) {
1276 #if DEBUG_PARALLEL_ASSIGN
1277 printf("# remove same memory %d ty %d+%d sz %d\n",car(t0),ty,cadr(t0),sz);
1278 #endif
1242 /* we should check size also (but currently useless */ 1279 /* we should check size also (but currently useless */
1243 remove0(&target,t0); 1280 remove0(&target,t0);
1244 /* still we have source to avoid overwrite */ 1281 /* still we have source to avoid overwrite */
1245 } 1282 }
1246 } 1283 }
1247 if(is_memory(s0)) { 1284 if(is_memory(s0)) {
1248 source=list3(s0,source,sz); 1285 source=list3(s0,source,sz);
1249 #if 1 1286 #if DEBUG_PARALLEL_ASSIGN
1250 printf("# source %d ty %d+%d sz %d\n",car(car(source)),ty,cadr(car(source)),sz); 1287 printf("# source %d ty %d+%d sz %d\n",car(car(source)),ty,cadr(car(source)),sz);
1251 #endif 1288 #endif
1252 } 1289 }
1253 } 1290 }
1254 1291
1298 e2 = emit_pop(0); 1335 e2 = emit_pop(0);
1299 printf("\tjmp *%s\n",register_name(e2,0)); 1336 printf("\tjmp *%s\n",register_name(e2,0));
1300 emit_pop_free(e2); 1337 emit_pop_free(e2);
1301 } 1338 }
1302 } 1339 }
1303
1304 #if 0
1305 int
1306 arg_size(int e3,int *nargs0)
1307 {
1308 int i,nargs,offset_list,e,t;
1309
1310 offset_list = 0;
1311 /* we should use prototypes's type */
1312 for (i = nargs = 0; e3;e3 =cadr(e3)) {
1313 e = car(e3); t = caddr(e3);
1314 if (i < MAX_REGISTER_VAR && scalar(t)) {
1315 offset_list = list3(-(REG_ESI+i++),offset_list,e);
1316 } else {
1317 offset_list =
1318 list3(nargs,offset_list,e);
1319 nargs += (car(e3)==CHAR?size_of_int:size(t));
1320 }
1321 }
1322 *nargs0 = -nargs;
1323 return offset_list;
1324 }
1325
1326
1327 void
1328 jump(int e1, int env)
1329 {
1330 int i,args,e2,e3,e4,e5,nargs,regs;
1331 NMTBL *n,*code0;
1332 int new_disp,scode,disp1,xreg;
1333 char *xrn;
1334
1335 /* We need three passes. Compute Stack size, Compute Arg, Copy it. */
1336 /* count number of args */
1337 args = caddr(e1);
1338 args = reverse0(args);
1339 nargs = arg_size(args,&new_disp); /* compute in normal order */
1340 disp1 = (fnptr->sc==CODE)?0:-size_of_int;
1341 if (new_disp+disp1 < disp) { /* have to extend stack */
1342 if (fnptr->sc==CODE)
1343 printf("\tleal %d(%%ebp),%%esp\n",new_disp-size_of_int);
1344 else
1345 printf("\tleal %d(%%ebp),%%esp\n",new_disp+disp_offset);
1346 }
1347 /* compute jump address */
1348 e2 = cadr(e1);
1349 if (car(e2) == FNAME) {
1350 code0=(NMTBL *)cadr(e2);
1351 if (code0->sc!=CODE) {
1352 error(STERR); return;
1353 }
1354 } else { /* indirect */
1355 g_expr(e2);
1356 emit_push();
1357 }
1358 /* compute arguments in reverse order */
1359 /* printf("## jump code_arg_offset=%d code_disp_offset=%d\n",code_arg_offset,code_disp_offset); */
1360 regs = 0;
1361 i=MAX_REGISTER_VAR;
1362 for (e3=nargs; e3;e3 =cadr(e3)) {
1363 n=(NMTBL *)(e5=(cadr(e4 = caddr(e3))));
1364 switch(car(e4)) {
1365 case FNAME:
1366 printf("\tlea %s,%s\n",n->nm,register_name(creg,0));
1367 emit_push();
1368 break;
1369 case ADDRESS:
1370 g_expr(e5);
1371 emit_push();
1372 break;
1373 case RLVAR:
1374 case CRLVAR:
1375 if (env==0 && fnptr->sc==CODE) {
1376 /* printf("## e5=%d car(e3)=%d\n",e5,car(e3)); */
1377 if (e5>=0 && e5==car(e3)) {
1378 /* The same positioned local variable. No need to copy */
1379 reg_stack[reg_sp++] = -2;
1380 }
1381 break;
1382 }
1383 g_expr(e4);
1384 emit_push();
1385 break;
1386 case REGISTER:
1387 /* printf("## i=%d rname[e5]=%d\n",i,rname[e5]); */
1388 if (i>0 && rname[e5]==REG_ESI+ --i) {
1389 /* The same register variable. No need to copy */
1390 reg_stack[reg_sp++] = e5;
1391 break;
1392 }
1393 default:
1394 g_expr(e4);
1395 emit_push();
1396 }
1397 regs++;
1398 }
1399 if (env) {
1400 /* change the frame pointer */
1401 g_expr(env);
1402 printf("\tmovl %s,%%ebp\n",register_name(creg,0));
1403 } else if (fnptr->sc==FUNCTION) {
1404 printf("\tlea %d(%%ebp),%%ebp\n",disp_offset);
1405 }
1406 /* force lvar offset mode to CODE */
1407 scode = fnptr->sc; fnptr->sc = CODE;
1408 /* printf("## jump2 code_arg_offset=%d code_disp_offset=%d\n",code_arg_offset,code_disp_offset); */
1409 /* copy arguments to destination environment if necessary */
1410 nargs = reverse0(nargs); /* pop in normal order */
1411 i=0;
1412 for (e3=nargs; e3;e3 =cadr(e3)) {
1413 if ((e4=car(e3))<0) {
1414 /* register case */
1415 if (reg_stack[--reg_sp]>=REG_ESI) {
1416 /* the same registger */
1417 } else {
1418 if(reg_stack[reg_sp]<0) {
1419 printf("\tpopl %s\n",reg_name[rname[REG_ESI+i]]); /* e4? */
1420 } else {
1421 printf("\tmovl %s,%s\n",
1422 reg_name[rname[reg_stack[reg_sp]]],
1423 reg_name[rname[REG_ESI+i]]); /* e4? */
1424 free_register(reg_stack[reg_sp]);
1425 }
1426 i++;
1427 }
1428 } else {
1429 /* local variable case */
1430 if (reg_stack[reg_sp-1]== -2) {
1431 /* same positioned variable */
1432 reg_sp--;
1433 } else {
1434 printf("\tmovl %s,%d(%%ebp)\n",register_name((xreg=emit_pop(0)),0), lvar(e4));
1435 }
1436 }
1437 }
1438 free_register(xreg);
1439 if (car(e2) != FNAME) {
1440 xrn=register_name((xreg=emit_pop(0)),0);
1441 }
1442 free_register(xreg);
1443 if (!env && new_disp+disp1>disp) {
1444 /* shrink stack if necessary */
1445 printf("\tleal %d(%%ebp),%%esp\n",new_disp-size_of_int);
1446 }
1447 if (car(e2) == FNAME) {
1448 printf("\tjmp %s\n",code0->nm);
1449 } else {
1450 printf("\tjmp *%s\n",xrn);
1451 }
1452 fnptr->sc = scode;
1453 }
1454 #endif
1455 1340
1456 void 1341 void
1457 machinop(int e1) 1342 machinop(int e1)
1458 { 1343 {
1459 int e2,e3,op; 1344 int e2,e3,op;