+
+/** Does some transformations to reduce register pressure.
+ */
+static void
+packRegisters (eBBlock * ebp)
+{
+ iCode *ic;
+ int change = 0;
+
+ D (D_ALLOC, ("packRegisters: entered.\n"));
+
+ while (1 && !DISABLE_PACK_ASSIGN)
+ {
+ change = 0;
+ /* look for assignments of the form */
+ /* iTempNN = TRueSym (someoperation) SomeOperand */
+ /* .... */
+ /* TrueSym := iTempNN:1 */
+ for (ic = ebp->sch; ic; ic = ic->next)
+ {
+ /* find assignment of the form TrueSym := iTempNN:1 */
+ if (ic->op == '=' && !POINTER_SET (ic))
+ change += packRegsForAssign (ic, ebp);
+ }
+ if (!change)
+ break;
+ }
+
+ for (ic = ebp->sch; ic; ic = ic->next)
+ {
+ /* Safe: address of a true sym is always constant. */
+ /* if this is an itemp & result of a address of a true sym
+ then mark this as rematerialisable */
+ D (D_ALLOC, ("packRegisters: looping on ic %p\n", ic));
+
+ if (ic->op == ADDRESS_OF &&
+ IS_ITEMP (IC_RESULT (ic)) &&
+ IS_TRUE_SYMOP (IC_LEFT (ic)) &&
+ bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+ !OP_SYMBOL (IC_LEFT (ic))->onStack)
+ {
+
+ OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+ OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+ OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+ }
+
+ /* Safe: just propagates the remat flag */
+ /* if straight assignment then carry remat flag if this is the
+ only definition */
+ if (ic->op == '=' &&
+ !POINTER_SET (ic) &&
+ IS_SYMOP (IC_RIGHT (ic)) &&
+ OP_SYMBOL (IC_RIGHT (ic))->remat &&
+ bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
+ {
+
+ OP_SYMBOL (IC_RESULT (ic))->remat =
+ OP_SYMBOL (IC_RIGHT (ic))->remat;
+ OP_SYMBOL (IC_RESULT (ic))->rematiCode =
+ OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+ }
+
+ /* if the condition of an if instruction is defined in the
+ previous instruction then mark the itemp as a conditional */
+ if ((IS_CONDITIONAL (ic) ||
+ ((ic->op == BITWISEAND ||
+ ic->op == '|' ||
+ ic->op == '^') &&
+ isBitwiseOptimizable (ic))) &&
+ ic->next && ic->next->op == IFX &&
+ bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
+ isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
+ OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
+ {
+
+ OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
+ continue;
+ }
+
+#if 0
+ /* reduce for support function calls */
+ if (ic->supportRtn || ic->op == '+' || ic->op == '-')
+ packRegsForSupport (ic, ebp);
+#endif
+
+ /* if pointer set & left has a size more than
+ one and right is not in far space */
+ if (!DISABLE_PACK_ONE_USE &&
+ POINTER_SET (ic) &&
+ /* MLH: no such thing.
+ !isOperandInFarSpace(IC_RIGHT(ic)) && */
+ !OP_SYMBOL (IC_RESULT (ic))->remat &&
+ !IS_OP_RUONLY (IC_RIGHT (ic)) &&
+ getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
+ {
+
+ packRegsForOneuse (ic, IC_RESULT (ic), ebp);
+ }
+
+ /* if pointer get */
+ if (!DISABLE_PACK_ONE_USE &&
+ POINTER_GET (ic) &&
+ /* MLH: dont have far space
+ !isOperandInFarSpace(IC_RESULT(ic))&& */
+ !OP_SYMBOL (IC_LEFT (ic))->remat &&
+ !IS_OP_RUONLY (IC_RESULT (ic)) &&
+ getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
+ {
+
+ packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+ }
+
+ /* pack registers for accumulator use, when the result of an
+ arithmetic or bit wise operation has only one use, that use is
+ immediately following the defintion and the using iCode has
+ only one operand or has two operands but one is literal & the
+ result of that operation is not on stack then we can leave the
+ result of this operation in acc:b combination */
+
+ if (!DISABLE_PACK_HL && IS_ITEMP (IC_RESULT (ic)))
+ {
+ packRegsForHLUse (ic);
+ }
+
+ if (!DISABLE_PACK_ACC && IS_ITEMP (IC_RESULT (ic)) &&
+ getSize (operandType (IC_RESULT (ic))) == 1)
+ {
+ packRegsForAccUse2 (ic);
+ }
+ }
+}
+
+/** Joins together two byte constant pushes into one word push.
+ */
+static iCode *
+joinPushes (iCode *lic)
+{
+ iCode *ic, *uic;
+
+ for (ic = lic; ic; ic = ic->next)
+ {
+ int first, second;
+ value *val;
+
+ uic = ic->next;
+
+ /* Anything past this? */
+ if (uic == NULL)
+ {
+ continue;
+ }
+ /* This and the next pushes? */
+ if (ic->op != IPUSH || uic->op != IPUSH)
+ {
+ continue;
+ }
+ /* Both literals? */
+ if ( !IS_OP_LITERAL (IC_LEFT (ic)) || !IS_OP_LITERAL (IC_LEFT (uic)))
+ {
+ continue;
+ }
+ /* Both characters? */
+ if ( getSize (operandType (IC_LEFT (ic))) != 1 || getSize (operandType (IC_LEFT (uic))) != 1)
+ {
+ continue;
+ }
+ /* Pull out the values, make a new type, and create the new iCode for it.
+ */
+ first = (int)operandLitValue ( IC_LEFT (ic));
+ second = (int)operandLitValue ( IC_LEFT (uic));
+
+ sprintf (buffer, "%u", ((first << 8) | (second & 0xFF)) & 0xFFFFU);
+ val = constVal (buffer);
+ SPEC_NOUN (val->type) = V_INT;
+ IC_LEFT (ic)->operand.valOperand = val;
+
+ /* Now remove the second one from the list. */
+ ic->next = uic->next;
+ if (uic->next)
+ {
+ /* Patch up the reverse link */
+ uic->next->prev = ic;
+ }
+ }
+
+ return lic;
+}
+