LINUX.ORG.RU

Поиск по массиву и x86-инструкция scas. Хочу scas!

 , ,


0

2

Собственно, в этом примере:

void main () {
	short int a[5]={12,15,1,17,248};
	short int i=0;
	short int b=17;
	for (;i<(sizeof a/sizeof *a);i++) {
		if (a[i]==b) printf("Hello, %d\n",i);
	}
}

GCC упорно не хочет генерировать из этого самый простой и логичный в данном случае машинный код -

repne scasw

Генерируется вместо этого цикл с явным cmp.

Почему и как сделать так, чтобы GCC вспомнил о существовании scas с префиксом repne (повторять пока не установлен zero flag) при поиске по массиву?

Спасибо!

★★★★★

Последнее исправление: DRVTiny (всего исправлений: 1)

А вообще, не думаю, что разработчики дураки, видимо, есть какие-то проблемы с этими инструкциями.

Deleted
()
Ответ на: комментарий от DRVTiny

Там про movsb, который будет копировать по одному байту, против memcpy, в котором копирование будет большими блоками.

i-rinat ★★★★★
()
Ответ на: комментарий от Deleted

При все -O, включая «нулевой» - генерируется код с je на метку.

Я всегда считал, что repe/repne scas весьма быстр, уж куда быстрее сбивающего конвеер je

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от anonymous

??? Анонимус, ты в адеквате?

DRVTiny ★★★★★
() автор топика

Я тоже долгое время думал, что gcc генерирует говно. Но потом померял его вариант инкремента против моего.

movl (var), %eax
addl $1, %eax
movl %eax, (var)
;; vs
addl $1, (var)
И оказалось, что его вариант быстрее.

Будь мужиком, ЗАБЕНЧМАРКАЙ с rdtsc. Кстати, есть ненулевая вероятность, что с -Os gcc сделает как раз repne scasw.

P. S. кстати, почитай о 16-битных словах в long mode. Нирикаминдую так делоть.

kawaii_neko ★★★★
()

как уже сказали, эти инструкции будут работать медленнее, чем то, что выдаёт компилятор, потому что вручную эти инструкции мало кто писал, а компиляторы их исторически не генерировали, в итоге производители процессоров стали делать упор на оптимизацию последовательностей инструкций, которые обычно выдаются компилятором, а на строковые инстркции забили и оставили их только ради совместимости

по крайней мере я такую версию знаю

Harald ★★★★★
()
Ответ на: комментарий от Gvidon

Если посоветуете вариант, как это протестировать - проверю :)

Пока вижу сценарий тестирования примерно как «скопировать ассемблерный код из objdump, переправить на repne, скомпилить, сравнить время выполнения 10^6 раз со временем исполнения Си-кода». Правильно мыслю или не очень? Только printf убрать нужно, а то это, наверное, процентов 80 всего времени исполнения...

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от kawaii_neko

16 бит только в качестве примера. Но когда я пробовал с обычным int'ом - тоже scas не генерировался.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от Harald

Вы правы. Вот, что мне ответили на StackOverflow:

http://stackoverflow.com/questions/34132889/how-to-force-gcc-to-produce-repne...

Видимо, в Intel в связи с тотальной многоядерностью забили на «длинные» инструкции. Получается, что программирование на CISC-овом Intel в RISC-like стиле теперь выгоднее использования встроенных в процессор «высокоуровневых» микропрограмм.

Печально, мне инструкции с rep'ом всегда нравились своей простотой и лаконичностью.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

А почему именно
addl $1, %eax
А не просто incl %eax?

inc не модифицирует флаг переноса, любая последующая зависящая от него инструкция - задержка

frame ★★★
()
Ответ на: комментарий от DRVTiny

Для этого gcc -s есть. Правь его. objdump не всегда выдаёт вылидный листинг.

mittorn ★★★★★
()
Ответ на: комментарий от DRVTiny

Потому что inc/dec изменяют только часть регистра флагов, что сильно замедляет.

kawaii_neko ★★★★
()

С помощью SIMD-инструкций можно искать байты и последовательности байтов гораздо быстрее, зуб даю.

anonymous
()
Ответ на: комментарий от anonymous

Если далее нет инструкции с зависимостью от флага переноса - да

frame ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.