- bitVect *uses ;
- iCode *dic, *sic;
-
- /* if returning a literal then do nothing */
- if (!IS_SYMOP(op))
- return NULL;
-
- /* only upto 2 bytes since we cannot predict
- the usage of b, & acc */
- if (getSize(operandType(op)) > (fReturnSize_390 - 2) &&
- ic->op != RETURN &&
- ic->op != SEND &&
- !POINTER_SET(ic) &&
- !POINTER_GET(ic))
- return NULL;
-
- /* this routine will mark the a symbol as used in one
- instruction use only && if the defintion is local
- (ie. within the basic block) && has only one definition &&
- that definiion is either a return value from a
- function or does not contain any variables in
- far space */
- uses = bitVectCopy(OP_USES(op));
- bitVectUnSetBit(uses,ic->key); /* take away this iCode */
- if (!bitVectIsZero(uses)) /* has other uses */
- return NULL ;
-
- /* if it has only one defintion */
- if (bitVectnBitsOn(OP_DEFS(op)) > 1)
- return NULL ; /* has more than one definition */
-
- /* get the that definition */
- if (!(dic =
- hTabItemWithKey(iCodehTab,
- bitVectFirstBit(OP_DEFS(op)))))
- return NULL ;
-
- /* found the definition now check if it is local */
- if (dic->seq < ebp->fSeq ||
- dic->seq > ebp->lSeq)
- return NULL ; /* non-local */
-
- /* now check if it is the return from
- a function call */
- if (dic->op == CALL || dic->op == PCALL ) {
- if (ic->op != SEND && ic->op != RETURN) {
- OP_SYMBOL(op)->ruonly = 1;
- return dic;
- }
- dic = dic->next ;
- }
-
-
- /* otherwise check that the definition does
- not contain any symbols in far space */
- if (isOperandInFarSpace(IC_LEFT(dic)) ||
- isOperandInFarSpace(IC_RIGHT(dic)) ||
- IS_OP_RUONLY(IC_LEFT(ic)) ||
- IS_OP_RUONLY(IC_RIGHT(ic)) ) {
- return NULL;
- }
-
- /* if pointer set then make sure the pointer
- is one byte */
- if (POINTER_SET(dic) &&
- !IS_DATA_PTR(aggrToPtr(operandType(IC_RESULT(dic)),FALSE)))
- return NULL ;
-
- if (POINTER_GET(dic) &&
- !IS_DATA_PTR(aggrToPtr(operandType(IC_LEFT(dic)),FALSE)))
- return NULL ;
-
- sic = dic;
-
- /* also make sure the intervenening instructions
- don't have any thing in far space */
- for (dic = dic->next ; dic && dic != ic ; dic = dic->next) {
-
- /* if there is an intervening function call then no */
- if (dic->op == CALL || dic->op == PCALL)
- return NULL;
- /* if pointer set then make sure the pointer
- is one byte */
- if (POINTER_SET(dic) &&
- !IS_DATA_PTR(aggrToPtr(operandType(IC_RESULT(dic)),FALSE)))
- return NULL ;
-
- if (POINTER_GET(dic) &&
- !IS_DATA_PTR(aggrToPtr(operandType(IC_LEFT(dic)),FALSE)))
- return NULL ;
-
- /* if address of & the result is remat the okay */
- if (dic->op == ADDRESS_OF &&
- OP_SYMBOL(IC_RESULT(dic))->remat)
- continue ;
-
- /* if operand has size of three or more & this
- operation is a '*','/' or '%' then 'b' may
- cause a problem */
- if (( dic->op == '%' || dic->op == '/' || dic->op == '*') &&
- getSize(operandType(op)) >= 3)
- return NULL;
-
- /* if left or right or result is in far space */
- if (isOperandInFarSpace(IC_LEFT(dic)) ||
- isOperandInFarSpace(IC_RIGHT(dic)) ||
- isOperandInFarSpace(IC_RESULT(dic)) ||
- IS_OP_RUONLY(IC_LEFT(dic)) ||
- IS_OP_RUONLY(IC_RIGHT(dic)) ||
- IS_OP_RUONLY(IC_RESULT(dic)) ) {
- return NULL;
- }
- }
-
+ if (isOperandInFarSpace(IC_RESULT(ic)) && !farSpacePackable(ic)) {
+ return 0;
+ }
+#endif
+
+ /* 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)
+ {
+ /* if there is a function call then don't pack it */
+ if ((dic->op == CALL || dic->op == PCALL))
+ {
+ dic = NULL;
+ break;
+ }
+
+ if (SKIP_IC2 (dic))
+ continue;
+
+ 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 (POINTER_SET (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);
+ 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;
+}
+
+/*------------------------------------------------------------------*/
+/* findAssignToSym : scanning backwards looks for first assig found */
+/*------------------------------------------------------------------*/
+static iCode *
+findAssignToSym (operand * op, iCode * ic)
+{
+ iCode *dic;
+
+ /* This routine is used to find sequences like
+ iTempAA = FOO;
+ ...; (intervening ops don't use iTempAA or modify FOO)
+ blah = blah + iTempAA;
+
+ and eliminate the use of iTempAA, freeing up its register for
+ other uses.
+ */
+
+ for (dic = ic->prev; dic; dic = dic->prev)
+ {
+
+ /* if definition by assignment */
+ if (dic->op == '=' &&
+ !POINTER_SET (dic) &&
+ IC_RESULT (dic)->key == op->key
+/* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */
+ )
+ {
+
+ /* we are interested only if defined in far space */
+ /* or in stack space in case of + & - */
+
+ /* if assigned to a non-symbol then return
+ FALSE */
+ if (!IS_SYMOP (IC_RIGHT (dic)))
+ return NULL;
+
+ /* if the symbol is in far space then we should not */
+ if (isOperandInFarSpace (IC_RIGHT (dic)))
+ return NULL;
+
+ /* for + & - operations make sure that
+ if it is on the stack it is the same
+ as one of the three operands */
+ if ((ic->op == '+' || ic->op == '-') &&
+ OP_SYMBOL (IC_RIGHT (dic))->onStack)
+ {
+
+ if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
+ IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
+ IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
+ return NULL;
+ }
+
+ break;
+
+ }
+
+ /* if we find an usage then we cannot delete it */
+ if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
+ return NULL;
+
+ if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
+ return NULL;
+
+ if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
+ return NULL;
+ }
+
+ /* now make sure that the right side of dic
+ is not defined between ic & dic */
+ if (dic)
+ {
+ iCode *sic = dic->next;
+
+ for (; sic != ic; sic = sic->next)
+ if (IC_RESULT (sic) &&
+ IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
+ return NULL;
+ }
+
+ return dic;
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForSupport :- reduce some registers for support calls */
+/*-----------------------------------------------------------------*/
+static int
+packRegsForSupport (iCode * ic, eBBlock * ebp)
+{
+ int change = 0;
+
+ /* for the left & right operand :- look to see if the
+ left was assigned a true symbol in far space in that
+ case replace them */
+ if (IS_ITEMP (IC_LEFT (ic)) &&
+ OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
+ {
+ iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
+ iCode *sic;
+
+ if (!dic)
+ goto right;
+
+ /* found it we need to remove it from the
+ block */
+ for (sic = dic; sic != ic; sic = sic->next) {
+ bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
+ sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key);
+ }
+
+ wassert(IS_SYMOP(IC_LEFT (ic)));
+ wassert(IS_SYMOP(IC_RIGHT (dic)));
+ IC_LEFT (ic)->operand.symOperand =
+ IC_RIGHT (dic)->operand.symOperand;
+ OP_SYMBOL(IC_LEFT(ic))->liveTo = ic->seq;
+ IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ remiCodeFromeBBlock (ebp, dic);
+ hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+ change++;
+ }
+
+ /* do the same for the right operand */
+right:
+ if (!change &&
+ IS_ITEMP (IC_RIGHT (ic)) &&
+ OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
+ {
+ iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
+ iCode *sic;
+
+ if (!dic)
+ return change;
+
+ /* if this is a subtraction & the result
+ is a true symbol in far space then don't pack */
+ if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
+ {
+ sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
+ if (IN_FARSPACE (SPEC_OCLS (etype)))
+ return change;
+ }
+ /* found it we need to remove it from the
+ block */
+ for (sic = dic; sic != ic; sic = sic->next) {
+ bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
+ sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key);
+ }
+
+ wassert(IS_SYMOP(IC_RIGHT (ic)));
+ wassert(IS_SYMOP(IC_RIGHT (dic)));
+ IC_RIGHT (ic)->operand.symOperand =
+ IC_RIGHT (dic)->operand.symOperand;
+ IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+ OP_SYMBOL(IC_RIGHT(ic))->liveTo = ic->seq;
+ remiCodeFromeBBlock (ebp, dic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+ change++;
+ }
+
+ return change;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* packRegsDPTRnuse - color live ranges that can go into extra DPTRS */
+/*-----------------------------------------------------------------*/
+static int packRegsDPTRnuse( operand *op , unsigned dptr)
+{
+ int i,key;
+ iCode *ic;
+
+ if (!IS_SYMOP(op) || !IS_ITEMP(op)) return 0;
+ if (OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly || OP_SYMBOL(op)->dptr)
+ return 0;
+
+ /* first check if any overlapping liverange has already been
+ assigned to this DPTR */
+ if (OP_SYMBOL(op)->clashes) {
+ for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ ) {
+ symbol *sym;
+ if (bitVectBitValue(OP_SYMBOL(op)->clashes,i)) {
+ sym = hTabItemWithKey(liveRanges,i);
+ if (sym->dptr == dptr) return 0;
+ }
+ }
+ }
+
+ /* future for more dptrs */
+ if (dptr > 1) {
+ OP_SYMBOL(op)->dptr = dptr;
+ return 1;
+ }
+
+ /* DPTR1 is special since it is also used as a scratch by the backend .
+ so we walk thru the entire live range of this operand and make sure
+ DPTR1 will not be used by the backed . The logic here is to find out if
+ more than one operand in an icode is in far space then we give up : we
+ don't keep it live across functions for now
+ */
+
+ ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
+ for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+ ic = hTabNextItem(iCodeSeqhTab,&key)) {
+ int nfs =0;
+
+ if (ic->op == CALL || ic->op == PCALL) return 0;
+
+ /* single operand icode are ok */
+ if (ic->op == IFX || ic->op == IPUSH)
+ continue ;
+
+ if (ic->op == SEND ) {
+ if (ic->argreg != 1 ) return 0;
+ else continue ;
+ }
+ /* two special cases first */
+ if (POINTER_GET(ic) && !isOperandEqual(IC_LEFT(ic),op) && /* pointer get */
+ !OP_SYMBOL(IC_LEFT(ic))->ruonly && /* with result in far space */
+ (isOperandInFarSpace(IC_RESULT(ic)) &&
+ !isOperandInReg(IC_RESULT(ic)))) {
+ return 0;
+ }
+
+ if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(ic),op) && /* pointer set */
+ !OP_SYMBOL(IC_RESULT(ic))->ruonly && /* with right in far space */
+ (isOperandInFarSpace(IC_RIGHT(ic)) &&
+ !isOperandInReg(IC_RIGHT(ic)))) {
+ return 0;
+ }
+
+ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) && /* if symbol operand */
+ !isOperandEqual(IC_RESULT(ic),op) && /* not the same as this */
+ ((isOperandInFarSpace(IC_RESULT(ic)) || /* in farspace or */
+ OP_SYMBOL(IC_RESULT(ic))->onStack) && /* on the stack */
+ !isOperandInReg(IC_RESULT(ic)))) { /* and not in register */
+ nfs++;
+ }
+ /* same for left */
+ if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) && /* if symbol operand */
+ !isOperandEqual(IC_LEFT(ic),op) && /* not the same as this */
+ ((isOperandInFarSpace(IC_LEFT(ic)) || /* in farspace or */
+ OP_SYMBOL(IC_LEFT(ic))->onStack) && /* on the stack */
+ !isOperandInReg(IC_LEFT(ic)))) { /* and not in register */
+ nfs++;
+ }
+ /* same for right */
+ if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) && /* if symbol operand */
+ !isOperandEqual(IC_RIGHT(ic),op) && /* not the same as this */
+ ((isOperandInFarSpace(IC_RIGHT(ic)) || /* in farspace or */
+ OP_SYMBOL(IC_RIGHT(ic))->onStack) && /* on the stack */
+ !isOperandInReg(IC_RIGHT(ic)))) { /* and not in register */
+ nfs++;
+ }
+
+ // Check that no other ops in this range have been assigned to dptr1.
+ // I don't understand why this is not caught by the first check, above.
+ // But it isn't always, see bug 769624.
+ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+ (OP_SYMBOL(IC_RESULT(ic))->dptr == 1))
+ {
+ //fprintf(stderr, "dptr1 already in use in live range #1\n");
+ return 0;
+ }
+
+ if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
+ (OP_SYMBOL(IC_LEFT(ic))->dptr == 1))
+ {
+ //fprintf(stderr, "dptr1 already in use in live range # 2\n");
+ return 0;
+ }
+
+ if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
+ (OP_SYMBOL(IC_RIGHT(ic))->dptr == 1))
+ {
+ //fprintf(stderr, "dptr1 already in use in live range # 3\n");
+ return 0;
+ }
+
+ if (nfs && IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+ OP_SYMBOL(IC_RESULT(ic))->ruonly) return 0;
+
+ if (nfs > 1) return 0;
+ }
+ OP_SYMBOL(op)->dptr = dptr;
+ return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsDPTRuse : - will reduce some registers for single Use */
+/*-----------------------------------------------------------------*/
+static iCode *
+packRegsDPTRuse (operand * op)
+{
+ /* go thru entire liveRange of this variable & check for
+ other possible usage of DPTR , if we don't find it the
+ assign this to DPTR (ruonly)
+ */
+ int i, key;
+ symbol *sym;
+ iCode *ic, *dic;
+ sym_link *type, *etype;
+
+ if (!IS_SYMOP(op) || !IS_ITEMP(op)) return NULL;
+ if (OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly) return NULL;
+
+ /* first check if any overlapping liverange has already been
+ assigned to DPTR */
+ if (OP_SYMBOL(op)->clashes) {
+ for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ ) {
+ if (bitVectBitValue(OP_SYMBOL(op)->clashes,i)) {
+ sym = hTabItemWithKey(liveRanges,i);
+ if (sym->ruonly) return NULL ;
+ }
+ }
+ }
+
+ /* no then go thru this guys live range */
+ dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
+ for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+ ic = hTabNextItem(iCodeSeqhTab,&key)) {
+
+ if (SKIP_IC3(ic)) continue;
+
+ /* if PCALL cannot be sure give up */
+ if (ic->op == PCALL) return NULL;
+
+ /* if SEND & not the first parameter then giveup */
+ if (ic->op == SEND && ic->argreg != 1 &&
+ ((isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic))) ||
+ isOperandEqual(op,IC_LEFT(ic)))) return NULL;
+
+ /* if CALL then make sure it is VOID || return value not used
+ or the return value is assigned to this one */
+ if (ic->op == CALL) {
+ if (OP_SYMBOL(IC_RESULT(ic))->liveTo ==
+ OP_SYMBOL(IC_RESULT(ic))->liveFrom) continue ;
+ etype = getSpec(type = operandType(IC_RESULT(ic)));
+ if (getSize(type) == 0 || isOperandEqual(op,IC_RESULT(ic)))
+ continue ;
+ return NULL ;
+ }
+
+ /* special case of add with a [remat] */
+ if (ic->op == '+' &&
+ OP_SYMBOL(IC_LEFT(ic))->remat &&
+ (isOperandInFarSpace(IC_RIGHT(ic)) &&
+ !isOperandInReg(IC_RIGHT(ic)))) return NULL ;
+
+ /* special cases */
+ /* pointerGet */
+ if (POINTER_GET(ic) && !isOperandEqual(IC_LEFT(ic),op) &&
+ getSize(operandType(IC_LEFT(ic))) > 1 ) return NULL ;
+
+ /* pointerSet */
+ if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(ic),op) &&
+ getSize(operandType(IC_RESULT(ic))) > 1 ) return NULL;
+
+ /* conditionals can destroy 'b' - make sure B wont
+ be used in this one*/
+ if ((IS_CONDITIONAL(ic) || ic->op == '*' || ic->op == '/' ||
+ ic->op == LEFT_OP || ic->op == RIGHT_OP ) &&
+ getSize(operandType(op)) > 3) return NULL;
+
+ /* if this is a cast to a bigger type */
+ if (ic->op==CAST) {
+ if (!IS_PTR(OP_SYM_TYPE(IC_RESULT(ic))) &&
+ getSize(OP_SYM_TYPE(IC_RESULT(ic))) >
+ getSize(OP_SYM_TYPE(IC_RIGHT(ic)))) {
+ return 0;
+ }
+ }
+
+ /* general case */
+ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+ !isOperandEqual(IC_RESULT(ic),op) &&
+ ( ( ( isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->onStack) &&
+ !isOperandInReg(IC_RESULT(ic))) ||
+ OP_SYMBOL(IC_RESULT(ic))->ruonly)) return NULL;
+
+ if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
+ !isOperandEqual(IC_RIGHT(ic),op) &&
+ (OP_SYMBOL(IC_RIGHT(ic))->liveTo >= ic->seq ||
+ IS_TRUE_SYMOP(IC_RIGHT(ic)) ||
+ OP_SYMBOL(IC_RIGHT(ic))->ruonly) &&
+ ( ( isOperandInFarSpace(IC_RIGHT(ic)) || OP_SYMBOL(IC_RIGHT(ic))->onStack) &&
+ !isOperandInReg(IC_RIGHT(ic))) ) return NULL;
+
+ if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
+ !isOperandEqual(IC_LEFT(ic),op) &&
+ (OP_SYMBOL(IC_LEFT(ic))->liveTo >= ic->seq ||
+ IS_TRUE_SYMOP(IC_LEFT(ic)) ||
+ OP_SYMBOL(IC_LEFT(ic))->ruonly) &&
+ ( ( isOperandInFarSpace(IC_LEFT(ic)) || OP_SYMBOL(IC_LEFT(ic))->onStack) &&
+ !isOperandInReg(IC_LEFT(ic))) ) return NULL;
+
+ if (IC_LEFT(ic) && IC_RIGHT(ic) &&
+ IS_ITEMP(IC_LEFT(ic)) && IS_ITEMP(IC_RIGHT(ic)) &&
+ (isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic))) &&
+ (isOperandInFarSpace(IC_RIGHT(ic)) && !isOperandInReg(IC_RIGHT(ic))))
+ return NULL;
+ }