/*-----------------------------------------------------------------*/ iCode * ifxForOp (operand * op, const iCode * ic) { iCode *ifxIc; /* if true symbol then needs to be assigned */ if (!IS_TRUE_SYMOP (op)) { /* if this has register type condition and while skipping ipop's (see bug 1509084), the next instruction is ifx with the same operand and live to of the operand is upto the ifx only then */ for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next) ; if (ifxIc && ifxIc->op == IFX && IC_COND (ifxIc)->key == op->key && OP_SYMBOL (op)->liveTo <= ifxIc->seq) return ifxIc; } return NULL; }
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; } }
/** Mark variables for assignment by the register allocator. */ static void serialRegMark (eBBlock ** ebbs, int count) { int i; short int max_alloc_bytes = SHRT_MAX; // Byte limit. Set this to a low value to pass only few variables to the register allocator. This can be useful for debugging. stm8_call_stack_size = 2; // Saving of register to stack temporarily. /* for all blocks */ for (i = 0; i < count; i++) { iCode *ic; if (ebbs[i]->noPath && (ebbs[i]->entryLabel != entryLabel && ebbs[i]->entryLabel != returnLabel)) continue; /* for all instructions do */ for (ic = ebbs[i]->sch; ic; ic = ic->next) { if ((ic->op == CALL || ic->op == PCALL) && ic->parmBytes + 5 > stm8_call_stack_size) { sym_link *dtype = operandType (IC_LEFT (ic)); sym_link *ftype = IS_FUNCPTR (dtype) ? dtype->next : dtype; /* 5 for saving all registers at call site + 2 for big return value */ stm8_call_stack_size = ic->parmBytes + 5 + 2 * (getSize (ftype->next) > 4); } if (ic->op == IPOP) wassert (0); /* if result is present && is a true symbol */ if (IC_RESULT (ic) && ic->op != IFX && IS_TRUE_SYMOP (IC_RESULT (ic))) OP_SYMBOL (IC_RESULT (ic))->allocreq++; /* some don't need registers, since there is no result. */ if (SKIP_IC2 (ic) || ic->op == JUMPTABLE || ic->op == IFX || ic->op == IPUSH || ic->op == IPOP || (IC_RESULT (ic) && POINTER_SET (ic))) continue; /* now we need to allocate registers only for the result */ if (IC_RESULT (ic)) { symbol *sym = OP_SYMBOL (IC_RESULT (ic)); D (D_ALLOC, ("serialRegAssign: in loop on result %p\n", sym)); if (sym->isspilt && sym->usl.spillLoc) // todo: Remove once remat is supported! { sym->usl.spillLoc->allocreq--; sym->isspilt = FALSE; } /* Make sure any spill location is definately allocated */ if (sym->isspilt && !sym->remat && sym->usl.spillLoc && !sym->usl.spillLoc->allocreq) sym->usl.spillLoc->allocreq++; /* if it does not need or is spilt or is already marked for the new allocator or will not live beyond this instructions */ if (!sym->nRegs || sym->isspilt || sym->for_newralloc || sym->liveTo <= ic->seq) { D (D_ALLOC, ("serialRegAssign: won't live long enough.\n")); continue; } if (sym->nRegs > 4 && ic->op == CALL) { spillThis (sym, TRUE); } else if (max_alloc_bytes >= sym->nRegs) { sym->for_newralloc = 1; max_alloc_bytes -= sym->nRegs; } else if (!sym->for_newralloc) { spillThis (sym, TRUE); printf ("Spilt %s due to byte limit.\n", sym->name); } } } } }
/*-----------------------------------------------------------------*/ 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; } } } }
/** 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; }