restrict example - reasonable?

P

pemo

If you were to compile/run the code below, and get the result '30', I'd be
very interested to know what compiler you're using - and its optimisation
settings [esp. if it supports the 'restrict' keyword]

#include <stdio.h>

int test(int * a, int * b)
{
*a = 5;
*b = 6;

return (*a) * (*b);
}

int main(void)
{
int x = 0;

int a = test(&x, &x);

printf("%d\n", a);
}

The 'hope' with the code was to find a case where the gcc optimiser doesn't
fetch *a and *b, but assumes their values to be 5 and 6. The gcc I'm using
produces 36 irrespective of what ever n's value is in -On switches.

I wanted to be able to compile some code with various optimisations - and
show that the code 'breaks' when a and b point to the same variable in main,
and then to introduce 'restrict' to show it get fixed. Would the above be a
reasonable candidate for showing such a thing?
 
M

mdler

Hello Pemo

You are calling function test with 2 times the same memory area
so a == b (always)

by setting *a you also giving *b a value and visa versa

so the line *a = 5; makes also *b = 5
line *b=6; makes also *a = 6;

the line return (*a) * (*b); returns 6 * 6

There will be no compiler option to change it.
This is the way pointes are working!!!

what you are doing looks linke this

int main(void)
{
int a, *b;
b = &a;
*b = 3; // is not importand
a=6;
printf("val = %d\n", a * (*b));
return 0;
}


pemo schreef:
 
P

pemo

mdler said:
If you were to compile/run the code below, and get the result '30',
I'd be very interested to know what compiler you're using - and its
optimisation settings [esp. if it supports the 'restrict' keyword]

#include <stdio.h>

int test(int * a, int * b)
{
*a = 5;
*b = 6;

return (*a) * (*b);
}

int main(void)
{
int x = 0;

int a = test(&x, &x);

printf("%d\n", a);
}

The 'hope' with the code was to find a case where the gcc optimiser
doesn't fetch *a and *b, but assumes their values to be 5 and 6.
The gcc I'm using produces 36 irrespective of what ever n's value is
in -On switches.

I wanted to be able to compile some code with various optimisations
- and show that the code 'breaks' when a and b point to the same
variable in main, and then to introduce 'restrict' to show it get
fixed. Would the above be a reasonable candidate for showing such a
thing?
You are calling function test with 2 times the same memory area
so a == b (always)

by setting *a you also giving *b a value and visa versa

so the line *a = 5; makes also *b = 5
line *b=6; makes also *a = 6;

the line return (*a) * (*b); returns 6 * 6

There will be no compiler option to change it.
This is the way pointes are working!!!

what you are doing looks linke this

int main(void)
{
int a, *b;
b = &a;
*b = 3; // is not importand
a=6;
printf("val = %d\n", a * (*b));
return 0;
}


Yes, I know what the code does (does it not sound so?) BUT an optimising
compiler might assume, it 'knows' what *a and *b values are in test(), and
that it can use 5 and 6 in the multiplication - rather than deref the
pointers.

Also,if you want to avoid being shouted at, please don't top post here.
 
A

Antonio Contreras

pemo said:
If you were to compile/run the code below, and get the result '30', I'd be
very interested to know what compiler you're using - and its optimisation
settings [esp. if it supports the 'restrict' keyword]

#include <stdio.h>

int test(int * a, int * b)
{
*a = 5;
*b = 6;

return (*a) * (*b);
}

int main(void)
{
int x = 0;

int a = test(&x, &x);

printf("%d\n", a);
}

The 'hope' with the code was to find a case where the gcc optimiser doesn't
fetch *a and *b, but assumes their values to be 5 and 6. The gcc I'm using
produces 36 irrespective of what ever n's value is in -On switches.

I wanted to be able to compile some code with various optimisations - and
show that the code 'breaks' when a and b point to the same variable in main,
and then to introduce 'restrict' to show it get fixed. Would the above be a
reasonable candidate for showing such a thing?

I think you should work the other way arround. I mean, declare both
parameters as restrict and show that this allows certain optimizations
to be done and that the code breaks when both parameters point to the
same variable.

Then compile the source without the restrict qualifier and show that
the compiler cannot longer make some assumptions and that that prevents
certain optimizations.

HTH
 
T

Thomas Maier-Komor

Antonio said:
pemo said:
If you were to compile/run the code below, and get the result '30', I'd be
very interested to know what compiler you're using - and its optimisation
settings [esp. if it supports the 'restrict' keyword]

#include <stdio.h>

int test(int * a, int * b)
{
*a = 5;
*b = 6;

return (*a) * (*b);
}

int main(void)
{
int x = 0;

int a = test(&x, &x);

printf("%d\n", a);
}

The 'hope' with the code was to find a case where the gcc optimiser doesn't
fetch *a and *b, but assumes their values to be 5 and 6. The gcc I'm using
produces 36 irrespective of what ever n's value is in -On switches.

I wanted to be able to compile some code with various optimisations - and
show that the code 'breaks' when a and b point to the same variable in main,
and then to introduce 'restrict' to show it get fixed. Would the above be a
reasonable candidate for showing such a thing?

I think you should work the other way arround. I mean, declare both
parameters as restrict and show that this allows certain optimizations
to be done and that the code breaks when both parameters point to the
same variable.

Then compile the source without the restrict qualifier and show that
the compiler cannot longer make some assumptions and that that prevents
certain optimizations.

HTH

maybe one should point out that "restrict" was introduced with C99. I.e.
the example of the OP must work correctly on all conforming compilers.
If you (pemo) want to prove that restrict gives a benefit (it can only
be performance), then you have to do as Antonio Contreras said.
 
P

pemo

Antonio said:
pemo said:
If you were to compile/run the code below, and get the result '30',
I'd be very interested to know what compiler you're using - and its
optimisation settings [esp. if it supports the 'restrict' keyword]

#include <stdio.h>

int test(int * a, int * b)
{
*a = 5;
*b = 6;

return (*a) * (*b);
}

int main(void)
{
int x = 0;

int a = test(&x, &x);

printf("%d\n", a);
}

The 'hope' with the code was to find a case where the gcc optimiser
doesn't fetch *a and *b, but assumes their values to be 5 and 6.
The gcc I'm using produces 36 irrespective of what ever n's value is
in -On switches.

I wanted to be able to compile some code with various optimisations
- and show that the code 'breaks' when a and b point to the same
variable in main, and then to introduce 'restrict' to show it get
fixed. Would the above be a reasonable candidate for showing such a
thing?

I think you should work the other way arround. I mean, declare both
parameters as restrict and show that this allows certain optimizations
to be done and that the code breaks when both parameters point to the
same variable.

Then compile the source without the restrict qualifier and show that
the compiler cannot longer make some assumptions and that that
prevents certain optimizations.

HTH

Thanks for the suggestion.

I've just tried it that way around, and the result with gcc 3.4.2 is always
the same, i.e., going from using no O flag, and then through using O1 .. O3
with

int test(int * restrict a, int * restrict b)

vs.

int test(int * a, int * b)

the output's always the same - 36.

btw, I'm not even certain that the compiler does anything with restrict,
i.e., I'm not sure whether it's something that the programmer should look
for, and respect if found, or whetehr it's something they'd expect the
compiler to check for them: that latter could be rather hard for it to work
out me thinks?
 
C

CBFalconer

Antonio said:
.... snip ...

I think you should work the other way arround. I mean, declare both
parameters as restrict and show that this allows certain optimizations
to be done and that the code breaks when both parameters point to the
same variable.

Then compile the source without the restrict qualifier and show that
the compiler cannot longer make some assumptions and that that prevents
certain optimizations.

Unless I am confused (fairly likely here) using restrict promises
that the routine will not be called with both pointers pointing to
the same memory. The intent is to allow more aggressive
optimization.
 
V

Vladimir S. Oka

pemo said:
If you were to compile/run the code below, and get the result '30', I'd be
very interested to know what compiler you're using - and its optimisation
settings [esp. if it supports the 'restrict' keyword]

#include <stdio.h>

int test(int * a, int * b)
{
*a = 5;
*b = 6;

return (*a) * (*b);
}

int main(void)
{
int x = 0;

int a = test(&x, &x);

printf("%d\n", a);
}

