public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Performance problem: unaligned loads/stores on structure  assignments on MIPS
@ 2007-02-25 21:44 Simon Kagstrom
  2007-02-27  6:07 ` Ian Lance Taylor
  0 siblings, 1 reply; 2+ messages in thread
From: Simon Kagstrom @ 2007-02-25 21:44 UTC (permalink / raw)
  To: gcc-help

[-- Attachment #1: Type: text/plain, Size: 2711 bytes --]

Hello!

GCC 4.1 seems to sometimes generate inefficient code when doing
structure assignments directly when compiling for MIPS1. When assigning
to structure members manually, it generates regular lw/sw sequences.
When assigning to the structure, you instead get lwl/lwr and swl/swr
pairs (for no reason, since the data is aligned).

I'm translating the MIPS code to Java bytecode, so the problem is even
worse for me as I then have to read four separate bytes and or
these together to implement a lwl/lwr pair.


I've attached a preprocessed file which exhibits this behavior. The two
functions below show this, the first doing a structure assignment and
the second member assignment.

  void dummy1(NavigateSegment *segments,
             int count,
             RoadMapPosition *src_pos,
             RoadMapPosition *dst_pos) {

      int i;
      int group_id = 0;
      NavigateSegment *segment;
 
      for (i=0; i < count; i++) {
         set_from_pos (&segments[i].from_pos);
         segments[i].shape_initial_pos = segments[i].from_pos;

      }
   }

   void dummy2(NavigateSegment *segments,
               int count,
               RoadMapPosition *src_pos,
               RoadMapPosition *dst_pos) {

      int i;
      int group_id = 0;
      NavigateSegment *segment;

      for (i=0; i < count; i++) {
         set_from_pos (&segments[i].from_pos);
         segments[i].shape_initial_pos.longitude = segments[i].from_pos.longitude;
         segments[i].shape_initial_pos.latitude = segments[i].from_pos.latitude;
      }
   }

And if you disassemble it you see that they look like

00000014 <dummy1>:
  14:   00003021        move    a2,zero
  18:   240804d2        li      t0,1234
  1c:   08000014        j       50 <dummy1+0x3c>
  20:   2407162e        li      a3,5678
  24:   ac88001c        sw      t0,28(a0)
  28:   ac870020        sw      a3,32(a0)
  2c:   8882001c        lwl     v0,28(a0)
  30:   88830020        lwl     v1,32(a0)
  ...

00000064 <dummy2>:
  64:   00001821        move    v1,zero
  68:   240604d2        li      a2,1234
  6c:   08000022        j       88 <dummy2+0x24>
  70:   2407162e        li      a3,5678
  74:   ac870020        sw      a3,32(a0)
  78:   ac86001c        sw      a2,28(a0)
  7c:   ac86002c        sw      a2,44(a0)
  80:   ac870030        sw      a3,48(a0)
  ....

If the loop is removed, both functions generate the same code (with
regular loads/stores). The GCC version is

   mips-linux-gnu-gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)

Should I consider this a bug and report it to the bug tracking system?
I looked for similar problems, but couldn't find any matching bug report.

(Ehud Shabtai discovered this problem)

-- 
// Simon

[-- Attachment #2: main.i --]
[-- Type: application/octet-stream, Size: 31664 bytes --]

# 1 "main.c"
# 1 "/home/ska/projects/private/games/cibyl/trunk/examples/j2me-test/c//"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "main.c"
# 1 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdio.h" 1
# 15 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdio.h"
# 1 "/home/ska/projects/private/games/cibyl/trunk/include/cibyl.h" 1
# 25 "/home/ska/projects/private/games/cibyl/trunk/include/cibyl.h"
typedef int bool_t;


typedef int NOPH_Exception_t;





# 1 "/home/ska/projects/private/games/cibyl/trunk/include/cibyl-syscall_defs.h" 1
# 35 "/home/ska/projects/private/games/cibyl/trunk/include/cibyl.h" 2


register NOPH_Exception_t NOPH_exception asm("$26");
# 16 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdio.h" 2
# 1 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stddef.h" 1
# 152 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stddef.h"
typedef int ptrdiff_t;
# 214 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stddef.h"
typedef unsigned int size_t;
# 326 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stddef.h"
typedef int wchar_t;
# 17 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdio.h" 2
# 1 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdarg.h" 1
# 43 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdarg.h"
typedef __builtin_va_list __gnuc_va_list;
# 105 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdarg.h"
typedef __gnuc_va_list va_list;
# 18 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdio.h" 2


static inline int __puts(const char* string) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__puts" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(string) : "memory" ); return (int) __v0; };


static inline int __putchar(int c) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__putchar" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(c) : "memory" ); return (int) __v0; };
# 35 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdio.h"
typedef int FILE;



extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;


static inline FILE* fopen(const char* path, const char* mode) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "fopen" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(path), "r"(mode) : "memory" ); return (FILE*) __v0; };

static inline int fclose(FILE* fp) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "fclose" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(fp) : "memory" ); return (int) __v0; };


static inline void clearerr(FILE* stream) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "clearerr" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(stream) : "memory" ); return (void) __v0; };

static inline int feof(FILE* stream) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "feof" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(stream) : "memory" ); return (int) __v0; };

static inline int ferror(FILE* stream) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "ferror" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(stream) : "memory" ); return (int) __v0; };





static inline int favail(FILE* stream) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "favail" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(stream) : "memory" ); return (int) __v0; };


static inline int fseek(FILE* stream, long offset, int whence) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".short 0xfefe\n" ".short %3\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "fseek" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(stream), "r"(offset), "r"(whence) : "memory" ); return (int) __v0; };

static inline int fflush(FILE* stream) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "fflush" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(stream) : "memory" ); return (int) __v0; };


static inline int fgetc(FILE* stream) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "fgetc" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(stream) : "memory" ); return (int) __v0; };

static inline char* fgets(char* s, int size, FILE* stream) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".short 0xfefe\n" ".short %3\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "fgets" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(s), "r"(size), "r"(stream) : "memory" ); return (char*) __v0; };

static inline int fputc(int c, FILE* stream) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "fputc" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(c), "r"(stream) : "memory" ); return (int) __v0; };

static inline int fputs(const char* ptr, FILE* stream) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "fputs" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(ptr), "r"(stream) : "memory" ); return (int) __v0; };


static inline size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".short 0xfefe\n" ".short %3\n" ".short 0xfefe\n" ".short %4\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "fread" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(ptr), "r"(size), "r"(nmemb), "r"(stream) : "memory" ); return (size_t) __v0; };

static inline size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".short 0xfefe\n" ".short %3\n" ".short 0xfefe\n" ".short %4\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "fwrite" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(ptr), "r"(size), "r"(nmemb), "r"(stream) : "memory" ); return (size_t) __v0; };

extern int vsnprintf(char* str, unsigned int size, const char* format, va_list ap);


extern int vprintf(const char* format, va_list ap);
extern int snprintf(char *buf, size_t n, const char *fmt, ...);

extern int fprintf(FILE *fp, const char* fmt, ...);
extern int printf(const char* fmt, ...);


static inline void __setup_io(FILE* addr_stdin, FILE* addr_stdout, FILE* addr_stderr) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".short 0xfefe\n" ".short %3\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__setup_io" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(addr_stdin), "r"(addr_stdout), "r"(addr_stderr) : "memory" ); return (void) __v0; };
# 2 "main.c" 2
# 1 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdlib.h" 1
# 16 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdlib.h"
# 1 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stddef.h" 1
# 17 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdlib.h" 2


static inline void exit(int code) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "exit" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(code) : "memory" ); return (void) __v0; };
extern void* malloc(size_t size);
extern void free(void* ptr);
extern int isdigit(int c);
extern int isspace(int c);
extern long int strtol(const char *nptr, char **endptr, int base);
extern float atof(const char *nptr);
extern int atoi(const char *nptr);


static inline int rand(void) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "rand" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : : "memory" ); return (int) __v0; };

static inline void srand(unsigned int seed) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "srand" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(seed) : "memory" ); return (void) __v0; };

# 1 "/home/ska/projects/private/games/cibyl/trunk/include/generated/string.h" 1
# 16 "/home/ska/projects/private/games/cibyl/trunk/include/generated/string.h"
# 1 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stddef.h" 1
# 17 "/home/ska/projects/private/games/cibyl/trunk/include/generated/string.h" 2



static inline char* __strcpy(char* dest, const char* src) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__strcpy" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(dest), "r"(src) : "memory" ); return (char*) __v0; };

static inline char* __strncpy(char* dest, const char* src, size_t n) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".short 0xfefe\n" ".short %3\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__strncpy" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(dest), "r"(src), "r"(n) : "memory" ); return (char*) __v0; };

static inline char* __strcat(char* dest, const char* src) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__strcat" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(dest), "r"(src) : "memory" ); return (char*) __v0; };

static inline char* __strncat(char* dest, const char* src, size_t n) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".short 0xfefe\n" ".short %3\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__strncat" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(dest), "r"(src), "r"(n) : "memory" ); return (char*) __v0; };

static inline int __strcmp(const char* s1, const char* s2) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__strcmp" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(s1), "r"(s2) : "memory" ); return (int) __v0; };

static inline int __strncmp(const char* s1, const char* s2, size_t n) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".short 0xfefe\n" ".short %3\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__strncmp" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(s1), "r"(s2), "r"(n) : "memory" ); return (int) __v0; };

static inline size_t __strlen(const char* s) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__strlen" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(s) : "memory" ); return (size_t) __v0; };

static inline void* __memset(void* s, int c, size_t n) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".short 0xfefe\n" ".short %3\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__memset" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(s), "r"(c), "r"(n) : "memory" ); return (void*) __v0; };

static inline int __memcmp(const void* s1, const void* s2, size_t n) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".short 0xfefe\n" ".short %2\n" ".short 0xfefe\n" ".short %3\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "__memcmp" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(s1), "r"(s2), "r"(n) : "memory" ); return (int) __v0; };




extern char *strcat(char *dest, const char *src);
extern char *strncat(char *dest, const char *src, size_t n);
extern char *strcpy(char *dest, const char *src);
extern char *strncpy(char *dest, const char *src, size_t n);
extern int strcmp(const char* s1, const char* s2);
extern int strncmp(const char *s1, const char *s2, size_t n);
extern int strcasecmp(const char *s1, const char *s2);
extern int strncasecmp(const char *s1, const char *s2, size_t n);
extern size_t strlen(const char *s);
extern void *memset(void *s, int c, size_t n);
extern void *memcpy(void *dest, const void *src, size_t n);
extern int memcmp(const void* s1, const void* s2, size_t n);
extern char *strchr(const char *s, int c);
extern char *strrchr(const char *s, int c);

extern char *strdup(const char *s);
extern char *strstr(const char *haystack, const char *needle);

static inline void *memmove(void *dest, const void *src, size_t n) {
return memcpy(dest, src, n);
}
# 34 "/home/ska/projects/private/games/cibyl/trunk/include/generated/stdlib.h" 2

static inline void *calloc(size_t nmemb, size_t size)
{
void *out = (void*)malloc(nmemb * size);
memset(out, 0, nmemb * size);

return out;
}

static inline void *realloc(void *ptr, size_t size)
{
void *out = (void*)malloc(size);
if (ptr) {
memcpy (out, ptr, size);
free(ptr);
}
return out;
}

static inline int abs(int x)
{
if (x > 0) return x;
else return -x;
}
# 3 "main.c" 2
# 1 "/home/ska/projects/private/games/cibyl/trunk/include/generated/time.h" 1
# 17 "/home/ska/projects/private/games/cibyl/trunk/include/generated/time.h"
typedef int time_t;


static inline time_t time(time_t* t) { register unsigned long __v0 asm("$2"); __asm__ volatile ( ".set  push\n.set  noreorder\n" ".short 0xfefe\n" ".short %1\n" ".section .cibylstrtab, \"aS\"\n" "1: .asciz \"" "time" "\"\n" ".section .text\n" ".long 1b\n" ".set\tpop\n" : "=r" (__v0) : "r"(t) : "memory" ); return (time_t) __v0; };
# 4 "main.c" 2
# 1 "navigate_main.h" 1
# 28 "navigate_main.h"
# 1 "roadmap_canvas.h" 1
# 33 "roadmap_canvas.h"
# 1 "roadmap_gui.h" 1
# 27 "roadmap_gui.h"
# 1 "roadmap_types.h" 1
# 29 "roadmap_types.h"
typedef unsigned short RoadMapZip;
typedef unsigned short RoadMapString;

typedef unsigned char LineRouteFlag;
typedef unsigned char LineRouteMax;
typedef unsigned short LineRouteTime;

typedef struct {
   int longitude;
   int latitude;
} RoadMapPosition;

typedef struct {
   int first;
   int count;
} RoadMapSortedList;

typedef struct {
   int east;
   int north;
   int west;
   int south;
} RoadMapArea;

typedef void (*RoadMapShapeItr) (int shape, RoadMapPosition *position);
# 28 "roadmap_gui.h" 2


typedef struct {

   int x;
   int y;

} RoadMapGuiPoint;

typedef struct {

   int minx;
   int miny;
   int maxx;
   int maxy;

} RoadMapGuiRect;
# 34 "roadmap_canvas.h" 2

enum { IMAGE_NORMAL,
       IMAGE_SELECTED
};

struct roadmap_canvas_pen;
typedef struct roadmap_canvas_pen *RoadMapPen;

struct roadmap_canvas_image;
typedef struct roadmap_canvas_image *RoadMapImage;

typedef void (*RoadMapCanvasMouseHandler) (RoadMapGuiPoint *point);
typedef void (*RoadMapCanvasConfigureHandler) (void);

void roadmap_canvas_register_button_pressed_handler
                    (RoadMapCanvasMouseHandler handler);

void roadmap_canvas_register_button_released_handler
                    (RoadMapCanvasMouseHandler handler);

void roadmap_canvas_register_mouse_move_handler
                    (RoadMapCanvasMouseHandler handler);

void roadmap_canvas_register_configure_handler
                    (RoadMapCanvasConfigureHandler handler);







void roadmap_canvas_get_text_extents
        (const char *text, int size, int *width,
            int *ascent, int *descent, int *can_tilt);






RoadMapPen roadmap_canvas_create_pen (const char *name);





RoadMapPen roadmap_canvas_select_pen (RoadMapPen pen);






void roadmap_canvas_set_foreground (const char *color);
void roadmap_canvas_set_thickness (int thickness);
int roadmap_canvas_get_thickness (RoadMapPen pen);
void roadmap_canvas_set_opacity (int opacity);




void roadmap_canvas_erase (void);
void roadmap_canvas_erase_area (const RoadMapGuiRect *rect);
# 123 "roadmap_canvas.h"
void roadmap_canvas_draw_string (RoadMapGuiPoint *position,
                                  int corner,
                                  const char *text);

void roadmap_canvas_draw_string_angle (const RoadMapGuiPoint *position,
                                       RoadMapGuiPoint *center,
                                       int angle, int size,
                                       const char *text);

void roadmap_canvas_draw_multiple_points (int count, RoadMapGuiPoint *points);

void roadmap_canvas_draw_multiple_lines
         (int count, int *lines, RoadMapGuiPoint *points, int fast_draw);

void roadmap_canvas_draw_multiple_polygons
         (int count, int *polygons, RoadMapGuiPoint *points, int filled,
                int fast_draw);

void roadmap_canvas_draw_multiple_circles
        (int count, RoadMapGuiPoint *centers, int *radius, int filled,
                int fast_draw);


int roadmap_canvas_width (void);
int roadmap_canvas_height (void);




void roadmap_canvas_refresh (void);

void roadmap_canvas_save_screenshot (const char* filename);

int roadmap_canvas_image_width (const RoadMapImage image);
int roadmap_canvas_image_height (const RoadMapImage image);

RoadMapImage roadmap_canvas_load_image (const char *path,
                                        const char* file_name);

void roadmap_canvas_draw_image (RoadMapImage image, const RoadMapGuiPoint *pos,
                                int opacity, int mode);

void roadmap_canvas_copy_image (RoadMapImage dst_image,
                                const RoadMapGuiPoint *pos,
                                const RoadMapGuiRect *rect,
                                RoadMapImage src_image, int mode);

void roadmap_canvas_draw_image_text (RoadMapImage image,
                                     const RoadMapGuiPoint *position,
                                     int size, const char *text);

void roadmap_canvas_free_image (RoadMapImage image);
# 29 "navigate_main.h" 2
# 1 "roadmap_plugin.h" 1
# 29 "roadmap_plugin.h"
# 1 "roadmap_screen.h" 1
# 30 "roadmap_screen.h"
enum { VIEW_MODE_2D = 0,
       VIEW_MODE_3D
};

enum { ORIENTATION_DYNAMIC = 0,
       ORIENTATION_FIXED
};

void roadmap_screen_initialize (void);
void roadmap_screen_shutdown (void);

void roadmap_screen_set_initial_position (void);

void roadmap_screen_zoom_in (void);
void roadmap_screen_zoom_out (void);
void roadmap_screen_zoom_reset (void);

void roadmap_screen_move_up (void);
void roadmap_screen_move_down (void);
void roadmap_screen_move_right (void);
void roadmap_screen_move_left (void);

void roadmap_screen_toggle_view_mode (void);
void roadmap_screen_toggle_orientation_mode (void);
void roadmap_screen_increase_horizon (void);
void roadmap_screen_decrease_horizon (void);

void roadmap_screen_rotate (int delta);

void roadmap_screen_refresh (void);
void roadmap_screen_redraw (void);

void roadmap_screen_hold (void);
void roadmap_screen_freeze (void);
void roadmap_screen_unfreeze (void);

void roadmap_screen_get_center (RoadMapPosition *center);

typedef void (*RoadMapScreenSubscriber) (void);

RoadMapScreenSubscriber roadmap_screen_subscribe_after_refresh
                                    (RoadMapScreenSubscriber handler);

void roadmap_screen_draw_one_line (RoadMapPosition *from,
                                   RoadMapPosition *to,
                                   int fully_visible,
                                   RoadMapPosition *first_shape_pos,
                                   int first_shape,
                                   int last_shape,
                                   RoadMapShapeItr shape_itr,
                                   RoadMapPen pen,
                                   int *total_length,
                                   RoadMapGuiPoint *middle,
                                   int *angle);

void roadmap_screen_draw_line_direction (RoadMapPosition *from,
                                         RoadMapPosition *to,
                                         RoadMapPosition *first_shape_pos,
                                         int first_shape,
                                         int last_shape,
                                         RoadMapShapeItr shape_itr,
                                         int width,
                                         int direction);

int roadmap_screen_is_dragging (void);
# 115 "roadmap_screen.h"
void dbg_time_start(int type);
void dbg_time_end(int type);
# 30 "roadmap_plugin.h" 2
# 42 "roadmap_plugin.h"
typedef struct {
   int plugin_id;
   int line_id;
   int cfcc;
   int fips;
} PluginLine;

typedef struct {
   int plugin_id;
   int street_id;
} PluginStreet;

typedef struct {
   const char *address;
   const char *street;
   const char *street_t2s;
   const char *city;
   PluginStreet plugin_street;
} PluginStreetProperties;




struct RoadMapNeighbour_t;

int roadmap_plugin_same_line (const PluginLine *line1, const PluginLine *line2);

int roadmap_plugin_same_street (const PluginStreet *street1,
                                const PluginStreet *street2);

void roadmap_plugin_get_street (const PluginLine *line, PluginStreet *street);

void roadmap_plugin_line_from (const PluginLine *line, RoadMapPosition *pos);

void roadmap_plugin_line_to (const PluginLine *line, RoadMapPosition *pos);

void roadmap_plugin_get_line_points (const PluginLine *line,
                                     RoadMapPosition *from_pos,
                                     RoadMapPosition *to_pos,
                                     int *first_shape,
                                     int *last_shape,
                                     RoadMapShapeItr *shape_itr);

int roadmap_plugin_get_id (const PluginLine *line);

int roadmap_plugin_get_fips (const PluginLine *line);

int roadmap_plugin_get_line_id (const PluginLine *line);

int roadmap_plugin_get_line_cfcc (const PluginLine *line);

int roadmap_plugin_get_street_id (const PluginStreet *street);

void roadmap_plugin_set_line (PluginLine *line,
                              int plugin_id,
                              int line_id,
                              int cfcc,
                              int fips);

void roadmap_plugin_set_street (PluginStreet *street,
                                int plugin_id,
                                int street_id);

int roadmap_plugin_activate_db (const PluginLine *line);

int roadmap_plugin_get_distance
            (const RoadMapPosition *point,
             const PluginLine *line,
             struct RoadMapNeighbour_t *result);



typedef int (*plugin_override_line_hook) (int line, int cfcc, int fips);

typedef int (*plugin_override_pen_hook) (int line,
                                         int cfcc,
                                         int fips,
                                         int pen_type,
                                         RoadMapPen *override_pen);

typedef void (*plugin_screen_repaint_hook) (int max_pen);
typedef int (*plugin_activate_db_func) (const PluginLine *line);
typedef void (*plugin_line_pos_func)
   (const PluginLine *line, RoadMapPosition *pos);

typedef int (*plugin_get_distance_func)
               (const RoadMapPosition *point,
                const PluginLine *line,
                struct RoadMapNeighbour_t *result);

typedef void (*plugin_get_street_func)
               (const PluginLine *line, PluginStreet *street);

typedef const char *(*plugin_street_full_name_func)
                       (const PluginLine *line);

typedef void (*plugin_street_properties_func)
              (const PluginLine *line, PluginStreetProperties *props);

typedef int (*plugin_find_connected_lines_func)
                  (const RoadMapPosition *crossing,
                   PluginLine *plugin_lines,
                   int max);

typedef void (*plugin_adjust_layer_hook)
               (int layer, int thickness, int pen_count);

typedef int (*plugin_get_closest_func)
       (const RoadMapPosition *position,
        int *categories, int categories_count,
        struct RoadMapNeighbour_t *neighbours, int count,
        int max);

typedef int (*plugin_line_route_direction) (PluginLine *line, int who);

typedef void (*plugin_shutdown) (void);

typedef struct {
   plugin_line_pos_func line_from;
   plugin_line_pos_func line_to;
   plugin_activate_db_func activate_db;
   plugin_get_distance_func get_distance;
   plugin_override_line_hook override_line;
   plugin_override_pen_hook override_pen;
   plugin_screen_repaint_hook screen_repaint;
   plugin_get_street_func get_street;
   plugin_street_full_name_func get_street_full_name;
   plugin_street_properties_func get_street_properties;
   plugin_find_connected_lines_func find_connected_lines;
   plugin_adjust_layer_hook adjust_layer;
   plugin_get_closest_func get_closest;
   plugin_line_route_direction route_direction;
   plugin_shutdown shutdown;

} RoadMapPluginHooks;




int roadmap_plugin_register (RoadMapPluginHooks *hooks);
void roadmap_plugin_unregister (int plugin_id);

int roadmap_plugin_override_line (int line, int cfcc, int fips);

int roadmap_plugin_override_pen (int line,
                                 int cfcc,
                                 int fips,
                                 int pen_type,
                                 RoadMapPen *override_pen);

void roadmap_plugin_screen_repaint (int max_pen);

const char *roadmap_plugin_street_full_name (const PluginLine *line);

void roadmap_plugin_get_street_properties (const PluginLine *line,
                                           PluginStreetProperties *props);

int roadmap_plugin_find_connected_lines (RoadMapPosition *crossing,
                                         PluginLine *plugin_lines,
                                         int max);

void roadmap_plugin_adjust_layer (int layer,
                                  int thickness,
                                  int pen_count);

int roadmap_plugin_get_closest
       (const RoadMapPosition *position,
        int *categories, int categories_count,
        struct RoadMapNeighbour_t *neighbours, int count,
        int max);

int roadmap_plugin_get_direction (PluginLine *line, int who);

int roadmap_plugin_calc_length (const RoadMapPosition *position,
                                const PluginLine *line,
                                int *total_length);

void roadmap_plugin_shutdown (void);
# 30 "navigate_main.h" 2


enum NavigateInstr {
   TURN_LEFT = 0,
   TURN_RIGHT,
   KEEP_LEFT,
   KEEP_RIGHT,
   CONTINUE,
   APPROACHING_DESTINATION,
   LAST_DIRECTION
};

typedef struct {
   PluginLine line;
   int line_direction;
   PluginStreet street;
   RoadMapPosition from_pos;
   RoadMapPosition to_pos;
   RoadMapPosition shape_initial_pos;
   int first_shape;
   int last_shape;
   RoadMapShapeItr shape_itr;
   enum NavigateInstr instruction;
   int group_id;
   int distance;
   int cross_time;

} NavigateSegment;

int navigate_is_enabled (void);
void navigate_main_initialize (void);
int navigate_main_reload_data (void);
void navigate_main_set (int status);
int navigate_main_calc_route (void);

void navigate_main_screen_repaint (int max_pen);

int navigate_main_override_pen (int line,
                                int cfcc,
                                int fips,
                                int pen_type,
                                RoadMapPen *override_pen);

void navigate_main_adjust_layer (int layer, int thickness, int pen_count);
# 5 "main.c" 2

void set_from_pos (RoadMapPosition *pos) {
  pos->longitude = 1234;
  pos->latitude = 5678;
}

void dummy1(NavigateSegment *segments,
           int count,
    RoadMapPosition *src_pos,
    RoadMapPosition *dst_pos) {

   int i;
   int group_id = 0;
   NavigateSegment *segment;

   for (i=0; i < count; i++) {

      set_from_pos (&segments[i].from_pos);
      segments[i].shape_initial_pos = segments[i].from_pos;

   }
}

void dummy2(NavigateSegment *segments,
            int count,
     RoadMapPosition *src_pos,
     RoadMapPosition *dst_pos) {

   int i;
   int group_id = 0;
   NavigateSegment *segment;

   for (i=0; i < count; i++) {

      set_from_pos (&segments[i].from_pos);
      segments[i].shape_initial_pos.longitude = segments[i].from_pos.longitude;
      segments[i].shape_initial_pos.latitude = segments[i].from_pos.latitude;

   }
}


int main(int argc, char *argv[])
{
  NavigateSegment segments[10];
  int i;


  for (i=0; i<10; i++) {
      segments[i].shape_initial_pos.longitude = 999;
      segments[i].shape_initial_pos.latitude = 999;
  }

  dummy1(segments, 10, ((void *)0), ((void *)0));

  printf ("We should get pairs of: 1234, 5678\n");
  for (i=0; i<10; i++) {
      printf("%d,%d ", segments[i].shape_initial_pos.longitude,
       segments[i].shape_initial_pos.latitude);
  }
  printf("\n");

  dummy2(segments, 10, ((void *)0), ((void *)0));

  printf ("This one seems to do it right: 1234, 5678\n");
  for (i=0; i<10; i++) {
      printf("%d,%d ", segments[i].shape_initial_pos.longitude,
       segments[i].shape_initial_pos.latitude);
  }
  printf("\n");
  return 0;
}

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Performance problem: unaligned loads/stores on structure  assignments on MIPS
  2007-02-25 21:44 Performance problem: unaligned loads/stores on structure assignments on MIPS Simon Kagstrom
@ 2007-02-27  6:07 ` Ian Lance Taylor
  0 siblings, 0 replies; 2+ messages in thread
From: Ian Lance Taylor @ 2007-02-27  6:07 UTC (permalink / raw)
  To: Simon Kagstrom; +Cc: gcc-help

Simon Kagstrom <simon.kagstrom@bth.se> writes:

> GCC 4.1 seems to sometimes generate inefficient code when doing
> structure assignments directly when compiling for MIPS1. When assigning
> to structure members manually, it generates regular lw/sw sequences.
> When assigning to the structure, you instead get lwl/lwr and swl/swr
> pairs (for no reason, since the data is aligned).

...

> Should I consider this a bug and report it to the bug tracking system?
> I looked for similar problems, but couldn't find any matching bug report.

This seems like a bug to me.

Ian

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2007-02-27  6:06 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-25 21:44 Performance problem: unaligned loads/stores on structure assignments on MIPS Simon Kagstrom
2007-02-27  6:07 ` Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).