lab-riscv-asm

Лабораторная работа №1

Вариант задания

Вариант 4

Вариант задания Передача параметров
Найти сумму положительных элементов массива. (N = 4, M = 2) По значению

Результат работы

  • lab1.S - программа на RISC-V Assembler
  • main.c - программа на C
  • lab1_O0.dump - дамп-файл c уровнем оптимизации O0
  • lab1_O1.dump - дамп-файл c уровнем оптимизации O1
  • lab1_O2.dump - дамп-файл С c уровнем оптимизации O2
  • lab1_O3.dump - дамп-файл С c уровнем оптимизации O3

Выполнение работы

Время копаться в дампах (^ _ ^.).
Будем разбирать только код main и sum. На всех уровнях оптимизации, callee-регистры сохраняются на стеке, на O0 он честно делает это в каждой функции, в то время, как на O1 и выше он не сохраняет регистры, которые не собирается изменять.

начало main_O0: 
   10200:	fc010113          	addi	sp,sp,-64
   10204:	02112e23          	sw	ra,60(sp)
   10208:	02812c23          	sw	s0,56(sp)

В целом O2 и O3 не отличаются вообще, O2 и O1 отличаются тем, что на O2 оптимизированы некоторые переходы.

sum_O2: 
   101c0:	00050813          	mv	a6,a0 - a6 = n 
   101c4:	04b05063          	blez    a1,10204 <sum+0x44>
   101c8:	00000893          	li	a7,0
   101cc:	00000513          	li	a0,0
   101d0:	00060713          	mv	a4,a2 #a4 - указатель на матрицу
   101d4:	00000793          	li	a5,0
   101d8:	01005e63          	blez    a6,101f4 <sum+0x34>
   101dc:	00072683          	lw	a3,0(a4) #a3 = current;
   101e0:	00178793          	addi	a5,a5,1 # a5++;
   101e4:	00470713          	addi	a4,a4,4 # a4 = next_value(a4);
   101e8:	00d05463          	blez	a3,101f0 <sum+0x30> # if(current > 0) a0 += a3; 
   101ec:	00d50533          	add	a0,a0,a3
   101f0:	fef816e3          	bne	a6,a5,101dc <sum+0x1c> if(a6 != a5) goto 101f0;
   101f4:	00188893          	addi	a7,a7,1 # a7++;
   101f8:	01060613          	addi	a2,a2,16 #a2 = next_line(a2);
   101fc:	fd159ae3          	bne	a1,a7,101d0 <sum+0x10>
   10200:	00008067          	ret
   10204:	00000513          	li	a0,0
   10208:	00008067          	ret

Вообще на O1 и выше компилятор уже достаточно хорошо выбирает регистры для своих целей (Например, он сразу выбрал a0 для result, в то время, как на O0 он активно использовал для этого a5, а в конце перекинул его в a0 перед ret). Также в сравнение с O0 он хорошо оптимизирует переходы, да и в принципе при сравнение O0 и O1 видно, что компилятор уже совершает очень много различных оптимизаций.

Вывод

GCC-компилятор - молодец, но нет предела совершенству)