The 'hope' with the code was to find a case where the gcc optimiser doesn't
fetch *a and *b, but assumes their values to be 5 and 6. The gcc I'm using
produces 36 irrespective of what ever n's value is in -On switches.

I wanted to be able to compile some code with various optimisations - and
show that the code 'breaks' when a and b point to the same variable in main,
and then to introduce 'restrict' to show it get fixed. Would the above be a
reasonable candidate for showing such a thing?

It does seem like a reasonable way to test this.

However (although I am not, and never have been compiler writer), I
think that when deciding on optimisations the code above should /never/
be optimised, precisely because of the possible problem you're trying
to highlight.
 
A

Antonio Contreras

Vladimir said:
pemo said:
If you were to compile/run the code below, and get the result '30', I'd be
very interested to know what compiler you're using - and its optimisation
settings [esp. if it supports the 'restrict' keyword]

#include <stdio.h>

int test(int * a, int * b)
{
*a = 5;
*b = 6;

return (*a) * (*b);
}

int main(void)
{
int x = 0;

int a = test(&x, &x);

printf("%d\n", a);
}

The 'hope' with the code was to find a case where the gcc optimiser doesn't
fetch *a and *b, but assumes their values to be 5 and 6. The gcc I'm using
produces 36 irrespective of what ever n's value is in -On switches.

I wanted to be able to compile some code with various optimisations - and
show that the code 'breaks' when a and b point to the same variable in main,
and then to introduce 'restrict' to show it get fixed. Would the above be a
reasonable candidate for showing such a thing?

It does seem like a reasonable way to test this.

However (although I am not, and never have been compiler writer), I
think that when deciding on optimisations the code above should /never/
be optimised, precisely because of the possible problem you're trying
to highlight.

But that's exactly the point behind the restrict keyword. If one or
both of the parameters are marked as restricted pointers then the code
could be safely optimized to:

int test(int * restrict a, int * restrict b)
{
*a = 5;
*b = 6;
return 30;
}

because by making the argument restricted pointers your telling the
compiler that the possible problem of the two pointer pointing to
overlapping positions of memory is guaranteed not to happen. I may be
wrong, but I think that if the parameters are marked as restrict and
they point to the same variable, the behaviour is undefined.
 
V

Vladimir S. Oka

Antonio said:
Vladimir said:
pemo said:
If you were to compile/run the code below, and get the result '30',
I'd be very interested to know what compiler you're using - and its
optimisation settings [esp. if it supports the 'restrict' keyword]

#include <stdio.h>

int test(int * a, int * b)
{
*a = 5;
*b = 6;

return (*a) * (*b);
}

int main(void)
{
int x = 0;

int a = test(&x, &x);

printf("%d\n", a);
}

The 'hope' with the code was to find a case where the gcc optimiser
doesn't
fetch *a and *b, but assumes their values to be 5 and 6. The gcc
I'm using produces 36 irrespective of what ever n's value is in -On
switches.

I wanted to be able to compile some code with various optimisations
- and show that the code 'breaks' when a and b point to the same
variable in main,
and then to introduce 'restrict' to show it get fixed. Would the
above be a reasonable candidate for showing such a thing?

It does seem like a reasonable way to test this.

However (although I am not, and never have been compiler writer), I
think that when deciding on optimisations the code above should
/never/ be optimised, precisely because of the possible problem
you're trying to highlight.

But that's exactly the point behind the restrict keyword. If one or
both of the parameters are marked as restricted pointers then the code
could be safely optimized to:

int test(int * restrict a, int * restrict b)
{
*a = 5;
*b = 6;
return 30;
}

because by making the argument restricted pointers your telling the
compiler that the possible problem of the two pointer pointing to
overlapping positions of memory is guaranteed not to happen. I may be
wrong, but I think that if the parameters are marked as restrict and
they point to the same variable, the behaviour is undefined.

Yes, of course.

I was just trying to say that if I were a compiler writer, I'd never
optimise such a construct in the first place, as it's easy to see how
it can be broken. Better safe then sorry...

Therefore, I wouldn't expect any /good/ compiler to make that mistake.

--
BR, Vladimir

Bugs, pl. n.:
Small living things that small living boys throw on small
living girls.
 
C

Christian Bau

"pemo said:
If you were to compile/run the code below, and get the result '30', I'd be
very interested to know what compiler you're using - and its optimisation
settings [esp. if it supports the 'restrict' keyword]

#include <stdio.h>

int test(int * a, int * b)
{
*a = 5;
*b = 6;

return (*a) * (*b);
}

int main(void)
{
int x = 0;

int a = test(&x, &x);

printf("%d\n", a);
}

The 'hope' with the code was to find a case where the gcc optimiser doesn't
fetch *a and *b, but assumes their values to be 5 and 6. The gcc I'm using
produces 36 irrespective of what ever n's value is in -On switches.

I wanted to be able to compile some code with various optimisations - and
show that the code 'breaks' when a and b point to the same variable in main,
and then to introduce 'restrict' to show it get fixed. Would the above be a
reasonable candidate for showing such a thing?

A reasonable candidate would be a broken C compiler.

Your example program is completely correct C, and a compiler is _not_
allowed to assume that *a equals 5 when the return statement is executed
(it is allowed to assume that *b equals 6). No matter how much a
compiler tries to optimise, if it cannot prove that a and b point to
different objects, it cannot do that optimisation. The printf call
_must_ print a value of 36.

However, if you change the function "test" to

int test (int *restrict a, int *restrict b)

then the compiler _is_ allowed to assume that a and b are different
pointers (in this case: As you store both to *a and *b, they must be
different pointers). The assumption is obviously false, but that is not
the fault of the compiler, it is the fault of the programmer who invoked
undefined behavior.

As a result, the compiler could then produce exactly the same code as
for:

*b = 6; *a = 5; return 30;

The point of "restrict" is to give the compiler more freedom to do
optimisations, by allowing it to assume that reads and writes based on
one pointer variable don't interfere with any other reads or writes. As
a result, using "restrict" will give you faster code if used correctly,
and undefined behavior if used incorrectly.
 
P

pemo

Christian said:
pemo said:
If you were to compile/run the code below, and get the result '30',
I'd be very interested to know what compiler you're using - and its
optimisation settings [esp. if it supports the 'restrict' keyword]

#include <stdio.h>

int test(int * a, int * b)
{
*a = 5;
*b = 6;

return (*a) * (*b);
}

int main(void)
{
int x = 0;

int a = test(&x, &x);

printf("%d\n", a);
}

The 'hope' with the code was to find a case where the gcc optimiser
doesn't fetch *a and *b, but assumes their values to be 5 and 6.
The gcc I'm using produces 36 irrespective of what ever n's value is
in -On switches.

I wanted to be able to compile some code with various optimisations
- and show that the code 'breaks' when a and b point to the same
variable in main, and then to introduce 'restrict' to show it get
fixed. Would the above be a reasonable candidate for showing such a
thing?

A reasonable candidate would be a broken C compiler.

Your example program is completely correct C, and a compiler is _not_
allowed to assume that *a equals 5 when the return statement is
executed (it is allowed to assume that *b equals 6). No matter how
much a compiler tries to optimise, if it cannot prove that a and b
point to different objects, it cannot do that optimisation. The
printf call _must_ print a value of 36.

However, if you change the function "test" to

int test (int *restrict a, int *restrict b)

then the compiler _is_ allowed to assume that a and b are different
pointers (in this case: As you store both to *a and *b, they must be
different pointers). The assumption is obviously false, but that is
not the fault of the compiler, it is the fault of the programmer who
invoked undefined behavior.

As a result, the compiler could then produce exactly the same code as
for:

*b = 6; *a = 5; return 30;

The point of "restrict" is to give the compiler more freedom to do
optimisations, by allowing it to assume that reads and writes based on
one pointer variable don't interfere with any other reads or writes.
As a result, using "restrict" will give you faster code if used
correctly, and undefined behavior if used incorrectly.

Yup, I totally agree with you here.

I put a very similar case to Guy Steele and Sam Harbison. One replied 'It
sounds good to me' whilst the other added, 'I think I'm confirming your
interpretation' - the latter [Sam] also added a very nice PS :

'A hint to the compiler is a command to the programmer'
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top