etc:common_activities:gcc_vectorization:autovect_ppc

This is an old revision of the document!


Автоматическая векторизация в GCC для архитектуры PowerPC

исходный код программы на языке C:

#define N 16
 
void fbar (float *);
void ibar (int *);
void sbar (short *);
 
/* multiple loops */
 
foo (int n)
{
  float a[N+1];
  float b[N];
  float c[N];
  float d[N];
  int i;
 
  /* Strided access. Vectorizable on platforms that support load of strided
     accesses (extract of even/odd vector elements).  */
  for (i = 0; i < N/2; i++){
    a[i] = b[2*i+1] * c[2*i+1] - b[2*i] * c[2*i];
    d[i] = b[2*i] * c[2*i+1] + b[2*i+1] * c[2*i];
  }
  fbar (a);
 
}

Строка компиляции: ppc-linux-gnu-gcc -O3 -maltivec -ftree-vectorizer-verbose=1 -ftree-vectorize -S vect-1.c

Каждая команда PowerPC имеет длину 32 бита. Первые 6 бит определяют команду, а остальные имеют различное значение, зависящее от команды. Тот факт, что команды имеют фиксированную длину, позволяет процессору выполнять их более эффективно. Поскольку команды PowerPC имеют длину только 32 бита, внутри команд, загружающих постоянные величины, в наличии имеется только 16 бит. Поэтому, так как адрес может быть до 64 бит в длину, мы должны загружать его небольшими порциями. Значок @ в ассемблере указывает ассемблеру использовать специальную форму.

Результат:

        .file   "vect-1.c"
        .section        ".text"
        .align 2
        .globl foo
        .type   foo, @function
