реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Пропуск операции
jorikdima
сообщение Dec 8 2009, 18:33
Сообщение #1


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Никак понять не могу почему ИАР (4.21.2 (4.21.2.50066) для MSP430 с аппаратным умножителем) пропускает операцию умножения. Я бывало уже смотрел в сторону этого компилятора косо, но все время неправым оказывался я smile.gif Может и теперь во мне дело.
Однако, вот такой вот код есть.
Код
#include "io430.h"

typedef signed char INT8;
typedef signed short INT16;
typedef signed long INT32;
typedef signed long long INT64;

typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned long UINT32;
typedef unsigned long long UINT64;

INT16 FilterSample(const INT16 sample );

const INT16 coeffs[4][2][3] ={
      {{16384, -28354, 16384}, {16384, -28552, 14866}},
      {{16384, -26784, 16384}, {16384, -25180, 11711}},
      {{16384, -20728, 16384}, {16384, -20769, 7916}},
      {{16384, 9571, 16384}, {16384, -16608, 4444}} };

INT16 state[2][2];
INT16 (*coef)[3];

int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  
  coef = (INT16(*)[3])&coeffs[0][0][0];

  FilterSample(783);
}


//#pragma optimize = none
INT16 FilterSample(const INT16 sample )
{
    INT32 res = (INT32)coef[0][0] * sample;
    for (UINT8 i = 0; i < 2; i++)
    {      
        INT32 r1 = (INT32)state[0][i] * coef[0][i + 1];
        INT32 r2 = (INT32)state[1][i] * coef[1][i + 1];
        
        res += r1 - r2;        

    }
    res = (INT16)(res >> 14);
        
    return res;
}


Конкретно интересует место
Код
INT32 r1 = (INT32)state[0][i] * coef[0][i + 1];
        INT32 r2 = (INT32)state[1][i] * coef[1][i + 1];
        
        res += r1 - r2;

Тут все просто берется два произведения, берется разность между ними и интегрируется в переменной res.
Так вот листинг этой функции (FilterSample) с включенной оптимизацией выглядит вот так вот:
Код
FilterSample:
004048    120A               push.w  R10
00404A    120B               push.w  R11
00404C    1208               push.w  R8
00404E    1209               push.w  R9
004050    1206               push.w  R6
    INT32 res = (INT32)coef[0][0] * sample;
004052    421A 1108          mov.w   &coef,R10
004056    1202               push.w  SR
004058    C232               dint
00405A    4303               nop
00405C    4AA2 0132          mov.w   @R10,&MPYS
004060    4C82 0138          mov.w   R12,&OP2
004064    421C 013A          mov.w   &RESLO,R12
004068    421D 013C          mov.w   &RESHI,R13
00406C    4132               pop.w   SR
    for (UINT8 i = 0; i < 2; i++)
00406E    403E 1100          mov.w   #0x1100,R14
004072    4A0B               mov.w   R10,R11
004074    522B               add.w   #0x4,R11
        res += r1 - r2;        
004076    1202               push.w  SR
004078    C232               dint
00407A    4303               nop
00407C    4132               pop.w   SR
00407E    580C               add.w   R8,R12
004080    690D               addc.w  R9,R13
004082    1202               push.w  SR
004084    C232               dint
004086    4303               nop
004088    4E92 0004 0132     mov.w   0x4(R14),&MPYS
00408E    4A92 0008 0138     mov.w   0x8(R10),&OP2
004094    4218 013A          mov.w   &RESLO,R8
004098    4219 013C          mov.w   &RESHI,R9
00409C    4132               pop.w   SR
00409E    880C               sub.w   R8,R12
0040A0    790D               subc.w  R9,R13
    for (UINT8 i = 0; i < 2; i++)
0040A2    532A               incd.w  R10
0040A4    532E               incd.w  R14


Почему я вижу только одно умножение??? Соответствующее рассчету r2. А умножение в рассчете r1 отсутствует, причем вся подготовка для него существует (в виде запрета прерывания, сохранение статусного регистра, затем его восстановления).
Я приаттачил проект, если кому интересно, точнее выдержку из рабочего проекта с интересующим кодом.
Интересно следующее, если отключить оптимизацию - работает, есть два умножения. Если включить опцию Hardware multiplier->Use only lib calls то тоже работает. В этом случае компайлер просто вызывает функции с умножением, а не инлайнит их как обычно, но работает.
Почему ИАР не умножает второй раз (точнее первый раз)?
Спасибо.

Прикрепленный файл  mult.rar ( 7.1 килобайт ) Кол-во скачиваний: 95
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Dec 9 2009, 13:54
Сообщение #2


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Никто не сталкивался с таким?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 9 2009, 14:29
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(jorikdima @ Dec 9 2009, 15:54) *
Никто не сталкивался с таким?
Не могли бы вы приложить полный листинг? Возможно опримизатор переставил вычисления местами. ИАРа нет, поэтому сам получить листинг из ваших исходников не могу.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
plombir
сообщение Dec 9 2009, 14:35
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 99
Регистрация: 14-12-05
Пользователь №: 12 191



Предположу, что вот эти множители coef[0][i + 1] и coef[1][i + 1] компилятор считает нулевыми.
Оптимизируя, убирает умножение.
Кстати, они 3-х размерные в таблице, а Вы берёте 2-ух. Так задумано?
Go to the top of the page
 
