Наткнулся на какой то баг компилятора?

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
V2oD2o
Встал на лапы
Сообщения: 90
Зарегистрирован: Чт дек 09, 2010 12:03:08
Откуда: Зеленоград
Контактная информация:

Наткнулся на какой то баг компилятора?

Сообщение V2oD2o »

C8T6, 72Мгц, внешний кварц, CMSIS без каких либо надстроек, g++

имеется прерывание 4мкс, он же счетчик для событий + необходимо некоторые данные обновлять \ считать

почему то скобки очень сильно влияют на время выполнения прерывания, например если условно:

a = (((b * 10) + (c / 60)) - 1) * 5; - прерывание будет выполняться 5.184135 мкс

а вот такая конструкция:

x = b * 10;
y = c / 60;
a = x + y - 1;
a *= 5;


не будет влиять на время прерывания, т.е. время прерывания чётко 4.000000мкс

что компилятору там могло в голову ударить ? :shock:
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18592
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Наткнулся на какой то баг компилятора?

Сообщение ARV »

V2oD2o писал(а):a = (((b * 10) + (c / 60)) - 1) * 5;
ну а если записать "естественно", без лишних скобок:a = (b*10 + c/60 - 1) * 5;? что будет?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Аватара пользователя
Мурик
Друг Кота
Сообщения: 3383
Зарегистрирован: Пн окт 11, 2010 19:00:08

Re: Наткнулся на какой то баг компилятора?

Сообщение Мурик »

Какие типы переменных? Float или Double среди них есть?
Результат первой и второй конструкции идентичен или отличается?
Оптимизация по скорости включена?
V2oD2o
Встал на лапы
Сообщения: 90
Зарегистрирован: Чт дек 09, 2010 12:03:08
Откуда: Зеленоград
Контактная информация:

Re: Наткнулся на какой то баг компилятора?

Сообщение V2oD2o »

[uquote="ARV",url="/forum/viewtopic.php?p=3416692#p3416692"]
V2oD2o писал(а):a = (((b * 10) + (c / 60)) - 1) * 5;
ну а если записать "естественно", без лишних скобок:a = (b*10 + c/60 - 1) * 5;? что будет?[/uquote]

Пример условный, но закономерность именно такая, всё считаешь в одной строке - лаг по времени прерывания, разделяешь - все нормально

Добавлено after 2 minutes 18 seconds:
[uquote="Мурик",url="/forum/viewtopic.php?p=3416697#p3416697"]Какие типы переменных? Float или Double среди них есть?
Результат первой и второй конструкции идентичен или отличается?
Оптимизация по скорости включена?[/uquote]

C8T6 не имеет FPU, в первом посте указал что только CMSIS без всяких надстроек т.е. никаких извращений с float на цельночисленном камне, тип данных uint16_t или 32_t - ситуация одинаковая, оптимизации пробовал разных уровней - результат малоотличим

Данные снимал анализатором, в прерывании ->ODR ^= и смотрел на интервалы прерывания

И еще, для понимания - калькуляция там не одна, их с десяток наберется, за пределы результирующей длины слова - не вылезает, по отладчику перепроверено несколько раз
Реклама
Эиком - электронные компоненты и радиодетали
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Наткнулся на какой то баг компилятора?

Сообщение Reflector »

[uquote="ARV",url="/forum/viewtopic.php?p=3416692#p3416692"]ну а если записать "естественно", без лишних скобок:a = (b*10 + c/60 - 1) * 5;? что будет?[/uquote]
А есть варианты? Твоя программа разбора выражений со скобками и без могла выдавать разные результаты?

V2oD2o, такое выражение целиком за пол мкс должно считаться, даже без оптимизации будет не на много больше, причем в таком случае медленнее должен быть вариант с промежуточными переменными, так что весьма вероятно баг где-то в другом месте.
Реклама
V2oD2o
Встал на лапы
Сообщения: 90
Зарегистрирован: Чт дек 09, 2010 12:03:08
Откуда: Зеленоград
Контактная информация:

