LINUX.ORG.RU

Оптимизатор GCC 4.4


0

0

Какой-то он странный стал, дурит.

Есть простой кусок кода, знаю так немного криво делать, но ничего плохого в этом нет, правда ведь? )))

#include <stddef.h>

#pragma pack(1)

typedef struct _footype {
  char          bar1[8];
  void*         bar2;
} footype;


footype *foo() {
  footype *dummy;

  dummy=(footype*)findbar();
  *((unsigned long*)&dummy)-=offsetof(footype,bar2);
  return dummy;
}
Компилирую gcc 4.4.0

$ gcc -c -S -O1 gcc.c получаю такой листинг

	.file	"gcc.c"
	.text
.globl foo
	.type	foo, @function
foo:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	call	findbar
	subl	$8, %eax   <== получаем указатель на footype
	leave
	ret
	.size	foo, .-foo
	.ident	"GCC: (GNU) 4.4.0 20090526 (prerelease)"
	.section	.note.GNU-stack,"",@progbits

с оптимизацией O2

$ gcc -c -S -O2 gcc.c

	.file	"gcc.c"
	.text
	.p2align 4,,15
.globl foo
	.type	foo, @function
foo:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	call	findbar
                          <===== где sub $8, б&я?
	leave
	ret
	.size	foo, .-foo
	.ident	"GCC: (GNU) 4.4.0 20090526 (prerelease)"
	.section	.note.GNU-stack,"",@progbits

Тот же код на 4.3.2 дает хоть и кривее листинг, но он корректен.

-O1

	.file	"gcc.c"
	.text
.globl foo
	.type	foo, @function
foo:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	call	findbar
	movl	%eax, -4(%ebp)
	subl	$8, -4(%ebp)
	movl	-4(%ebp), %eax
	leave
	ret
	.size	foo, .-foo
	.ident	"GCC: (GNU) 4.3.2"
	.section	.note.GNU-stack,"",@progbits

-O2

	.file	"gcc.c"
	.text
.globl foo
	.type	foo, @function
foo:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	call	findbar
	movl	%eax, -4(%ebp)
	subl	$8, -4(%ebp)
	leave
	ret
	.size	foo, .-foo
	.ident	"GCC: (GNU) 4.3.2"
	.section	.note.GNU-stack,"",@progbits

т.е. прямо по стеку фигачит и возвращает значение.

Естественно в этом месте я код поправил, но хотелось бы знать почему гцц приподнес мне такую жопу? И что от него еще ждать. Одну ошибку я так и не могу найти ((( при использовании 4.3.2 все ОК.

там многое поменяли, более того GCC 4.4.x некоторые пакеты собирает весьма некорректно, можете отписать в их багзиллу

ps: листинги я не понимаю.

Sylvia ★★★★★
()

> *((unsigned long*)&dummy)-=offsetof(footype,bar2);

Преобразование указателя в не указатель - это очень плохо. Кто гарантирует, что sizeof(unsigned long) == sizeof(void *)? Надо примерно так:

dummy = ((char *) dummy) - offsetof(footype, bar2);

А в багзиллу всё-таки отпишись.

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

И да, по какой причине тебе нужно использовать такой изврат? Думаю что в реальных программах такое в любом случае применять не следует.

Deleted
()

-fno-strict-aliasing не то?

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

Ну так уж случилось, что это код портирован )) Система строго 32 бит, так что sizeof(unsigned long) == sizeof(void *) точно.

Я объяснил, что понимаю, что так делать не очень корректно, но все же никакого драматизма в этом коде нет. Должно работать! ))

> dummy = ((char *) dummy) - offsetof(footype, bar2);

именно на это и исправил.

> -fno-strict-aliasing не то?

Спасибо, помогло. Case closed.)))

piroflip
() автор топика
Ответ на: комментарий от piroflip

А по-моему не должно.  Так как изменялась переменная типа long,
то ни один указатель не изменил своего значения.

См. аналогичный пример (имхо проще для понимания) ниже.

/*
 * Works as intended on little-endian only!
 *
 * $ gcc file.c
 * $ ./a.out
 * 1. v=10
 * 2. v=11
 * 3. v=11
 *
 * $ gcc -O2 file.c
 * $ ./a.out
 * 1. v=10
 * 2. v=10
 * 3. v=11
 */

#include <stdio.h>

void f(int *i, long *l)
{
  printf("1. v=%ld\n", *l);
  *i = 11;
  printf("2. v=%ld\n", *l);
}

int main()
{
  long a = 10;
  f((int *) &a, &a);
  printf("3. v=%ld\n", a);
}

bvvv
()
Ответ на: комментарий от piroflip

Ну и соответственно на 4.4 с no-strict-aliasing тоже

piroflip
() автор топика
Ответ на: комментарий от bvvv

> См. аналогичный пример (имхо проще для понимания) ниже.

Давал бы уж ссылку на первоисточник:
http://www.opennet.ru/base/dev/porting_code.txt.html. Статья очень очень полезная, рекомендуется топикстартеру =).

Deleted
()
Ответ на: комментарий от bvvv

/* * Works as intended on little-endian only! * * $ gcc file.c * $ ./a.out * 1. v=10 * 2. v=11 * 3. v=11 * * $ gcc -O2 file.c * $ ./a.out * 1. v=10 * 2. v=10 * 3. v=11 */

У меня на GCC 4.4.0 точно так же.

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