Fixed some BITFIELD related problems
[fw/sdcc] / src / SDCCcse.c
index c5ee399c31398416581139b1998dc0b32f3aeb3c..f0859751141166730d13a55c8646bbe59ae76b32 100644 (file)
@@ -81,7 +81,7 @@ int pcseDef (void *item, va_list ap)
 /* replaceAllSymBySym - replaces all operands by operand in an     */
 /*                      instruction chain                          */
 /*-----------------------------------------------------------------*/
-void replaceAllSymBySym (iCode *ic, operand *from , operand *to)
+void replaceAllSymBySym (iCode *ic, operand *from , operand *to, bitVect **ndpset)
 {
     iCode *lic;
 
@@ -122,12 +122,20 @@ void replaceAllSymBySym (iCode *ic, operand *from , operand *to)
            if (POINTER_SET(lic)) {
                bitVectUnSetBit (OP_USES(from),lic->key);
                OP_USES(to) = bitVectSetBit (OP_USES(to),lic->key);
+
+               /* also check if the "from" was in the non-dominating 
+                  pointer sets and replace it with "to" in the bitVector */
+               if (bitVectBitValue(*ndpset,from->key)) {
+                   bitVectUnSetBit(*ndpset,from->key);
+                   bitVectSetBit(*ndpset,to->key);
+               }
+
            }
            else {              
                bitVectUnSetBit (OP_DEFS(from),lic->key);
                OP_DEFS(to) = bitVectSetBit (OP_DEFS(to),lic->key);
-           }
-           siaddr = IC_RESULT(lic)->isaddr ;
+           }       
+           siaddr = IC_RESULT(lic)->isaddr ;       
            IC_RESULT(lic) = operandFromOperand(to);
            IC_RESULT(lic)->isaddr = siaddr ;
        }
@@ -148,7 +156,7 @@ void replaceAllSymBySym (iCode *ic, operand *from , operand *to)
            siaddr = IC_LEFT(lic)->isaddr ;
            IC_LEFT(lic) = operandFromOperand(to);
            IC_LEFT(lic)->isaddr = siaddr ;
-       }
+       }       
     }
 }
 
@@ -183,7 +191,7 @@ DEFSETFUNC(removeFromInExprs)
     ebp->visited = 1;
     deleteItemIf(&ebp->inExprs,iCodeKeyIs,ic->key);
     if (ebp != cbp && !bitVectBitValue(cbp->domVect,ebp->bbnum))
-       replaceAllSymBySym(ebp->sch,from,to);
+       replaceAllSymBySym(ebp->sch,from,to,&ebp->ndompset);
 
     applyToSet(ebp->succList,removeFromInExprs,ic,from,to,cbp);
     return 0;
@@ -199,7 +207,7 @@ static bool isGlobalInNearSpace (operand *op)
        suggested by Jean-Louis VERN, with 8051s we have no
        advantage of putting variables in near space into
        registers */
-    if (isOperandGlobal(op)  &&
+    if (isOperandGlobal(op)  && !IN_FARSPACE(SPEC_OCLS(type)) &&
        IN_DIRSPACE(SPEC_OCLS(type)))
        return TRUE;
     else
@@ -368,6 +376,17 @@ DEFSETFUNC(ifDefGlobal)
     return (isOperandGlobal(cdp->sym));
 }
 
+/*-----------------------------------------------------------------*/
+/* ifAnyGetPointer - if get pointer icode                          */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(ifAnyGetPointer)
+{
+    cseDef *cdp = item;
+    
+    if (cdp->diCode && POINTER_GET(cdp->diCode)) return 1;
+    return 0;
+}
+
 /*-----------------------------------------------------------------*/
 /* ifOperandsHave - if any of the operand are the same as this     */
 /*-----------------------------------------------------------------*/
@@ -965,6 +984,7 @@ DEFSETFUNC(diCodeForSym)
 int constFold (iCode *ic, set *cseSet)
 {
     iCode *dic = NULL;
+    iCode *ldic= NULL;
     /* this routine will change
        a = b + 10;
        c = a + 10;
@@ -998,6 +1018,16 @@ int constFold (iCode *ic, set *cseSet)
     if (!IS_OP_LITERAL(IC_RIGHT(dic)))
        return 0;
 
+    /* find the definition of the left operand
+       of dic.then check if this defined with a
+       get_pointer return 0 if the pointer size is
+       less than 2 (MCS51 specific) */
+    if (!(applyToSet(cseSet,diCodeForSym,IC_LEFT(dic),&ldic)))
+       return 0;
+
+    if (POINTER_GET(ldic) && getSize(operandType(IC_LEFT(ldic))) <= 1)
+       return 0;
+    
     /* it is if the operations are the same*/
     /* the literal parts need to be added  */
     IC_LEFT(ic) = operandFromOperand(IC_LEFT(dic));    
@@ -1089,6 +1119,27 @@ DEFSETFUNC(delGetPointerSucc)
     return applyToSet(ebp->succList,delGetPointerSucc,op,dfnum);
 }    
 
