12Fermer14
SallyLe 10/10/2003 à 11:11
Bon, alors j'ai fait quelques tests et je conclus à ma troisième possibilité : il y a un bug. Kevin ? grin
En fait -Os déconne complètement, la preuve, ça optimise mieux avec -O :
j'ai compilé ce code :
extern int flag, machin, truc;
void bouclecomplexe () {
  int i;
  asm ("|for de base");
  for (i = 0; i < 42; i++) {
    if (flag) machin |= truc;
    else machin &= truc;
  }

  asm ("|for à l'envers");
  for (i = 42; i--; ) {
    if (flag) machin |= truc;
    else machin &= truc;
  }

  asm ("|do-while avec --i");
  i = 42; do {
    if (flag) machin |= truc;
    else machin &= truc;
  } while (--i);

  asm ("|do-while avec i--");
  i = 41; do {
    if (flag) machin |= truc;
    else machin &= truc;
  } while (i--);
}


Voici ce que donne -Os : bouclecomplexe:      link.w %a6,#0      movm.l #0x1c00,-(%sp) #APP      |for de base #NO_APP      clr.w %d3      move.w flag,%d5      move.w machin,%d2      move.w truc,%d4      jbra .L2      .even .L8:      move.w %d2,%d1      addq.w #1,%d3      or.w %d4,%d2      tst.w %d5      jbne .L2      move.w %d1,%d2      and.w %d4,%d2 .L2:      cmp.w #41,%d3      jble .L8      move.w %d2,machin #APP      |for à l'envers #NO_APP      moveq.l #42,%d3      move.w flag,%d4      move.w truc,%a0      jbra .L32      .even .L15:      move.w %d2,%d1      move.w %a0,%d0      or.w %d0,%d2      tst.w %d4      jbne .L32      move.w %d1,%d2      and.w %d0,%d2 .L32:      dbra %d3,.L15      move.w %d2,machin #APP      |do-while avec --i #NO_APP      moveq.l #42,%d3      move.w flag,%a1      move.w truc,%d4 .L16:      move.w %a1,%d5      move.w %d2,%d1      move.w %d3,%a0      subq.w #1,%a0      or.w %d4,%d2      tst.w %d5      jbne .L18      move.w %d1,%d2      and.w %d4,%d2 .L18:      move.w %a0,%d3      jbne .L16      move.w %d2,machin #APP      |do-while avec i-- #NO_APP      moveq.l #41,%d3      move.w %d2,%d1      move.w truc,%d2 .L22:      move.w %d3,%a0      subq.w #1,%a0      tst.w %d5      jbeq .L25      or.w %d2,%d1      jbra .L24      .even .L25:      and.w %d2,%d1 .L24:      move.w %a0,%d3      cmp.w #-1,%d3      jbne .L22      move.w %d1,machin      movm.l (%sp)+,#0x38      unlk %a6      rts
Non seulement il pessimise les boucles comme un gros taré, mais en plus il fait des manipulations de registres totalement ésotériques...

Par contre, avec -O on a ce à quoi on s'attend : les solutions de BiHi et Pollux donnent toutes deux exactement le même résultat (initialisation à 41 et dbra à la fin) (dbra = dbf ??), mais celle de PpHd donne un subq suivi de bne.

Avec -O2, c'est encore mieux car il retourne la première boucle (tout de même !) mais il ne la finit pas par un dbra : il met subq suivi de jbpl (c'est quoi jbpl ?) À part ça il ne change pas grand-chose, sauf qu'il modifie les if pour que dans un cas ça branche deux fois et dans l'autre pas du tout, au lieu de une fois dans chaque (je ne comprends pas l'intérêt, mais au moins ça ne change pas la taille...)

Alors j'ai cherché s'il y avait un flag spécifique activé par -Os et pas par -O2 qui faisait tout merder, mais je n'en ai pas trouvé dans la doc (d'ailleurs la doc est fausse par endroits, elle dit que -fomit-frame-pointer est activé par -Os, or ce n'est pas le cas...)