Может ли указатель когда-либо указывать на регистр процессора? - PullRequest
4 голосов
/ 15 октября 2010

Мне интересно, может ли указатель указывать на регистр процессора, поскольку в этом случае использование указателя вместо указателя, где это возможно, даст возможность компилятору выполнить некоторые оптимизации, поскольку объект, на который ссылаются, может находиться в каком-то регистре, но объект, на который указывает указатель, не может.

Ответы [ 7 ]

9 голосов
/ 15 октября 2010

Как правило, регистры ЦП не имеют адресов памяти, хотя архитектура ЦП могла бы сделать их адресуемыми (я не знаком с ними - если кто-то знает один, я был бы признателен за комментарий).Однако в C нет стандартного способа получить адрес регистра.Фактически, если вы помечаете переменную классом хранения register, вам не разрешается брать адрес этой переменной с помощью оператора &.

Ключевой вопрос заключается в наложении псевдонимов - если компилятор может определить, чтообъект не является псевдонимом, тогда он обычно может выполнять оптимизацию (доступ к объекту осуществляется через указатель или ссылку).Я не думаю, что вы получите какую-либо выгоду от оптимизации, используя ссылку на указатель (в общем случае).

Однако, если вы скопируете объект в локальную переменную, компилятор может сделать более простое определение, чтонет никакого намека на местное, если вы не передаете временный адрес.Это тот случай, когда вы можете помочь компилятору оптимизировать;однако, если операция копирования стоит дорого, в конце она может не окупиться.

Для чего-то, что могло бы поместиться в регистр ЦП, копирование во временную папку часто является хорошим способом - компиляторы хороши в оптимизациите к регистрам.

3 голосов
/ 15 октября 2010

Когда ссылка передается функции, компилятор, вероятно, реализует ее как скрытый указатель - поэтому изменение типа не имеет значения.

Когда ссылка создается и используется локально, компилятор можетбыть достаточно умным, чтобы знать, к чему он относится, и рассматривать его как псевдоним указанной переменной.Если переменная оптимизирована для регистра, компилятор будет знать, что ссылка также является тем же регистром.

Указатель всегда должен указывать на область памяти.Даже на нечетной архитектуре, которая дает места памяти для его регистров, кажется маловероятным, что компилятор поддержит такую ​​операцию.

Редактировать: В качестве примера, вот сгенерированный код от MicrosoftC ++ с оптимизацией.Код для указателя и переданной ссылки идентичны.Параметр, передаваемый по значению, по какой-то причине не попал в регистр, даже когда я переставил список параметров.Тем не менее, после того, как значение было скопировано в регистр, и локальная переменная, и локальная ссылка использовали один и тот же регистр без перезагрузки.

void __fastcall test(int i, int * ptr, int & ref)
{
_i$ = 8                         ; size = 4
_ref$ = 12                      ; size = 4
?test@@YIXHPAHAAH@Z PROC                ; test, COMDAT
; _ptr$ = ecx

; 8    :    global_int1 += *ptr;

    mov edx, DWORD PTR [ecx]

; 9    : 
; 10   :    global_int2 += ref;

    mov ecx, DWORD PTR _ref$[esp-4]
    mov eax, DWORD PTR _i$[esp-4]
    add DWORD PTR ?global_int1@@3HA, edx    ; global_int1
    mov edx, DWORD PTR [ecx]
    add DWORD PTR ?global_int2@@3HA, edx    ; global_int2

; 11   : 
; 12   :    int & ref2 = i;
; 13   :    global_int3 += ref2;

    add DWORD PTR ?global_int3@@3HA, eax    ; global_int3

; 14   : 
; 15   :    global_int4 += i;

    add DWORD PTR ?global_int4@@3HA, eax    ; global_int4
2 голосов
/ 15 октября 2010

Я думаю, что вы хотели сказать, находится ли интегральное значение, на которое ссылается ссылка, в регистре.

Обычно большинство компиляторов обрабатывают ссылки так же, как указатели. То есть ссылки - это просто указатели со встроенной специальной семантикой «разыменования». Так что, к сожалению, обычно нет никакой оптимизации в отличие от целочисленных значений, которые могут вписываться в регистры. Единственное различие между ссылкой и указателем состоит в том, что ссылка должна (но не поддерживается компилятором) ссылаться на действительный объект, тогда как указатель может быть NULL.

1 голос
/ 15 октября 2010

Я бы сказал, вообще нет.Как упоминалось в приведенном выше комментарии, есть некоторые процессоры, в которых вы можете адресовать регистр в области памяти, но это, вероятно, плохая идея (если микросхема не была разработана для вас, чтобы программировать ее таким образом).

Этобольше похоже на то, что происходит на самом деле.Оптимизаторы могут видеть, что вы делаете с указателем и на что он указывает, и, в зависимости от архитектуры, могут фактически не использовать регистр для указателя и регистр для хранения того, на что он указывает, но, например, могут жестко закодировать адрес в инструкции, используянет регистров вообще.Может загружать указанное значение в регистр, но использовать регистр для адреса или использовать его дольше, чем требуется для получения значения.Иногда это не так эффективно, оно может сохранить значение в регистре в оперативную память, чтобы оно могло считывать его обратно в регистр, используя его адрес, когда изменение кода позволит избежать этих двух шагов.Это сильно зависит от программы / кода и набора команд и компилятора.

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

1 голос
/ 15 октября 2010

Во многих (если не в большинстве или во всех) реализациях ссылка глубоко реализуется через указатель. Поэтому я думаю, что делать это с помощью указателя или ссылки в значительной степени не имеет значения для оптимизатора.

0 голосов
/ 15 октября 2010

Майкл Берр прав.Регистры ЦП не имеют адресов памяти.

0 голосов
/ 15 октября 2010

Указатель указывает на ячейки памяти.Поэтому невозможно получить доступ к регистрам ЦП с помощью указателей.Ссылки являются менее мощной версией указателей (вы не можете выполнять арифметику над ссылками).Однако компиляторы обычно помещают переменные в регистры для выполнения операций.Например, компилятор может поместить счетчик цикла в один из регистров ЦП для быстрого доступа.Или может поместить параметры функций, которые не занимают много места в регистрах.В C есть ключевое слово, которое вы можете использовать для запроса компилятора о внесении определенной переменной в регистр процессора.Ключевое слово: register:

for (int i = 0; i < I; i++)
    for (int j = 0; j < J; j++)
        for (register int k = 0; k < K; k++)
        {
            // to do
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...