+/*-----------------------------------------------------------------*/
+/* fixUpTypes - KLUGE HACK fixup a lowering problem                */
+/*-----------------------------------------------------------------*/
+static void fixUpTypes(iCode *ic)
+{
+       link *t1 = operandType(IC_LEFT(ic)) ,*t2;
+       
+       if (IS_DS390_PORT)
+       {
+           /* hack-o-matic! */
+           return;
+       }
+       
+       /* for pointer_gets if the types of result & left r the
+          same then change it type of result to next */
+       if (IS_PTR(t1) &&
+           checkType(t2=operandType(IC_RESULT(ic)),t1) == 1) {
+               setOperandType(IC_RESULT(ic),t2->next);
+       }
+}
+
 /*-----------------------------------------------------------------*/
 /* cseBBlock - common subexpression elimination for basic blocks   */
 /*             this is the hackiest kludgiest routine in the whole */
@@ -1134,6 +1185,13 @@ int cseBBlock ( eBBlock *ebb, int computeOnly,
        if (SKIP_IC2(ic))
            continue ;
 
+       /* if this is an assignment from true symbol
+          to a temp then do pointer post inc/dec optimzation */
+       if (ic->op == '=' && !POINTER_SET(ic) &&
+           IS_PTR(operandType(IC_RESULT(ic)))) {
+           ptrPostIncDecOpt(ic);
+       }
+
        /* clear the def & use chains for the operands involved */
        /* in this operation . since it can change due to opts  */
        unsetDefsAndUses (ic);
@@ -1150,6 +1208,10 @@ int cseBBlock ( eBBlock *ebb, int computeOnly,
            /* delete global variables from the cseSet
               since they can be modified by the function call */
            deleteItemIf(&cseSet,ifDefGlobal);
+           /* delete all getpointer iCodes from cseSet, this should
+              be done only for global arrays & pointers but at this
+              point we don't know if globals, so to be safe do all*/
+           deleteItemIf(&cseSet,ifAnyGetPointer);
        }
 
        /* for pcall & ipush we need to add to the useSet */
@@ -1209,6 +1271,8 @@ int cseBBlock ( eBBlock *ebb, int computeOnly,
        if (POINTER_GET(ic) && !IS_PTR(operandType(IC_LEFT(ic)))) {
            setOperandType(IC_LEFT(ic),
                           aggrToPtr(operandType(IC_LEFT(ic)),FALSE));
+           fixUpTypes(ic);
+
        }
        if (POINTER_SET(ic) && !IS_PTR(operandType(IC_RESULT(ic)))) {
            setOperandType(IC_RESULT(ic),
@@ -1231,7 +1295,8 @@ int cseBBlock ( eBBlock *ebb, int computeOnly,
            /* update the spill location for this */
            updateSpillLocation (ic);
 
-           if (POINTER_SET(ic)) {
+           if (POINTER_SET(ic) &&
+               !(IS_BITFIELD(OP_SYMBOL(IC_RESULT(ic))->etype))) {
                pdop = NULL ;
                applyToSetFTrue (cseSet,findCheaperOp,IC_RESULT(ic),&pdop);
                if (pdop && IS_ITEMP(pdop) && !computeOnly)                 
@@ -1310,11 +1375,15 @@ int cseBBlock ( eBBlock *ebb, int computeOnly,
        pdic = NULL ;   
        if (!( POINTER_GET(ic)                      &&
               (IS_BITFIELD(OP_SYMBOL(IC_RESULT(ic))->etype) ||
-              isOperandVolatile(IC_LEFT(ic),TRUE))) &&
+              isOperandVolatile(IC_LEFT(ic),TRUE)           ||
+              bitVectBitValue(ebb->ndompset,IC_LEFT(ic)->key))) &&
            ! ASSIGNMENT(ic)                        && 
              IS_ITEMP(IC_RESULT(ic))               &&
            ! computeOnly) {
            applyToSet (cseSet,findPrevIc,ic,&pdic);
+           if (pdic && checkType(operandType(IC_RESULT(pdic)),
+                                 operandType(IC_RESULT(ic))) != 1)
+                   pdic = NULL;
        } 
        
        /* if found then eliminate this and add to*/
@@ -1325,7 +1394,7 @@ int cseBBlock ( eBBlock *ebb, int computeOnly,
            if (IS_ITEMP(IC_RESULT(ic))) {
 
                /* replace in the remaining of this block */
-               replaceAllSymBySym(ic->next,IC_RESULT(ic),IC_RESULT(pdic));
+               replaceAllSymBySym(ic->next,IC_RESULT(ic),IC_RESULT(pdic),&ebb->ndompset);
                /* remove this iCode from inexpressions of all
                   its successors, it cannot be in the in expressions
                   of any of the predecessors */        
@@ -1339,7 +1408,7 @@ int cseBBlock ( eBBlock *ebb, int computeOnly,
                    eBBlock *owner ;
                    for (owner = setFirstItem(ic->movedFrom); owner ;
                         owner = setNextItem(ic->movedFrom))
-                       replaceAllSymBySym(owner->sch,IC_RESULT(ic),IC_RESULT(pdic));
+                       replaceAllSymBySym(owner->sch,IC_RESULT(ic),IC_RESULT(pdic),&owner->ndompset);
                }
                pdic->movedFrom = unionSets(pdic->movedFrom,ic->movedFrom,THROW_NONE);
            } 
@@ -1391,7 +1460,7 @@ int cseBBlock ( eBBlock *ebb, int computeOnly,
            /* if we find it then locally replace all
               references to the result with what we assigned */
            if (pdop) {
-               replaceAllSymBySym(ic->next,IC_RESULT(ic),pdop);
+               replaceAllSymBySym(ic->next,IC_RESULT(ic),pdop,&ebb->ndompset);
            }
        }