00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "defs.h"
00029 #include "tracing.h"
00030 #include "errors.h"
00031 #include "wn.h"
00032 #include "mempool.h"
00033 #include "bb.h"
00034 #include "op.h"
00035 #include "tn.h"
00036 #include "cg.h"
00037 #include "cgtarget.h"
00038 #include "dominate.h"
00039
00040 static BOOL tracing = FALSE;
00041 #define Trace(msg) if (tracing) fprintf(TFile, msg "\n");
00042
00043 static MEM_POOL def_info_pool;
00044 static TN_MAP tn_def_bbs;
00045 static TN_MAP tn_use_bbs;
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 static BOOL
00056 Defs_Can_Be_Merged (TN *tn)
00057 {
00058 #define MAXDEFBBS 16
00059 BB *bb;
00060 BB *pred_bb;
00061 BB *dbbs[MAXDEFBBS];
00062 BB_SET *bbdef_set = (BB_SET*) TN_MAP_Get (tn_def_bbs, tn);
00063 INT i = 0;
00064 INT n;
00065 INT j;
00066 if (BB_SET_Size(bbdef_set) > MAXDEFBBS) {
00067 if (tracing) fprintf(TFile, "give up on tn%d cause %d def bbs\n",
00068 TN_number(tn), BB_SET_Size(bbdef_set));
00069 return FALSE;
00070 }
00071
00072 FOR_ALL_BB_SET_members (bbdef_set, bb) {
00073 dbbs[i] = bb;
00074 ++i;
00075 }
00076 n = i;
00077 for (i = 0; i < n; ++i) {
00078 pred_bb = BB_Unique_Predecessor(dbbs[i]);
00079 if (pred_bb == NULL) continue;
00080
00081
00082 if (BBlist_Len(BB_succs(pred_bb)) != 2)
00083 continue;
00084 for (j = i+1; j < n; ++j) {
00085 if (BB_Unique_Predecessor(dbbs[j]) == pred_bb) {
00086
00087 OP *opi, *opj;
00088 BOOL same = TRUE;
00089
00090 FOR_ALL_BB_OPs_FWD (dbbs[i], opi) {
00091 if (OP_Refs_TN(opi, tn))
00092 same = FALSE;
00093 if (OP_Defs_TN(opi, tn))
00094 break;
00095 }
00096 FOR_ALL_BB_OPs_FWD (dbbs[j], opj) {
00097 if (OP_Refs_TN(opj, tn))
00098 same = FALSE;
00099 if (OP_Defs_TN(opj, tn))
00100 break;
00101 }
00102 FmtAssert(opi && opj, ("didn't find def in bb?"));
00103 if (OP_code(opi) != OP_code(opj))
00104 break;
00105 for (INT k = 0; k < OP_opnds(opi); ++k) {
00106 if (OP_opnd(opi,k) != OP_opnd(opj,k))
00107 same = FALSE;
00108
00109
00110 if (TN_is_register(OP_opnd(opi,k)))
00111 same = FALSE;
00112 }
00113 if (same) {
00114
00115 if (tracing)
00116 fprintf(TFile,
00117 "move def of tn %d from bbs %d and %d to pred bb %d\n",
00118 TN_number(tn), BB_id(dbbs[i]), BB_id(dbbs[j]), BB_id(pred_bb) );
00119 BB_Move_Op_Before (pred_bb, BB_xfer_op(pred_bb), dbbs[i], opi);
00120 BB_Remove_Op (dbbs[j], opj);
00121 bbdef_set = BB_SET_Union1D(bbdef_set, pred_bb, &def_info_pool);
00122
00123 FOR_ALL_BB_OPs_FWD (dbbs[i], opi) {
00124 if (OP_Defs_TN(opi, tn))
00125 break;
00126 }
00127 if (opi == NULL)
00128 bbdef_set = BB_SET_Difference1D(bbdef_set, dbbs[i]);
00129 FOR_ALL_BB_OPs_FWD (dbbs[j], opj) {
00130 if (OP_Defs_TN(opj, tn))
00131 break;
00132 }
00133 if (opj == NULL)
00134 bbdef_set = BB_SET_Difference1D(bbdef_set, dbbs[j]);
00135 TN_MAP_Set (tn_def_bbs, tn, bbdef_set);
00136 return TRUE;
00137 }
00138 }
00139 }
00140 }
00141 return FALSE;
00142 }
00143
00144 #define DEF_NOT_BEFORE_USE 0
00145 #define DEF_BEFORE_USE 1
00146 #define DEF_MAYBE_BEFORE_USE 2
00147
00148
00149
00150
00151 static INT
00152 Def_Before_Use (TN *tn, BB *bb)
00153 {
00154 OP *op;
00155 BOOL def = FALSE;
00156 INT status = -1;
00157 FOR_ALL_BB_OPs (bb, op) {
00158 if (OP_Refs_TN(op, tn)) {
00159 if (status == -1)
00160 status = DEF_NOT_BEFORE_USE;
00161 else if (def && status == DEF_NOT_BEFORE_USE)
00162 status = DEF_MAYBE_BEFORE_USE;
00163 }
00164 if (OP_Defs_TN(op, tn)) {
00165 if (status == -1)
00166 status = DEF_BEFORE_USE;
00167 def = TRUE;
00168 }
00169 }
00170 FmtAssert(status != -1, ("unexpected def_before_use"));
00171 return status;
00172 }
00173
00174
00175 static void
00176 Set_Pred_Reachable(BB *bb, BB_SET *reachable)
00177 {
00178 BBLIST *blst;
00179 FOR_ALL_BB_PREDS(bb, blst) {
00180 BB *pred = BBLIST_item(blst);
00181 if (!BB_SET_MemberP(reachable, pred)) {
00182 BB_SET_Union1D(reachable, pred, NULL);
00183 Set_Pred_Reachable(pred, reachable);
00184 }
00185 }
00186 }
00187
00188
00189 static BB*
00190 Def_BB_For_Use (TN *tn, BB *use_bb)
00191 {
00192 BB_SET *bbdef_set = (BB_SET*) TN_MAP_Get (tn_def_bbs, tn);
00193 BB *def_bb = NULL;
00194 BB *bb;
00195 BB_SET *reachable = BB_SET_Create_Empty(PU_BB_Count + 2, &def_info_pool);
00196
00197 if (bbdef_set == NULL)
00198 return NULL;
00199
00200 Set_Pred_Reachable (use_bb, reachable);
00201
00202 FOR_ALL_BB_SET_members (bbdef_set, bb) {
00203 if (bb == use_bb) {
00204
00205 INT status = Def_Before_Use (tn, bb);
00206 if (status == DEF_BEFORE_USE) {
00207 return bb;
00208 }
00209 else if (status == DEF_MAYBE_BEFORE_USE) {
00210
00211 return NULL;
00212 }
00213 else if (BB_SET_MemberP(reachable, bb)) {
00214
00215 return NULL;
00216 }
00217 }
00218 else if (BB_SET_MemberP(reachable, bb)) {
00219
00220 if (def_bb != NULL) {
00221 if (BB_SET_MemberP(BB_dom_set(def_bb), bb)
00222
00223 && BB_SET_MemberP(BB_dom_set(use_bb), def_bb))
00224 {
00225
00226 if (tracing) fprintf(TFile,
00227 "bb %d is later def than bb %d for use bb %d\n",
00228 BB_id(def_bb), BB_id(bb), BB_id(use_bb));
00229 }
00230 else if (BB_SET_MemberP(BB_dom_set(bb), def_bb)
00231
00232 && BB_SET_MemberP(BB_dom_set(use_bb), bb))
00233 {
00234
00235 if (tracing) fprintf(TFile,
00236 "bb %d is later def than bb %d for use bb %d\n",
00237 BB_id(bb), BB_id(def_bb), BB_id(use_bb));
00238 def_bb = bb;
00239 }
00240 else {
00241 return NULL;
00242 }
00243 }
00244 else {
00245 def_bb = bb;
00246 }
00247 }
00248 }
00249 return def_bb;
00250 }
00251
00252
00253 static BOOL
00254 Each_Use_Has_Single_Def (TN *tn)
00255 {
00256 BB *def_bb;
00257 BB *use_bb;
00258 BB_SET *bbuse_set = (BB_SET*) TN_MAP_Get (tn_use_bbs, tn);
00259 if (bbuse_set == NULL)
00260 return TRUE;
00261
00262 FOR_ALL_BB_SET_members (bbuse_set, use_bb) {
00263 if ( ! Def_BB_For_Use (tn, use_bb))
00264 return FALSE;
00265 }
00266 return TRUE;
00267 }
00268
00269
00270
00271 void
00272 Create_Unique_Defs_For_TNs (void)
00273 {
00274
00275
00276
00277 BB *bb;
00278 OP *op;
00279 TN *tn;
00280 BB_SET *bbdef_set;
00281 BB_SET *bbuse_set;
00282 INT i, j;
00283 INT opt_count = 0;
00284
00285 tracing = Get_Trace(TP_EBO, 0x400);
00286 MEM_POOL_Initialize (&def_info_pool, "def_info_pool", FALSE);
00287 MEM_POOL_Push(&def_info_pool);
00288
00289 tn_def_bbs = TN_MAP_Create();
00290 tn_use_bbs = TN_MAP_Create();
00291
00292
00293
00294
00295 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
00296 FOR_ALL_BB_OPs (bb, op) {
00297
00298 for (i = 0; i < OP_opnds(op); i++) {
00299 tn = OP_opnd(op,i);
00300 if (!TN_is_register(tn))
00301 continue;
00302 bbuse_set = (BB_SET*) TN_MAP_Get (tn_use_bbs, tn);
00303 if (bbuse_set == NULL) {
00304 bbuse_set = BB_SET_Create_Empty (PU_BB_Count+2, &def_info_pool);
00305 bbuse_set = BB_SET_Union1D (bbuse_set, bb, &def_info_pool);
00306 }
00307 else {
00308 bbuse_set = BB_SET_Union1D (bbuse_set, bb, &def_info_pool);
00309 }
00310 TN_MAP_Set (tn_use_bbs, tn, bbuse_set);
00311 }
00312
00313 for (i = 0; i < OP_results(op); i++) {
00314 tn = OP_result(op,i);
00315 if (!TN_is_register(tn))
00316 continue;
00317 bbdef_set = (BB_SET*) TN_MAP_Get (tn_def_bbs, tn);
00318 if (bbdef_set == NULL) {
00319 bbdef_set = BB_SET_Create_Empty (PU_BB_Count+2, &def_info_pool);
00320 bbdef_set = BB_SET_Union1D (bbdef_set, bb, &def_info_pool);
00321 }
00322 else if (BB_SET_MemberP(bbdef_set, bb)) {
00323
00324
00325 bbdef_set = BB_SET_Union1D (bbdef_set, bb, &def_info_pool);
00326 bbdef_set = BB_SET_Union1D (bbdef_set, REGION_First_BB, &def_info_pool);
00327 }
00328 else {
00329 bbdef_set = BB_SET_Union1D (bbdef_set, bb, &def_info_pool);
00330 }
00331 TN_MAP_Set (tn_def_bbs, tn, bbdef_set);
00332 }
00333 }
00334 }
00335
00336 TN_NUM tnum;
00337 BB *dbbs[4];
00338 TN *dtns[4];
00339
00340 for (tnum = First_REGION_TN; tnum <= Last_TN; ++tnum) {
00341 tn = TNvec(tnum);
00342 bbdef_set = (BB_SET*) TN_MAP_Get (tn_def_bbs, tn);
00343 if (bbdef_set == NULL)
00344 continue;
00345 if (BB_SET_Size(bbdef_set) == 1) {
00346 Set_TN_has_one_def(tn);
00347 continue;
00348 }
00349
00350 if (Defs_Can_Be_Merged (tn)) {
00351
00352 bbdef_set = (BB_SET*) TN_MAP_Get (tn_def_bbs, tn);
00353 if (BB_SET_Size(bbdef_set) == 1)
00354 continue;
00355 }
00356
00357 if (BB_SET_MemberP(bbdef_set, REGION_First_BB))
00358 continue;
00359 if (BB_SET_Size(bbdef_set) > 4)
00360 continue;
00361
00362 if (Each_Use_Has_Single_Def(tn)) {
00363 ++opt_count;
00364
00365 if (tracing)
00366 fprintf(TFile, "%d: TN%d defs are independent\n",
00367 opt_count, TN_number(tn));
00368 }
00369 else
00370 continue;
00371
00372 if (tracing) { Print_TN (tn, TRUE); fprintf(TFile, "\n"); }
00373
00374
00375 for (i = 0; i < 4; ++i) {
00376 dbbs[i] = NULL;
00377 dtns[i] = NULL;
00378 }
00379 i = 0;
00380 FOR_ALL_BB_SET_members (bbdef_set, bb) {
00381 dbbs[i] = bb;
00382 dtns[i] = Dup_TN(tn);
00383 Set_TN_has_one_def(dtns[i]);
00384 if (tracing) fprintf(TFile, "def in bb %d is tn%d\n", BB_id(dbbs[i]), TN_number(dtns[i]));
00385 ++i;
00386 }
00387 bbuse_set = (BB_SET*) TN_MAP_Get (tn_use_bbs, tn);
00388
00389
00390
00391 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
00392 TN *def_tn = NULL;
00393 TN *use_tn = NULL;
00394 if (BB_SET_MemberP(bbdef_set, bb)) {
00395 for (i = 0; i < 4; ++i) {
00396 if (dbbs[i] == bb) {
00397 def_tn = dtns[i];
00398 continue;
00399 }
00400 }
00401 }
00402 if (bbuse_set != NULL && BB_SET_MemberP(bbuse_set, bb)) {
00403 BB *defbb = Def_BB_For_Use (tn, bb);
00404 FmtAssert(defbb, ("defbb null?"));
00405 for (i = 0; i < 4; ++i) {
00406 if (dbbs[i] == defbb)
00407 use_tn = dtns[i];
00408 }
00409 }
00410 if (def_tn || use_tn) {
00411 FOR_ALL_BB_OPs (bb, op) {
00412 for (i = 0; i < OP_results(op); i++) {
00413 if (tn == OP_result(op,i)) {
00414 FmtAssert(def_tn, ("no def_tn?"));
00415 Set_OP_result(op,i, def_tn);
00416 if (TN_from_shared_load(tn)) {
00417 Set_TN_from_shared_load(def_tn);
00418 }
00419 }
00420 }
00421 for (i = 0; i < OP_opnds(op); i++) {
00422 if (tn == OP_opnd(op,i)) {
00423 FmtAssert(use_tn, ("no use_tn?"));
00424 Set_OP_opnd(op,i, use_tn);
00425 }
00426 }
00427 }
00428 }
00429 }
00430 }
00431
00432 TN_MAP_Delete (tn_use_bbs);
00433 TN_MAP_Delete (tn_def_bbs);
00434 MEM_POOL_Pop(&def_info_pool);
00435 MEM_POOL_Delete (&def_info_pool);
00436 }
00437