2013-06-29 3 views
3

J'essaie d'optimiser ce code de manière correcte. Ce que je veux dire par correct est ... J'imagine qu'il existe une approche générale pour effectuer ces optimisations de telle sorte que si quelqu'un d'autre regardait le code, il serait capable de supprimer les optimisations.Optimisation d'une boucle dans l'assemblage SPARC

échantillon C de code pour la lisibilité ...

int a = 1; // mapped to %l0 
int b = 5; // mapped to %l1 
int c = 0; // mapped to %l2 
int d;  // mapped to %l3 

while(a < b) { 
    c += a * b; 
    ++a; 
} 

d = c * b; 

SPARC version montage ...

mov %g0, %l2 

    cmp %l0, %l1 
    bge END_LOOP 
    nop 

LOOP: 
    mov %l0, %o0 
    call .mul 
    mov %l1, %o1  ! Fill delay slot with second argument 
    add %l2, %o0, %l2 
    inc %l0 

    cmp %l0, %l1 
    bl  LOOP 
    nop 

END_LOOP: 
    mov %l2, %o0 
    call .mul   ! Fill delay sot with second argument 
    mov %l1, %o1 

    mov %o0, %l3 

Je peux optimiser la première partie (pas sûr si correctement), mais je suis Je ne sais pas comment optimiser la deuxième partie.

mov %g0, %l2 

    cmp %l0, %l1 
    bge,a END_LOOP  ! Annul branch to execute if branch is taken 
    mov %l2, %o0  ! Instruction at target 

LOOP: 
    mov %l0, %o0 
    call .mul 
    mov %l1, %o1  ! Fill delay slot with second argument 
    add %l2, %o0, %l2 
    inc %l0 

    cmp %l0, %l1 
    bl  LOOP 
    nop 

    mov %l2, %o0  ! Move the instruction to above the target 

END_LOOP: 
    call .mul   ! Fill delay sot with second argument 
    mov %l1, %o1 

    mov %o0, %l3 

Toute aide sur la façon d'effectuer ces optimisations serait très appréciée.

+0

Si vous ciblez SPARC v8 ou une version ultérieure, vous pouvez utiliser l'instruction 'SMUL' au lieu de passer un appel à la routine de la bibliothèque système' .mul'. – Michael

+0

J'aurais probablement dû ajouter cela aussi. C'est une ancienne machine SPARC 32 bits. – logbaseinfinity

Répondre

3

En général, votre approche est correcte. En supposant que vous n'avez pas de dépendance de données ou de transfert d'instruction de contrôle immédiatement après la cible, vous pouvez généralement suivre la convention suivante.

Vous avez fait cela, probablement sans se rendre compte:

Aller à la cible de la branche, copiez l'instruction dans la fente de retard et annuler la branche. Comme vous l'avez indiqué, vous annulez la branche pour empêcher l'exécution de l'instruction si la branche n'est pas prise. Ensuite, déplacez l'instruction sur la cible au-dessus de l'étiquette.

Dans votre code, en suivant les étapes ci-dessus, vous devez faire ceci:

J'ai enlevé vos commentaires afin que vous puissiez voir explicitement ce que je changé.

mov %g0, %l2 

    cmp %l0, %l1 
    bge,a END_LOOP 
    mov %l2, %o0 

    mov %l0, %o0  ! 3. Move the instruction formerly after the loop 
         ! above the label 
LOOP: 
    [ mov %l0, %o0 ] ! Instruction was here 

    call .mul 
    mov %l1, %o1 
    add %l2, %o0, %l2 
    inc %l0 

    cmp %l0, %l1 
    bl,a LOOP   ! 1. Go to the target and copy that instruction into 
         ! they delay slot. 
         ! 2. Annul the branch 
    mov %l0, %o0  ! Instruction formerly after LOOP: 

    mov %l2, %o0 

END_LOOP: 
    call .mul 
    mov %l1, %o1 

    mov %o0, %l3 

Si vous examinez attentivement le code, vous verrez que la logique tient toujours et il y a une façon systématique pour dénouer les optimisations. Peu importe si vous entrez ou non dans la boucle, votre code exécutera correctement le code suivant la boucle.

Ceci est l'approche générale pour optimiser le code et est similaire à ce que le compilateur fera. La clé est toujours de s'assurer qu'une dépendance de données n'existe pas.