LINUX.ORG.RU

[gcc][avr] Оптимизация делает хуже

 ,


0

1

Наверно ещё рано идти в багтрекер, возникает вопрос зачем это сделано и нельзя ли отключить.

u16_t u_mul_u16_u88_rough(u16_t x, u16_t m)
{
	union { u16_t s; u8_t b[2]; }	um;

	u16_t		r = 0;
	u8_t		i = 1;

	um.s = m;

	do {
		if (um.b[0] & i) {

			r += x;
		}

		r >>= 1;
		i <<= 1;
	}
	while (i != 0);

	i = 1;

	do {
		if (um.b[1] & i) {

			r += x;
		}

		x <<= 1;
		i <<= 1;
	}
	while (i != 0);

	return r;
}

$ avr-gcc -c util.c -Wall -pipe -std=c99 -Os -fconserve-stack -fno-strict-aliasing -mmcu=atmega16 -S

.global	u_mul_u16_u88_rough
	.type	u_mul_u16_u88_rough, @function
u_mul_u16_u88_rough:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
	ldi r20,lo8(8)
	ldi r21,hi8(8)
	ldi r30,lo8(1)
	ldi r18,lo8(0)
	ldi r19,hi8(0)
.L29:
	mov r31,r30
	and r31,r22
	breq .L28
	add r18,r24
	adc r19,r25
.L28:
	lsr r19
	ror r18
	lsl r30
	subi r20,lo8(-(-1))
	sbci r21,hi8(-(-1))
	brne .L29
	ldi r20,lo8(8)
	ldi r21,hi8(8)
	ldi r22,lo8(1)
.L32:
	mov r30,r22
	and r30,r23
	breq .L30
	add r18,r24
	adc r19,r25
.L30:
	lsl r22
	subi r20,lo8(-(-1))
	sbci r21,hi8(-(-1))
	breq .L31
	lsl r24
	rol r25
	rjmp .L32
.L31:
	movw r24,r18
/* epilogue start */
	ret

Добавляется новый счетчик цикла в регистрах r20/r21 который, только не ясно зачем. На x86 тоже происходит что-то похожее. Но зачем? инструкция сдвига или сложения уже ставит флаги и следующей инструкцией уже может быть условный переход.

Если передать i как параметр функции то первый цикл становиться таким.

	ldi r18,lo8(0)
	ldi r19,hi8(0)
.L29:
	mov r21,r20
	and r21,r22
	breq .L28
	add r18,r24
	adc r19,r25
.L28:
	lsr r19
	ror r18
	lsl r20
	brne .L29

Вот так и надо, было.

★★

Это фокус следующей фазы оптимизации:

Canonical induction variable creation. This pass creates a simple
counter for number of iterations of the loop and replaces the exit
condition of the loop using it, in case when a complicated
analysis is necessary to determine the number of iterations.
Later optimizations then may determine the number easily. The
pass is implemented in `tree-ssa-loop-ivcanon.c'.

Можно попробовать отменить: -fno-tree-loop-ivcanon

На x86 работает.

io ★★
()
Ответ на: комментарий от io

Да работает, наверно этим и успокоюсь.

amaora ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.