2016-10-19 16 views
5

Có lẽ đây là tất cả về thậm chí không vi mô nhưng nanooptimizations, nhưng đối tượng quan tâm đến tôi và tôi muốn biết nếu có bất kỳ hình phạt khi sử dụng kích thước đăng ký không phải bản địa trong chế độ dài?Có thể có bất kỳ hình phạt nào khi sử dụng thanh ghi 64/32-bit ở chế độ Dài không?

Tôi đã học được từ nhiều nguồn khác nhau, việc cập nhật một phần đăng ký (như ax thay vì eax) có thể khiến hiệu suất của eflags bị ngừng và làm suy giảm hiệu suất. Nhưng tôi không chắc về chế độ dài. Kích thước đăng ký nào được coi là nguyên gốc cho chế độ hoạt động của bộ xử lý này? x86-64 vẫn là phần mở rộng cho kiến ​​trúc x86, do đó tôi tin rằng 32 bit vẫn là bản địa. Hoặc là tôi sai?

Ví dụ, hướng dẫn như

sub eax, r14d 

hoặc

sub rax, r14 

có cùng kích thước, nhưng có thể có được bất kỳ hình phạt khi sử dụng một trong những? Có thể có bất kỳ hình phạt nào khi trộn kích cỡ đăng ký trong các hướng dẫn liên tiếp như dưới đây không? (Giả sử dword cao là zero trong mọi trường hợp)

sub ecx, eax 
sub r14, rax 
+0

Có các hình phạt cho quyền truy cập 16 bit. Sử dụng thanh ghi 32 bit và tránh r8-r15 là OK và trên thực tế thường dẫn đến kích thước mã nhỏ hơn. –

+4

Việc ghi vào thanh ghi 32 bit sẽ tự động xóa 32 bit trên cùng, do đó tránh được vấn đề cập nhật từng phần. – Jester

+0

Đăng ký EFLAGS được ảo hóa rất nhiều trong các bộ vi xử lý hiện đại. Giống như tất cả các thanh ghi. Nhất thiết như vậy, quá nhiều hướng dẫn sửa đổi nó và đó là một damper lớn về thực hiện siêu vô hướng. Những gì còn thiếu trong mã của bạn là một lệnh thực sự * sử dụng * thanh ghi. Vì vậy, không có lý do thuyết phục nào để bộ xử lý khóa và khóa mã bạn đăng. Không bao giờ lấy ý kiến ​​của ai đó về cách nó nên/có thể làm việc. Điểm duy nhất để viết mã assembly là làm cho nó nhanh hơn trình biên dịch C. Đo. –

Trả lời

8

có thể là bất kỳ hình phạt khi trộn 32 và kích thước đăng ký 64-bit trong hướng dẫn liên tiếp?

No, writing to a 32-bit register always zero-extends to the full register, vì vậy x86-64 tránh mọi hình phạt đăng ký một phần cho lệnh 32 và 64 bit.

vì vậy tôi tin rằng 32 bit vẫn là nguồn gốc.

Có, kích thước mặc định là 32 bit cho hầu hết các hướng dẫn (other than PUSH/POP). 64-bit cần tiền tố REX với bit W được đặt thành 1. Vì vậy, thích 32-bit vì lý do kích thước mã. Đây là lý do tại sao trình biên dịch sử dụng mov r32, imm32 cho địa chỉ của dữ liệu tĩnh (vì mô hình mã mặc định yêu cầu mã và địa chỉ dữ liệu tĩnh nằm trong 2GiB thấp của không gian địa chỉ ảo).

Đó là một lựa chọn thiết kế của AMD. Họ có thể đã chọn cách khác, và yêu cầu một tiền tố để có được kích thước toán hạng 32 bit. Vì chế độ dài là một chế độ riêng biệt, mã máy x86-64 có thể khác với mã máy x86-32 nhưng nó muốn. AMD đã chọn để giảm thiểu sự khác biệt để họ có thể chia sẻ càng nhiều bóng bán dẫn càng tốt trong bộ giải mã. Kết luận của bạn là chính xác, nhưng lý do của bạn là hoàn toàn không có thật.


cập nhật đăng ký từng phần (như rìu thay vì eax) có thể gây ra gian hàng eflags và suy giảm hiệu suất.

Quầy cờ một phần riêng biệt với các quầy đăng ký một phần. Chúng được xử lý tương tự trong nội bộ (các phần được đổi tên riêng của EFLAGS phải được hợp nhất giống như một AX đã sửa đổi phải được hợp nhất với các byte trên chưa sửa đổi của EAX). Nhưng một không gây ra khác.

# partial-reg stall 
setcc al   # leaves the upper 3 (or 7) bytes unmodified 
add  edx, eax  # reads full EAX. Older CPUs stall while merging 

Zeroing EAX ahead of the flag-setting and setcc with xor eax,eax avoids the partial-register penalty entirely. (Core2/Nehalem quầy hàng cho chu kỳ ít hơn so với CPU trước đó, nhưng vẫn còn gian hàng cho 2 hoặc 3c trong khi chèn một uop sáp nhập.Sandybridge không dừng lại ở tất cả trong khi chèn uop sáp nhập).

(Một bản tóm tắt các hình phạt đăng ký một phần trên các CPU khác nhau: Why doesn't GCC use partial registers?, nói về cơ bản giống nhau).

AMD không bị các quầy đăng ký từng phần khi đọc toàn bộ sổ đăng ký sau đó, nhưng thay vào đó ghi một phần ghi và đọc có phụ thuộc sai trên thanh ghi đầy đủ. (CPU AMD không đổi tên riêng các sổ đăng ký phụ ở vị trí đầu tiên. Intel P4 và Silvermont/Knight's Landing cũng giống như vậy.)

Intel Haswell/Skylake (và có thể Ivybridge) không đổi tên al riêng biệt rax tại tất cả, vì vậy chúng không bao giờ cần hợp nhất các thanh ghi low8/low16. Nhưng setcc al có sự phụ thuộc sai về giá trị cũ. Họ vẫn đổi tên và hợp nhất ah. (Details on HSW/SKL partial-reg performance.)


# partial flag stall when reading a flag that didn't come from 
# the last instruction to write any flags. 
clc 
# edi and esi = one-past-the-end of dst and src 
# ecx = -count 
bigInt_add: 
    mov eax, [esi+ecx*4] 
    adc [edi+ecx*4], eax # reads CF, partial flag stall on 2nd and later iterations 
    inc ecx    # writes all flags except CF 
    jl bitInt_add   # loop upwards towards zero 

Xem this Q&A để thảo luận thêm về phần-cờ vấn đề về Intel trước Sandybridge vs Sandybridge.


Xem thêm Agner Fog's microarch pdf, và các liên kết khác trong thẻ wiki để biết thêm chi tiết về tất cả điều này.

+0

Cảm ơn bạn rất nhiều –

Các vấn đề liên quan