• Welcome to Theos PowerBasic Museum 2017.

(Optimization) Don't use ISTRUE if you can use (X<>0)

Started by Theo Gottwald, January 02, 2007, 09:38:54 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Theo Gottwald

Found another cycles-eating monster today. We already assumed it was there after my last post about ISFALSE.

WHILE ISTRUE(GetMessage(tmsg, BYVAL %NULL, 0, 0)) 
'
'will be compiled to:
'
41119C 6A00                   PUSH BYTE 00
41119E 6A00                   PUSH BYTE 00
4111A0 6A00                   PUSH BYTE 00
4111A2 8D9D28FEFFFF           LEA EBX, DWORD PTR [EBP+FFFFFE28]
4111A8 53                     PUSH EBX
4111A9 FF1508744100           CALL DWORD PTR [00417408]
4111AF E821290000             CALL L413AD5
4111B4 E823110000             CALL L4122DC
4111B9 D9E4                   FTST
4111BB DFE0                   FNSTSW AX
4111BD 9E                     SAHF
4111BE DDD8                   FSTPST, ST(0)
4111C0 66B8FFFF               MOV AX, WORD FFFF
4111C4 7502                   JNZ SHORT L4111C8
4111C6 6640                   INC  AX
4111C8 E804110000             CALL L4122D1
4111CD D9E4                   FTST
4111CF DFE0                   FNSTSW AX
4111D1 9E                     SAHF
4111D2 DDD8                   FSTPST, ST(0)
4111D4 0F849A000000           JZ  L411274


' alternatively use:
WHILE (GetMessage(tmsg, BYVAL %NULL, 0, 0)<>0) 
'
' and get this:
'
41119C 6A00                   PUSH BYTE 00
41119E 6A00                   PUSH BYTE 00
4111A0 6A00                   PUSH BYTE 00
4111A2 6A00                   PUSH BYTE 00
4111A4 8D9D28FEFFFF           LEA EBX, DWORD PTR [EBP+FFFFFE28]
4111AA 53                     PUSH EBX
4111AB FF1508744100           CALL DWORD PTR [00417408]
4111B1 E8FF280000             CALL L413AB5
4111B6 8F45D4                 POP DWORD PTR [EBP-2C]
4111B9 3B45D4                 CMP EAX, DWORD PTR [EBP-2C]
4111BC 0F849A000000           JZ  L41125C


No floatingpoint-operations. Much shorter.

Donald Darden

Note that saying something like:
    IF aa <> 0 THEN
as a way of testing inequality is going to perform the same way as this:
    IF aa THEN
because testing any value for a TRUE condition is effectively a test for an non-
zero state.  This works for any integer or floating point value

Saying
    IF aa = o THEN
is about as short as you can get, but some people like to say
    IF aa = %FALSE THEN
with the same results.

You could also reverse logic by saying
    IF NOT aa THEN
or
    IF NOT aa = 0 THEN
or even
    IF aa THEN
    ELSE
        ....
    END IF

The rules of logic as applied to computers is pretty straight forward, and can
include the use of parentheses (), AND, OR, XOR, and NOT (some languages
also support NOR and NAND, which are really abbreviations for NOT OR and
NOT AND).

Logic results are always evalutated as TRUE if the results are non-zero, and
FALSE if the results are exactly zero.

Parentheses () have a special purpose in PowerBasic when used in logical
expressions, as AND and OR are understood to mean each condition before
and after these terms is evaluated for a TRUE or FALSE result separately.
    IF a AND b THEN
would mean that a must be TRUE and b must be TRUE before the expression
a AND b would be determined to be TRUE.  The actual values of a and b are
inmaterial, except both would be non-zero.

However, if you wrote the expression as this:
    IF (a AND b) THEN
then the compiler understands that you want it to relate the value in a directly
to the value in b on a bitwise basis, and if any bit is set in both a and b, then
the result will be considered TRUE, otherwise if all bits examined in a and b are
found to have either or both set to zero, then the outcome will be FALSE.

Bitwise operation in such cases may give unexpected results.  Unless you know
what you are doing, and know what the results of bitwise operations will be,
you might be better off leaving out the parentheses or including explicit tests
for a and b like so:
    IF a AND b THEN
or:
    IF a THEN If b THEN
or:
    IF a THEN
        IF b THEN
        END IF
    END IF
or:
   IF (a <> 0 AND b <> 0) THEN

You can even do this:
    IF (a <> 0 AND b) THEN
because the a<>0 test will be performed first, a matter of operator precident,
and a TRUE state would be a -1 (not a positive 1, but negative 1).  A negative
1 ANDed with any integer value is automatically going to find at least one pair
of bits both set if the second value is non-zero.  But this would only work if b
is an Integer - it might well fail if b is a floating point type whose value is out
of the range of an integer (involving a decimal value or very large numeric
value with no bits set in the lower interger range).

Such tricks are not uncommon when looking at the code of someone well
versed in lower level features of the compiler, but some techniques can also result in code that can be hard to debug when you see it do something that was not expected.  The best advice then is to replace implicit tests (such as the
last one involving b) with explicit tests (such as using b=0 or b<>0) so as to
close any loopholes based on a faulty understanding between what was expected and what actually occurred.