Как оптимизировать код для доступа к элементу std :: tuple? - PullRequest
0 голосов
/ 01 мая 2020

Я пытаюсь добавить некоторые обобщения в проект C ++, поэтому я использую std :: tuple для хранения полей.

Я исследую разницу в коде ассемблера между std :: get <1> (myClass. myTuple) .read () и myClass.myField.read (). Я использую ARM GNU Toolchain 9.2 и процессор ARM-M4F.

myField.read () скомпилирован как:

9A02                ldr        r2, [r13, #8]
E71F                b          #0x16a0

, что очевидно и ожидаемо.

Хотя std :: get <1> (myTuple) .read () компилируется следующим образом:

9B82                ldr        r3, [r13, #0x208]
695B                ldr        r3, [r3, #0x14]
42AB                cmp        r3, r5
D11B                bne        #0x1a3c

F8BD0210            ldrh.w     r0, [r13, #0x210]
E761                b          #0x1792

Теоретически std :: get должен оцениваться во время компиляции, и результат должен быть одинаковым в обоих случаях .

По какой причине мы получаем это дополнительное сравнение?

9B82                ldr        r3, [r13, #0x208]
695B                ldr        r3, [r3, #0x14]
42AB                cmp        r3, r5
D11B                bne        #0x1a3c

Я не могу найти ситуацию, когда код следует за этой ветвью.

Что я могу сделать, чтобы упростить этот код?

Могу ли я что-то изменить в своем коде C ++, чтобы получить результат, эквивалентный прямому доступу к полю (myField.read ())?

Как заставить компилятор не генерировать это дополнительный кусок кода?

Любая помощь приветствуется.

Ниже я приложил минимальный воспроизводимый пример.

class Base {
public:
    virtual uint32_t read1() const = 0;
    virtual void write1(const uint32_t n) = 0;
};

class Neighbor : public Base {
public:
    uint32_t read_val1 = 1;

    uint32_t read1() const {
        return read_val1;
    }
    void write1(const uint32_t n) {
        read_val1 = n;
    }
};

struct Abc1 {

    std::tuple<Neighbor, Neighbor, Neighbor, Neighbor, Neighbor, Neighbor, Neighbor, Neighbor, Neighbor, Neighbor> att;

    Abc1() : att (
               Neighbor(),
               Neighbor(),
               Neighbor(),
               Neighbor(),
               Neighbor(),
               Neighbor(),
               Neighbor(),
               Neighbor(),
               Neighbor(),
               Neighbor()
           ) {}

    uint32_t read1(uint32_t index) {
        switch(index){
        case 0:
            return std::get < 0 > (att).read1();
        case 1:
            return std::get < 1 > (att).read1();
        case 2:
            return std::get < 2 > (att).read1();
        case 3:
            return std::get < 3 > (att).read1();
        case 4:
            return std::get < 4 > (att).read1();
        case 5:
            return std::get < 5 > (att).read1();
        case 6:
            return std::get < 6 > (att).read1();
        case 7:
            return std::get < 7 > (att).read1();
        case 8:
            return std::get < 8 > (att).read1();
        case 9:
            return std::get < 9 > (att).read1();
        }
        return 0;
    }

    void write1(uint32_t index, uint32_t n) {
        switch(index){
        case 0:
            std::get < 0 > (att).write1(n);
            break;
        case 1:
            std::get < 1 > (att).write1(n);
            break;
        case 2:
            std::get < 2 > (att).write1(n);
            break;
        case 3:
            std::get < 3 > (att).write1(n);
            break;
        case 4:
            std::get < 4 > (att).write1(n);
            break;
        case 5:
            std::get < 5 > (att).write1(n);
            break;
        case 6:
            std::get < 6 > (att).write1(n);
            break;
        case 7:
            std::get < 7 > (att).write1(n);
            break;
        case 8:
            std::get < 8 > (att).write1(n);
            break;
        case 9:
            std::get < 9 > (att).write1(n);
            break;
        }
        return;
    }
};

int main(){
    volatile uint32_t no = 0;
    for(volatile int j = 0; j<10000; j++){
        no += abc1.read1(j%10);
        abc1.write1(j%10, no);
    }
}

/ Адам

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