Использование IACA с несборной процедурой
Я играл с IACA (статический анализатор кода Intel).
Он отлично работает при тестировании с фрагментами сборки, где я могу ввести байты magic marker вручную, например:
procedure TSlice.BitSwap(a, b: integer);
asm
//RCX = self
//edx = a
//r8d = b
mov ebx, 111 // Start IACA marker bytes
db $64, $67, $90 // Start IACA marker bytes
xor eax, eax
xor r10d, r10d
mov r9d, [rcx] // read the value
mov ecx,edx // need a in cl for the shift
btr r9d, edx // read and clear the a bit
setc al // convert cf to bit
shl eax, cl // shift bit to ecx position
btr r9d, r8d // read and clear the b bit
mov ecx, r8d // need b in ecx for shift
setc r10b // convert cf to bit
shl r10d, cl // shift bit to edx position
or r9d, eax // copy in old edx bit
or r9d, r10d // copy in old ecx bit
mov [r8], r9d // store result
ret
mov ebx, 222 // End IACA marker bytes
db $64, $67, $90 // End IACA marker bytes
end;
Существует ли способ префиксации / суффикса несборного кода с требуемыми маркерами magic, чтобы я мог анализировать сгенерированный компилятором код?
я знаю, что могу скопировать-вставить сгенерированную сборку из представления CPU и создать процедуру, используя ее, но я надеялся, что есть более простой рабочий процесс
EDIT
Я ищу решения, которые работают в 64-битном компиляторе. Я знаю, что могу смешивать ассемблер и обычный код в 32-битном компиляторе.
Обновить
Предложение @Dsm работает.
Трюк @ rudy's этого не делает.
Работает следующий фиктивный код:
Throughput Analysis Report
--------------------------
Block Throughput: 13.33 Cycles Throughput Bottleneck: Dependency chains (possibly between iterations)
Port Binding In Cycles Per Iteration:
---------------------------------------------------------------------------------------
| Port | 0 - DV | 1 | 2 - D | 3 - D | 4 | 5 | 6 | 7 |
---------------------------------------------------------------------------------------
| Cycles | 1.3 0.0 | 1.4 | 1.0 1.0 | 1.0 1.0 | 0.0 | 1.4 | 2.0 | 0.0 |
---------------------------------------------------------------------------------------
N - port number or number of cycles resource conflict caused delay, DV - Divider pipe (on port 0)
D - Data fetch pipe (on ports 2 and 3), CP - on a critical path
F - Macro Fusion with the previous instruction occurred
* - instruction micro-ops not bound to a port
^ - Micro Fusion happened
# - ESP Tracking sync uop was issued
@ - SSE instruction followed an AVX256/AVX512 instruction, dozens of cycles penalty is expected
X - instruction not supported, was not accounted in Analysis
| Num Of | Ports pressure in cycles | |
| Uops | 0 - DV | 1 | 2 - D | 3 - D | 4 | 5 | 6 | 7 | |
---------------------------------------------------------------------------------
| 3^ | 0.3 | 0.3 | 1.0 1.0 | | | 0.3 | 1.0 | | CP | ret
| X | | | | | | | | | | int3
[... more int3's]
| X | | | | | | | | | | int3
| 1 | 1.0 | | | | | | | | | shl eax, 0x10
| 1 | | 0.6 | | | | 0.3 | | | | cmp eax, 0x64
| 3^ | | 0.3 | | 1.0 1.0 | | 0.6 | 1.0 | | CP | ret
| X | | | | | | | | | | int3
| X | | | | | | | | | | int3
[...]
Total Num Of Uops: 8
Обновление 2
Если там есть оператор вызова, IACA, похоже, бомбит и не хочет анализировать код. Жалуются на незаконные инструкции. Однако ... основная идея работает. Очевидно, что вам нужно вычесть начальную ret
и связанную с ней стоимость.
1 ответ:
Я не использую IACA, поэтому я не могу проверить эту идею, и я удалю ответ, если он не работает, но не можете ли вы просто сделать что-то вроде этого:
procedure TForm10.Button1Click(Sender: TObject); begin asm //RCX = self //edx = a //r8d = b mov ebx, 111 // Start IACA marker bytes db $64, $67, $90 // Start IACA marker bytes end; fRotate( fLine - Point(0,1), 23 ); asm mov ebx, 222 // End IACA marker bytes db $64, $67, $90 // End IACA marker bytes end; end;
Это был просто образец процедуры из чего-то другого, чтобы проверить, что он компилирует, что он и делает.
К сожалению, это работает только для 32 бит - как указывает Йохан, это не разрешено для 64 бит.
Для 64 бит следующее может работать,но снова я не могу проверить его.
procedure TForm10.Button1Click(Sender: TObject); procedure Test1; asm //RCX = self //edx = a //r8d = b mov ebx, 111 // Start IACA marker bytes db $64, $67, $90 // Start IACA marker bytes end; procedure Test2; begin fRotate( fLine - Point(0,1), 23 ); end; procedure Test3; asm mov ebx, 222 // End IACA marker bytes db $64, $67, $90 // End IACA marker bytes end; begin Test1; Test2; Test3; end;