1. C++ / Говнокод #24032

    +2

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    // We have to put a separate function with 'if constexpr' here as Visual Studio
    // produces a false positive warning in a case of RegDstUInt == uint32
    // (shifting uint32 left by 32 is an undefined behavior)
    // See: https://developercommunity.visualstudio.com/content/problem/225040/c4293-false-positive-on-unreacheable-code.html
    static RegDstUInt get_hi_part( RegDstUInt value)
    {
        // Clang-Tidy generates a false positive 'misc-suspicious-semicolon' warning
        // on `if constexpr ()` with template
        // LLVM bug 35824: https://bugs.llvm.org/show_bug.cgi?id=35824
        if constexpr( (sizeof(RegDstUInt) > 4)
            return value >> 32; // NOLINT
    
        // GCC bug 81676 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81676
        // Wrong warning with unused-but-set-parameter within 'if constexpr'
        (void)(value); 
        return 0;
    }

    В попытке починить сборку в Visual Studio поломали GCC и Clang-Tidy.

    Запостил: pavelmips, 29 Марта 2018

    Комментарии (25) RSS

    • P. S. В строке 10 лишняя скобка (опечатался при раскрытии константы)
      Ответить
    • > false positive warning
      Ну нихуя себе false positive. Сдвиг 32-битного числа на 32 -- самый настоящий UB.

      З.Ы. Или всё-таки implementation defined (лень стандарт с мобилы листать). Впрочем, это ничего не меняет.
      Ответить
      • Никто не спорит, что это UB. Потому и добавлена проверка, чтобы так с числами с sizeof <= 4 не делать
        Ответить
        • Странно, что кому-то вообще понадобился 32-битный high part для чисел <= 32 бит. Горе от ума какое-то, имхо.
          Ответить
          • а это шаблон, у него RegDstUInt прилетает из параметра
            Ответить
            • Да просто разбиение на high part и low part с жёстко зафиксированным размером low part на 32 бита как бы намекает, что работа всегда идёт с 64-битным числом. А если число подразумевается 64-битное, то почему бы именно так и не написать (кастом перед разбиением, к примеру)? И не будет всех этих костылей. И даже пирфоманс не упадёт при включенной оптимизации.
              Ответить
              • > что работа всегда идёт с 64-битным числом

                да, но тогда нужно будет делать разные функции для работы с 64-битными и 32-битными числами — тот же костыль. а здесь до начала педантичной борьбы с ворнингами был очень простой код: foo( HAS_32_BIT ? val >> 32 : 0);

                > кастом перед разбиением

                есть случай с RegDstUInt == uint128, так что без костыля тоже не получитcя
                Ответить
                • > uint128
                  Но блин, оно же вернёт старшие 96 бит... Каким алгоритмам нужно такое странное разбиение?
                  Ответить
                  • это код из модели регистрового файла для симулятора процессора, в котором статически можно выбрать между MIPS и RISC-V — на модели кэшей, бренч предиктора и прочего это не влияет.

                    у MIPS32 умножение пишет 64 бита в два 32-битных регистра. у RISCV128 команды пишут 128 бит в один 128-битный регистр (умножение пока опустим). эта разбивалка вызывается, только если класс регистрового файла инстанцирован под MIPS
                    Ответить
                    • Зачем регистровый файл занимается разбиениями? Это же задача конкретных команд (а они на все 146% уверены в разрядности своих операндов).
                      Ответить
                      • так тоже можно сделать, у класса команды будут два метода: "получить результат 1" и "получить результат 2". но помимо регистрового файла, есть ещё модель байпасов между стадиями конвейера, и там тоже всё придётся удваивать
                        Ответить
                        • Но ведь в реальном проце одна половинка результата может пойти по байпассу, а вторая -- нет (т.к. пока никому не нужна)? Т.е. там всё равно должна быть какая-то логика с разбиением результата (раз команда это не сделала сразу)... Или я туплю?

                          З.Ы. Проект опенсурсный?
                          Ответить
                          • > одна половинка результата может пойти по байпассу, а вторая -- нет (т.к. пока никому не нужна)?

                            тогда надо понять, какая нужна, а какая нет)
                            при делении в lo пишется частное, в hi остаток — что нужно последующему коду, надо успеть понять.

                            > З.Ы. Проект опенсурсный?

                            да
                            Ответить
                            • > да
                              Можно линк?
                              Ответить
                            • Кстати, а мипс обе половинки одновременно сохраняет в регистры или же одна откладывается на следующий такт?
                              Ответить
                              • это уже детали микроархитектуры. в каких-то процессорах могут за один, в каких-то нет. если процессор out-of-order superscalar, вроде R10000, то он скорее всего умеет делать параллельно несколько записей от разных команд (двух-трёх)
                                Ответить
                          • в любом случае, мы хотим сделать универсальную модель, которую потом можно будет к реальному железу приближать путём отрезания фич
                            Ответить
      • > Сдвиг 32-битного числа на 32 -- самый настоящий UB

        Зачем?
        Ответить
        • Отсылочка к устройству barrel shifter'а у большинства процов -- лишние биты тупо отбрасываются чтобы не усложнять схему и сдвиг 32-битного числа на 32 превращается в сдвиг на 0, на 33 - в сдвиг на 1 и т.п.

          А UB тут нужен чтобы конпелятору не приходилось втыкать костыли и замедлять код если величина сдвига берётся из переменной.
          Ответить
          • Костыли на процы? Типа одни процы обрезают, а другие нет?
            Ответить
            • Ну да, если в стандарте написать "получится 0" или "лишние биты проебутся", то под какие-то процы придётся генерить плохой код. А крестостандартизаторы такое не любят.

              Плюс те же восьмибитные числа обычно апкастятся до слова, и может выйти забавная ситуация - сдвиг на 9 даст 0, а сдвиг на 33 будет выглядеть как сдвиг на 1.
              Ответить
    • Сколько ненужного говна, только чтобы заткнуть ворнинги? И столько коментов, чтобы обьяснить эти затычки? Для функции, которая не делает нихуя?
      Ответить
      • удобно, чтобы быстро проверить, починили ли баги, и убрать костыли при необходимости
        Ответить
    • Я бы прагмами ворнинги заткнул.

      "shift count negative or too big, undefined behavior!" — раздался пронзительный голос со стороны параши.

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

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

    Добавить комментарий