|
|
  |
Пропуск операции |
|
|
|
Dec 8 2009, 18:33
|

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

|
Никак понять не могу почему ИАР (4.21.2 (4.21.2.50066) для MSP430 с аппаратным умножителем) пропускает операцию умножения. Я бывало уже смотрел в сторону этого компилятора косо, но все время неправым оказывался я  Может и теперь во мне дело. Однако, вот такой вот код есть. Код #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
|
|
|
|
|
Dec 9 2009, 19:54
|

тут может быть ваша реклама
    
Группа: Свой
Сообщений: 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
|
|
|
|
|
Dec 10 2009, 12:21
|
Частый гость
 
Группа: Участник
Сообщений: 99
Регистрация: 14-12-05
Пользователь №: 12 191

|
Цитата(jorikdima @ Dec 9 2009, 22:54)  coef это указатель на массив... Виноват, выше не заметил... Тогда нулевой state[][]. Присвоение к нему не нашёл.
|
|
|
|
|
Dec 11 2009, 07:03
|

тут может быть ваша реклама
    
Группа: Свой
Сообщений: 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 Может кто проверить на более ранних версиях ИАР с включенной оптимизацией? Просто этот код я сделал давно и частично его отладил (конкретно это место) и вопросов у меня тогда не возникло. А сейчас взялся доделать и... Но может я и путаю чего.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|