В общем пишу на сишечке программу, компилирую MinGW-w64. Захотелось мне тут посмотреть на свой код через IDA Pro. Для примера взял такой код: Код (C): for(unsigned int i=0; i<MSize*MSize; i++) MSize объявлен как unsigned int. Вижу в качестве проверки условия в IDA Pro: Код (ASM): loc_40167A: mov eax, [rbp-40h+MSize] imul eax, [rbp-40h+MSize] cmp [rbp-40h+i], eax jb short loc_401644 Т.о. при проверке условия он делает знаковое умножение, это вообще нормально? И как с этим бороться? Я понимаю, что вряд ли квадрат переменной MSize выйдет за пределы максимального знакового целого, но всё-таки такое поведение компилятора раздражает.
вполне нормально, если отключена оптимизация, или MSize - глобальная переменная, то есть может быть в любое время изменена из другого потока...
А почему если MSize - глобальная переменная, то он такую фигню делает? Собрал программу в Release конфигурации (опции компилятора: "-O2;-Wall"), но всё равно он юзает imul.
я же писал: MSize может быть изменена из другого потока, если это глобальная переменная, тогда выражение MSize * MSize нужно вычислять на каждой иттерации цикла, чтобы не терять семантику написанного кода... чтобы этого не было, объяви переменную auto MSize2 = MSize * MSize, и используй ее в качестве предела для иттераций цикла... есть еще -O3... -Wall не имеет никакого отношения к оптимизации...
Rel, кажется вы меня не правильно поняли. Проблема не в том, что произведение вычисляется на каждой итерации, а в том, что вместо беззнакового умножения mul используется знаковое imul.
а, сорян... насчет этого не знаю... можно канеш предположить, что imul выполняется быстрее mul... но это странно... думаю, что тебе лучше об этом спросить в мейл-листе GCC или MinGW...
Проблемы нет, так как отличие знакового умножения от беззнакового только в устанавливаемых флагах; в edx:eax будет одно и то же.
При форме imul такой, как я привёл в #1 в edx ничего записано не будет. А на счёт того, что разницы не будет, это - да, я не подумал (разница будет в верхнем двойном слове, которое никуда записано не будет).
Вообще, использовать голый unsigned int нынче некошерно. Лучше что-нить типа size_t. Ну и умножение лучше из for вынести в отдельную переменную. Не всяк компилятор умён настолько. По поводу imul - всё уже правильно сказали.
Да, в принципе, не много плохого: писать приходится немного больше символов, чем size_t, и портабельность страдает: на x32 sizeof(unsigned int) = 32, sizeof(size_t) = 32, а вот на x64 sizeof(unsigned int) = 32, а sizeof(size_t) = 64.
В C++ чтение произвольной переменной, которая потенциально меняется в другом потоке, без должной синхронизации (установления отношения happens before) называется data race и приводит к неопределённому поведению. Короче, не может глобальная переменная (не atomic) в любое время меняться из другого потока. Не нужно и никто не вычисляет, в чём можно легко убедиться. Берём код Код (C): unsigned MSize = 30; unsigned f() { unsigned ret = 0; for (unsigned i = 0; i < MSize*MSize; i++) ret += i; return ret; } и компилируем gcc: Код (ASM): f(): mov ecx, DWORD PTR MSize[rip] imul ecx, ecx test ecx, ecx je .L4 xor edx, edx xor eax, eax .L3: add eax, edx add edx, 1 cmp edx, ecx jne .L3 rep ret .L4: xor eax, eax ret MSize: .long 30 или msvc: Код (ASM): MSize DD 01eH f PROC mov r9d, DWORD PTR MSize xor ecx, ecx imul r9d, r9d mov edx, ecx mov r10d, ecx mov eax, ecx cmp r9d, 2 jb SHORT $LC10@f lea r8d, DWORD PTR [r9-1] npad 2 $LL11@f: inc edx add ecx, eax add edx, eax add eax, 2 cmp eax, r8d jb SHORT $LL11@f $LC10@f: cmp eax, r9d cmovb r10d, eax lea eax, DWORD PTR [rdx+rcx] add eax, r10d ret 0 f ENDP Ну а насчёт imul уже сказали. Но я тоже скажу.
Код (C++): unsigned MSize = 30; unsigned f() { unsigned ret = 0; for (unsigned i = 0; i < MSize*MSize; i++) ret += i; return ret; } а нужно вычислять? Код (C++): unsigned ret = 900;
CurryHowardIsomorphism, Excusez-moi, je me suis dépêché et mal interprété la condition Код (C++): ret = 405000 // (1+899)*450
Mikl___, да я даже не про арифметику (кстати, она опять некорректная, должно быть 404550), а что замена здесь на константу неправомерна.