C99 restrict Type qualifier

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When using C99, does avr-gcc optimize code when it sees the restrict type qualifier?

This topic has a solution.
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Personally I haven't seen any real-world code using the 'restrict' type qualifier, yet. But GCC, in general, implements a lot of C99, so I'm sure it knows how to deal with it. If you're looking for some particular type of optimization, then the best thing to do is to experiment to see if the compiler is doing what you expect it to do.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Other operating system's libraries at least started using "restrict"
some time ago. I guess we should start in avr-libc as well, at least
for non-asm code. Well, perhaps some of the asm code could even be
replaced by C code then...

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried some examples of code that should be optimized when restrict is used but the assemble code doesn't change.

void foo ( uint8_t * a1, uint8_t * a2)
{
    uint8_t i;
    
    for ( i = 0; i < 10; i++ )
        a1[i] += a2[i];
    
    a1 = a2;    //-OK, without restrict

}

void bar ( uint8_t *restrict a1, uint8_t *restrict a2)
{
    uint8_t i;
    
    for ( i = 0; i < 10; i++ )
        a1[i] += a2[i];
 
    a1 = a2;    //- UnDefined
  
}
  22               	/* prologue: frame size=0 */
  23               	/* prologue end (size=0) */
  24               	.LVL0:
  25 0000 DC01      		movw r26,r24
  26 0002 20E0      		ldi r18,lo8(0)
  27 0004 30E0      		ldi r19,hi8(0)
  28               	.L2:
  29               	.LM2:
  30 0006 FB01      		movw r30,r22
  31 0008 E20F      		add r30,r18
  32 000a F31F      		adc r31,r19
  33 000c 8C91      		ld r24,X
  34               	.LVL1:
  35 000e 9081      		ld r25,Z
  36 0010 890F      		add r24,r25
  37 0012 8D93      		st X+,r24
  38 0014 2F5F      		subi r18,lo8(-(1))
  39 0016 3F4F      		sbci r19,hi8(-(1))
  40               	.LM3:
  41 0018 2A30      		cpi r18,10
  42 001a 3105      		cpc r19,__zero_reg__
  43 001c 01F4      		brne .L2
  44               	/* epilogue: frame size=0 */
  45 001e 0895      		ret
  46               	/* epilogue end (size=1) */
  47               	/* function foo size 16 (15)*/
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dl8dtl wrote:
Other operating system's libraries at least started using "restrict"
some time ago. I guess we should start in avr-libc as well, at least
for non-asm code. Well, perhaps some of the asm code could even be
replaced by C code then...

Then we need to make sure that our policy is to build to the C99 standard.

I'd also rather not change asm code to C, because with the asm code, it doesn't change according to the optimization setting and compiler version. If anything I would rather go from C to asm, but I know that it would be difficult for some functions like printf, scanf, qsort, etc.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was looking at the opposite problem: the deliberate use of type-punned pointers (which have an implicit restrict). The discussion indicated that the gcc people were trying to start implementing optimisations.

I found that the latest version of gcc gave me a code size 2 bytes smaller when I used (with -0s) -fno-strict-aliaising, which for an optimisation is a change in the wrong direction, but indicates that something is changing. As a consequence, I am now using -fno-strict-aliasing, in the expectation that a new version of gcc is coming which will have optimisations for (implicit or explicit) 'restrict'.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, this is a really old thread. But the optimizer and support of GCC has increased.

 

So I tried the following test program:

#include <avr/io.h>

#define VECTOR_SIZE 4U

void vectorCopy1(uint8_t *a, uint8_t *b, uint8_t *c)
{
	uint8_t i;
	for (i = 0U; i < VECTOR_SIZE; ++i)
	{
		b[i] = a[i]-1U;	
		c[i] = a[i]+1U;	
	}	
}

void vectorCopy2(uint8_t *restrict a, uint8_t *restrict b, uint8_t *restrict c)
{
	uint8_t i;
	for (i = 0U; i < VECTOR_SIZE; ++i)
	{
		b[i] = a[i]-1U;
		c[i] = a[i]+1U;
	}
}

int main(void)
{
	uint8_t x[VECTOR_SIZE] = {1U,2U,3U,4U};
	uint8_t y[VECTOR_SIZE];
	uint8_t z[VECTOR_SIZE];
	
	vectorCopy1(x, y, z);
	vectorCopy2(x, y, z);
}

Looking in the assembler code, I found function vectorCopy2 smaller than vectorCopy1.

In the beginning was the Word, and the Word was with God, and the Word was God.

Last Edited: Thu. Mar 5, 2015 - 12:04 AM