Просмотр кода после оптимизации компилятором

Скажите пожалуйста , как просмотреть оптимизированый код после прохождения компилятором , перед основной компиляцией…
Спасибо

подпишусь

С чего ты решил, что такой код есть?

1 лайк

Много раз встречал , как некоторые мастера описывали проблемы кода связанные с тем , что компилятор оптимизирует некоторый код на свое усмотрение . например если стандартная переменная обьявлена не как volatile , но при этом используется в коде с условием , но не изменяется в нем , то компилятор может решить ее исключить (раз она все равно не принимает значение нужное в условии) При этом они писали ,
… запустите компилятор и просмотрите листинг кода сформированный компилятором после оптимизации , как видите компилятор при первом прохождении исключает эту переменную т.к думает…

к сожалению они упускают то, что не все знают как его посмотреть …

вот либо перед компиляцией, либо после компиляции

Код после компиляции не имеет ничего общего с исходным текстом. Это программа в машинных кодах. Вы уверены, что что-нибудь разберете там?
Начните с ответа на вопрос, знаете ли вы ассемблер.

1 лайк

В том то и дело . они иммеют ввиду не код после компиляции в кодах , а именно код оптимизированый …

сhar str[125];
for(size_t i = 0; i < strlen(str); i++)
{
    ...
}

код в скетче

сhar str[125];
size_t length = strlen(str);
for(size_t i = 0; i < lenght; i++)
{
    ...
}

код после оптимизации перед компиляцией

Покажите хоть одну ссылку на такое обсуждение, где бы обсуждался именно ОПТИМИЗИРОВАННЫЙ КОМПИЛЯТОРОМ код.
Сколько видел таких дискуссий - всегда берут код ПОСЛЕ КОМПИЛЯЦИИ и дизассембоируют его.

Бред какой-то написал. Где тут оптимизация? Это фундаментально другой код.

1 лайк

https://habr.com/ru/post/673428/

ну например … правда здесь он не говорит давайте посмотрим… постараюсь и те найти но как то не думал , что это проблема

правда возможно я не правильно понял и они иммели ввиду действительно дизассемблированный код , но явно это не указывалось… поэтому и возник вопрос

а зря не думали.
Вы обознались. Никакого кода после оптимизации никто не обсуждает, потому что компилятор не создает никакого промежуточного кода “после оптимизации”, он сразу компилирует его в машинный код.
То, что вы хотите посмотреть - просто не существует .

Разницу между volatile и нет в принципе нельзя увидеть на высокуровневом языке. Он не оперирует регистрами процессора. И тот факт, что в статье они не упомянуты, говорит о том, что статья дилетантская.

2 лайка

Понял. спасибо вопрос снят

Прочел.
Абсолютно бестолковая статья. Какой-то новичок долго не мог понять, зачем нужно volatile. Потом ему показалось, что понял, и он решил осчастливить мир своим открытием.

Дело в том, что оптимизация включает много аспектов.

  • часть из них может быть выполнена как до, так и после компиляции (аппаратно независимая оптимизация),
  • часть - только после (аппаратно зависимая оптимизация),
  • часть - вообще неподвластна компилятору (ее должен выполнять человек).

Т.е. теоретически мог бы существовать вариант:

  1. Аппаратно независимая оптимизация,
  2. Компиляция.
  3. Аппаратно зависимая оптимизация.

Сразу отмечу, что даже в этом случае после этапа 1 мы получим неполную оптимизацию.
Но главное даже не в этом.
Мне кажется вполне очевидным, что разработчики оптимизирующего компилятора позаботятся и о том, чтобы сам компилятор работал оптимально. Т.е. по возможности быстрее. (т.е. проведут ту самую “человеческую” оптимизацию).
И тут сразу появляются два обстоятельства:

  1. Компьютеру “легче” (а, следовательно, - быстрее) работать с бинарными данными, чем с текстовыми. Следовательно, даже аппаратно независимую оптимизацию оптимальнее делать после компиляции, а не до.
  2. Каждый проход компиляции сопровождается чтением исходных данных с диска и записью на диск результатов работы. А дисковые операции - довольно медленная штука. Зачастую именно они и занимают бОльшую часть времени. Следовательно нужно стремиться к минимизации количества проходов.