Re: Наткнулся на какой то баг компилятора?

Сообщение V2oD2o »

[uquote="Reflector",url="/forum/viewtopic.php?p=3416718#p3416718"][uquote="ARV",url="/forum/viewtopic.php?p=3416692#p3416692"]ну а если записать "естественно", без лишних скобок:a = (b*10 + c/60 - 1) * 5;? что будет?[/uquote]
А есть варианты? Твоя программа разбора выражений со скобками и без могла выдавать разные результаты?

V2oD2o, такое выражение целиком за пол мкс должно считаться, даже без оптимизации будет не на много больше, причем в таком случае медленнее должен быть вариант с промежуточными переменными, так что весьма вероятно баг где-то в другом месте.[/uquote]

выражение условное, там несколько десятков расчётов завязанные на разные временные события и внешние прерывания, основная масса расчетов ведётся по данным ADC через DMA - 4 канала

попробую сформировать вечером реальный пример, на котором можно увидеть "у себя" описанную проблему

результат - всегда одинаковый, просто разбивание строки со скобками убирает проблему полностью, таймер начинает считать нормально
Реклама
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Re: Наткнулся на какой то баг компилятора?

Сообщение Siarzhuk »

[uquote="V2oD2o",url="/forum/viewtopic.php?p=3416714#p3416714"]тип данных uint16_t или 32_t - ситуация одинаковая[/uquote]
В многострочном варианте промежуточный результат явно приводится к типу присваиваемых переменных, в однострочном - нет. Проверьте, интересу ради, вариант a = (uint_16t)(((uint_16t)(b * 10) + (uint_16t)(c / 60)) - 1) * 5; Кроме того, теоретически, операции "перемножение" и "домножение" имеют разное количество аргументов - и компилятор вполне может решить пользоваться разными инструкциями буде такие в его распоряжении на рассматриваемой платформе. А сгенерированный ASM код наверняка неидентичен - может туда глянуть? ;-)
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
V2oD2o
Встал на лапы
Сообщения: 90
Зарегистрирован: Чт дек 09, 2010 12:03:08
Откуда: Зеленоград
Контактная информация:

Re: Наткнулся на какой то баг компилятора?

Сообщение V2oD2o »

[uquote="Siarzhuk",url="/forum/viewtopic.php?p=3416741#p3416741"][uquote="V2oD2o",url="/forum/viewtopic.php?p=3416714#p3416714"]тип данных uint16_t или 32_t - ситуация одинаковая[/uquote]
В многострочном варианте промежуточный результат явно приводится к типу присваиваемых переменных, в однострочном - нет. Проверьте, интересу ради, вариант a = (uint_16t)(((uint_16t)(b * 10) + (uint_16t)(c / 60)) - 1) * 5; Кроме того, теоретически, операции "перемножение" и "домножение" имеют разное количество аргументов - и компилятор вполне может решить пользоваться разными инструкциями буде такие в его распоряжении на рассматриваемой платформе. А сгенерированный ASM код наверняка неидентичен - может туда глянуть? ;-)[/uquote]

На работе к сожалению нет возможности objdump сделать, дома по-любому буду построчно разбирать и бряки делать на каждом шагу, вчера ночью только наткнулся на этупроблему, особо времени не было разбираться

Насчет приведения к типам - хорошая идея, попробую вечером
Аватара пользователя
Мурик
Друг Кота
Сообщения: 3383
Зарегистрирован: Пн окт 11, 2010 19:00:08

Re: Наткнулся на какой то баг компилятора?

Сообщение Мурик »

Эту строку.

Код: Выделить всё

a = (((b * 10) + (c / 60)) - 1) * 5;
GCC компилировал так (все переменные uint32_t).

Код: Выделить всё

//      a = (((b * 10) + (c / 60)) - 1) * 5;
080004AC	ldr	r1, [pc, #64]	; (0x80004f0 <main+116>)
080004B0	add.w	r2, r2, r2, lsl #2
080004B4	umull	r1, r3, r1, r3
080004B8	lsrs	r3, r3, #5
080004BA	add.w	r3, r3, r2, lsl #1
080004BE	add.w	r3, r3, r3, lsl #2
080004C2	subs	r3, #5
Эти строки.

Код: Выделить всё

    x = b * 10;
    y = c / 60;
    a = x + y - 1;
    a *= 5;
скомпилировались в такой код.

Код: Выделить всё

//      x = b * 10;
080004B0	add.w	r2, r2, r2, lsl #2
//      y = c / 60;
080004AC	ldr	r1, [pc, #64]	; (0x80004f0 <main+116>)
080004B4	umull	r1, r3, r1, r3
080004B8	lsrs	r3, r3, #5
//      a = x + y - 1;
080004BA	add.w	r3, r3, r2, lsl #1
080004BE	subs	r3, #1
//      a *= 5;
080004C0	add.w	r3, r3, r3, lsl #2
V2oD2o
Встал на лапы
Сообщения: 90
Зарегистрирован: Чт дек 09, 2010 12:03:08
Откуда: Зеленоград
Контактная информация:

Re: Наткнулся на какой то баг компилятора?

Сообщение V2oD2o »

[uquote="Мурик",url="/forum/viewtopic.php?p=3416775#p3416775"]Эту строку.

Код: Выделить всё

a = (((b * 10) + (c / 60)) - 1) * 5;
GCC компилировал так (все переменные uint32_t).

Код: Выделить всё

//      a = (((b * 10) + (c / 60)) - 1) * 5;
080004AC	ldr	r1, [pc, #64]	; (0x80004f0 <main+116>)
080004B0	add.w	r2, r2, r2, lsl #2
080004B4	umull	r1, r3, r1, r3
080004B8	lsrs	r3, r3, #5
080004BA	add.w	r3, r3, r2, lsl #1
080004BE	add.w	r3, r3, r3, lsl #2
080004C2	subs	r3, #5
Эти строки.

Код: Выделить всё

    x = b * 10;
    y = c / 60;
    a = x + y - 1;
    a *= 5;
скомпилировались в такой код.

Код: Выделить всё

//      x = b * 10;
080004B0	add.w	r2, r2, r2, lsl #2
//      y = c / 60;
080004AC	ldr	r1, [pc, #64]	; (0x80004f0 <main+116>)
080004B4	umull	r1, r3, r1, r3
080004B8	lsrs	r3, r3, #5
//      a = x + y - 1;
080004BA	add.w	r3, r3, r2, lsl #1
080004BE	subs	r3, #1
//      a *= 5;
080004C0	add.w	r3, r3, r3, lsl #2
[/uquote]

Уровень оптимизации какой ?
Судя по строке
080004C2 subs r3, #5 - что то пошло не так
Последний раз редактировалось V2oD2o Пн июл 09, 2018 13:13:42, всего редактировалось 1 раз.
Аватара пользователя
Мурик
Друг Кота
Сообщения: 3383
Зарегистрирован: Пн окт 11, 2010 19:00:08

Re: Наткнулся на какой то баг компилятора?

Сообщение Мурик »

-Ofast.
Необязательно для всего проекта. Можно только для нужной функции.
V2oD2o
Встал на лапы
Сообщения: 90
Зарегистрирован: Чт дек 09, 2010 12:03:08
Откуда: Зеленоград
Контактная информация:

Re: Наткнулся на какой то баг компилятора?

Сообщение V2oD2o »

[uquote="Мурик",url="/forum/viewtopic.php?p=3416778#p3416778"]-Ofast.
Необязательно для всего проекта. Можно только для нужной функции.[/uquote]

Обновил пред коммент, откуда там?
080004C2 subs r3, #5
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Наткнулся на какой то баг компилятора?

Сообщение Reflector »

[uquote="V2oD2o",url="/forum/viewtopic.php?p=3416780#p3416780"]откуда там?
080004C2 subs r3, #5[/uquote]
Современные компиляторы очень умные, в данном случае он раскрыл скобки(b * 50 + c / 12 - 5), заменил деление умножением, умножение заменил сдвигами и сложением, более того т.к. из-за целочисленного деления результат упрощенного выражения может быть другим, то было предусмотрено и это. Так что не нужно искать баги у компилятора, ищи баги у себя :)
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: Наткнулся на какой то баг компилятора?

Сообщение dosikus »

V2oD2o , покажите полносттю обработчик прерывания таймера.
Особенно интересует сброс флага...
V2oD2o
Встал на лапы
Сообщения: 90
Зарегистрирован: Чт дек 09, 2010 12:03:08
Откуда: Зеленоград
Контактная информация:

Re: Наткнулся на какой то баг компилятора?

Сообщение V2oD2o »

[uquote="dosikus",url="/forum/viewtopic.php?p=3416916#p3416916"]V2oD2o , покажите полносттю обработчик прерывания таймера.
Особенно интересует сброс флага...[/uquote]

Там все в порядке, проект рабочий, после доработок, не сразу, но было замечено увеличение времени отсчета по таймеру примерно х1.8 - х2, т.е. событие по 10мс, выполнялось в 18.5064мс

Добавлено after 7 minutes 45 seconds:
[uquote="Siarzhuk",url="/forum/viewtopic.php?p=3416741#p3416741"][uquote="V2oD2o",url="/forum/viewtopic.php?p=3416714#p3416714"]тип данных uint16_t или 32_t - ситуация одинаковая[/uquote]
В многострочном варианте промежуточный результат явно приводится к типу присваиваемых переменных, в однострочном - нет. Проверьте, интересу ради, вариант a = (uint_16t)(((uint_16t)(b * 10) + (uint_16t)(c / 60)) - 1) * 5; Кроме того, теоретически, операции "перемножение" и "домножение" имеют разное количество аргументов - и компилятор вполне может решить пользоваться разными инструкциями буде такие в его распоряжении на рассматриваемой платформе. А сгенерированный ASM код наверняка неидентичен - может туда глянуть? ;-)[/uquote]

"Дело было не в бобине" - и действительно, приведение к типам дало прирост, очень ощутимый, было 18мс вместо 10мс, перевёл все расчеты на u32_t (в 16 не влезу) - стало 13.3мс, добавил -O3 - и увидел заветные 10мс, пробовал нагрузить еще всякими вычислениями, даже гораздо более сложными и считать их каждый тик, а не по событию - проблема решилась, каждый тик ровно 5.000 мкс, спасибо за наводку! 8)

Что интересно -Ох без использования однотипных данных - почти ничего не давало
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: Наткнулся на какой то баг компилятора?

Сообщение dosikus »

[uquote="dosikus",url="/forum/viewtopic.php?p=3416916#p3416916"]Особенно интересует сброс флага...[/uquote]
И все же, многие влетали на эти грабли сбрасывая флаг в конце распухшего прерывания...
V2oD2o
Встал на лапы
Сообщения: 90
Зарегистрирован: Чт дек 09, 2010 12:03:08
Откуда: Зеленоград
Контактная информация:

Re: Наткнулся на какой то баг компилятора?

Сообщение V2oD2o »

[uquote="dosikus",url="/forum/viewtopic.php?p=3417406#p3417406"][uquote="dosikus",url="/forum/viewtopic.php?p=3416916#p3416916"]Особенно интересует сброс флага...[/uquote]
И все же, многие влетали на эти грабли сбрасывая флаг в конце распухшего прерывания...[/uquote]

Да, я не исключение, проходили
Ответить

Вернуться в «ARM»