foo:
        # Переместить значение из Link Register(похоже что это адрес текущей инструкции)  в регистр 0
     mflr 0
 
        # Store Word with Update (сохранить значение регистра 1(биты 32...63), в адрес памяти(EA) = <значение регистра 1>+<число -224>
        # EA <- (1) - 224
        # MEM(EA, 4) <- (1)32:63
        # (1) <- EA
     stwu 1,-224(1)
 
        # Load Immediate Shifted(непосредственная загрузка)
        # Она загружает величину (биты 16-31 адреса LC1)
        # сдвигает число на 16 бит налево и затем сохраняет результат в регистре 11
        # Биты 16-31 регистра 11 содержат биты 16-31 адреса.
     lis 11,.LC1@ha
 
     lis 9,.LC0@ha
 
        # Load Address
        # la RT,SI(RS) (equivalent to: addi RT,RA,SI)
        # if RA = 0 then RT <- EXTS(SI)
        # else           RT <- (RA) + EXTS(SI)
        # The sum (RA|0) + SI is placed into register RT.
        # Поместить в 11 регистр сумму 11 регистра и битов 0:15 LC1
        # Хы: в 11 регистре окажутся 0:31 биты из ячейки по адресу LC1
     la 11,.LC1@l(11)
 
        # в 10 регистре сумма значение 1 регистра + 16 (число)
     addi 10,1,16
 
        # Store Word
        # stw RS,D(RA)
        # if RA = 0 then b <- 0
        # else           b <- (RA)
        # EA <- b + EXTS(D)
        # MEM(EA, 4) <- (RS)32:63
        # Let the effective address (EA) be the sum (RA|0)+ D. (RS)32:63 are stored into the word in storage addressed by EA.
        # биты 32:63 регистра 0 будут помещены по адресу значение регистра 1 + 228 (в биты 0-31?)
        # сначала мы отняли 224 потом прибавили 228, в итоге в регичтре 0 лежит начальное для функции значение регситра 1 + 4
     stw 0,228(1)
 
        # прибавить к значению регистра 10 число 16 и  положить результат в 8
        # до этого в регистре 10 был регистр 1 увеличенный на 16  
     addi 8,10,16
 
        # Load Vector Indexed
        # lvx vD, rA, rB 
        # Let the effective address EA be the sum of the contents of register rA, or the value '0' if rA is equal '0', and the contents of register rB
        # Load the quadword in memory addressed by the EA into vD
        # помещает в 11 регистр данные из 11 регистра (:
     lvx 11,0,11
 
        # в 11 регистр помещается сумма значения 1 регистра и 16  
     addi 11,1,16
 
        # полностью копирует 11 регистр в 13
     lvx 13,0,11
 
        # в 11 регистр сумму значения 1 регистра и 80
     addi 11,1,80
 
        # скопировали значение 11 регистра в 10 регистр 
     lvx 10,0,11
 
     addi 11,1,96
 
     lvx 1,0,11
 
     addi 11,1,112
 
     lvx 8,0,11
 
        # Поместить в 9 регистр сумму 9 регистра и битов 0:15 LC0
        # Хы: в 9 регистре окажутся 0:31 биты из ячейки по адресу LC0
     la 9,.LC0@l(9)
 
     addi 11,1,128
 
     lvx 7,0,9
 
     lvx 6,0,8
 
     addi 9,8,32
 
     lvx 0,0,11
 
     addi 8,8,16
 
     lvx 4,0,9
 
     addi 9,1,144
 
     lvx 12,0,8
 
        # mr Rx, Ry на самом деле or Rx,Ry,Ry
        # or RA, RS, RB
        # RA <- (RS) | (RB)  
     mr 3,9
 
        # Vector Permute
        # vperm vD, vA, vB, vC
        # temp[0:255] <- (vA) || (vB) // || --- конкатенация
        # do i=0 to 127 by 8
        #   b <- (vC)[i+3:i+7] || 0b000
        #   (vD)[i:i+7] <- temp[b:b+7]
        # end
        # Let the source vector be the concatenation of the contents of register vA followed by the contents of register vB.
        # For each integer i in the range 0-15, the contents of the byte element in the source vector specisied in bits [3-7] 
        # of byte element i in vC are placed into byte element i of register vD.
        # судя из картинки в документации работает так:
        # vA и vB -- исходные вектора по 16 8-битных элементов. после их конкатенции все элементы пронумерованы от 0x00 до 0x1F
        # в vC[i] написано число от 0x00 до 0x1F и означает какой из 32 элементов vA||vB положить в vD[i]
     vperm 3,8,0,11
 
     vperm 5,10,1,11
     vperm 9,13,6,11
     vperm 8,8,0,7
     vperm 10,10,1,7
     vperm 13,13,6,7
 
     vspltisw 0,-1
        vslw 0,0,0
        vmaddfp 13,13,10,0
        vmaddfp 9,9,5,0
        vsubfp 13,13,9
        stvx 13,0,9
        addi 9,9,16
        vperm 11,12,4,11
        vperm 12,12,4,7
        vmaddfp 11,11,3,0
        vmaddfp 12,12,8,0
        vsubfp 12,12,11
        stvx 12,0,9
        vor 1,0,0
        bl fbar
        lwz 0,228(1)
        addi 1,1,224
        mtlr 0
        blr
        .size   foo, .-foo
        .section        .rodata.cst16,"aM",@progbits,16
        .align 4
.LC0:
        .byte   4
        .byte   5
        .byte   6
        .byte   7
        .byte   12
        .byte   13
        .byte   14
        .byte   15
        .byte   20
        .byte   21
        .byte   22
        .byte   23
        .byte   28
        .byte   29
        .byte   30
        .byte   31
.LC1:
        .byte   0
        .byte   1
        .byte   2
        .byte   3
        .byte   8
        .byte   9
        .byte   10
        .byte   11
        .byte   16
        .byte   17
        .byte   18
        .byte   19
        .byte   24
        .byte   25
        .byte   26
        .byte   27
        .ident  "GCC: (GNU) 4.3.0 20080202 (experimental)"
        .section        .note.GNU-stack,"",@progbits
etc/common_activities/gcc_vectorization/autovect_ppc.1201978956.txt.gz · Last modified: 2008/02/02 22:02 by zps