Почему clang ++ предпочитает adcx над adc - PullRequest
0 голосов
/ 03 июня 2018

Я реализовал многоточное сложение, используя следующий код:

    bool carry{};
    std::array<uint64_t, N> r{};

    for (auto i = 0; i < N; ++i) {
       uint64_t aa = a[i];
       __uint128_t res = static_cast<__uint128_t>(aa) + b[i] + carry;
       carry = res >> 64;
       r[i] = res;
    }

И clang ++ 6.0 произвел следующую сборку:

400a49: 4c 01 c1                add    %r8,%rcx
400a4c: 66 49 0f 38 f6 c1       adcx   %r9,%rax
400a52: 66 49 0f 38 f6 f2       adcx   %r10,%rsi
400a58: 66 48 0f 38 f6 d7       adcx   %rdi,%rdx

Может кто-нибудь объяснить, почему выбрал clangиспользовать ADCX над ADC?Насколько я могу судить, у boto одинаковое время выполнения, но кодировка adc составляет 3 байта против 6 для adcx.

Обновление: я играл с ним немного больше, и кажется, что поведение довольно случайное,если аргументы передаются как константная ссылка, я получаю adcx https://godbolt.org/g/noFZNS, если я передаю по значению, я получаю adc:

https://godbolt.org/g/RkBWhV

, и если код не находится внутри функции,просто в основном, это полный беспорядок.

1 Ответ

0 голосов
/ 03 июня 2018

Это выглядит для меня как упущенная оптимизация.Я думаю adc - лучший выбор.На Skylake они имеют одинаковые характеристики производительности согласно некоторым быстрым тестам пропускной способности (с xor eax,eax / times 4 adcx eax,edx в цикле).Агнер Фог, как ни странно, не перечисляет adox / adcx в своих таблицах инструкций (http://agner.org/optimize/), в SKL ADC / ADCX / ADOX - все 1 моп для p0 / p6, с задержкой 1c.

Если что,запись всех флагов, а не только CF, с меньшей вероятностью приведет к проблемам с производительностью.

Вы должны сообщить об этом на https://bugs.llvm.org/buglist.cgi.

Пока clang не знает, как на самом деле чередовать с ADOX, когда есть две параллельныеПри использовании цепочек, тратить лишний размер кода на ADCX бессмысленно.

Я мог бы представить редкий случай, когда сохранение других флагов было полезным, и недавние процессоры Intel, кажется, очень эффективны при работе с частичными флагами даже без необходимостислияние. Но это очень ниша, а не то, что здесь происходит (add забивает все флаги).

...