Mercurial > hg > CbC > old > device
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; |