Page 1 of 1

Macro/Literal Expressions

Posted: Tue Jul 31, 2018 7:52 pm
by joshklod
I often use macro expressions like the following in my code:

Code: Select all

#define LENGTH 16
if idx > LENGTH*3/4 then print "Almost full"
I can see that the preprocessor correctly expands this to:

Code: Select all

if idx > 16*3/4 then print "Almost full"
Is the Basic compiler smart enough to optimize`16*3/4` to `12`, or will the expression be evaluated at runtime?

Also, how does the compiler handle the following examples, where variables and literal expressions are mixed?

Code: Select all

dim a as integer
a = 3
' I would expect these expressions to be evaluated in the following ways:
print a*(5/2) ' => a*(2)  [6]  (A)
print a*5/2   ' => a*5/2  [7]  (B)
print 5*2*a   ' => (10)*a [30] (C)
print a*5*2   ' =? a*(10) [30] (D)
print a*6/2   ' =? a*(3)  [9]  (E)
Optimization of expressions A and C seems natural due to order of operations/evaluation order. Similarly, expression B cannot be optimized, because though algebraically equal, integer division would yield a different result.
Expressions D and E are less obvious. Though optimization would change the order in which the expression is evaluated, the result should be the same, unless integer overflow occurs. This would also be more difficult for the compiler to detect, as these situations often cannot be identified by syntax alone.

Edit:
What if I use `CONST` instead of `#define` in the first example? As in:

Code: Select all

CONST LENGTH = 16
if idx > LENGTH*3/4 then print "Almost full"

Re: Macro/Literal Expressions

Posted: Sun Aug 05, 2018 9:53 pm
by basicchip
It is a little difficult for the user to figure out what the compiler optimizes for and what it does not.

I many cases if the compiler thinks the expression is a constant it evaluates it immediately. I do have a tool I can use which dumps out compiled code in the opcode format we use. DEBUG mode if you will.

In the first case

Code: Select all

CONST LENGTH=16
if idx > LENGTH*3/4 then print "Almost full"
It currently does not optimize. But if you had written

Code: Select all

CONST LENGTH=16
if idx > (LENGTH*3/4) then print "Almost full"
As in this case it evaluates the expression inside the () and sees it is a constant. Fooled myself on this one, in that it does pre-evaluate if you use a #define rather than a CONST. So there is room for compiler improvement. I usually use #define (force of habit, and also more typical of C programming)

As for you other examples A and C are optimized, B is not. And D and E are not, really D might expected to be, but E would be a bit trickier for the compiler.

One way you could tell is by timing the operations, which I often do, enclosing them in

Code: Select all

i=1000000
while x
  .. whatever code...
  i =i-1
loop

Re: Macro/Literal Expressions

Posted: Sun Aug 05, 2018 9:56 pm
by basicchip
PS these optimizations are only done on integers currently.

Re: Macro/Literal Expressions

Posted: Mon Aug 06, 2018 1:04 pm
by joshklod
Thank you for the info!

To be clear (maybe my edit was confusing), my first example uses `#define`. Are parentheses required to trigger optimization in this case?

It sounds like I can guarantee optimization as long as I wrap constant expressions (or sub-expressions) in parentheses. This is probably a good habit to get into anyway.

Re: Macro/Literal Expressions

Posted: Mon Aug 06, 2018 2:13 pm
by basicchip
No it was me, I tried CONST first and that is a function of the compiler.

#define is done by the preprocessor, separate from the compiler, so those replacements are done to the source before the compiler sees them.