Velocity Reviews > Optimizing the expression (x * 1000 / 1000)

# Optimizing the expression (x * 1000 / 1000)

pozz
Guest
Posts: n/a

 02-23-2011
I have the following code:
---
#define HZ 1000
unsigned int calc(unsigned int x) {
x = x * HZ / 1000;
}
void main(void) {
unsigned int y = calc(23);
...
}
---

When I compile it with a compiler for a 16-bit embedded
microcontroller, I see the code for multiplication and division in
calc function. The optimization is on.

Is there any method to avoid the time consuming multiplication and
division?

Jens Thoms Toerring
Guest
Posts: n/a

 02-23-2011
pozz <(E-Mail Removed)> wrote:
> I have the following code:

> #define HZ 1000
> unsigned int calc(unsigned int x) {
> x = x * HZ / 1000;
> }
> void main(void) {
> unsigned int y = calc(23);
> ...
> }

> When I compile it with a compiler for a 16-bit embedded
> microcontroller, I see the code for multiplication and division in
> calc function. The optimization is on.

> Is there any method to avoid the time consuming multiplication and
> division?

I would try as a first step to put the 'HZ / 1000' bit into
parentheses. The expression 'x * Hz / 1000' is evaluated
left to right and 'x * Hz' could for example overflow, thus
'x * 1000 / 1000' could have quite a different result from
'x * ( 1000 / 1000 )'. Thus the compiler isn't allowed to
optimize out the (for a human reader rather obviously)
redundant multiplication and division. Telling the compiler
what you really want will probably give it the information
it needs to further optimize (but, of course, the compiler
isn't in any sense required to optimize, that's just a
question of the quality of the implementation).

Regards, Jens
--
\ Jens Thoms Toerring ___ http://www.velocityreviews.com/forums/(E-Mail Removed)
\__________________________ http://toerring.de

pozz
Guest
Posts: n/a

 02-23-2011
On 23 Feb, 11:16, (E-Mail Removed) (Jens Thoms Toerring) wrote:
> I would try as a first step to put the 'HZ / 1000' bit into
> parentheses.

Oh yes, in that way the compiler doesn't add multiplication and
division instructions.

But what happens if I declare HZ as 1500?
x = x * (HZ / 1000);

James Kuyper
Guest
Posts: n/a

 02-23-2011
On 02/23/2011 05:58 AM, pozz wrote:
> On 23 Feb, 11:16, (E-Mail Removed) (Jens Thoms Toerring) wrote:
>> I would try as a first step to put the 'HZ / 1000' bit into
>> parentheses.

>
> Oh yes, in that way the compiler doesn't add multiplication and
> division instructions.
>
> But what happens if I declare HZ as 1500?
> x = x * (HZ / 1000);

That statement will be equivalent to
x = x * 1;
or
x = x;
or, since x is not volatile, it's also equivalent to doing nothing at
all. Therefore, a decently optimizing compile will probably drop the
statement entirely. If that's not what you want; if the calculation you
actually want it to perform is (x*1500)/1000, separate multiplications
and division are unavoidable (except insofar as the compiler finds other
faster ways of achieving identical results).
--
James Kuyper

James Kuyper
Guest
Posts: n/a

 02-23-2011
On 02/23/2011 04:42 AM, pozz wrote:
> I have the following code:
> ---
> #define HZ 1000
> unsigned int calc(unsigned int x) {
> x = x * HZ / 1000;

Just a nit pick: isn't there a missing 'return' statement here?

> }
> void main(void) {
> unsigned int y = calc(23);

Without the return statement in calc(), the use of the return value from
calc() to initialize y renders the behavior of your entire program
undefined.

--
James Kuyper

Willem
Guest
Posts: n/a

 02-23-2011
pozz wrote:
) I have the following code:
) ---
) #define HZ 1000
) unsigned int calc(unsigned int x) {
) x = x * HZ / 1000;
) }
) void main(void) {
) unsigned int y = calc(23);
) ...
) }
) ---
)
) When I compile it with a compiler for a 16-bit embedded
) microcontroller, I see the code for multiplication and division in
) calc function. The optimization is on.
)
) Is there any method to avoid the time consuming multiplication and
) division?

#define HZ 1000
unsigned int calc(unsigned int x) {
if (HZ != 1000) x = x * HZ / 1000;
}

Since the condition is a constant, the whole if should be optimized away.

Alternatively:

#define HZ 1000
unsigned int calc(unsigned int x) {
#if (HZ != 1000)
x = x * HZ / 1000;
#endif
}

By the way: your code won't work as-is, as it doesn't return anything.

SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

BartC
Guest
Posts: n/a

 02-23-2011

"pozz" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On 23 Feb, 11:16, (E-Mail Removed) (Jens Thoms Toerring) wrote:
>> I would try as a first step to put the 'HZ / 1000' bit into
>> parentheses.

>
> Oh yes, in that way the compiler doesn't add multiplication and
> division instructions.
>
> But what happens if I declare HZ as 1500?
> x = x * (HZ / 1000);

This is equivalent (ignoring overflows) to x = x*3/2. I would guess that you
compiler can multiply by , and divide by 2, more efficiently than by 1500
and 1000.

What are the likely values of HZ, anything? If in steps of 500, then:

#define STEP 500

x = x * (HZ/STEP)/(1000/STEP)

might perhaps jog the compiler into generating better code: either x*2/2
(HZ=1000), or x*3/2.

--
Bartc

James Kuyper
Guest
Posts: n/a

 02-23-2011
On 02/23/2011 06:42 AM, Willem wrote:
> pozz wrote:
> ) I have the following code:
> ) ---
> ) #define HZ 1000
> ) unsigned int calc(unsigned int x) {
> ) x = x * HZ / 1000;
> ) }
> ) void main(void) {
> ) unsigned int y = calc(23);
> ) ...
> ) }

....
> By the way: your code won't work as-is, as it doesn't return anything.

Not quite; the behavior is undefined by the C standard, which means that
any behavior is permitted. In particular, a compiler is permitted to
generate code that would make the program work as intended. It's not
entirely implausible that it would do so, either. There's a decent
chance, depending upon the ABI, that the same register would be used for
both 'x' and the return value from calc().

--
James Kuyper

pozz
Guest
Posts: n/a

 02-23-2011
On 23 Feb, 12:42, James Kuyper <(E-Mail Removed)> wrote:
> > I have the following code:
> > ---
> > #define HZ 1000
> > unsigned int calc(unsigned int x) {
> > * *x = x * HZ / 1000;

>
> Just a nit pick: isn't there a missing 'return' statement here?

You are right, I forgot to write the return statement, but it is
present in my program.

pozz
Guest
Posts: n/a

 02-23-2011
On 23 Feb, 12:42, Willem <(E-Mail Removed)> wrote:
> Alternatively:
>
> #define HZ 1000
> unsigned int calc(unsigned int x) {
> #if (HZ != 1000)
> * x = x * HZ / 1000;
> #endif
>
> }

Yes, I can code in this way. But it isn't a general method, because
the
"optimization" should be performed also if HZ is 2000 or 3000.

I thought there was a way to always reduce a trivial calculation
(1000/1000
or 2000/1000 or similar) to a very simple operation (nothing or
multiplication
by 2) so avoiding multiplication *and* division by 1000.

Of course, if the calculus is 1500/1000 the compiler should include
both
operations.