00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "defs.h"
00025 #include "tracing.h"
00026 #include "errors.h"
00027 #include "wn.h"
00028 #include "bb.h"
00029 #include "bb_set.h"
00030 #include "op.h"
00031 #include "tn.h"
00032 #include "cg.h"
00033 #include "cgtarget.h"
00034 #include "whirl2ops.h"
00035 #include "opt_alias_interface.h"
00036 #include "opt_alias_mgr.h"
00037 #include "findloops.h"
00038
00039 static BOOL tracing = FALSE;
00040 #define Trace(msg) if (tracing) fprintf(TFile, msg "\n");
00041
00042 static BOOL
00043 OP_is_shared_memory (OP *op)
00044 {
00045 if (OP_store(op) || OP_load(op))
00046 return (TN_enum(OP_opnd(op,1)) == ECV_space_shared);
00047 else
00048 return FALSE;
00049 }
00050
00051
00052
00053
00054 static BOOL
00055 Safe_To_Rematerialize_Load_In_BB (OP *load_op, OP *first_op, OP *last_op)
00056 {
00057 OP *op = first_op;
00058 Is_True(op == NULL || OP_bb(first_op) == OP_bb(last_op), ("ops not in same bb?"));
00059 while (op != NULL) {
00060 if (OP_store(op) && OP_is_shared_memory(op)
00061 && OP_is_shared_memory(load_op))
00062 {
00063
00064 WN *load_wn;
00065 WN *store_wn;
00066 ALIAS_RESULT result;
00067 Trace("check alias of load with store");
00068 if (Alias_Manager == NULL) return FALSE;
00069 load_wn = Get_WN_From_Memory_OP(load_op);
00070 store_wn = Get_WN_From_Memory_OP(op);
00071 if (load_wn == NULL || store_wn == NULL)
00072 return FALSE;
00073 result = Aliased(Alias_Manager, load_wn, store_wn);
00074 if (result != NOT_ALIASED)
00075 return FALSE;
00076 }
00077 else if (CGTARG_Is_OP_Barrier(op)) {
00078 Trace("barrier in bb stops remat");
00079 return FALSE;
00080 }
00081 if (op == last_op) break;
00082 op = OP_next(op);
00083 }
00084 return TRUE;
00085 }
00086
00087
00088
00089 static BOOL
00090 Safe_To_Rematerialize_Load (BB *load_bb, OP *load_op, BB *use_bb, OP *use_op)
00091 {
00092 Is_True(load_bb != use_bb, ("bbs are same?"));
00093 if ( ! Safe_To_Rematerialize_Load_In_BB (load_op,
00094 BB_first_op(use_bb), use_op))
00095 return FALSE;
00096
00097 BOOL found = FALSE;
00098 BB *bb = use_bb;
00099 if (BB_Has_One_Pred(use_bb)) {
00100 bb = BB_Unique_Predecessor(use_bb);
00101 }
00102
00103
00104 while (bb != NULL && !found) {
00105 if (bb == load_bb) {
00106 found = TRUE;
00107
00108 return Safe_To_Rematerialize_Load_In_BB (load_op,
00109 OP_next(load_op), BB_last_op(load_bb));
00110 }
00111 else {
00112
00113 if ( ! Safe_To_Rematerialize_Load_In_BB (load_op,
00114 BB_first_op(bb), BB_last_op(bb)))
00115 return FALSE;
00116 }
00117
00118 if (BB_Has_One_Pred(bb)) {
00119 bb = BB_Unique_Predecessor(bb);
00120 }
00121 else {
00122
00123 BB_SET *loopbbs = NULL;
00124 LOOP_DESCR *loopd = LOOP_DESCR_Find_Loop(bb);
00125 if (loopd) {
00126 loopbbs = LOOP_DESCR_bbset(loopd);
00127 if (loopbbs) {
00128
00129
00130 BB *bbl;
00131 FOR_ALL_BB_SET_members(loopbbs, bbl) {
00132 if (bbl == load_bb) {
00133 found = TRUE;
00134 }
00135
00136 if ( ! Safe_To_Rematerialize_Load_In_BB (load_op,
00137 BB_first_op(bbl), BB_last_op(bbl)))
00138 return FALSE;
00139 }
00140 if (found) break;
00141
00142 bbl = LOOP_DESCR_loophead(loopd);
00143 BBLIST *edge;
00144 bb = NULL;
00145 FOR_ALL_BB_PREDS(bbl, edge) {
00146 if ( ! BB_SET_MemberP(loopbbs, BBLIST_item(edge)))
00147 bb = BBLIST_item(edge);
00148 }
00149 }
00150 }
00151 else {
00152
00153 BB *pred1 = NULL;
00154 BB *pred2 = NULL;
00155 BBLIST *edge;
00156 FOR_ALL_BB_PREDS(bb, edge) {
00157 if (pred1 == NULL) pred1 = BBLIST_item(edge);
00158 else if (pred2 == NULL) pred2 = BBLIST_item(edge);
00159 else return FALSE;
00160 }
00161 FmtAssert(pred2, ("pred2 not set?"));
00162
00163 if (BB_Unique_Predecessor(pred2) == pred1) {
00164
00165 if ( ! Safe_To_Rematerialize_Load_In_BB (load_op,
00166 BB_first_op(pred2), BB_last_op(pred2)))
00167 return FALSE;
00168 bb = pred1;
00169 }
00170
00171 else if (BB_Has_One_Pred(pred1)
00172 && (BB_Unique_Predecessor(pred1) == BB_Unique_Predecessor(pred2)))
00173 {
00174
00175 if ( ! Safe_To_Rematerialize_Load_In_BB (load_op,
00176 BB_first_op(pred1), BB_last_op(pred1)))
00177 return FALSE;
00178 if ( ! Safe_To_Rematerialize_Load_In_BB (load_op,
00179 BB_first_op(pred2), BB_last_op(pred2)))
00180 return FALSE;
00181 bb = BB_Unique_Predecessor(pred1);
00182 }
00183 else {
00184
00185 bb = NULL;
00186 }
00187 }
00188 }
00189 }
00190 return found;
00191 }
00192
00193 void
00194 Rematerialize_GRF (void)
00195 {
00196 BB *bb;
00197 OP *op;
00198 TN *tn;
00199 INT i;
00200
00201 tracing = Get_Trace(TP_EBO, 0x100);
00202
00203 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
00204 if (tracing) fprintf(TFile, "rematerialize_grf: bb %d\n", BB_id(bb));
00205 FOR_ALL_BB_OPs (bb, op) {
00206 for (i = 0; i < OP_opnds(op); i++) {
00207 tn = OP_opnd(op,i);
00208 if (TN_from_shared_load(tn)) {
00209 OP *load_op = NULL;
00210 INT j;
00211
00212 load_op = Find_Reaching_Def (tn, op);
00213 if (load_op == NULL)
00214 continue;
00215 if (OP_bb(load_op) == bb)
00216 continue;
00217
00218
00219 if (!OP_load(load_op))
00220 continue;
00221 if (!OP_is_shared_memory(load_op))
00222 continue;
00223
00224 BOOL one_def = TRUE;
00225 TN *base_tn;
00226 for (j = 0; j < OP_opnds(load_op); j++) {
00227 base_tn = OP_opnd(load_op,j);
00228 if (TN_is_register(base_tn)) {
00229
00230 if (TN_has_one_def(base_tn))
00231 continue;
00232 else {
00233 OP *base1_op = Find_Reaching_Def (base_tn, load_op);
00234 OP *base2_op = Find_Reaching_Def (base_tn, op);
00235 if (base1_op != NULL && base1_op == base2_op)
00236 continue;
00237 else {
00238 Trace("base defs don't match");
00239 one_def = FALSE;
00240 }
00241 }
00242 }
00243 }
00244 if (one_def) {
00245 if (Safe_To_Rematerialize_Load (OP_bb(load_op), load_op, bb, op)) {
00246 Trace("safe to insert shared load at use");
00247 OP *new_op = Dup_OP(load_op);
00248 BB_Insert_Op_Before (bb, op, new_op);
00249 }
00250 }
00251 }
00252 }
00253 }
00254 }
00255 }