【问题标题】:Extracting Subvector from Vector Register in LLVM IR从 LLVM IR 中的向量寄存器中提取子向量
【发布时间】:2019-06-25 04:50:39
【问题描述】:

我正在寻找一种更紧凑的方法来从<8 x float>(例如ymm0)寄存器中提取连续的<4 x float>(例如xmm0),最终将使用SIMD 向量宽度命名。

这是按预期工作的,但相当复杂:

%out.1 = extractelement <8 x float> %out.0, i32 0
%out.2 = extractelement <8 x float> %out.0, i32 1
%out.3 = extractelement <8 x float> %out.0, i32 2
%out.4 = extractelement <8 x float> %out.0, i32 3
%out.5 = insertelement <4 x float> undef, float %out.1, i32 0
%out.6 = insertelement <4 x float> %out.5, float %out.2, i32 1
%out.7 = insertelement <4 x float> %out.6, float %out.3, i32 2
%out.8 = insertelement <4 x float> %out.7, float %out.4, i32 3

有没有更精简的方法来完成同样的任务?

【问题讨论】:

  • 总是高 4 (vextractf128) 还是低 4(只是重新解释)?或者您有时是否需要元素 2..5 或其他内容,并希望 LLVM 优化为 vpermpd ymm, ymm, imm 以在 xmm 中创建您想要的结果? (或带有元素 1..4 或 3..6 的矢量控制的 vpermps。)我实际上不太了解 LLVM-IR,但如果它可以在一个 LLVM-IR 中表达任何 x86 shuffle 指令指令,使用它。
  • 它将始终是高位或低位部分,无需洗牌,只需一个不同的寄存器名称。但是,如果 LLVM 用寄存器名称更改替换它,则在 IR 中使用 shuffle 可能是一种选择。我会尝试并报告。
  • @PeterCordes 这就是诀窍。谢谢!
  • 提取高 128 确实需要 x86 asm 中的洗牌,例如vextractf128。它不像 ARM32 那样,q10 的高半部分和低半部分别名为 d21d20,可以直接访问。只有 YMM 的低半部分被 XMM reg 别名。但无论如何,肯定就像在你的答案中一样,你可以将它写成一个随机播放,每个元素都有一个单独的索引,如果你使用不同的索引,LLVM 会将它编译为一个提取物,或者什么都没有,或者编译为 vpermps

标签: vector llvm simd llvm-ir


【解决方案1】:

shufflevector 将完成与上述相同的操作(前提是您只对 %out.8 感兴趣)并且 LLVM 将用一个简单的寄存器名称更改来替换它(例如,如果 %out.1ymm0%out.8 将是xmm0)。

单行替换八行:

%out.8 = shufflevector <8 x float> %out.0, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>

【讨论】:

    猜你喜欢
    • 2015-11-01
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多