2008-12-08 16:30 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)

* harbour/bin/hb-mkslib.sh
    ! fixed last modification

  * harbour/doc/Makefile
  + harbour/doc/cmpopt.txt
    + added small description for Harbour compile time optimization

  * harbour/include/hbexpra.c
    + allow to use hb_mutexCreate() as static variable initializer, f.e.:
         static s_mtxarr := { "MTX1" => hb_mutexCreate(), ;
                              "MTX2" => hb_mutexCreate(), ;
                              "MTX3" => hb_mutexCreate() }
  * harbour/include/hbexprb.c
    % comment

  * harbour/source/common/expropt2.c
    + added some missing optimizations for date constants
    + added optimization for multiple negate expressions
This commit is contained in:
Przemyslaw Czerpak
2008-12-08 15:28:49 +00:00
parent b60157c4ed
commit b46a548172
7 changed files with 292 additions and 5 deletions

View File

@@ -8,6 +8,26 @@
2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org)
*/
2008-12-08 16:30 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/bin/hb-mkslib.sh
! fixed last modification
* harbour/doc/Makefile
+ harbour/doc/cmpopt.txt
+ added small description for Harbour compile time optimization
* harbour/include/hbexpra.c
+ allow to use hb_mutexCreate() as static variable initializer, f.e.:
static s_mtxarr := { "MTX1" => hb_mutexCreate(), ;
"MTX2" => hb_mutexCreate(), ;
"MTX3" => hb_mutexCreate() }
* harbour/include/hbexprb.c
% comment
* harbour/source/common/expropt2.c
+ added some missing optimizations for date constants
+ added optimization for multiple negate expressions
2008-12-07 22:22 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com)
* harbour/contrib/gtwvg/makefile
* harbour/contrib/gtwvg/common.mak

View File

@@ -96,7 +96,7 @@ if [ "${SLIB_EXT}" != ".dylib" ]; then
echo "cannot read file: ${f}"
exit 1
fi
cp "${dir}/${f}" "${OTMPDIR}" || exit 1
cp "${f}" "${OTMPDIR}" || exit 1
;;
*.a)
if [ "${f#/}" == "${f}" ]; then
@@ -110,7 +110,7 @@ if [ "${SLIB_EXT}" != ".dylib" ]; then
d="${f##*/}"
mkdir $d
cd $d
${CCPREFIX}ar -x "${dir}/${f}" || exit 1
${CCPREFIX}ar -x "${f}" || exit 1
cd ..
;;
*)

View File

@@ -6,6 +6,7 @@ ROOT = ../
DOC_FILES=\
c_std.txt \
cmpopt.txt \
class_tp.txt \
cmdline.txt \
codebloc.txt \

165
harbour/doc/cmpopt.txt Normal file
View File

@@ -0,0 +1,165 @@
/*
* $Id$
*/
Przemyslaw Czerpak (druzus/at/priv.onet.pl)
Harbour compile time optimizations.
1. Function call optimization.
Just like Clipper Harbour compiler can optimize few function calls if
parameters are well known constant values. Here is the list of functions
optimized at compile time:
- Clipper compatible:
AT( <cConst1>, <cConst2> ) // Clipper wrongly calculates
// "" $ <cConst> as .T.
CHR( <nConst> )
UPPER( <cConst> ) // <cConst> cannot contain characters different then
[0-9A-Za-z]
- Harbour extension:
INT( <cConst> )
ASC( <cConst> [ , ... ] )
MIN( <xConst1>, <xConst2> ) // <xConstN> is N, D or L value
MAX( <xConst1>, <xConst2> ) // <xConstN> is N, D or L value
EMPTY( <aConst> | <hConst> | <cConst> | <bConst> |
<nConst> | <dConst>| <lConst> | NIL )
LEN( <cConst> | <aConst> | <hConst> )
CTOD( <cConst> [ , ... } )
DTOS( <dConst> ] )
STOD( [ <cConst> ] )
HB_STOD( [ <cConst> ] )
HB_BITNOT( <nConst> [, ... ] )
HB_BITAND( <nConst1>, <nConst2> [, <nConstN> ] )
HB_BITOR( <nConst1>, <nConst2> [, <nConstN> ] )
HB_BITXOR( <nConst1>, <nConst2> [, <nConstN> ] )
HB_BITTEST( <nConst1>, <nConst2> [, ... ] )
HB_BITSET( <nConst1>, <nConst2> [, ... ] )
HB_BITRESET( <nConst1>, <nConst2> [, ... ] )
HB_BITSHIFT( <nConst1>, <nConst2> [, ... ] )
- Harbour special functions:
HB_I18N_GETTEXT_NOOP( <cConst1> [ , <cConst2> ] )
HB_I18N_NGETTEXT_NOOP( <cConst1> | <acConst1> [ , <cConst2> ] )
HB_MUTEXCREATE()
2. Expresion optimization:
Just like Clipper Harbour compiler can optimize some expresions if
arguments are well known and can be callculated at compile time:
- Clipper compatible:
<nConst1> + <nConst2> => <nConst>
<nConst1> + <dConst2> => <dConst>
<dConst1> + <nConst2> => <dConst>
<cConst1> + <cConst2> => <cConst>
// In Clipper neither <cConst1> nor <cConst2>
// can contain '&' character. Harbour checks
// if concatenation can change existing valid
// macro expression
<nConst1> - <nConst2> => <nConst>
<dConst1> - <dConst2> => <dConst>
<dConst1> - <nConst2> => <dConst>
<cConst1> - <cConst2> => <cConst>
// In Clipper neither <cConst1> nor <cConst2>
// can contain '&' character. Harbour checks
// if concatenation can change existing valid
// macro expression
<nConst1> * <nConst2> => <nConst>
<nConst1> / <nConst2> => <nConst> // Clipper optimize only integers
<nConst1> % <nConst2> => <nConst>
<cConst1> $ <cConst2> => <lConst> // Clipper wrongly calculates
// "" $ <cConst> as .T.
<lConst1> == <lConst2> => <lConst>
<nConst1> == <nConst2> => <lConst>
<dConst1> == <dConst2> => <lConst>
<cConst1> == <cConst2> => <lConst>
NIL == <xConst> => <lConst>
<xConst> == NIL => <lConst>
<lConst1> = <lConst2> => <lConst>
<nConst1> = <nConst2> => <lConst>
<dConst1> = <dConst2> => <lConst>
NIL = <xConst> => <lConst>
<xConst> = NIL => <lConst>
"" = "" => .T.
<lConst1> != <lConst2> => <lConst>
<nConst1> != <nConst2> => <lConst>
<dConst1> != <dConst2> => <lConst>
NIL != <xConst> => <lConst>
<xConst> != NIL => <lConst>
"" != "" => .F.
<lConst1> >= <lConst2> => <lConst>
<nConst1> >= <nConst2> => <lConst>
<dConst1> >= <dConst2> => <lConst>
<lConst1> <= <lConst2> => <lConst>
<nConst1> <= <nConst2> => <lConst>
<dConst1> <= <dConst2> => <lConst>
<lConst1> > <lConst2> => <lConst>
<nConst1> > <nConst2> => <lConst>
<dConst1> > <dConst2> => <lConst>
<lConst1> < <lConst2> => <lConst>
<nConst1> < <nConst2> => <lConst>
<dConst1> < <dConst2> => <lConst>
.NOT. .T. => .F.
.NOT. .F. => .T.
<lConst1> .AND. <lConst2> => <lConst>
<lConst1> .OR. <lConst2> => <lConst>
IIF( .T., <expr1>, <expr2> ) => <expr1>
IIF( .F., <expr1>, <expr2> ) => <expr2>
- optimizations disabled by -z compiler switch
.T. .AND. <expr> => <expr>
<expr> .AND. .T. => <expr>
.F. .OR. <expr> => <expr>
<expr> .OR. .F. => <expr>
.F. .AND. <expr> => .F.
<expr> .AND. .F. => .F.
.T. .OR. <expr> => .T.
<expr> .OR. .T. => .T.
- Harbour extension:
<nConst1> ^ <nConst2> => <nConst>
<aValue> [ <nConst> ] => <xArrayItem>
( <expr> ) => <expr> // it allows to optimize expresions like: 1+(2)
- Harbour extension which may disable RT errors in wrong expressions:
.NOT. .NOT. <expr> => <expr>
- - <expr> => <expr>
<expr> + 0 => <expr>
0 + <expr> => <expr>
<expr> + "" => <expr>
"" + <expr> => <expr>
In cases when result is miningless Harbour compiler can skip code
for operation, f.e. such line of .prg code:
( <exp1> <op> <exp2> )
where result of <op> operation is ignored Harbour reduced the code
to:
( <exp1>, <exp2> )
In Clipper in some places optiomization is not enabled, f.e. Clipper
does not optimize <exp> in expressions like:
<exp> : msg( ... )
Unlike Clipper Harbour tries to optimize all expressions.
If some code needs strict Clipper behavior then it can be forced by using
-kc Harbour compiler switch. It disabled Harbour extensions and enables
replicating some Clipper bugs like optimizing "" $ <cConst> to .T. at
compile time when it runtime it's .F.
Expressions fully optimized to constant values at compile time can be used
to intialize static variables, f.e.:
static s_var := ( 1 + 2 / 3 )
Harbour has additional optimization phase which operates on generated PCODE.
It can also reduce expressions, joins jumps, removes death or meaningless
code which can appear after all other optimizations and were not optimized
by expression optimizer.

