Language question - optimization

G

Guest

Given this code

void test(int a, int b, char * c) {

long d;

d = a + b;
memcpy(c, &d, sizeof(d));
}

Apart from having its address taken d is unused. Is a compiler at liberty
to optimize away the assignment to d?

Should taking the address of d do anything more than ensure storage is
allocated for it?

I have searched around and can't seem to find anything which defines what a
compiler is required to do with the above example.

TIA.
 
P

Peter Nilsson

nospam said:
Given this code

void test(int a, int b, char * c) {
   long d;
   d = a + b;
   memcpy(c, &d, sizeof(d));
}

Apart from having its address taken d is unused.

You could write the code (with the same issues and
potential for undefined behaviour) as...

void test(int a, int b, char * c) {
* (long *) c = a + b;
}

But what are you gaining or saving?
Is a compiler at liberty to optimize away the
assignment to d?

The compiler must implement the semantics of the abstract
machine. How it does that is it's own look out.
Should  taking the address of d do anything more than
ensure storage is allocated for it?

The only thing the address operator ensures is that a
diagnostic is required if d were declared with register
storage class.

<snip>
 
B

Ben Bacarisse

nospam said:
Given this code

void test(int a, int b, char * c) {

long d;

d = a + b;
memcpy(c, &d, sizeof(d));
}

Apart from having its address taken d is unused. Is a compiler at liberty
to optimize away the assignment to d?

Yes, provided it puts the correct bytes into c[0], c[1], etc.
Should taking the address of d do anything more than ensure storage is
allocated for it?

I don't think it need do even that. In fact, in a call like this:

test(4, 5, s);

gcc will optimise away the call to the 'test' function, and there will
be no sign of 'd' or the memcpy call.

The compiler can optimise almost anything away provided the effect of
the code is unchanged[1]. If accesses are important, the volatile
qualifier can be used.

[1] This is not very precise and there are corner cases that can be
argued about.

<snip>
 
D

DDD

nospam said:
Given this code

void test(int a, int b, char * c) {

long d;

d = a + b;
memcpy(c, &d, sizeof(d));
}

Apart from having its address taken d is unused. Is a compiler at liberty
to optimize away the assignment to d?

Should taking the address of d do anything more than ensure storage is
allocated for it?

I have searched around and can't seem to find anything which defines what a
compiler is required to do with the above example.

TIA.

But what do you want it to do?
 
B

Barry Schwarz

You could write the code (with the same issues and
potential for undefined behaviour) as...

void test(int a, int b, char * c) {
* (long *) c = a + b;
}

If c points to an area at least sizeof(long) bytes, the original code
did not invoke undefined behavior. With your code, if the value in c
is not properly aligned for a long, it does.
 
N

Nick

nospam said:
Given this code

void test(int a, int b, char * c) {

long d;

d = a + b;
memcpy(c, &d, sizeof(d));
}

Apart from having its address taken d is unused. Is a compiler at liberty
to optimize away the assignment to d?

Not to the extent that it would break the program. As long as there is
sizeof(long) space at c, it has to work.
Should taking the address of d do anything more than ensure storage is
allocated for it?

There shouldn't be any need.
I have searched around and can't seem to find anything which defines what a
compiler is required to do with the above example.

Generally, if the code is well defined, the compiler is not allowed to
break it through over-enthusiastic optimisation.
 
N

Nick Keighley

Given this code

void test(int a, int b, char * c) {

   long d;

   d = a + b;
   memcpy(c, &d, sizeof(d));

}

Apart from having its address taken d is unused. Is a compiler at liberty
to optimize away the assignment to d?

Should  taking the address of d do anything more than ensure storage is
allocated for it?

I have searched around and can't seem to find anything which defines what a
compiler is required to do with the above example.

why do you care?
 
M

Michael Foukarakis

nospam said:
Given this code
void test(int a, int b, char * c) {
   long d;
   d = a + b;
   memcpy(c, &d, sizeof(d));
}
Apart from having its address taken d is unused. Is a compiler at liberty
to optimize away the assignment to d?

Yes, provided it puts the correct bytes into c[0], c[1], etc.

