/*-----------------------------------------------------------------------*/ static iCode * findPointerGetSet (iCode * sic, operand * op) { iCode *ic = sic; for (; ic; ic = ic->next) { if ((POINTER_SET (ic) && isOperandEqual (op, IC_RESULT (ic))) || (POINTER_GET (ic) && isOperandEqual (op, IC_LEFT (ic)))) return ic; /* if we find any other usage or definition of op null */ if (IC_RESULT (ic) && isOperandEqual (IC_RESULT (ic), op)) return NULL; if (IC_RIGHT (ic) && isOperandEqual (IC_RIGHT (ic), op)) return NULL; if (IC_LEFT (ic) && isOperandEqual (IC_LEFT (ic), op)) return NULL; } return NULL; }
/*-----------------------------------------------------------------*/ void replaceSymBySym (set * sset, operand * src, operand * dest) { set *loop; eBBlock *rBlock; /* for all blocks in the set do */ for (loop = sset; loop; loop = loop->next) { iCode *ic; rBlock = loop->item; /* for all instructions in this block do */ for (ic = rBlock->sch; ic; ic = ic->next) { /* if we find usage */ if (ic->op == IFX && isOperandEqual (src, IC_COND (ic))) { bitVectUnSetBit (OP_USES (IC_COND (ic)), ic->key); IC_COND (ic) = operandFromOperand (dest); OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key); continue; } if (isOperandEqual (IC_RIGHT (ic), src)) { bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key); IC_RIGHT (ic) = operandFromOperand (dest); IC_RIGHT (ic)->isaddr = 0; OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key); } if (isOperandEqual (IC_LEFT (ic), src)) { bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key); if (POINTER_GET (ic) && IS_ITEMP (dest)) { IC_LEFT (ic) = operandFromOperand (dest); IC_LEFT (ic)->isaddr = 1; } else { IC_LEFT (ic) = operandFromOperand (dest); IC_LEFT (ic)->isaddr = 0; } OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key); } /* special case for pointer sets */ if (POINTER_SET (ic) && isOperandEqual (IC_RESULT (ic), src)) { bitVectUnSetBit (OP_USES (IC_RESULT (ic)), ic->key); IC_RESULT (ic) = operandFromOperand (dest); IC_RESULT (ic)->isaddr = 1; OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key); } } } }
/*-----------------------------------------------------------------*/ iCode * usedInRemaining (operand * op, iCode * ic) { iCode *lic = ic; if (!IS_SYMOP (op)) return 0; for (; lic; lic = lic->next) { /* if the operand is a parameter */ /* then check for calls and return */ /* true if there is a call */ /* if this is a global variable then return true */ if (lic->op == CALL || lic->op == PCALL) { if ((IS_PARM (op) && isParameterToCall (IC_ARGS (lic), op)) || isOperandGlobal (op)) return lic; } if (ic->op == SEND && isOperandEqual (IC_LEFT (lic), op)) return lic; if (SKIP_IC1 (lic)) continue; /* if ifx then check the condition */ if (lic->op == IFX && isOperandEqual (IC_COND (lic), op)) return lic; if (lic->op == JUMPTABLE && isOperandEqual (IC_JTCOND (lic), op)) return lic; if (IC_RIGHT (lic) && isOperandEqual (IC_RIGHT (lic), op)) return lic; if (IC_LEFT (lic) && isOperandEqual (IC_LEFT (lic), op)) return lic; /* for a pointer assignment usage */ if (POINTER_SET (lic) && isOperandEqual (op, IC_RESULT (lic))) return lic; else if (IC_RESULT (lic) && isOperandEqual (IC_RESULT (lic), op)) return NULL; } return NULL; }
/*-----------------------------------------------------------------*/ int usedBetweenPoints (operand * op, iCode * start, iCode * end) { iCode *lic = start; for (; lic != end; lic = lic->next) { /* if the operand is a parameter */ /* then check for calls and return */ /* true if there is a call */ if (IS_PARM (op) && (lic->op == CALL || lic->op == PCALL)) if (isParameterToCall (IC_ARGS (lic), op)) return 1; if (SKIP_IC2 (lic)) continue; /* if ifx then check the condition */ if (lic->op == IFX && IC_COND (lic)->key == op->key) return 1; if (lic->op == JUMPTABLE && IC_JTCOND (lic)->key == op->key) return 1; if (IC_RIGHT (lic) && IC_RIGHT (lic)->key == op->key) return 1; if (IC_LEFT (lic) && IC_LEFT (lic)->key == op->key) return 1; /* for a pointer assignment usage */ if (POINTER_SET (lic) && op->key == IC_RESULT (lic)->key) return 1; else if (IC_RESULT (lic) && op->key == IC_RESULT (lic)->key) return 0; } return 0; }
/*-----------------------------------------------------------------------*/ static int addPattern1(iCode *ic) { iCode *dic; operand *tmp; /* transform : iTempAA = iTempBB + iTempCC iTempDD = iTempAA + CONST to iTempAA = iTempBB + CONST iTempDD = iTempAA + iTempCC */ if (!isOperandLiteral(IC_RIGHT(ic))) return 0; if ((dic=findBackwardDef(IC_LEFT(ic),ic->prev)) == NULL) return 0; if (bitVectnBitsOn(OP_SYMBOL(IC_RESULT(dic))->uses) > 1) return 0; if (dic->op != '+') return 0; tmp = IC_RIGHT(ic); IC_RIGHT(ic) = IC_RIGHT(dic); IC_RIGHT(dic) = tmp; return 1; }
static int pattern1 (iCode *sic) { /* this is what we do. look for sequences like iTempX := _SOME_POINTER_; iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) sic->next _SOME_POINTER_ := iTempY; sic->next->next either iTempZ := @[iTempX]; sic->next->next->next or *(iTempX) := ..something.. sic->next->next->next if we find this then transform this to iTempX := _SOME_POINTER_; either iTempZ := @[iTempX]; or *(iTempX) := ..something.. iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) _SOME_POINTER_ := iTempY; */ /* sounds simple enough so let's start , here I use negative tests all the way to return if any test fails */ iCode *pgs, *sh, *st; if (!(sic->next && sic->next->next && sic->next->next->next)) return 0; if (sic->next->op != '+' && sic->next->op != '-') return 0; if (!(sic->next->next->op == '=' && !POINTER_SET (sic->next->next))) return 0; if (!isOperandEqual (IC_LEFT (sic->next), IC_RIGHT (sic)) || !IS_OP_LITERAL (IC_RIGHT (sic->next))) return 0; if (operandLitValue (IC_RIGHT (sic->next)) != getSize (operandType (IC_RIGHT (sic))->next)) return 0; if (!isOperandEqual (IC_RESULT (sic->next->next), IC_RIGHT (sic))) return 0; if (!isOperandEqual (IC_RESULT (sic->next), IC_RIGHT (sic->next->next))) return 0; if (!(pgs = findPointerGetSet (sic->next->next, IC_RESULT (sic)))) return 0; /* found the pattern .. now do the transformation */ sh = sic->next; st = sic->next->next; /* take the two out of the chain */ sic->next = st->next; st->next->prev = sic; /* and put them after the pointer get/set icode */ if ((st->next = pgs->next)) st->next->prev = st; pgs->next = sh; sh->prev = pgs; return 1; }
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 pattern2 (iCode *sic) { /* this is what we do. look for sequences like iTempX := _SOME_POINTER_; iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) sic->next iTempK := iTempY; sic->next->next _SOME_POINTER_ := iTempK; sic->next->next->next either iTempZ := @[iTempX]; sic->next->next->next->next or *(iTempX) := ..something.. sic->next->next->next->next if we find this then transform this to iTempX := _SOME_POINTER_; either iTempZ := @[iTempX]; or *(iTempX) := ..something.. iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) iTempK := iTempY; _SOME_POINTER_ := iTempK; */ /* sounds simple enough so let's start , here I use negative tests all the way to return if any test fails */ iCode *pgs, *sh, *st; if (!(sic->next && sic->next->next && sic->next->next->next && sic->next->next->next->next)) return 0; /* yes I can OR them together and make one large if... but I have simple mind and like to keep things simple & readable */ if (!(sic->next->op == '+' || sic->next->op == '-')) return 0; if (!isOperandEqual(IC_RIGHT(sic),IC_LEFT(sic->next))) return 0; if (!IS_OP_LITERAL (IC_RIGHT (sic->next))) return 0; if (operandLitValue (IC_RIGHT (sic->next)) != getSize (operandType (IC_RIGHT (sic))->next)) return 0; if (!IS_ASSIGN_ICODE(sic->next->next)) return 0; if (!isOperandEqual(IC_RIGHT(sic->next->next),IC_RESULT(sic->next))) return 0; if (!IS_ASSIGN_ICODE(sic->next->next->next)) return 0; if (!isOperandEqual(IC_RIGHT(sic->next->next->next),IC_RESULT(sic->next->next))) return 0; if (!isOperandEqual(IC_RESULT(sic->next->next->next),IC_LEFT(sic->next))) return 0; if (!(pgs = findPointerGetSet (sic->next->next->next, IC_RESULT (sic)))) return 0; /* found the pattern .. now do the transformation */ sh = sic->next; st = sic->next->next->next; /* take the three out of the chain */ sic->next = st->next; st->next->prev = sic; /* and put them after the pointer get/set icode */ if ((st->next = pgs->next)) st->next->prev = st; pgs->next = sh; sh->prev = pgs; return 1; }
static bool _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right) { sym_link *test = NULL; value *val; if ( ic->op != '*') { return FALSE; } if ( IS_LITERAL (left)) { test = left; val = OP_VALUE (IC_LEFT (ic)); } else if ( IS_LITERAL (right)) { test = right; val = OP_VALUE (IC_RIGHT (ic)); } /* 8x8 unsigned multiplication code is shorter than call overhead for the multiplication routine. */ else if ( IS_CHAR (right) && IS_UNSIGNED (right) && IS_CHAR (left) && IS_UNSIGNED(left) && !IS_GB) { return TRUE; } else { return FALSE; } if ( getSize (test) <= 2) { return TRUE; } return FALSE; }
/*--------------------------------------------------------------------*/ void ptrPseudoSymConvert (symbol *sym, iCode *dic, char *name) { symbol *psym = newSymbol (name, 1); psym->psbase = ptrBaseRematSym (OP_SYMBOL (IC_LEFT (dic))); psym->type = sym->type; psym->etype = psym->psbase->etype; strcpy (psym->rname, psym->name); sym->isspilt = 1; sym->usl.spillLoc = psym; #if 0 // an alternative fix for bug #480076 /* now this is a useless assignment to itself */ remiCodeFromeBBlock (ebbs, dic); #else /* now this really is an assignment to itself, make it so; it will be optimized out later */ dic->op='='; ReplaceOpWithCheaperOp(&IC_RIGHT(dic), IC_RESULT(dic)); IC_LEFT(dic)=NULL; #endif }
/*--------------------------------------------------------------------*/ symbol * ptrBaseRematSym (symbol *ptrsym) { iCode * ric; if (!ptrsym->remat) return NULL; ric = ptrsym->rematiCode; while (ric) { if (ric->op == '+' || ric->op == '-') ric = OP_SYMBOL (IC_LEFT (ric))->rematiCode; else if (IS_CAST_ICODE (ric)) ric = OP_SYMBOL (IC_RIGHT (ric))->rematiCode; else break; } if (ric && IS_SYMOP (IC_LEFT (ric))) return OP_SYMBOL (IC_LEFT (ric)); else return NULL; }
static void RegFix (eBBlock ** ebbs, int count) { int i; /* Check for and fix any problems with uninitialized operands */ for (i = 0; i < count; i++) { iCode *ic; if (ebbs[i]->noPath && (ebbs[i]->entryLabel != entryLabel && ebbs[i]->entryLabel != returnLabel)) continue; for (ic = ebbs[i]->sch; ic; ic = ic->next) { if (SKIP_IC2 (ic)) continue; if (ic->op == IFX) { verifyRegsAssigned (IC_COND (ic), ic); continue; } if (ic->op == JUMPTABLE) { verifyRegsAssigned (IC_JTCOND (ic), ic); continue; } verifyRegsAssigned (IC_RESULT (ic), ic); verifyRegsAssigned (IC_LEFT (ic), ic); verifyRegsAssigned (IC_RIGHT (ic), ic); } } }
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; } }
/*-----------------------------------------------------------------*/ int killDeadCode (eBBlock ** ebbs, int count) { int change = 1; int gchange = 0; int i = 0; /* basic algorithm :- */ /* first the exclusion rules :- */ /* 1. if result is a global or volatile then skip */ /* 2. if assignment and result is a temp & isaddr then skip */ /* since this means array & pointer access, will be taken */ /* care of by alias analysis. */ /* 3. if the result is used in the remainder of the block skip */ /* 4. if this definition does not reach the end of the block */ /* i.e. the result is not present in the outExprs then KILL */ /* 5. if it reaches the end of block & is used by some success */ /* or then skip */ /* else KILL */ /* this whole process is carried on iteratively till no change */ while (1) { change = 0; /* for all blocks do */ for (i = 0; i < count; i++) { iCode *ic; /* for all instructions in the block do */ for (ic = ebbs[i]->sch; ic; ic = ic->next) { int kill, j; kill = 0; if (SKIP_IC (ic) || ic->op == IFX || ic->op == RETURN) continue; /* if the result is volatile then continue */ if (IC_RESULT (ic) && isOperandVolatile (IC_RESULT (ic), FALSE)) continue; /* if the result is a temp & isaddr then skip */ if (IC_RESULT (ic) && POINTER_SET (ic)) continue; /* if the result is used in the remainder of the */ /* block then skip */ if (usedInRemaining (IC_RESULT (ic), ic->next)) continue; /* does this definition reach the end of the block or the usage is zero then we can kill */ if (!bitVectBitValue (ebbs[i]->outDefs, ic->key)) kill = 1; /* if not we can kill it */ else { /* if this is a global variable or function parameter */ /* we cannot kill anyway */ if (isOperandGlobal (IC_RESULT (ic)) || (OP_SYMBOL (IC_RESULT (ic))->_isparm && !OP_SYMBOL (IC_RESULT (ic))->ismyparm)) continue; /* if we are sure there are no usages */ if (bitVectIsZero (OP_USES (IC_RESULT (ic)))) { kill = 1; goto kill; } /* reset visited flag */ for (j = 0; j < count; ebbs[j++]->visited = 0); /* find out if this definition is alive */ if (applyToSet (ebbs[i]->succList, isDefAlive, ic)) continue; kill = 1; } kill: /* kill this one if required */ if (kill) { change = 1; gchange++; /* eliminate this */ remiCodeFromeBBlock (ebbs[i], ic); /* now delete from defUseSet */ deleteItemIf (&ebbs[i]->outExprs, ifDiCodeIsX, ic); bitVectUnSetBit (ebbs[i]->outDefs, ic->key); /* and defset of the block */ bitVectUnSetBit (ebbs[i]->defSet, ic->key); /* for the left & right remove the usage */ if (IS_SYMOP (IC_LEFT (ic))) bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key); if (IS_SYMOP (IC_RIGHT (ic))) bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key); } } /* end of all instructions */ if (!ebbs[i]->sch && !ebbs[i]->noPath) disconBBlock (ebbs[i], ebbs, count); } /* end of for all blocks */ if (!change) break; } /* end of while(1) */ return gchange; }
/*-----------------------------------------------------------------*/ static void cnvToFcall (iCode * ic, eBBlock * ebp) { iCode *ip; iCode *newic; operand *left; operand *right; symbol *func = NULL; int lineno = ic->lineno; int bytesPushed=0; ip = ic->next; /* insertion point */ /* remove it from the iCode */ remiCodeFromeBBlock (ebp, ic); left = IC_LEFT (ic); right = IC_RIGHT (ic); switch (ic->op) { case '+': func = __fsadd; break; case '-': func = __fssub; break; case '/': func = __fsdiv; break; case '*': func = __fsmul; break; case EQ_OP: func = __fseq; break; case NE_OP: func = __fsneq; break; case '<': func = __fslt; break; case '>': func = __fsgt; break; case LE_OP: func = __fslteq; break; case GE_OP: func = __fsgteq; break; } /* if float support routines NOT compiled as reentrant */ if (!options.float_rent) { /* first one */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) { newic = newiCode (SEND, IC_LEFT (ic), NULL); } else { newic = newiCode ('=', NULL, IC_LEFT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* second one */ if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) { newic = newiCode (SEND, IC_LEFT (ic), NULL); } else { newic = newiCode ('=', NULL, IC_RIGHT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } else { /* push right */ if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) { newic = newiCode (SEND, right, NULL); } else { newic = newiCode (IPUSH, right, NULL); newic->parmPush = 1; bytesPushed+=4; } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* insert push left */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) { newic = newiCode (SEND, left, NULL); } else { newic = newiCode (IPUSH, left, NULL); newic->parmPush = 1; bytesPushed+=4; } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } /* insert the call */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); newic->lineno = lineno; newic->parmBytes+=bytesPushed; addiCodeToeBBlock (ebp, newic, ip); }
/*-----------------------------------------------------------------*/ static void replaceRegEqv (eBBlock ** ebbs, int count) { int i; for (i = 0; i < count; i++) { iCode *ic; for (ic = ebbs[i]->sch; ic; ic = ic->next) { if (SKIP_IC2 (ic)) continue; if (ic->op == IFX) { if (IS_TRUE_SYMOP (IC_COND (ic)) && OP_REQV (IC_COND (ic))) IC_COND (ic) = opFromOpWithDU (OP_REQV (IC_COND (ic)), OP_SYMBOL (IC_COND (ic))->defs, OP_SYMBOL (IC_COND (ic))->uses); continue; } if (ic->op == JUMPTABLE) { if (IS_TRUE_SYMOP (IC_JTCOND (ic)) && OP_REQV (IC_JTCOND (ic))) IC_JTCOND (ic) = opFromOpWithDU (OP_REQV (IC_JTCOND (ic)), OP_SYMBOL (IC_JTCOND (ic))->defs, OP_SYMBOL (IC_JTCOND (ic))->uses); continue; } if (ic->op == RECEIVE) { if (OP_SYMBOL (IC_RESULT (ic))->addrtaken) OP_SYMBOL (IC_RESULT (ic))->isspilt = 1; } /* general case */ if (IC_RESULT (ic) && IS_TRUE_SYMOP (IC_RESULT (ic)) && OP_REQV (IC_RESULT (ic))) { if (POINTER_SET (ic)) { IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)), OP_SYMBOL (IC_RESULT (ic))->defs, OP_SYMBOL (IC_RESULT (ic))->uses); IC_RESULT (ic)->isaddr = 1; } else IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)), OP_SYMBOL (IC_RESULT (ic))->defs, OP_SYMBOL (IC_RESULT (ic))->uses); } if (IC_RIGHT (ic) && IS_TRUE_SYMOP (IC_RIGHT (ic)) && OP_REQV (IC_RIGHT (ic))) { IC_RIGHT (ic) = opFromOpWithDU (OP_REQV (IC_RIGHT (ic)), OP_SYMBOL (IC_RIGHT (ic))->defs, OP_SYMBOL (IC_RIGHT (ic))->uses); IC_RIGHT (ic)->isaddr = 0; } if (IC_LEFT (ic) && IS_TRUE_SYMOP (IC_LEFT (ic)) && OP_REQV (IC_LEFT (ic))) { IC_LEFT (ic) = opFromOpWithDU (OP_REQV (IC_LEFT (ic)), OP_SYMBOL (IC_LEFT (ic))->defs, OP_SYMBOL (IC_LEFT (ic))->uses); IC_LEFT (ic)->isaddr = 0; } } } }
/*-----------------------------------------------------------------*/ static void convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op) { symbol *func = NULL; iCode *ip = ic->next; iCode *newic; int lineno = ic->lineno; int bwd; int su; int bytesPushed=0; remiCodeFromeBBlock (ebp, ic); /* depending on the type */ for (bwd = 0; bwd < 3; bwd++) { for (su = 0; su < 2; su++) { if (compareType (type, __multypes[bwd][su]) == 1) { if (op == '*') func = __muldiv[0][bwd][su]; else if (op == '/') func = __muldiv[1][bwd][su]; else if (op == '%') func = __muldiv[2][bwd][su]; else if (op == RRC) func = __rlrr[1][bwd][su]; else if (op == RLC) func = __rlrr[0][bwd][su]; else if (op == RIGHT_OP) func = __rlrr[1][bwd][su]; else if (op == LEFT_OP) func = __rlrr[0][bwd][su]; else assert (0); goto found; } } } assert (0); found: /* if int & long support routines NOT compiled as reentrant */ if (!options.intlong_rent) { /* first one */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) newic = newiCode (SEND, IC_LEFT (ic), NULL); else { newic = newiCode ('=', NULL, IC_LEFT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* second one */ if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) newic = newiCode (SEND, IC_RIGHT (ic), NULL); else { newic = newiCode ('=', NULL, IC_RIGHT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } else { /* compiled as reentrant then push */ /* push right */ if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) { newic = newiCode (SEND, IC_RIGHT (ic), NULL); } else { newic = newiCode (IPUSH, IC_RIGHT (ic), NULL); newic->parmPush = 1; bytesPushed += getSize(operandType(IC_RIGHT(ic))); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* insert push left */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) { newic = newiCode (SEND, IC_LEFT (ic), NULL); } else { newic = newiCode (IPUSH, IC_LEFT (ic), NULL); newic->parmPush = 1; bytesPushed += getSize(operandType(IC_LEFT(ic))); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } /* for the result */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); newic->lineno = lineno; newic->parmBytes+=bytesPushed; // to clear the stack after the call addiCodeToeBBlock (ebp, newic, ip); }
/*-----------------------------------------------------------------*/ static void cnvFromFloatCast (iCode * ic, eBBlock * ebp) { iCode *ip, *newic; symbol *func; sym_link *type = operandType (IC_LEFT (ic)); int lineno = ic->lineno; int bwd, su; ip = ic->next; /* remove it from the iCode */ remiCodeFromeBBlock (ebp, ic); /* depending on the type */ for (bwd = 0; bwd < 3; bwd++) { for (su = 0; su < 2; su++) { if (compareType (type, __multypes[bwd][su]) == 1) { func = __conv[1][bwd][su]; goto found; } } } assert (0); found: /* if float support routines NOT compiled as reentrant */ if (!options.float_rent) { /* first one */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) newic = newiCode (SEND, IC_RIGHT (ic), NULL); else { newic = newiCode ('=', NULL, IC_RIGHT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } else { /* push the left */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) newic = newiCode (SEND, IC_RIGHT (ic), NULL); else { newic = newiCode (IPUSH, IC_RIGHT (ic), NULL); newic->parmPush = 1; } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } /* make the call */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; }
/*-----------------------------------------------------------------*/ 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); }
/** Register reduction for assignment. */ static int packRegsForAssign (iCode *ic, eBBlock *ebp) { iCode *dic, *sic; if (!IS_ITEMP (IC_RIGHT (ic)) || OP_SYMBOL (IC_RIGHT (ic))->isind || OP_LIVETO (IC_RIGHT (ic)) > ic->seq) return 0; /* Avoid having multiple named address spaces in one iCode. */ if (IS_SYMOP (IC_RESULT (ic)) && SPEC_ADDRSPACE (OP_SYMBOL (IC_RESULT (ic))->etype)) return 0; /* find the definition of iTempNN scanning backwards if we find a a use of the true symbol in before we find the definition then we cannot */ for (dic = ic->prev; dic; dic = dic->prev) { /* PENDING: Don't pack across function calls. */ if (dic->op == CALL || dic->op == PCALL) { dic = NULL; break; } if (SKIP_IC2 (dic)) continue; if (dic->op == IFX) { if (IS_SYMOP (IC_COND (dic)) && (IC_COND (dic)->key == IC_RESULT (ic)->key || IC_COND (dic)->key == IC_RIGHT (ic)->key)) { dic = NULL; break; } } else { if (IS_TRUE_SYMOP (IC_RESULT (dic)) && IS_OP_VOLATILE (IC_RESULT (dic))) { dic = NULL; break; } if (IS_SYMOP (IC_RESULT (dic)) && IC_RESULT (dic)->key == IC_RIGHT (ic)->key) { if (POINTER_SET (dic)) dic = NULL; break; } if (IS_SYMOP (IC_RIGHT (dic)) && (IC_RIGHT (dic)->key == IC_RESULT (ic)->key || IC_RIGHT (dic)->key == IC_RIGHT (ic)->key)) { dic = NULL; break; } if (IS_SYMOP (IC_LEFT (dic)) && (IC_LEFT (dic)->key == IC_RESULT (ic)->key || IC_LEFT (dic)->key == IC_RIGHT (ic)->key)) { dic = NULL; break; } if (IS_SYMOP (IC_RESULT (dic)) && IC_RESULT (dic)->key == IC_RESULT (ic)->key) { dic = NULL; break; } } } if (!dic) return 0; /* did not find */ /* if assignment then check that right is not a bit */ if (ASSIGNMENT (ic) && !POINTER_SET (ic)) { sym_link *etype = operandType (IC_RESULT (dic)); if (IS_BITFIELD (etype)) { /* if result is a bit too then it's ok */ etype = operandType (IC_RESULT (ic)); if (!IS_BITFIELD (etype)) { return 0; } } } /* if the result is on stack or iaccess then it must be the same atleast one of the operands */ if (OP_SYMBOL (IC_RESULT (ic))->onStack || OP_SYMBOL (IC_RESULT (ic))->iaccess) { /* the operation has only one symbol operator then we can pack */ if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) || (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic)))) goto pack; if (!((IC_LEFT (dic) && IC_RESULT (ic)->key == IC_LEFT (dic)->key) || (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key))) return 0; } pack: /* found the definition */ /* replace the result with the result of */ /* this assignment and remove this assignment */ bitVectUnSetBit (OP_SYMBOL (IC_RESULT (dic))->defs, dic->key); IC_RESULT (dic) = IC_RESULT (ic); if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq) { OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq; } /* delete from liverange table also delete from all the points inbetween and the new one */ for (sic = dic; sic != ic; sic = sic->next) { bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key); if (IS_ITEMP (IC_RESULT (dic))) bitVectSetBit (sic->rlive, IC_RESULT (dic)->key); } remiCodeFromeBBlock (ebp, ic); // PENDING: Check vs mcs51 bitVectUnSetBit (OP_SYMBOL (IC_RESULT (ic))->defs, ic->key); hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL); OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); return 1; }
/*-----------------------------------------------------------------*/ static void rlivePoint (eBBlock ** ebbs, int count, bool emitWarnings) { int i, key; eBBlock *succ; bitVect *alive; /* for all blocks do */ for (i = 0; i < count; i++) { iCode *ic; /* for all instructions in this block do */ for (ic = ebbs[i]->sch; ic; ic = ic->next) { if (!ic->rlive) ic->rlive = newBitVect (operandKey); if (SKIP_IC2(ic)) continue; if (ic->op == JUMPTABLE && IS_SYMOP(IC_JTCOND(ic))) { incUsed (ic, IC_JTCOND(ic)); if (!IS_AUTOSYM(IC_JTCOND(ic))) continue; findPrevUse (ebbs[i], ic, IC_JTCOND(ic), ebbs, count, emitWarnings); if (IS_ITEMP(IC_JTCOND(ic))) { unvisitBlocks(ebbs, count); ic->rlive = bitVectSetBit (ic->rlive, IC_JTCOND(ic)->key); findNextUse (ebbs[i], ic->next, IC_JTCOND(ic)); } continue; } if (ic->op == IFX && IS_SYMOP(IC_COND(ic))) { incUsed (ic, IC_COND(ic)); if (!IS_AUTOSYM(IC_COND(ic))) continue; findPrevUse (ebbs[i], ic, IC_COND(ic), ebbs, count, emitWarnings); if (IS_ITEMP(IC_COND(ic))) { unvisitBlocks (ebbs, count); ic->rlive = bitVectSetBit (ic->rlive, IC_COND(ic)->key); findNextUse (ebbs[i], ic->next, IC_COND(ic)); } continue; } if (IS_SYMOP(IC_LEFT(ic))) { incUsed (ic, IC_LEFT(ic)); if (IS_AUTOSYM(IC_LEFT(ic)) && ic->op != ADDRESS_OF) { findPrevUse (ebbs[i], ic, IC_LEFT(ic), ebbs, count, emitWarnings); if (IS_ITEMP(IC_LEFT(ic))) { unvisitBlocks(ebbs, count); ic->rlive = bitVectSetBit (ic->rlive, IC_LEFT(ic)->key); findNextUse (ebbs[i], ic->next, IC_LEFT(ic)); /* if this is a send extend the LR to the call */ if (ic->op == SEND) { iCode *lic; for (lic = ic; lic; lic = lic->next) { if (lic->op == CALL || lic->op == PCALL) { markAlive (ic, lic->prev, IC_LEFT (ic)->key); break; } } } } } } if (IS_SYMOP(IC_RIGHT(ic))) { incUsed (ic, IC_RIGHT(ic)); if (IS_AUTOSYM(IC_RIGHT(ic))) { findPrevUse (ebbs[i], ic, IC_RIGHT(ic), ebbs, count, emitWarnings); if (IS_ITEMP(IC_RIGHT(ic))) { unvisitBlocks(ebbs, count); ic->rlive = bitVectSetBit (ic->rlive, IC_RIGHT(ic)->key); findNextUse (ebbs[i], ic->next, IC_RIGHT(ic)); } } } if (POINTER_SET(ic) && IS_SYMOP(IC_RESULT(ic))) incUsed (ic, IC_RESULT(ic)); if (IS_AUTOSYM(IC_RESULT(ic))) { if (POINTER_SET(ic)) { findPrevUse (ebbs[i], ic, IC_RESULT(ic), ebbs, count, emitWarnings); } if (IS_ITEMP(IC_RESULT(ic))) { unvisitBlocks(ebbs, count); ic->rlive = bitVectSetBit (ic->rlive, IC_RESULT(ic)->key); findNextUse (ebbs[i], ic->next, IC_RESULT(ic)); /* findNextUse sometimes returns 0 here, which means that ic is dead code. Something should be done about this dead code since e.g. register allocation suffers. */ } } if (!POINTER_SET(ic) && IC_RESULT(ic)) ic->defKey = IC_RESULT(ic)->key; } /* check all symbols that are alive in the last instruction */ /* but are not alive in all successors */ succ = setFirstItem (ebbs[i]->succList); if (!succ) continue; alive = succ->sch->rlive; while ((succ = setNextItem (ebbs[i]->succList))) { if (succ->sch) alive = bitVectIntersect (alive, succ->sch->rlive); } if (ebbs[i]->ech) alive = bitVectCplAnd ( bitVectCopy (ebbs[i]->ech->rlive), alive); if(!alive) continue; for (key = 1; key < alive->size; key++) { if (!bitVectBitValue (alive, key)) continue; unvisitBlocks(ebbs, count); findNextUseSym (ebbs[i], NULL, hTabItemWithKey (liveRanges, key)); } } }
/*-----------------------------------------------------------------*/ static int findNextUseSym (eBBlock *ebp, iCode *ic, symbol * sym) { int retval = 0; iCode *uic; eBBlock *succ; hTabAddItemIfNotP (&liveRanges, sym->key, sym); if (!ic) goto check_successors; /* if we check a complete block and the symbol */ /* is alive at the beginning of the block */ /* and not defined in the first instructions */ /* then a next use exists (return 1) */ if ((ic == ebp->sch) && bitVectBitValue(ic->rlive, sym->key)) { /* check if the first instruction is a def of this op */ if (ic->op == JUMPTABLE || ic->op == IFX || SKIP_IC2(ic)) return 1; if (IS_ITEMP(IC_RESULT(ic))) if (IC_RESULT(ic)->key == sym->key) return 0; return 1; } if (ebp->visited) return 0; if (ic == ebp->sch) ebp->visited = 1; /* for all remaining instructions in current block */ for (uic = ic; uic; uic = uic->next) { if (SKIP_IC2(uic)) continue; if (uic->op == JUMPTABLE) { if (IS_ITEMP(IC_JTCOND(uic)) && IC_JTCOND(uic)->key == sym->key) { markAlive(ic, uic, sym->key); return 1; } continue; } if (uic->op == IFX) { if (IS_ITEMP(IC_COND(uic)) && IC_COND(uic)->key == sym->key) { markAlive(ic, uic, sym->key); return 1; } continue; } if (IS_ITEMP (IC_LEFT (uic))) if (IC_LEFT (uic)->key == sym->key) { markAlive(ic, uic, sym->key); return 1; } if (IS_ITEMP (IC_RIGHT (uic))) if (IC_RIGHT (uic)->key == sym->key) { markAlive (ic, uic, sym->key); return 1; } if (IS_ITEMP (IC_RESULT (uic))) if (IC_RESULT (uic)->key == sym->key) { if (POINTER_SET (uic)) { markAlive (ic, uic, sym->key); return 1; } else return 0; } } /* check all successors */ check_successors: succ = setFirstItem (ebp->succList); for (; succ; succ = setNextItem (ebp->succList)) { retval += findNextUseSym (succ, succ->sch, sym); } if (retval) { if (ic) markAlive (ic, ebp->ech, sym->key); return 1; } return 0; }
/*-----------------------------------------------------------------*/ static void computeClash (eBBlock ** ebbs, int count) { int i; /* for all blocks do */ for (i = 0; i < count; i++) { iCode *ic; /* for every iCode do */ for (ic = ebbs[i]->sch; ic; ic = ic->next) { symbol *sym1, *sym2; int key1, key2; /* for all iTemps alive at this iCode */ for (key1 = 1; key1 < ic->rlive->size; key1++) { if (!bitVectBitValue(ic->rlive, key1)) continue; sym1 = hTabItemWithKey(liveRanges, key1); if (!sym1->isitmp) continue; /* for all other iTemps alive at this iCode */ for (key2 = key1+1; key2 < ic->rlive->size; key2++) { if (!bitVectBitValue(ic->rlive, key2)) continue; sym2 = hTabItemWithKey(liveRanges, key2); if (!sym2->isitmp) continue; /* if the result and left or right is an iTemp */ /* than possibly the iTemps do not clash */ if ((ic->op != JUMPTABLE) && (ic->op != IFX) && IS_ITEMP(IC_RESULT(ic)) && (IS_ITEMP(IC_LEFT(ic)) || IS_ITEMP(IC_RIGHT(ic)))) { if (OP_SYMBOL(IC_RESULT(ic))->key == key1 && sym1->liveFrom == ic->seq && sym2->liveTo == ic->seq) { if (IS_SYMOP(IC_LEFT(ic))) if (OP_SYMBOL(IC_LEFT(ic))->key == key2) continue; if (IS_SYMOP(IC_RIGHT(ic))) if (OP_SYMBOL(IC_RIGHT(ic))->key == key2) continue; } if (OP_SYMBOL(IC_RESULT(ic))->key == key2 && sym2->liveFrom == ic->seq && sym1->liveTo == ic->seq) { if (IS_SYMOP(IC_LEFT(ic))) if (OP_SYMBOL(IC_LEFT(ic))->key == key1) continue; if (IS_SYMOP(IC_RIGHT(ic))) if (OP_SYMBOL(IC_RIGHT(ic))->key == key1) continue; } } /* the iTemps do clash. set the bits in clashes */ sym1->clashes = bitVectSetBit (sym1->clashes, key2); sym2->clashes = bitVectSetBit (sym2->clashes, key1); /* check if they share the same spill location */ /* what is this good for? */ if (SYM_SPIL_LOC(sym1) && SYM_SPIL_LOC(sym2) && SYM_SPIL_LOC(sym1) == SYM_SPIL_LOC(sym2)) { if (sym1->reqv && !sym2->reqv) SYM_SPIL_LOC(sym2)=NULL; else if (sym2->reqv && !sym1->reqv) SYM_SPIL_LOC(sym1)=NULL; else if (sym1->used > sym2->used) SYM_SPIL_LOC(sym2)=NULL; else SYM_SPIL_LOC(sym1)=NULL; } } } } } }
/*-----------------------------------------------------------------*/ static void convertToFcall (eBBlock ** ebbs, int count) { int i; /* for all blocks do */ for (i = 0; i < count; i++) { iCode *ic; /* for all instructions in the block do */ for (ic = ebbs[i]->sch; ic; ic = ic->next) { /* floating point operations are converted to function calls */ if ((IS_CONDITIONAL (ic) || IS_ARITHMETIC_OP (ic)) && (IS_FLOAT (operandType (IC_RIGHT (ic))))) { cnvToFcall (ic, ebbs[i]); } /* casting is a little different */ if (ic->op == CAST) { if (IS_FLOAT (operandType (IC_RIGHT (ic)))) cnvFromFloatCast (ic, ebbs[i]); else if (IS_FLOAT (operandType (IC_LEFT (ic)))) cnvToFloatCast (ic, ebbs[i]); } /* if long / int mult or divide or mod */ if (ic->op == '*' || ic->op == '/' || ic->op == '%') { sym_link *leftType = operandType (IC_LEFT (ic)); if (IS_INTEGRAL (leftType) && getSize (leftType) > port->support.muldiv) { sym_link *rightType = operandType (IC_RIGHT (ic)); if (port->hasNativeMulFor != NULL && port->hasNativeMulFor (ic, leftType, rightType)) { /* Leave as native */ } else { convilong (ic, ebbs[i], leftType, ic->op); } } } if (ic->op == RRC || ic->op == RLC || ic->op == LEFT_OP || ic->op == RIGHT_OP) { sym_link *type = operandType (IC_LEFT (ic)); if (IS_INTEGRAL (type) && getSize (type) > port->support.shift && port->support.shift >= 0) { convilong (ic, ebbs[i], type, ic->op); } } } } }