static void visit (set **visited, iCode *ic, const int key) { symbol *lbl; while (ic && !isinSet (*visited, ic) && bitVectBitValue (ic->rlive, key)) { addSet (visited, ic); switch (ic->op) { case GOTO: ic = hTabItemWithKey (labelDef, (IC_LABEL (ic))->key); break; case RETURN: ic = hTabItemWithKey (labelDef, returnLabel->key); break; case JUMPTABLE: for (lbl = setFirstItem (IC_JTLABELS (ic)); lbl; lbl = setNextItem (IC_JTLABELS (ic))) visit (visited, hTabItemWithKey (labelDef, lbl->key), key); break; case IFX: visit (visited, hTabItemWithKey (labelDef, (IC_TRUE(ic) ? IC_TRUE (ic) : IC_FALSE (ic))->key), key); ic = ic->next; break; default: ic = ic->next; if (!POINTER_SET (ic) && IC_RESULT (ic) && IS_SYMOP (IC_RESULT (ic)) && OP_SYMBOL_CONST (IC_RESULT (ic))->key == key) { addSet (visited, ic); return; } } } }
static void split_edge(T_t &T, G_t &G, typename boost::graph_traits<G_t>::edge_descriptor e, const iCode *ic, operand *tmpop) { // Insert new iCode into chain. iCode *newic = newiCode (ic->op, IC_LEFT (ic), IC_RIGHT (ic)); IC_RESULT(newic) = tmpop; newic->filename = ic->filename; newic->lineno = ic->lineno; newic->prev = G[boost::source(e, G)].ic; newic->next = G[boost::target(e, G)].ic; G[boost::source(e, G)].ic->next = newic; G[boost::target(e, G)].ic->prev = newic; //if (ic->op != ADDRESS_OF && IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic))) // bitVectSetBit (OP_SYMBOL (IC_LEFT (ic))->uses, ic->key); //if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic))) // bitVectSetBit (OP_SYMBOL (IC_RIGHT (ic))->uses, ic->key); //bitVectSetBit (OP_SYMBOL (IC_RESULT (ic))->defs, ic->key); // Insert node into cfg. typename boost::graph_traits<G_t>::vertex_descriptor n = boost::add_vertex(G); // TODO: Exact cost. G[n].ic = newic; G[n].uses = false; boost::add_edge(boost::source(e, G), n, G[e], G); boost::add_edge(n, boost::target(e, G), 3.0, G); #ifdef DEBUG_LOSPRE std::cout << "Calculating " << OP_SYMBOL_CONST(tmpop)->name << " at ic " << newic->key << "\n"; #endif // Update tree-decomposition. // TODO: More efficiently. for(typename boost::graph_traits<T_t>::vertex_descriptor n1 = 0; n1 < boost::num_vertices(T); ++n1) { if(T[n1].bag.find(boost::source(e, G)) == T[n1].bag.end()) continue; if(T[n1].bag.find(boost::target(e, G)) == T[n1].bag.end()) continue; // Found bag that contains both endpoints of original edge. // Add new tree node with bag there. Let nicify() sort things out later. typename boost::graph_traits<T_t>::vertex_descriptor n2 = boost::add_vertex(T); T[n2].bag.insert(boost::source(e, G)); T[n2].bag.insert(boost::target(e, G)); T[n2].bag.insert(n); boost::add_edge(n1, n2, T); break; } // Remove old edge from cfg. boost::remove_edge(e, G); }
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); }
static void forward_lospre_assignment(G_t &G, typename boost::graph_traits<G_t>::vertex_descriptor i, const iCode *ic, const assignment_lospre& a) { typedef typename boost::graph_traits<G_t>::adjacency_iterator adjacency_iter_t; adjacency_iter_t c, c_end; operand *tmpop = IC_RIGHT(ic); const std::pair<int, int> forward(IC_RESULT(ic)->key, IC_RIGHT(ic)->key); for(;;) { if (G[i].forward == forward) break; // Was here before. iCode *nic = G[i].ic; if (isOperandEqual(IC_RESULT(ic), IC_LEFT(nic)) && nic->op != ADDRESS_OF && (!POINTER_GET(nic) || !IS_PTR(operandType(IC_RESULT(nic))) || !IS_BITFIELD(operandType(IC_LEFT(nic))->next) || compareType(operandType(IC_LEFT(nic)), operandType(tmpop)) == 1)) { bool isaddr = IC_LEFT (nic)->isaddr; #ifdef DEBUG_LOSPRE std::cout << "Forward substituted left operand " << OP_SYMBOL_CONST(IC_LEFT(nic))->name << " at " << nic->key << "\n"; #endif //bitVectUnSetBit (OP_SYMBOL (IC_LEFT (nic))->uses, nic->key); IC_LEFT(nic) = operandFromOperand (tmpop); //bitVectSetBit (OP_SYMBOL (IC_LEFT (nic))->uses, nic->key); IC_LEFT (nic)->isaddr = isaddr; } if (isOperandEqual(IC_RESULT(ic), IC_RIGHT(nic))) { #ifdef DEBUG_LOSPRE std::cout << "Forward substituted right operand " << OP_SYMBOL_CONST(IC_RIGHT(nic))->name << " at " << nic->key << "\n"; #endif //bitVectUnSetBit (OP_SYMBOL (IC_RIGHT (nic))->uses, nic->key); IC_RIGHT(nic) = operandFromOperand (tmpop); //bitVectSetBit (OP_SYMBOL (IC_RIGHT (nic))->uses, nic->key); } if (POINTER_SET(nic) && isOperandEqual(IC_RESULT(ic), IC_RESULT(nic)) && (!IS_PTR(operandType(IC_RESULT(nic))) || !IS_BITFIELD(operandType(IC_RESULT(nic))->next) || compareType(operandType(IC_RESULT(nic)), operandType(tmpop)) == 1)) { #ifdef DEBUG_LOSPRE std::cout << "Forward substituted result operand " << OP_SYMBOL_CONST(IC_RESULT(nic))->name << " at " << nic->key << "\n"; #endif //bitVectUnSetBit (OP_SYMBOL (IC_RESULT (nic))->uses, nic->key); IC_RESULT(nic) = operandFromOperand (tmpop); IC_RESULT(nic)->isaddr = true; //bitVectSetBit (OP_SYMBOL (IC_RESULT (nic))->uses, nic->key); } if (nic->op == LABEL) // Reached label. Continue only if all edges goining here are safe. { typedef typename boost::graph_traits<G_t>::in_edge_iterator in_edge_iter_t; in_edge_iter_t e, e_end; for (boost::tie(e, e_end) = boost::in_edges(i, G); e != e_end; ++e) if (G[boost::source(*e, G)].forward != forward) break; if(e != e_end) break; } if (isOperandEqual(IC_RESULT (ic), IC_RESULT(nic)) && !POINTER_SET(nic) /*|| G[i].uses*/) break; if ((nic->op == CALL || nic->op == PCALL || POINTER_SET(nic)) && IS_TRUE_SYMOP(IC_RESULT(ic))) break; G[i].forward = forward; if (nic->op == GOTO || nic->op == IFX || nic->op == JUMPTABLE) { adjacency_iter_t c, c_end; for(boost::tie(c, c_end) = boost::adjacent_vertices(i, G); c != c_end; ++c) { if(!((a.global[i] & true) && !G[i].invalidates) && (a.global[*c] & true)) // Calculation edge continue; forward_lospre_assignment(G, *c, ic, a); } break; } boost::tie(c, c_end) = adjacent_vertices(i, G); if(c == c_end) break; if(!((a.global[i] & true) && !G[i].invalidates) && (a.global[*c] & true)) // Calculation edge break; i = *c; } }