static int implement_lospre_assignment(const assignment_lospre a, T_t &T, G_t &G, const iCode *ic) // Assignment has to be passed as a copy (not reference), since the transformations on the tree-decomposition will invalidate it otherwise. { operand *tmpop; unsigned substituted = 0, split = 0; typedef typename boost::graph_traits<G_t>::edge_iterator edge_iter_t; typedef typename boost::graph_traits<G_t>::edge_descriptor edge_desc_t; std::set<edge_desc_t> calculation_edges; // Use descriptor, not iterator due to possible invalidation of iterators when inserting vertices or edges. edge_iter_t e, e_end; for(boost::tie(e, e_end) = boost::edges(G); e != e_end; ++e) if(!((a.global[boost::source(*e, G)] & true) && !G[boost::source(*e, G)].invalidates) && (a.global[boost::target(*e, G)] & true)) calculation_edges.insert(*e); if(!calculation_edges.size()) return(0); #ifdef DEBUG_LOSPRE std::cout << "Optimizing at " << ic->key << "\n"; std::cout.flush(); #endif tmpop = newiTempOperand (operandType (IC_RESULT (ic)), TRUE); tmpop->isvolatile = false; #ifdef DEBUG_LOSPRE std::cout << "New tmpop: " << OP_SYMBOL_CONST(tmpop)->name << " "; printTypeChain(operandType (IC_RESULT(ic)), stdout); std::cout << "\n"; #endif for(typename std::set<edge_desc_t>::iterator i = calculation_edges.begin(); i != calculation_edges.end(); ++i) { split_edge(T, G, *i, ic, tmpop); split++; } typedef typename boost::graph_traits<G_t>::vertex_iterator vertex_iter_t; vertex_iter_t v, v_end; for(boost::tie(v, v_end) = boost::vertices(G); v != v_end; ++v) { if(!G[*v].uses) continue; typename boost::graph_traits<G_t>::in_edge_iterator e = in_edges(*v, G).first; if (a.global.size() <= *v) continue; if(!((a.global[*v] & true) && !G[*v].invalidates || boost::source(*e, G) < a.global.size() && (a.global[boost::source(*e, G)] & true))) continue; #ifdef DEBUG_LOSPRE std::cout << "Substituting ic " << G[*v].ic->key << "\n"; #endif substituted++; iCode *ic = G[*v].ic; //if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic))) // bitVectUnSetBit (OP_SYMBOL (IC_LEFT (ic))->uses, ic->key); //if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic))) // bitVectUnSetBit (OP_SYMBOL (IC_RIGHT (ic))->uses, ic->key); IC_RIGHT(ic) = tmpop; //bitVectSetBit (OP_SYMBOL (IC_RIGHT(ic))->uses, ic->key); if (!POINTER_SET (ic)) { IC_LEFT(ic) = 0; ic->op = '='; IC_RESULT(ic) = operandFromOperand (IC_RESULT (ic)); IC_RESULT(ic)->isaddr = 0; } if(IS_OP_VOLATILE(IC_RESULT (ic))) continue; { typedef typename boost::graph_traits<G_t>::adjacency_iterator adjacency_iter_t; adjacency_iter_t c, c_end; boost::tie(c, c_end) = adjacent_vertices(*v, G); if (c != c_end) forward_lospre_assignment(G, *c, ic, a); } } if(substituted <= 0) { std::cerr << "Introduced " << OP_SYMBOL_CONST(tmpop)->name << ", but did not substitute any calculations.\n"; return (-1); } if(substituted < split) // Todo: Remove this warning when optimization for speed instead of code size is implemented! std::cout << "Introduced " << OP_SYMBOL_CONST(tmpop)->name << ", but did substitute only " << substituted << " calculations, while introducing "<< split << ".\n"; std::cout.flush(); return(1); }
/*-----------------------------------------------------------------*/ void separateLiveRanges (iCode *sic, ebbIndex *ebbi) { iCode *ic; set *candidates = 0; symbol *sym; // printf("separateLiveRanges()\n"); for (ic = sic; ic; ic = ic->next) { if (ic->op == IFX || ic->op == GOTO || ic->op == JUMPTABLE || !IC_RESULT (ic) || !IS_ITEMP (IC_RESULT (ic)) || bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) <= 1 || isinSet (candidates, OP_SYMBOL (IC_RESULT (ic)))) continue; addSet (&candidates, OP_SYMBOL (IC_RESULT (ic))); } if (!candidates) return; for(sym = setFirstItem (candidates); sym; sym = setNextItem (candidates)) { // printf("Looking at %s, %d definitions\n", sym->name, bitVectnBitsOn (sym->defs)); int i; set *defs = 0; for (i = 0; i < sym->defs->size; i++) if (bitVectBitValue (sym->defs, i)) { iCode *dic; if(dic = hTabItemWithKey (iCodehTab, i)) addSet (&defs, hTabItemWithKey (iCodehTab, i)); else { werror (W_INTERNAL_ERROR, __FILE__, __LINE__, "Definition not found"); return; } } do { set *visited = 0; set *newdefs = 0; int oldsize; wassert (defs); wassert (setFirstItem (defs)); // printf("Looking at def at %d now\n", ((iCode *)(setFirstItem (defs)))->key); if (!bitVectBitValue (((iCode *)(setFirstItem (defs)))->rlive, sym->key)) { werror (W_INTERNAL_ERROR, __FILE__, __LINE__, "Variable is not alive at one of its definitions"); break; } visit (&visited, setFirstItem (defs), sym->key); addSet (&newdefs, setFirstItem (defs)); do { oldsize = elementsInSet(visited); ic = setFirstItem (defs); for(ic = setNextItem (defs); ic; ic = setNextItem (defs)) { // printf("Looking at other def at %d now\n", ic->key); set *visited2 = 0; set *intersection = 0; visit (&visited2, ic, sym->key); intersection = intersectSets (visited, visited2, THROW_NONE); intersection = subtractFromSet (intersection, defs, THROW_DEST); if (intersection) { visited = unionSets (visited, visited2, THROW_DEST); addSet (&newdefs, ic); } deleteSet (&intersection); deleteSet (&visited2); } } while (oldsize < elementsInSet(visited)); defs = subtractFromSet (defs, newdefs, THROW_DEST); if (newdefs && defs) { operand *tmpop = newiTempOperand (operandType (IC_RESULT ((iCode *)(setFirstItem (newdefs)))), TRUE); // printf("Splitting %s from %s, using def at %d, op %d\n", OP_SYMBOL_CONST(tmpop)->name, sym->name, ((iCode *)(setFirstItem (newdefs)))->key, ((iCode *)(setFirstItem (newdefs)))->op); for (ic = setFirstItem (visited); ic; ic = setNextItem (visited)) { if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic)) == sym) IC_LEFT (ic) = operandFromOperand (tmpop); if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)) && OP_SYMBOL (IC_RIGHT (ic)) == sym) IC_RIGHT (ic) = operandFromOperand (tmpop); if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)) && OP_SYMBOL (IC_RESULT (ic)) == sym && !POINTER_SET(ic) && ic->next && !isinSet (visited, ic->next)) continue; if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)) && OP_SYMBOL (IC_RESULT (ic)) == sym) { bool pset = POINTER_SET(ic); IC_RESULT (ic) = operandFromOperand (tmpop); if (pset) IC_RESULT(ic)->isaddr = TRUE; } bitVectUnSetBit (sym->uses, ic->key); } } deleteSet (&newdefs); deleteSet (&visited); } while (elementsInSet(defs) > 1); deleteSet (&defs); } deleteSet (&candidates); }