In modern processors it is possible to load a register from memory and then post-modify the indexing pointer by a desired value. For example, in our embedded processor, this will be done by:
ldr r0, [r1], +12
which means – load the value pointed to by r1 into r0 and then increment r1 by 12:
r0 = [r1]
r1 = r1 + 12
In the C language, using pointer arithmetics, one can assign a value using a pointer and then advance the pointer by 1:
char i, *p, a[3]={10, 20, 30};
p = &(a[0]);
i = *p++;
// now i==10 and p==&(a[1]).
I am looking for a way to dereference a pointer while post-modifying it by an offset other than 1. Is this possible in C, so it maps nicely to the similar asm instruction?
Note that:
i = *p+=2;
increases the value in a[0] w/o modifying the pointer, and:
i = *(p+=2);
pre-modifies the pointer, so in this case i==30.
Yes this is possible.
You shouldn’t be doing weird pointer math to make it happen.
Not only is it about optimization settings, your GCC back-end needs to tell GCC that it has such a feature (i.e. when GCC itself is being compiled). Based on this knowledge, GCC automatically combines the relevant sequence into a single instruction.
i.e. if your back-end is written right, even something like:
should become a single post-modify instruction.
How to correctly set this up when writing a back-end? (ask your friendly neighbourhood GCC back-end developer to do it for you):
If your GCC back-end is called
foo:gcc/config/foo/.foo.hwhich contains a lot of#definesdescribing machine features.HAVE_POST_INCREMENTto evaluate to true, and if it supports post-modify, then define the macroHAVE_POST_MODIFY_DISPto true. (post-increment =>ptr++, post-modify =>ptr += CONST). Maybe there are a few other things to be handled as well.Assuming that your processor’s back-end has got this right, lets move to what happens when you compile your code containing said post-modify sequence:
There is a specific GCC optimization pass that goes through instruction pairs that fall into this category and combines them. The source for that pass is here, and has a rather clear description of what GCC will do and how to get it to do it.
But this, in the end, is not in your control as a GCC user. It is in the control of the developer who wrote your GCC back-end. All you should be doing, like the most upvoted comment says, is: