簡體   English   中英

uint32_t * uint32_t = uint64_t 向量乘法與 gcc

[英]uint32_t * uint32_t = uint64_t vector multiplication with gcc

我正在嘗試將uint32_t的向量相乘以產生完整的 64 位結果,從而生成 gcc 中的uint64_t向量。 我期望的結果是 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 應該看到每個uint64_t的前 32 位為 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來實現這一點。 不走運,它回退到 4 個IMUL操作碼。

有沒有辦法告訴 gcc 我想要它做什么(32 * 32 = 64 乘以完美放置的一切)?

注意:內聯匯編或內在不是答案。 手動編寫操作碼顯然有效。 但隨后我將不得不為許多目標架構和功能集編寫不同版本的代碼。 我希望 gcc 能夠理解問題並從單個源代碼中生成正確的解決方案。

正如 chtz 在評論中所指出的, mul1 和 mul2 都由 clang 進行了優化。 類似於 mul3 但使用 for 循環的代碼也將被優化(但不是那么好)。

所以在我看來,表達代碼應該做什么的語法是正確的,而 gcc 到目前為止只是缺乏正確優化它的聰明才智。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM