Поиск ненужных буферных копий в ассемблерном коде - PullRequest
3 голосов
/ 26 апреля 2011

Я использую Visual Studio 2008 C ++ для Windows Mobile 6 ARMV4I и пытаюсь научиться читать код сборки ARM, сгенерированный VS, чтобы минимизировать ненужные копии буфера в приложении. Итак, я создал тестовое приложение, которое выглядит так:

#include <vector>

typedef std::vector< BYTE > Buf;

class Foo
{
public:
    Foo( Buf b ) { b_.swap( b ); };
private:
    Buf b_;
};

Buf Create()
{
    Buf b( 1024 );
    b[ 0 ] = 0x0001;
    return b;
}

int _tmain( int argc, _TCHAR* argv[] )
{
    Foo f( Create() );
    return 0;
}

Я хотел бы понять, копируется ли буфер, возвращаемый Create, когда передается конструктору Foo, или компилятор может оптимизировать эту копию. В сборке выпуска с включенными оптимизациями создается сборка, подобная этой:

class Foo
{
public:
    Foo( Buf b ) { b_.swap( b ); };
0001112C  stmdb       sp!, {r4 - r7, lr} 
00011130  mov         r7, r0 
00011134  mov         r3, #0 
00011138  str         r3, this 
0001113C  str         r3, [r7, #4] 
00011140  str         r3, [r7, #8] 
00011144  ldr         r3, this 
00011148  ldr         r2, this 
0001114C  mov         r5, r7 
00011150  mov         r4, r1 
00011154  str         r3, this, #4 
00011158  str         r2, this, #4 
0001115C  mov         r6, r1 
00011160  ldr         r2, this 
00011164  ldr         r3, this 
00011168  mov         lr, r7 
0001116C  str         r3, this 
00011170  str         r2, this 
00011174  ldr         r2, [lr, #8]! 
00011178  ldr         r3, [r6, #8]! 
0001117C  str         r3, this 
00011180  str         r2, this 
00011184  ldr         r3, this 
00011188  movs        r0, r3 
0001118C  beq         |Foo::Foo + 0x84 ( 111b0h )| 
00011190  ldr         r3, [r1, #8] 
00011194  sub         r1, r3, r0 
00011198  cmp         r1, #0x80 
0001119C  bls         |Foo::Foo + 0x80 ( 111ach )| 
000111A0  bl          000112D4 
000111A4  mov         r0, r7 
000111A8  ldmia       sp!, {r4 - r7, pc} 
000111AC  bl          |stlp_std::__node_alloc::_M_deallocate ( 11d2ch )| 
000111B0  mov         r0, r7 
000111B4  ldmia       sp!, {r4 - r7, pc} 
--- ...\stlport\stl\_vector.h -----------------------------
// snip!
--- ...\asm_test.cpp
    private:
        Buf b_;
    };

Buf Create()
{
00011240  stmdb       sp!, {r4, lr} 
00011244  mov         r4, r0 
    Buf b( 1024 );
00011248  mov         r1, #1, 22 
0001124C  bl          |    
    b[ 0 ] = 0x0001;
00011250  ldr         r3, [r4] 
00011254  mov         r2, #1 
    return b;
}

int _tmain( int argc, _TCHAR* argv[] )
{
00011264  str         lr, [sp, #-4]! 
00011268  sub         sp, sp, #0x18 
    Foo f( Create() );
0001126C  add         r0, sp, #0xC 
00011270  bl          |Create ( 11240h )| 
00011274  mov         r1, r0 
00011278  add         r0, sp, #0 
0001127C  bl          |Foo::Foo ( 1112ch )| 
    return 0;
00011280  ldr         r0, argc 
00011284  cmp         r0, #0 
00011288  beq         |wmain + 0x44 ( 112a8h )| 
0001128C  ldr         r3, [sp, #8] 
00011290  sub         r1, r3, r0 
00011294  cmp         r1, #0x80 
00011298  bls         |wmain + 0x40 ( 112a4h )| 
0001129C  bl          000112D4 
000112A0  b           |wmain + 0x44 ( 112a8h )| 
000112A4  bl          |stlp_std::__node_alloc::_M_deallocate ( 11d2ch )| 
000112A8  mov         r0, #0 
}

Какие шаблоны можно найти в коде сборки, чтобы понять, куда копируется структура Buf?

Ответы [ 2 ]

0 голосов
/ 30 апреля 2011

Анализ Create довольно прост, потому что код очень короткий. Здесь явно применяется NRVO, потому что инструкция return не генерирует инструкций, возвращаемое значение создается на месте в r0.

Копия, которая будет иметь место для параметра передачи по значению Foo::Foo, немного сложнее проанализировать, но между вызовами Create и Foo::Foo, где должна быть сделана копия, очень мало кода место, и ничего, что сделало бы глубокую копию std::vector. Похоже, что эта копия также была удалена. Другая возможность - пользовательское соглашение о вызовах для Foo::Foo, когда аргумент фактически передается по ссылке и копируется внутри функции. Вам нужен кто-то, способный к более глубокому анализу сборки ARM, который я должен исключить.

0 голосов
/ 30 апреля 2011

Буфер будет скопирован;вы используете семантику передачи по значению в c ++;никакой компилятор не оптимизирует это для вас.То, как его скопировать, будет зависеть от конструктора копирования std :: vector.

...