---
title: 选项 -ftree-slp-transpose-vectorize
description: "该选项在循环拆分阶段增强对存在连续访存读的循环的数据流分析能力，通过插入临时数组实现循环拆分。在矢量化（SLP）阶段，新增对grouped_stores进行转置的SLP分析。"
url: https://www.hikunpeng.com/document/detail/zh/kunpengdevkithistory/hgcc/hist-hgcc/kunpenghgcc_06_0024.html
sourcePath: /source/zh/kunpengdevkithistory/hgcc/hist-hgcc/kunpenghgcc_06_0024.html
indexId: de24d7dbc7fecafc422ac3f974ae1800ac1134fe2b621585391d7532a29238ea71
---
# 选项 -ftree-slp-transpose-vectorize

该选项在循环拆分阶段增强对存在连续访存读的循环的数据流分析能力，通过插入临时数组实现循环拆分。在矢量化（SLP）阶段，新增对grouped_stores进行转置的SLP分析。

```
int foo (unsigned char *oxa, int ia, unsigned char *oxb, int ib)
{
    unsigned tmp[4][4];
    unsigned a0, a1, a2, a3;
    int sum = 0;
    for (int i = 0; i < 4; i++, oxa += ia, oxb += ib)
    {
        a0 = (oxa[0] - oxb[0]) + ((oxa[4] - oxb[4]) << 16);
        a1 = (oxa[1] - oxb[1]) + ((oxa[5] - oxb[5]) << 16);
        a2 = (oxa[2] - oxb[2]) + ((oxa[6] - oxb[6]) << 16);
        a3 = (oxa[3] - oxb[3]) + ((oxa[7] - oxb[7]) << 16);
        int t0 = a0 + a1;
        int t1 = a0 - a1;
        int t2 = a2 + a3;
        int t3 = a2 - a3;
        tmp[i][0] = t0 + t2;
        tmp[i][2] = t0 - t2;
        tmp[i][1] = t1 + t3;
        tmp[i][3] = t1 - t3;
    }

    for (int i = 0; i < 4; i++)
    {
        int t0 = tmp[0][i] + tmp[1][i];
        int t1 = tmp[0][i] - tmp[1][i];
        int t2 = tmp[2][i] + tmp[3][i];
        int t3 = tmp[2][i] - tmp[3][i];
        a0 = t0 + t2;
        a2 = t0 - t2;
        a1 = t1 + t3;
        a3 = t1 - t3;
        sum += a0 + a1 + a2 + a3;
    }
    return sum;
}
```

对于如上所示的用例，针对第一个for循环，可以拆分为如下形式

```
for (int i = 0; i < 4; i++, oxa += ia, oxb += ib)
{
    a00[i] = (oxa[0] - oxb[0]) + ((oxa[4] - oxb[4]) << 16);
    a11[i] = (oxa[1] - oxb[1]) + ((oxa[5] - oxb[5]) << 16);
    a22[i] = (oxa[2] - oxb[2]) + ((oxa[6] - oxb[6]) << 16);
    a33[i] = (oxa[3] - oxb[3]) + ((oxa[7] - oxb[7]) << 16);
}

for (int i = 0; i < 4; i++)
{
    int t0 = a00[i] + a11[i];
    int t1 = a00[i] - a11[i];
    int t2 = a22[i] + a33[i];
    int t3 = a22[i] - a33[i];
    tmp[i][0] = t0 + t2;
    tmp[i][2] = t0 - t2;
    tmp[i][1] = t1 + t3;
    tmp[i][3] = t1 - t3;
}
```

针对拆分所得的第一个循环，等号右侧的计算具有同构性且为连续load，具备矢量化条件。但由于左侧a00[i]、a11[i]、a22[i]、a33[i]的内存地址不连续，无法构成矢量化SLP树的根节点，因此失去该场景下的矢量化机会。在将a00[i]、a11[i]、a22[i]、a33[i]写入内存时，期望寄存器中的内容为：

| register | values |
| --- | --- |
| vec0 | a00[0] a00[1] a00[2] a00[3] |
| vec1 | a11[0] a11[1] a11[2] a11[3] |
| vec2 | a22[0] a22[1] a22[2] a22[3] |
| vec3 | a33[0] a33[1] a33[2] a33[3] |


而每次迭代内可以计算得到寄存器的内容为：

| register | values |
| --- | --- |
| vec0 | a00[0] a11[0] a22[0] a33[0] |
| vec1 | a00[1] a11[1] a22[1] a33[1] |
| vec2 | a00[2] a11[2] a22[2] a33[2] |
| vec3 | a00[3] a11[3] a22[3] a33[3] |


将grouped_stores进行转置，即可得到预期的SLP树根节点。再利用SLP原有的能力，进行后续的矢量化分析。

此外，针对拆分所得的第二个循环以及示例中的最后一个循环，tmp二维数组存在写入内存后立刻读取的行为，针对这种场景，将访存行为优化为寄存器之间的permutation行为。该访存优化默认开启。

#### 使用方法

在选项中加入：

```
-O3 -ftree-slp-transpose-vectorize
```


-ftree-slp-transpose-vectorize选项，需要在-O3开启的基础上才使能。
