На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Обязан ли компилятор читать volatile , переменную ?
    допустим имеем
    volatile int *pMachineRegister;

    void SomeFoo()
    {
    int dummyVar = *pMachineRegister;
    }
    Переменная dummyVar нигде больше не используется, этот код написан для того, чтобы компилятор все-таки произвел чтение volatile регистра. Просто на целевой машине чтение этого регистра влияет на состояние процессора, о чем компилятор, естественно не знает. Понятно что лучше бы dummyVar сделать тоже volatile, тогда чтение точно произойдет. Но вопрос именно стандарта - должен ли компилятор производить чтение volatile переменной, если результат его не интересут.
      Цитата DmitryRyvkin @
      Но вопрос именно стандарта - должен ли компилятор производить чтение volatile переменной, если результат его не интересут.

      Думаю, должен:
      Цитата
      -6- The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions.*

      [Footnote: An implementation can offer additional library I/O functions as an extension. Implementations that do so should treat calls to those functions as ``observable behavior'' as well. --- end foonote]
      -7- Accessing an object designated by a volatile lvalue (basic.lval), modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment.

      Раз состояние среды выполнения меняется при чтении volatile - оптимизатор не имеет права трогать это чтение.
        Гм. На двух компиляторах проверяли, один читает, другой нет (GCC). Компиляторы для микроконтроллеров, но сути дела это менять не должно..
          Стандарт С++ освещает это тему слабо, ссылаясь на Стандарт С. В нём же:
          Цитата
          An object that has volatile-qualified type may be modified in ways unknown to the
          implementation or have other unknown side effects. Therefore any expression referring
          to such an object shall be evaluated strictly according to the rules of the abstract machine,
          as described in 5.1.2.3.
          .....
          A volatile declaration may be used to describe an object corresponding to a memory-mapped
          input/output port or an object accessed by an asynchronously interrupting function. Actions on
          objects so declared shall not be ‘‘optimized out’’ by an implementation or reordered except as
          permitted by the rules for evaluating expressions.
          .....
          In the abstract machine, all expressions are evaluated as specified by the semantics. An
          actual implementation need not evaluate part of an expression if it can deduce that its
          value is not used and that no needed side effects are produced (including any caused by
          calling a function or accessing a volatile object).
            Цитата DmitryRyvkin @
            Гм. На двух компиляторах проверяли, один читает, другой нет (GCC).


            Попробуйте отключить оптимизацию. А лучше поэкспериментировать
            с уровнем оптимизации.

            В крайнем случае компилятор можно обмануть.
            (хотя это и не лучший способ)
            Например написать "довольно сложный" алгоритм использующий
            эту волатиле-переменную. Но при выполнении некого условия..
            которое никогда не наступит(а это только вам известно).
            В результате компилер не сможет вообще такую переменную игнорировать.
              Цитата SergI @
              В крайнем случае компилятор можно обмануть.
              (хотя это и не лучший способ)
              Например написать "довольно сложный" алгоритм использующий
              эту волатиле-переменную. Но при выполнении некого условия..
              которое никогда не наступит(а это только вам известно).
              В результате компилер не сможет вообще такую переменную игнорировать.

              Зачем извращаться-то?
              Автор сам предложил решение:
              ExpandedWrap disabled
                volatile int dummyVar = *pMachineRegister;
                Цитата Hryak @
                Автор сам предложил решение:


                В том то и дело, что это не решение.
                Некоторые компиляторы (особенно для эмбеддед, IAR например) при высоких уровнях
                оптимизации начинают выбрасывать (физичеки) целые куски процедур.
                В тех случаях, когда результаты их деятельности нигде потом не используются.
                Это можно понять - у "мелких" процессоров ресурсы весьма ограничены, и незачем
                использовать их "впустую".

                Ситуаци у DmitryRyvkin-а требует прочтения регистра "для чего то там и фсе".
                Так надо.
                Компилер видит, что результат не используется и выбрасывает кусок кода.

                Менять уровень оптимизации всего модуля или всего проекта - тоже не всегда "гут".
                Чтобы найти оптимум можно попробовать вынести эту операцию в отдельный
                программный модуль. И компилить только этот модуль без оптимизации.
                ;)
                  Или только
                  ExpandedWrap disabled
                    asm ("push r16");
                    asm ("lds r16, pMachineRegister");
                    asm ("lds r16, pMachineRegister + 1");
                    asm ("pop r16");

                  100 % гарантия, что будет правильно работать при любых уровнях оптимизации.
                    Цитата SergI @
                    Некоторые компиляторы (особенно для эмбеддед, IAR например) при высоких уровнях
                    оптимизации начинают выбрасывать (физичеки) целые куски процедур.
                    В тех случаях, когда результаты их деятельности нигде потом не используются.

                    И компиляторы для невстроенных систем запросто могут выкинуть многое.
                    Однако,
                    ExpandedWrap disabled
                      volatile int i;
                      i = 8;
                    тронуть не могут. Не вижу смысла и прочим компиляторам "оптимизировать" присваивание, нарушая Стандарт. Т.к. нифига на этом не сэкономишь - volatile не так уж и часто употребляется, а если употребляется - то программист хочет именно отключения агрессивной оптимизации в этом участке кода.
                      ууу, тут я тоже вижу эмбеддеры есть бывшие :-) Вобщем смутный вопросик...
                        Цитата Hryak @
                        Однако,
                        ExpandedWrap disabled
                          volatile int i;
                          i = 8;
                        тронуть не могут.


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

                        Цитата DmitryRyvkin

                        тут я тоже вижу эмбеддеры есть бывшие


                        Почему "бывшие" ? ;) Как раз наоборот.
                        Припоминаю - Вы навещали Телесистемы.
                        :D :D :D
                          Кстати да, бывший эмбеддер - такой же оксиморон, как бывший наркоман.
                            SergI
                            Чего-то я плохо понимаю, чего ты тут хочешь сказать.

                            Цитата
                            volatile - запрещение регистровой "оптимизации" для данной переменной.
                            Какое-то попсовое определение. Повторю еще раз:
                            Цитата
                            An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects.

                            Unknown side effects, понимаешь?

                            Цитата
                            Никакого отношения к уровню оптимизации программы
                            компилером "вообще" это не имеет.
                            volatile действует при любых уровнях оптимизации.
                            И не является причиной для отказа в оптимизации по любым
                            другим критериям.

                            Бесспорно, объявление чего-то volatile не влияет на оптимизицию всего кода программы, но не относящегося непосредственно к доступу к volatile-объектам.
                            Если написано:
                            ExpandedWrap disabled
                              volatile int *pMachineRegister;
                              ....
                              volatile int dummyVar;
                              .....
                              dummyVar = *pMachineRegister;
                              ......
                            то компилятор может выкинуть все выше и ниже, но код от строки dummyVar = *pMachineRegister; оставить обязан.
                              SergI и сейчас навещаю, как DASM :-)) Вобщем всем спасибо за ответы !!
                                Между прочим, а кто действующие лица? (Компилятор, версия его, дивайс)?
                                Тока што попробовал с тем же avr-gcc:
                                ExpandedWrap disabled
                                  volatile int * const r = 300;  
                                    
                                  int main ()
                                     {
                                     int tmp;
                                     for (;;)
                                        tmp = *r;
                                     return 0;
                                     }

                                компиляция:
                                avr-gcc -S -O3 -mmcu=atmega16 test.c
                                test.s:
                                ExpandedWrap disabled
                                  ;.....
                                  main:
                                  /* prologue: frame size=0 */
                                      ldi r28,lo8(__stack - 0)
                                      ldi r29,hi8(__stack - 0)
                                      out __SP_H__,r29
                                      out __SP_L__,r28
                                  /* prologue end (size=4) */
                                  .L2:
                                      lds r24,300
                                      lds r25,(300)+1
                                      rjmp .L2

                                еще раз компиляция:
                                arm-elf-gcc -S -O3 test.c
                                ExpandedWrap disabled
                                  main:
                                      @ args = 0, pretend = 0, frame = 0
                                      @ frame_needed = 0, uses_anonymous_args = 0
                                      @ link register save eliminated.
                                      @ lr needed for prologue
                                      mov r2, #300
                                  .L2:
                                      ldr r3, [r2, #0]
                                      ldr r3, [r2, #0]
                                      b   .L2
                                      .size   main, .-main
                                      .ident  "GCC: (GNU) 3.4.3"

                                - без комментариев
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0413 ]   [ 16 queries used ]   [ Generated: 27.04.24, 16:28 GMT ]