View File

@@ -547,10 +547,35 @@ HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex, HB_CO
/* ************************************************************************* */
#ifndef HB_MACRO_SUPPORT
/* List of functions which can be used as static initializers */
static const char * s_szStaticFun[] = {
"HB_MUTEXCREATE"
};
#define STATIC_FUNCTIONS ( sizeof( s_szStaticFun ) / sizeof( char * ) )
static BOOL hb_compStaticFunction( const char * szName )
{
unsigned int ui;
for( ui = 0; ui < STATIC_FUNCTIONS; ++ui )
{
if( strcmp( szName, s_szStaticFun[ ui ] ) == 0 )
return TRUE;
}
return FALSE;
}
static void hb_compExprCheckStaticInitializer( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr, HB_COMP_DECL )
{
if( pRightExpr->ExprType > HB_ET_FUNREF ||
pRightExpr->ExprType == HB_ET_SELF )
if( ( pRightExpr->ExprType > HB_ET_FUNREF ||
pRightExpr->ExprType == HB_ET_SELF ) &&
!( pRightExpr->ExprType == HB_ET_FUNCALL &&
pRightExpr->value.asFunCall.pFunName->ExprType == HB_ET_FUNNAME &&
hb_compStaticFunction( pRightExpr->value.asFunCall.pFunName->
value.asSymbol ) &&
hb_compExprParamListLen( pRightExpr->value.asFunCall.pParms ) == 0 ) )
{
/* Illegal initializer for static variable (not a constant value)
*/

View File

@@ -3127,6 +3127,8 @@ static HB_EXPR_FUNC( hb_compExprUseNot )
return pSelf;
}
/* handler for = operator
*/
static HB_EXPR_FUNC( hb_compExprUseEqual )
{
switch( iMessage )

View File

@@ -756,6 +756,16 @@ HB_EXPR_PTR hb_compExprReduceNegate( HB_EXPR_PTR pSelf, HB_COMP_DECL )
HB_COMP_EXPR_FREE( pSelf );
pSelf = pExpr;
}
else if( pExpr->ExprType == HB_EO_NEGATE && HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
pExpr->ExprType = HB_ET_NONE; /* suppress deletion of operator components */
pExpr = pExpr->value.asOperator.pLeft;
HB_COMP_EXPR_FREE( pSelf );
pSelf = pExpr;
}
return pSelf;
}
@@ -875,6 +885,17 @@ HB_EXPR_PTR hb_compExprReduceNE( HB_EXPR_PTR pSelf, HB_COMP_DECL )
}
break;
case HB_ET_DATE:
{
BOOL bResult = pLeft->value.asNum.val.l != pRight->value.asNum.val.l;
HB_COMP_EXPR_FREE( pLeft );
HB_COMP_EXPR_FREE( pRight );
pSelf->ExprType = HB_ET_LOGICAL;
pSelf->ValType = HB_EV_LOGICAL;
pSelf->value.asLogical = bResult;
}
break;
case HB_ET_NIL:
HB_COMP_EXPR_FREE( pLeft );
HB_COMP_EXPR_FREE( pRight );
@@ -972,6 +993,17 @@ HB_EXPR_PTR hb_compExprReduceGE( HB_EXPR_PTR pSelf, HB_COMP_DECL )
}
break;
case HB_ET_DATE:
{
BOOL bResult = pLeft->value.asNum.val.l >= pRight->value.asNum.val.l;
HB_COMP_EXPR_FREE( pLeft );
HB_COMP_EXPR_FREE( pRight );
pSelf->ExprType = HB_ET_LOGICAL;
pSelf->ValType = HB_EV_LOGICAL;
pSelf->value.asLogical = bResult;
}
break;
}
/* TODO: add checking of incompatible types
else
@@ -1036,6 +1068,17 @@ HB_EXPR_PTR hb_compExprReduceLE( HB_EXPR_PTR pSelf, HB_COMP_DECL )
}
break;
case HB_ET_DATE:
{
BOOL bResult = pLeft->value.asNum.val.l <= pRight->value.asNum.val.l;
HB_COMP_EXPR_FREE( pLeft );
HB_COMP_EXPR_FREE( pRight );
pSelf->ExprType = HB_ET_LOGICAL;
pSelf->ValType = HB_EV_LOGICAL;
pSelf->value.asLogical = bResult;
}
break;
}
/* TODO: add checking of incompatible types
else
@@ -1100,6 +1143,17 @@ HB_EXPR_PTR hb_compExprReduceGT( HB_EXPR_PTR pSelf, HB_COMP_DECL )
}
break;
case HB_ET_DATE:
{
BOOL bResult = pLeft->value.asNum.val.l > pRight->value.asNum.val.l;
HB_COMP_EXPR_FREE( pLeft );
HB_COMP_EXPR_FREE( pRight );
pSelf->ExprType = HB_ET_LOGICAL;
pSelf->ValType = HB_EV_LOGICAL;
pSelf->value.asLogical = bResult;
}
break;
}
/* TODO: add checking of incompatible types
else
@@ -1164,8 +1218,17 @@ HB_EXPR_PTR hb_compExprReduceLT( HB_EXPR_PTR pSelf, HB_COMP_DECL )
}
break;
default:
case HB_ET_DATE:
{
BOOL bResult = pLeft->value.asNum.val.l < pRight->value.asNum.val.l;
HB_COMP_EXPR_FREE( pLeft );
HB_COMP_EXPR_FREE( pRight );
pSelf->ExprType = HB_ET_LOGICAL;
pSelf->ValType = HB_EV_LOGICAL;
pSelf->value.asLogical = bResult;
}
break;
}
/* TODO: add checking of incompatible types
else
@@ -1246,6 +1309,17 @@ HB_EXPR_PTR hb_compExprReduceEQ( HB_EXPR_PTR pSelf, HB_COMP_DECL )
}
break;
case HB_ET_DATE:
{
BOOL bResult = pLeft->value.asNum.val.l == pRight->value.asNum.val.l;
HB_COMP_EXPR_FREE( pLeft );
HB_COMP_EXPR_FREE( pRight );
pSelf->ExprType = HB_ET_LOGICAL;
pSelf->ValType = HB_EV_LOGICAL;
pSelf->value.asLogical = bResult;
}
break;
case HB_ET_NIL:
HB_COMP_EXPR_FREE( pLeft );
HB_COMP_EXPR_FREE( pRight );