uint32_t * uint32_t = uint64_t умножение вектора с помощью gcc

Я пытаюсь перемножить векторы uint32_t получение полного 64-битного результата в uint64_tвектор в gcc. В результате, я ожидаю, что gcc выдаст одинVPMULUDQинструкция. Но то, что gcc выводит как код, ужасно перетасовывает индивидуумuint32_tисходных векторов, а затем полное 64*64=64 умножение. Вот что я пробовал:

#include <stdint.h>

typedef uint32_t v8lu __attribute__ ((vector_size (32)));
typedef uint64_t v4llu __attribute__ ((vector_size (32)));

v4llu mul(v8lu x, v8lu y) {
    x[1] = 0; x[3] = 0; x[5] = 0; x[7] = 0;
    y[1] = 0; y[3] = 0; y[5] = 0; y[7] = 0;
    return (v4llu)x * (v4llu)y;
}

Первый маскирует нежелательные части uint32_tвектор в надежде, что gcc оптимизирует ненужные части умножения 64*64=64, а затем увидит, что маскирование также бессмысленно. Нет такой удачи.

v4llu mul2(v8lu x, v8lu y) {
    v4llu tx = {x[0], x[2], x[4], x[6]};
    v4llu ty = {y[0], y[2], y[4], y[6]};
    return tx * ty;
}

Здесь я пытаюсь создать uint64_tвектор с нуля с набором только использованных деталей. Опять же, gcc должен увидеть верхние 32 бита каждогоuint64_tравны 0 и не выполняют полное умножение 64*64=64. Вместо этого происходит много извлечения и возврата значений, и 64*64=64 умножаются.

v4llu mul3(v8lu x, v8lu y) {
    v4llu t = {x[0] * (uint64_t)y[0], x[2] * (uint64_t)y[2], x[4] * (uint64_t)y[4], x[6] * (uint64_t)y[6]};
    return t;
}

Построим вектор результата, умножив части. Может быть, gcc видит, что может использоватьVPMULUDQчтобы добиться именно этого. Не повезло, он возвращается к 4IMUL коды операций.

Есть ли способ сказать gcc, что я хочу, чтобы он делал (32*32=64 умножение, все размещено идеально)?

Примечание: встроенный asm или встроенный - это не ответ. Написание кода операции вручную, очевидно, работает. Но тогда мне пришлось бы писать разные версии кода для многих целевых архитектур и наборов функций. Я хочу, чтобы gcc понял проблему и создал правильное решение из единого исходного кода.

1 ответ

Как отмечено в комментариях chtz, mul1 и mul2 оптимизированы с помощью clang. Код, похожий на mul3, но с использованием цикла for, тоже будет оптимизирован (но не так хорошо).

Поэтому мне кажется, что синтаксис правильный, чтобы выразить то, что должен делать код, а gcc пока просто не хватает умов, чтобы оптимизировать это правильно.

Другие вопросы по тегам