+Quote Post
rezident
сообщение Dec 9 2009, 14:37
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Не вдаваясь в разбор исходника, хочу заметить, что IAR оптимизирует обращение к константам, подставляя их значение "по месту", и, вычисляя результат операций с константами заранее, на уровне препроцессора.
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Dec 9 2009, 19:54
Сообщение #6


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Цитата(Сергей Борщ @ Dec 9 2009, 17:29) *
Не могли бы вы приложить полный листинг? Возможно опримизатор переставил вычисления местами. ИАРа нет, поэтому сам получить листинг из ваших исходников не могу.


Я упростил код немного для иллюстрации. Предыдущий вариант кода был выдран из рабочего, поэтому с точки зрения демонстрации был перегружен непонятностями. Вот ниже упрощенный с полным листингом.
Код
#include "io430.h"

typedef signed char INT8;
typedef signed short INT16;
typedef signed long INT32;

typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned long UINT32;

INT16 FilterSample(const INT16 sample );

const INT16 coeffs[2][3] =
     {{16384, -28354, 16384}, {16384, -28552, 14866}};

INT16 state[2][2];

int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  
  FilterSample(783);
}

//#pragma optimize = none
INT16 FilterSample(const INT16 sample )
{
    INT32 res = (INT32)coeffs[0][0] * sample;
    for (UINT8 i = 0; i < 2; i++)
    {      
        INT32 r1 = (INT32)state[0][i] * coeffs[0][i + 1];
        INT32 r2 = (INT32)state[1][i] * coeffs[1][i + 1];
        
        res += r1 - r2;        

    }        
    return res;
}


Листинг полный приаттачен. Никаких переставлений не узрел.

Прикрепленный файл  main.txt ( 4.83 килобайт ) Кол-во скачиваний: 212


Цитата(plombir @ Dec 9 2009, 17:35) *
Предположу, что вот эти множители coef[0][i + 1] и coef[1][i + 1] компилятор считает нулевыми.
Оптимизируя, убирает умножение.
Кстати, они 3-х размерные в таблице, а Вы берёте 2-ух. Так задумано?

coef это указатель на массив, а не сам массив, который назывался coeffs. Похожими названиями запутал, поэтому упростил код, см. выше.

Цитата(rezident @ Dec 9 2009, 17:37) *
Не вдаваясь в разбор исходника, хочу заметить, что IAR оптимизирует обращение к константам, подставляя их значение "по месту", и, вычисляя результат операций с константами заранее, на уровне препроцессора.

Константность непричем, я убирал const - нет разницы. Кроме того, константа умножалась на переменную все же, а это заранее не расчитать.

Упрощенный проет прикрепил.
Прикрепленный файл  mult.rar ( 8.48 килобайт ) Кол-во скачиваний: 98
Go to the top of the page
 
+Quote Post
plombir
сообщение Dec 10 2009, 12:21
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 99
Регистрация: 14-12-05
Пользователь №: 12 191



Цитата(jorikdima @ Dec 9 2009, 22:54) *
coef это указатель на массив...
Виноват, выше не заметил...

Тогда нулевой state[][]. Присвоение к нему не нашёл.
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Dec 10 2009, 12:39
Сообщение #8


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Цитата(plombir @ Dec 10 2009, 15:21) *
Виноват, выше не заметил...

Тогда нулевой state[][]. Присвоение к нему не нашёл.

обнуляется при инициализации, ибо глобальная переменная. В исходном коде (не образанном мною для демонстрации) ей присваиваются значения.
Более того, компайлер не может так поступить с глобальной переменной, он понятия не имеет как и где она меняется.
Еще более того, почему расчет r2 он делает, а r1 - нет, хотя делает всю подготовку для этого в виде запрета прерываний. r1 ничем не хуже r2.
Go to the top of the page
 
+Quote Post
scifi
сообщение Dec 10 2009, 15:44
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Такой вопрос: а вообще код работает корректно? То есть если не заглядывать в дизассемблер, результаты выдаёт правильные или нет?
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Dec 11 2009, 07:03
Сообщение #10


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Цитата(scifi @ Dec 10 2009, 18:44) *
Такой вопрос: а вообще код работает корректно? То есть если не заглядывать в дизассемблер, результаты выдаёт правильные или нет?

нет, неправильные. Конкретно тот проект, что я прикрепил работает корректно с точки зрения конечного результата при самом первом вызове функции (собственно как у меня, я только единожды вызвал ф-цию FilterSample )? но это чисто случайно, так как регистры R8, R9 там равны 0 еще после инициализации контроллера. Но в рабочем варианте в R8 R9 лежит мусор от предыдущих операций и этот мусор используется в
Код
00407E    580C               add.w   R8,R12
004080    690D               addc.w  R9,R13

Хотя правильно было бы строчкой выше залить в R8 R9 результаты с умножителя, как это делается в
Код
004084    C232               dint
004086    4303               nop
004088    4E92 0004 0132     mov.w   0x4(R14),&MPYS
00408E    4A92 0008 0138     mov.w   0x8(R10),&OP2
004094    4218 013A          mov.w   &RESLO,R8
004098    4219 013C          mov.w   &RESHI,R9
00409C    4132               pop.w   SR
00409E    880C               sub.w   R8,R12
0040A0    790D               subc.w  R9,R13


Может кто проверить на более ранних версиях ИАР с включенной оптимизацией? Просто этот код я сделал давно и частично его отладил (конкретно это место) и вопросов у меня тогда не возникло. А сейчас взялся доделать и... Но может я и путаю чего.
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Dec 23 2009, 20:45
Сообщение #11


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Судя по всему это был баг ИАРа. В одном из патчей пролечили, скачав последний патч, благодаря Ксении, увидел правильный код.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 26th June 2025 - 11:37
Рейтинг@Mail.ru


Страница сгенерированна за 0.01455 секунд с 7
ELECTRONIX ©2004-2016