ARM-NEON:基于参数的条件寄存器交换

时间:2014-03-07 19:45:57

标签: performance optimization assembly arm neon

我正在NEON中编写一个用于图像处理的子程序,它进行颜色交换,即,我顺序加载数组中的R,G,B通道,并根据某些配置,置换其中的一些。

最多6个permutes

  (RGB) -> { (RGB),(RBG),(GRB),(GBR),(BRG),(BGR) }

最有效的方法是为每个案例和相应的VSWP指令分别设置一个子程序。由于子程序将执行其他几项操作,我宁愿将所有内容保留在一个子程序中,即使它不是那么有效,

另请注意,不建议使用条件执行和分支。所以,如果我想把它放在一个无分支代码的块中,我唯一想到的就是

New_R = a(0)*R+a(1)*G+a(2)*B
New_G = a(3)*R+a(4)*G+a(5)*B
New_B = a(6)*R+a(7)*G+a(8)*B

每个行和列中只有一个a(i)每次= 1,其余的将是= 0

问题:任何更聪明的方法,记住它必须编码为NEON?

1 个答案:

答案 0 :(得分:1)

VTBL.8是NEON中交换字节最强大的工具。

将3x8字节加载到寄存器d0,d1,d2看起来像

  R G B R G B R G | B R G B R G B R | G B R G B R G B |
  0 1 2 3 4 5 6 7   8 9 a b c d e f ....            17

VTBL d3, { d0,d1,d2 }, d6  ;; select bytes to d3 from d0,d1,d2 based on d6
VTBL d4, { d0,d1,d2 }, d7
VTBL d5, { d0,d1,d2 }, d8

其中d6,d7,d8编码要在新字节中读取的位置。 例如'0 1 2 3 4 5 6 7'用于原始排列,'0 2 1 3 5 4 6 8','7 ...'用于交换G和B.常量向量d6..d8需要加载一旦在例程的开始。

另一种可能性是使用交错读取编码以下序列;

VLD3.8 { d0,d1,d2 }, [r0]    ; // Read R, G, B to separate registers
VLD3.8 { d3,d4,d5 }, [r0]    ; // Make a second copy (or use some other instruction)

VBIT d3, d1, d6              ; // d3 is now either R or G
VBIT d4, d2, d7              ; // d4 is now either G or B
VBIT d5, d0, d8              ; // d5 is now either B or R

VBIT d0, d4, d9              ; // d0 is now R or (G or B)
VBIT d1, d5, d10             ; // d1 is now G or (B or R)
VBIT d2, d3, d11             ; // d2 is now B or (R or G)

即使在示例中使用了6个条件代码寄存器,但3个独立寄存器应该足够 - 如果需要使用反向逻辑,也可以使用VBIF。