Оптимизированный выход GCC для ARM A7 со сбоями - PullRequest
1 голос
/ 15 октября 2019

Внимание гуру сборки ARM!

У меня есть код, который неожиданно завершается неудачей при оптимизации. Я выделил его в простом модульном тесте на моем встроенном устройстве. Код построен для встроенной среды ARM A7 с использованием gcc-arm-8.3-2019.03-x86_64-arm-eabi.

Код представляет собой базовый поиск двоичного дерева как часть шаблона:

map_node_s<KEY, VALUE> * _getMutableNode(
    const KEY & key, 
    OUT map_node_s<KEY, VALUE> *** ptrToChildLink,
    OUT map_node_s<KEY, VALUE> ** ptrToParent
    )
{
    map_node_s<KEY, VALUE> * parent = NULL;
    map_node_s<KEY, VALUE> ** linkToChild = &_root;
    map_node_s<KEY, VALUE> * current = *linkToChild;

    while (current)
    {
        if (current->key == key)
        {
            break;
        }

        parent = current;
        if (key < current->key)
        {
            linkToChild = &parent->left;
            current = parent->left;
        }
        else
        {
            linkToChild = &parent->right;
            current = parent->right;
        }
    }

    *ptrToParent = parent;
    *ptrToChildLink = linkToChild;
    return current;
}

Это вызывается методом _getStoredKey, а KEY и VALUE имеют значения int.

Оптимизатор (O2) выдает следующее, что выглядит правильно:

    map_node_s<KEY, VALUE> * _getStoredKey(const KEY & key)
63174910: e92d 43f7     stmdb sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, lr}
63174914: 4604          mov   r4, r0
        map_node_s<KEY, VALUE> * current = *linkToChild;
63174916: 6843          ldr   r3, [r0, #4]
    map_node_s<KEY, VALUE> * _getStoredKey(const KEY & key)
63174918: 4689          mov   r9, r1
        map_node_s<KEY, VALUE> ** linkToChild = &_root;
6317491a: 1d07          adds    r7, r0, #4
        map_node_s<KEY, VALUE> * parent = NULL;
6317491c: f04f 0800     mov.w r8, #0
        while (current)
63174920: b17b          cbz   r3, 63174942 <_ZNSt3mapImSt4pairImSt6vectorIhN3csd9allocatorIhEEEEE13_getStoredKeyERKm+0x32>
            if (current->key == key)
63174922: 6819          ldr   r1, [r3, #0]
63174924: f8d9 2000     ldr.w r2, [r9]
63174928: 4291          cmp   r1, r2
6317492a: d00a          beq.n 63174942 <_ZNSt3mapImSt4pairImSt6vectorIhN3csd9allocatorIhEEEEE13_getStoredKeyERKm+0x32>
                current = parent->right;
6317492c: e9d3 2106     ldrd    r2, r1, [r3, #24]
                linkToChild = &parent->left;
63174930: bf8e          itee    hi
63174932: f103 0718     addhi.w   r7, r3, #24
                linkToChild = &parent->right;
63174936: f103 071c     addls.w   r7, r3, #28
                current = parent->right;
6317493a: 460a          movls r2, r1
6317493c: 4698          mov   r8, r3
6317493e: 4613          mov   r3, r2
63174940: e7ee          b.n   63174920 <_ZNSt3mapImSt4pairImSt6vectorIhN3csd9allocatorIhEEEEE13_getStoredKeyERKm+0x10>
        current = _getMutableNode(key, &linkToChild, &parent);
63174942: 9301          str   r3, [sp, #4]

Но при запуске получается неправильная сортировка, если я не отключаю оптимизацию для метода !! Неоптимизированная сборка выглядит совершенно иначе.

Код также будет работать, если я добавлю точку останова. Я не знаю, как это влияет на конвейер команд, или I-кеш, или что-то еще.

Кроме того, если я сделаю небольшую корректировку, код будет работать:

        if (key < current->key)
        {
            linkToChild = &parent->left;
        }
        else
        {
            linkToChild = &parent->right;
        }
        current = *linkToChild;

который испускает

6317ff34:   b168        cbz r0, 6317ff52 <_ZNSt3mapIiiE15_getMutableNodeERKiPPPSt10map_node_sIiiES6_+0x28>
            if (current->key == key)
6317ff36:   680b        ldr r3, [r1, #0]
6317ff38:   6806        ldr r6, [r0, #0]
6317ff3a:   429e        cmp r6, r3
6317ff3c:   d009        beq.n   6317ff52 <_ZNSt3mapIiiE15_getMutableNodeERKiPPPSt10map_node_sIiiES6_+0x28>
                linkToChild = &parent->left;
6317ff3e:   bfc7        ittee   gt
6317ff40:   68c6        ldrgt   r6, [r0, #12]
6317ff42:   f100 040c   addgt.w r4, r0, #12
                linkToChild = &parent->right;
6317ff46:   6906        ldrle   r6, [r0, #16]
6317ff48:   f100 0410   addle.w r4, r0, #16
    map_node_s<KEY, VALUE> * _getMutableNode(
6317ff4c:   4605        mov r5, r0
6317ff4e:   4630        mov r0, r6
6317ff50:   e7f0        b.n 6317ff34 <_ZNSt3mapIiiE15_getMutableNodeERKiPPPSt10map_node_sIiiES6_+0xa>

Что-то не так с созданной компилятором сборкой?

Есть ли дополнительные директивы asm, которые я могу вставить, чтобы попытаться проверить наличие проблем с выполнением?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...