встроенная сборка + управление указателем

Я очень новичок в отношении использования встроенной сборки в кодах C ++.
То, что я хочу сделать, это в основном вид memcopy для указателя с размером по модулю 32.

В C ++ код используется примерно так:

void my_memcpy(const std::uint8_t* in,std::uint8_t* out,const std::size_t& sz)
{

assert((sz%32 == 0));

for(const std::uint8_t* it = beg; it != (beg+sz);it+=32,out+=32)
{
__m256i = _mm256_stream_load_si256(reinterpret_cast<__m256i*>(it));
_mm256_stream_si256(reinterpret_cast<__m256i*>(out),tmp);

}
}

Я уже сделал небольшую встроенную сборку, но каждый раз я заранее знал как размер вкладки ввода, так и вкладку вывода.

Итак, я попробовал это:

void my_memcpy(const std::uint8_t* in,std::uint8_t* out,const std::size_t& sz)
{

assert((sz%32 == 0));

__asm__ volatile(

"mov %1, %%eax \n""mov $0, %%ebx \n"
"L1: \n"
"vmovntdqa (%[src],%%ebx), %%ymm0 \n""vmovntdq  %%ymm0, (%[dst],%%ebx) \n"
"add %%ebx, $32 \n"
"cmp %%eax, %%ebx \n""jz L1 \n"
:[dst]"=r"(out)
:[src]"r"(in),"m"(sz)
:"memory");

}

G ++ сказал мне:

Error: unsupported instruction `mov'
Error: `(%rdi,%ebx)' is not a valid base/index expression
Error: `(%rdi,%ebx)' is not a valid base/index expression
Error: operand type mismatch for `add'

Итак, я попробовал это:

void my_memcpy(const std::uint8_t* in,std::uint8_t* out,const std::size_t& sz)
{

assert((sz%32 == 0));
__asm__ volatile(

"mov %1, %%eax \n""mov $0, %%ebx \n"
"L1: \n"
"vmovntdqa %%ebx(%[src]), %%ymm0 \n""vmovntdq  %%ymm0, (%[dst],%%ebx) \n"
"add %%ebx, $32 \n"
"cmp %%eax, %%ebx \n""jz L1 \n"
:[dst]"=r"(out)
:[src]"r"(in),"m"(sz)
:"memory");

}

Я получаю из G ++:

Error: unsupported instruction `mov'
Error: junk `(%rdi)' after register
Error: `(%rdi,%ebx)' is not a valid base/index expression
Error: operand type mismatch for `add'

В каждом случае я безуспешно пытался найти решение.
Я испытываю также это решение:

void my_memcpy(const std::uint8_t* in,std::uint8_t* out,const std::size_t& sz)
{

__asm__ volatile (
".intel_syntax noprefix;"
"mov eax, [SZ];""mov ebx, 0;"
"L1 : "
"vmovntdqa ymm0, [src+ebx];""vmovntdq [dst+ebx], ymm0;"
"add ebx, 32 \n"
"cmp ebx, eax \n""jz L1 \n"".att_syntax;": [dst]"=r"(out)
: [SZ]"m"(sz),[src]"r"(in)
: "memory");}

G ++:

undefined reference to `SZ'
undefined reference to `src'
undefined reference to `dst'

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

Я также знаю, что мои попытки не строго соответствуют коду, который я написал на C ++.

Я хотел бы понять, что не так с моей попыткой, а также как перевести как можно ближе мою функцию C ++.

Заранее спасибо.

-1

Решение

Ваш первый пример является наиболее правильным и имеет следующие ошибки:

  • Он использует 32-битные регистры вместо 64-битных.
  • Изменены 3 регистра, которые не указаны как выходы или сгустки.
  • EAX загружается с адресом источника, а не с размером.
  • dst объявляется как выход, когда это должен быть вход.
  • Аргументы в пользу add инструкция неверна, в AT&Синтаксис T: регистр назначения последний.
  • Используется нелокальная метка, которая потерпит неудачу, если оператор asm будет дублирован, например, путем вставки.

И следующие проблемы с производительностью:

  • sz Параметр передается по ссылке. (Может также ухудшить оптимизацию в вызывающих функциях)
  • Затем он передается в asm в качестве аргумента памяти, который требует его записи в память.
  • Затем он копируется в другой регистр.
  • Исправленные регистры используются вместо того, чтобы позволить компилятору выбирать.

Вот исправленная версия, которая не быстрее, чем эквивалентный C ++ со встроенными функциями:

void my_memcpy(const std::uint8_t* in,std::uint8_t* out,const std::size_t sz)
{
std::size_t count = 0;
__m256i temp;

assert((sz%32 == 0));

__asm__ volatile(

"1: \n"
"vmovntdqa (%[src],%[count]), %[temp] \n""vmovntdq  %[temp], (%[dst],%[count]) \n"
"add $32, %[count] \n"
"cmp %[sz], %[count] \n""jz 1b \n"
:[count]"+r"(count), [temp]"=x"(temp)
:[dst]"r"(out), [src]"r"(in), [sz]"r"(sz)
:"memory", "cc");

}

Параметры источника и пункта назначения наоборот memcpy что потенциально сбивает с толку.

При добавлении версии синтаксиса Intel также не используется правильный синтаксис для ссылки на аргументы (например, %[dst]).

2

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector