Fixed some BITFIELD related problems
[fw/sdcc] / src / SDCCcse.c
index 04e6337f071d2010121341b95dfb65ba9a04be64..f0859751141166730d13a55c8646bbe59ae76b32 100644 (file)
@@ -67,6 +67,8 @@ int pcseDef (void *item, va_list ap)
     cseDef *cdp = item;
     iCodeTable *icTab ;
 
+    (void)ap;
+    
     if (!cdp->sym)
        fprintf(stdout,"**null op**");
     printOperand(cdp->sym,stdout);
@@ -79,29 +81,67 @@ 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;
 
     for (lic = ic ; lic ; lic = lic->next ) {
        int siaddr ;
 
+       /* do the special cases first */
+       if (lic->op == IFX) {
+               if (IS_SYMOP(to) &&
+                   IC_COND(lic)->key == from->key) {
+                       
+                       bitVectUnSetBit (OP_USES(from),lic->key);
+                       OP_USES(to) = bitVectSetBit(OP_USES(to),lic->key);
+                       siaddr = IC_COND(lic)->isaddr ;
+                       IC_COND(lic) = operandFromOperand(to);
+                       IC_COND(lic)->isaddr = siaddr ;
+                       
+               }
+               continue ;
+       }
+
+       if (lic->op == JUMPTABLE) {
+               if (IS_SYMOP(to) &&
+                   IC_JTCOND(lic)->key == from->key) {
+                       
+                       bitVectUnSetBit (OP_USES(from),lic->key);
+                       OP_USES(to) = bitVectSetBit(OP_USES(to),lic->key);
+                       siaddr = IC_COND(lic)->isaddr ;
+                       IC_JTCOND(lic) = operandFromOperand(to);
+                       IC_JTCOND(lic)->isaddr = siaddr ;
+                       
+               }
+               continue ;
+       }
+
        if (IC_RESULT(lic) && IC_RESULT(lic)->key == from->key ) {
            /* maintain du chains */
            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 ;
        }
 
-       if (IC_RIGHT(lic) && IC_RIGHT(lic)->key == from->key ) {
+       if (IS_SYMOP(to) &&
+           IC_RIGHT(lic) && IC_RIGHT(lic)->key == from->key ) {
            bitVectUnSetBit (OP_USES(from),lic->key);
            OP_USES(to) = bitVectSetBit(OP_USES(to),lic->key);
            siaddr = IC_RIGHT(lic)->isaddr ;
@@ -109,13 +149,14 @@ void replaceAllSymBySym (iCode *ic, operand *from , operand *to)
            IC_RIGHT(lic)->isaddr = siaddr ;
        }
 
-       if (IC_LEFT(lic) && IC_LEFT(lic)->key == from->key ) {
+       if (IS_SYMOP(to) &&
+           IC_LEFT(lic) && IC_LEFT(lic)->key == from->key ) {
            bitVectUnSetBit (OP_USES(from),lic->key);
            OP_USES(to) = bitVectSetBit(OP_USES(to),lic->key);
            siaddr = IC_LEFT(lic)->isaddr ;
            IC_LEFT(lic) = operandFromOperand(to);
            IC_LEFT(lic)->isaddr = siaddr ;
-       }
+       }       
     }
 }
 
@@ -150,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;
@@ -166,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
@@ -335,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     */
 /*-----------------------------------------------------------------*/
@@ -854,7 +906,7 @@ void ifxOptimize (iCode *ic, set *cseSet,
     /* if the conditional is a literal then */
     if (IS_OP_LITERAL(IC_COND(ic))) {         
 
-       if ( operandLitValue(IC_COND(ic)) && IC_TRUE(ic)) {
+       if ( (operandLitValue(IC_COND(ic)) != 0.0) && IC_TRUE(ic)) {
            
            /* change to a goto */
            ic->op = GOTO ;
@@ -932,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;
@@ -965,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));    
@@ -1056,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 */
@@ -1101,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);
@@ -1117,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 */
@@ -1176,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),
@@ -1198,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)                 
@@ -1277,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*/
@@ -1292,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 */        
@@ -1306,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);
            } 
@@ -1358,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);
            }
        }