Отсюда приходим единственно возможному варианту:

  1. Компиляция.
  2. Оптимизация.

Таким образом в результате простейших рассуждений приходим к выводу: варианта “после оптимизации, но до компиляции” существовать не может ввиду того, что этапы компиляции и оптимизации производятся в обратном порядке.

2 лайка

а я тут побаловался на linux, т е если ТС дружит с командной строкой GCC и может откомпилировать Arduino код, то почему бы ему не вытащить код после препроцессора и ассемблерный код - пусть наслаждается/разбирается.

Спойлер
# 1 "ftp2cl.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "ftp2cl.cpp"


# 1 "/usr/include/string.h" 1 3 4
# 26 "/usr/include/string.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 1 3 4
# 33 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 461 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 452 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 453 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/long-double.h" 1 3 4
# 454 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 462 "/usr/include/features.h" 2 3 4
# 485 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4
# 486 "/usr/include/features.h" 2 3 4
# 34 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 2 3 4
# 27 "/usr/include/string.h" 2 3 4


# 28 "/usr/include/string.h" 3 4
extern "C" {




# 1 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" 1 3 4
# 209 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 34 "/usr/include/string.h" 2 3 4
# 43 "/usr/include/string.h" 3 4
extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
       size_t __n) throw () __attribute__ ((__nonnull__ (1, 2)));


extern void *memmove (void *__dest, const void *__src, size_t __n)
     throw () __attribute__ ((__nonnull__ (1, 2)));





extern void *memccpy (void *__restrict __dest, const void *__restrict __src,
        int __c, size_t __n)
     throw () __attribute__ ((__nonnull__ (1, 2)));




extern void *memset (void *__s, int __c, size_t __n) throw () __attribute__ ((__nonnull__ (1)));


extern int memcmp (const void *__s1, const void *__s2, size_t __n)
     throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));



extern "C++"
{
extern void *memchr (void *__s, int __c, size_t __n)
      throw () __asm ("memchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern const void *memchr (const void *__s, int __c, size_t __n)
      throw () __asm ("memchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
# 89 "/usr/include/string.h" 3 4
}
# 99 "/usr/include/string.h" 3 4
extern "C++" void *rawmemchr (void *__s, int __c)
     throw () __asm ("rawmemchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern "C++" const void *rawmemchr (const void *__s, int __c)
     throw () __asm ("rawmemchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));







extern "C++" void *memrchr (void *__s, int __c, size_t __n)
      throw () __asm ("memrchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern "C++" const void *memrchr (const void *__s, int __c, size_t __n)
      throw () __asm ("memrchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
# 122 "/usr/include/string.h" 3 4
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
     throw () __attribute__ ((__nonnull__ (1, 2)));

extern char *strncpy (char *__restrict __dest,
        const char *__restrict __src, size_t __n)
     throw () __attribute__ ((__nonnull__ (1, 2)));


extern char *strcat (char *__restrict __dest, const char *__restrict __src)
     throw () __attribute__ ((__nonnull__ (1, 2)));

extern char *strncat (char *__restrict __dest, const char *__restrict __src,
        size_t __n) throw () __attribute__ ((__nonnull__ (1, 2)));


extern int strcmp (const char *__s1, const char *__s2)
     throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));

extern int strncmp (const char *__s1, const char *__s2, size_t __n)
     throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));


extern int strcoll (const char *__s1, const char *__s2)
     throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));

extern size_t strxfrm (char *__restrict __dest,
         const char *__restrict __src, size_t __n)
     throw () __attribute__ ((__nonnull__ (2)));



# 1 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" 1 3 4
# 22 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" 1 3 4
# 28 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" 3 4
struct __locale_struct
{

  struct __locale_data *__locales[13];


  const unsigned short int *__ctype_b;
  const int *__ctype_tolower;
  const int *__ctype_toupper;


  const char *__names[13];
};

typedef struct __locale_struct *__locale_t;
# 23 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" 2 3 4

typedef __locale_t locale_t;
# 154 "/usr/include/string.h" 2 3 4


extern int strcoll_l (const char *__s1, const char *__s2, locale_t __l)
     throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2, 3)));


extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n,
    locale_t __l) throw () __attribute__ ((__nonnull__ (2, 4)));





extern char *strdup (const char *__s)
     throw () __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1)));






extern char *strndup (const char *__string, size_t __n)
     throw () __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1)));
# 204 "/usr/include/string.h" 3 4
extern "C++"
{
extern char *strchr (char *__s, int __c)
     throw () __asm ("strchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern const char *strchr (const char *__s, int __c)
     throw () __asm ("strchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
# 224 "/usr/include/string.h" 3 4
}






extern "C++"
{
extern char *strrchr (char *__s, int __c)
     throw () __asm ("strrchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern const char *strrchr (const char *__s, int __c)
     throw () __asm ("strrchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
# 251 "/usr/include/string.h" 3 4
}
# 261 "/usr/include/string.h" 3 4
extern "C++" char *strchrnul (char *__s, int __c)
     throw () __asm ("strchrnul") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern "C++" const char *strchrnul (const char *__s, int __c)
     throw () __asm ("strchrnul") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
# 273 "/usr/include/string.h" 3 4
extern size_t strcspn (const char *__s, const char *__reject)
     throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));


extern size_t strspn (const char *__s, const char *__accept)
     throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));


extern "C++"
{
extern char *strpbrk (char *__s, const char *__accept)
     throw () __asm ("strpbrk") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
extern const char *strpbrk (const char *__s, const char *__accept)
     throw () __asm ("strpbrk") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
# 301 "/usr/include/string.h" 3 4
}




Спойлер
	.file	"ftp2cl.cpp"
	.text
	.section	.rodata
	.align 4
	.type	_ZL34_cat_ftp_client_max_size_char_user, @object
	.size	_ZL34_cat_ftp_client_max_size_char_user, 4
_ZL34_cat_ftp_client_max_size_char_user:
	.long	32
	.align 4
	.type	_ZL33_cat_ftp_client_max_size_temp_buf, @object
	.size	_ZL33_cat_ftp_client_max_size_temp_buf, 4
_ZL33_cat_ftp_client_max_size_temp_buf:
	.long	512
	.align 4
	.type	_ZL28_cat_ftp_client_max_recv_buf, @object
	.size	_ZL28_cat_ftp_client_max_recv_buf, 4
_ZL28_cat_ftp_client_max_recv_buf:
	.long	1024
.LC0:
	.string	"MDTM"
.LC1:
	.string	"213 "
	.text
	.align 2
	.globl	_ZN12CatFTPclient11getFileDateEPcS0_
	.type	_ZN12CatFTPclient11getFileDateEPcS0_, @function
_ZN12CatFTPclient11getFileDateEPcS0_:
.LFB15:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$544, %rsp
	movq	%rdi, -520(%rbp)
	movq	%rsi, -528(%rbp)
	movq	%rdx, -536(%rbp)
	movq	-520(%rbp), %rax
	movzbl	82(%rax), %eax
	testb	%al, %al
	je	.L2
	leaq	-512(%rbp), %rax
	movl	$1297368141, (%rax)
	movw	$32, 4(%rax)
	movq	-528(%rbp), %rdx
	leaq	-512(%rbp), %rax
	movq	%rdx, %rsi
	movq	%rax, %rdi
	call	strcat@PLT
	leaq	-512(%rbp), %rax
	movq	%rax, %rdi
	call	strlen@PLT

Эти два кода не эквивалентны и ни один оптимизатор никогда не преобразует первый код во второй.

Кода на С++ “после оптимизации” в природе не существует, он не появляется ни на каком этапе.

Можно посмотреть код после препроцессора, если интересно. Я иногда смотрю. С ардуино IDE он появляется безо всяких танцев с бубнами в папке build.

1 лайк

Ну хотя бы после препроцессора … только вот папки build не нашел … у меня ide 2 версии
смотрел везде и в скрытых/системных тоже

с GCC не вышло … c иде его нет, а пакеты win-avr и avr-gcc с ошибкой . первый ругается на сам код, а второй на отсутствие файлов… пока не разобрался еще что хотят

В папке temp не смотрел? (cd %temp%)

1 лайк