Efficient C for ARM

Avoid Array Indexing

Accessing an array element uses two variables
Base and Index.
Usually there’s a limit value to test against too.
e.g. length of array.
If you can substitute a single pointer variable instead of Base and Index, you can:
Replace per-access computations with a periodically incrementing pointer.
Usually save a register (3 variables -> 2 variables).

If we rewrite the nameToNumber example routine from earlier as follows:

int nameToNumber3(const char *name)
{
  static const struct map
  {
    const char name[7]; /* NB. PIC */
    int        value;
  }
  map[] = ...

  const struct map *entry, *end;

  end = map + NELEMS(map);
  for (entry = &map[0]; entry < end; entry++)
    if (strcmp(name, entry->name) == 0)
      return entry->value;

  return -1; /* default case */
}

ARMCC -O2 -Otime outputs the following:

nameToNumber3 STMFD    sp!,{r4-r6,lr}
              LDR      r4,=mapaddr     ; address of "map"
              MOV      r6,r0           ; stash copy of name
              ADD      r5,r4,#0x30     ; R5 = end
              CMP      r4,r5           ; out of data?
              BCS      exit
loop          MOV      r1,r4           ; R1 = entry->name
              MOV      r0,r6           ; R0 = name
              BL       strcmp
              CMP      r0,#0           ; match?
              LDREQ    r0,[r4,#8]      ; fetch entry->value
              LDMEQFD  sp!,{r4-r6,pc}  ; return it
              ADD      r4,r4,#0xc      ; otherwise no match
              CMP      r4,r5           ; loop until out..
              BCC      loop            ; ..of data
exit          MVN      r0,#0
              LDMFD    sp!,{r4-r6,pc}  ; return -1

Navigate