Isn't it required that each variable, including multiple instances of
the same variable in recursive calls, have distinct locations? It's
the same reason for the various -fmerge-all-constants GCC flamewars.
I don't think it need do even that.  In fact, in a call like this:

  test(4, 5, s);

gcc will optimise away the call to the 'test' function,

This happens (potentially) with all function calls which depend on
constants. It's not specific to the OP's concern.
 
R

robertwessel2

Yes, provided it puts the correct bytes into c[0], c[1], etc.

Isn't it required that each variable, including multiple instances of
the same variable in recursive calls, have distinct locations? It's
the same reason for the various -fmerge-all-constants GCC flamewars.


Somewhat simplified, it's required to *appear*, within the constraints
of visibility as defined in the standard, as if that's the case.
Whatever the compiler does under the hood to accomplish that, is OK.
Variables can, and commonly are, (physically) deleted by various
optimization.
 
B

Ben Bacarisse

Michael Foukarakis said:
nospam said:
Given this code
void test(int a, int b, char * c) {
   long d;
   d = a + b;
   memcpy(c, &d, sizeof(d));
}
Apart from having its address taken d is unused. Is a compiler at liberty
to optimize away the assignment to d?

Yes, provided it puts the correct bytes into c[0], c[1], etc.

Isn't it required that each variable, including multiple instances of
the same variable in recursive calls, have distinct locations?

I would not call them "the same variable". To me a variable (not
defined by the language standard) is a named object -- an object being a
region of storage. Even if the implementation arranges for one x to use
the same location as a subsequent x, the two are distinct in the
abstract machine the describes how C programs behave. This is because
the compiler must have either proved that the program can't tell if the
two things called x share an address or the previous x must have been
destroyed before the new one came into being.

Anyway, terminology aside, there is no requirement that d exist at all
since the program does nothing with it that can't be done some other way
if the implementation chooses.
It's
the same reason for the various -fmerge-all-constants GCC flamewars.

Sorry, that passed me by.
This happens (potentially) with all function calls which depend on
constants. It's not specific to the OP's concern.

No, but it illustrates the point. The OP asked if 'd' must exist
because its address is taken and I wanted to show that nothing that the
OP wrote ends up directly represented in the compiled code. 'd' is gone
but so is the 'test' function and the 'memcpy' call. All that's left is
a zeroing operation and a move of a literal 9.
 
G

Guest

Nick said:
Not to the extent that it would break the program. As long as there is
sizeof(long) space at c, it has to work.

Thanks to you and the others for the replies.

My use of memcpy the example was good because indicated that the contents
of d was used for something, bad because compilers (like GCC) can have more
understanding and internal implementations of memcpy compared to some other
function from a library or other complication unit.

I have a GCC implementation which makes no assignment to d and copies
garbage from the stack to c. I was trying to determine if it is broken and
what specifically says it is broken in this case.

I think I had trouble finding something specific because there isn't really
anything wrong with the code and it doesn't compile it correctly so it is
just pain broken.

It looks like the compiler is only broken for memcpy and probably other
functions with internal compiler implementations.
 
D

David Resnick

My use of memcpy the example was good because indicated that the contents
of d was used for something, bad because compilers (like GCC) can have more
understanding and internal implementations of memcpy compared to some other
function from a library or other complication unit.

I have a GCC implementation which makes no assignment to d and copies
garbage from the stack to c. I was trying to determine if it is broken and
what specifically says it is broken in this case.

I think I had trouble finding something specific because there isn't really
anything wrong with the code and it doesn't compile it correctly so it is
just pain broken.

It looks like the compiler is only broken for memcpy and probably other
functions with internal compiler implementations.

Just curious, can you pleases post the minimal complete compilable
program that demonstrates the issue (with includes and main)?

-David
 
M

Malcolm McLean

It looks like the compiler is only broken for memcpy and probably other
functions with internal compiler implementations.- Hide quoted text -
The compiler isn't broken if the code produces the correct output.

If for some reason you need d to be a physical variable in memory,
there is the "volatile" keyword. It's for exactly this situation.
 

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,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top