Няшная / Говнокод #28309 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 87
  88. 88
  89. 89
  90. 90
  91. 91
  92. 92
  93. 93
  94. 94
  95. 95
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

void swap(uint8_t *x, uint8_t *y)
{
    uint8_t tmp;
    tmp = *x;
    *x = *y;
    *y = tmp;
}

// эту хуйню тоже можно нагенерировать
uint64_t cmp_bits(uint8_t a[restrict 9])
{
  return 
  ((uint64_t)(a[0] < a[1]) << 0) |
  ((uint64_t)(a[0] < a[2]) << 1) |
  ((uint64_t)(a[0] < a[3]) << 2) |
  ((uint64_t)(a[0] < a[4]) << 3) |
  ((uint64_t)(a[0] < a[5]) << 4) |
  ((uint64_t)(a[0] < a[6]) << 5) |
  ((uint64_t)(a[0] < a[7]) << 6) |
  ((uint64_t)(a[0] < a[8]) << 7) |

  ((uint64_t)(a[1] < a[2]) << 8)  |
  ((uint64_t)(a[1] < a[3]) << 9)  |
  ((uint64_t)(a[1] < a[4]) << 10) |
  ((uint64_t)(a[1] < a[5]) << 11) |
  ((uint64_t)(a[1] < a[6]) << 12) |
  ((uint64_t)(a[1] < a[7]) << 13) |
  ((uint64_t)(a[1] < a[8]) << 14) |

  ((uint64_t)(a[2] < a[3]) << 15) |
  ((uint64_t)(a[2] < a[4]) << 16) |
  ((uint64_t)(a[2] < a[5]) << 17) |
  ((uint64_t)(a[2] < a[6]) << 18) |
  ((uint64_t)(a[2] < a[7]) << 19) |
  ((uint64_t)(a[2] < a[8]) << 20) |

  ((uint64_t)(a[3] < a[4]) << 21) |
  ((uint64_t)(a[3] < a[5]) << 22) |
  ((uint64_t)(a[3] < a[6]) << 23) |
  ((uint64_t)(a[3] < a[7]) << 24) |
  ((uint64_t)(a[3] < a[8]) << 25) |

  ((uint64_t)(a[4] < a[5]) << 26) |
  ((uint64_t)(a[4] < a[6]) << 27) |
  ((uint64_t)(a[4] < a[7]) << 28) |
  ((uint64_t)(a[4] < a[8]) << 29) |

  ((uint64_t)(a[5] < a[6]) << 30) |
  ((uint64_t)(a[5] < a[7]) << 31) |
  ((uint64_t)(a[5] < a[8]) << 32) |

  ((uint64_t)(a[6] < a[7]) << 33) |
  ((uint64_t)(a[6] < a[8]) << 34) |

  ((uint64_t)(a[7] < a[8]) << 35);
}

void printshit(uint8_t a[restrict 9])
{
  size_t i = 0;
  while(*a != 4)
  {
    a++;
    i++;
  }
  printf("arr[%" PRIu64 "] = %zu\n", cmp_bits(a), i);
}

void permute(char *a, size_t l, size_t r)
{
  size_t i;
  if (l == r)
    printshit(a);
  else
  {
    for (i = l; i <= r; i++)
    {
      swap((a+l), (a+i));
      permute(a, l+1, r);
      swap((a+l), (a+i));
    }
  }
}

int main()
{
    uint8_t a[] = {0,1,2,3,4,5,6,7,8};
    size_t n = 9;
    permute(a, 0, n-1);
    return 0;
}

https://govnokod.ru/24496#comment782476

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

Запостил: j123123 j123123, (Updated )

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

  • хотя это хуйня конечно, если для 9 элементов. Вот для 7 это рациональнее будет.
    Ну и еще такое говно можно как-нибудь аппаратно реализовать
    Ответить
    • > Ну и еще такое говно можно как-нибудь аппаратно реализовать

      Борманд в прошлом треде уже показал pshufb.
      В принципе если компилятор достаточно умён он шаффлы
      typedef union
      {
          int64_t v;
          struct
          {
              int b0:8; int b1:8; int b2:8; int b3:8; int b4:8; int b5:8; int b6:8; int b7:8;
      
          };
      } MMX;

      Превратит в MMX/SSE инструкции.
      Ответить
      • > Превратит в SSE инструкции.

        Но обычно они сливают этот шанс если что-то посложнее тупого копирования (((
        Ответить
        • Обычно да. Но шланг меня приятно удивил.
          https://godbolt.org/z/EasbMjffP

          Надо будет попробовать расширить тот говнопример на произвольные размеры и шаффлы.
          Ответить
          • Да шланг тоже часто срывался в какую-то дичь если арифметику начать делать...

            Походу интринсиками ебашить -- пока единственный способ.
            Ответить
            • > Походу интринсиками ебашить -- пока единственный способ
              Почему же?

              Интринсиками непортабельно.
              А вот препроцессором имитировать PSHUFB чтобы мракос развернулся в мувы int8_t внутри структуры, тогда код будет портабельный.
              На умном компиляторе быстрый, на глупом — медленный, со сдвигами и битовыми масками.
              Ответить
              • > На умном компиляторе быстрый

                Это если он не охуеет от количества операций... Должен же быть какой-то порог в пределах которого он мёржит операции в одну.
                Ответить
                • А много и не надо.
                  8 — MMX
                  16 — SSE
                  32 — AVX-2

                  В примере выше, он легко понимает что копирования 16 элементов это сдвиг.
                  Как будет вдохновение попробую сделать тасующий регистр на препроцесоре.
                  Ответить
                • > Это если он не охуеет от количества операций...

                  Ну вот, всё работает:
                  https://godbolt.org/z/KsPq5soo9
                  #pragma pack(push,1)
                  
                  typedef union
                  {
                      int64_t v;
                      struct
                      {
                          int b0:8; int b1:8; int b2:8; int b3:8; int b4:8; int b5:8; int b6:8; int b7:8;
                      };
                  } Num;
                  
                  Num diff(Num n0, Num n1)
                  {
                      n0.b0 = -(n0.b0 > n1.b0); n0.b1 = -(n0.b1 > n1.b1); n0.b2 = -(n0.b2 > n1.b2); n0.b3 = -(n0.b3 > n1.b3); n0.b4 = -(n0.b4 > n1.b4); n0.b5 = -(n0.b5 > n1.b5); n0.b6 = -(n0.b6 > n1.b6); n0.b7 = -(n0.b7 > n1.b7);
                  
                      return n0;
                  }
                  
                  
                  diff:
                          movq    xmm0, rdi
                          movq    xmm1, rsi
                          pcmpgtb xmm0, xmm1
                          movq    rax, xmm0
                          ret

                  Осталось шуффлы напилить.
                  Ответить
            • > шланг тоже часто срывался в какую-то дичь если арифметику начать делать.
              Да, на массивах и векторах-структурах шланг городит дичь.
              А вот недавняя версия gcc 12.1 структуры векторизует хорошо, а массивы просто отлично.

              >Походу интринсиками ебашить -- пока единственный способ.
              Я по заветам Царя переделал на массивы: выхлоп стал ГОРАЗДО чище.
              https://godbolt.org/z/478cY9jP7
              GCC 11.3 и младше конечно так хорошо не умели, так что налицо прогресс.
              sort:
                      movq    xmm1, rdi
                      pshuflw xmm0, xmm1, 177
                      movdqa  xmm2, xmm0
                      pminsw  xmm0, xmm1
                      pmaxsw  xmm2, xmm1
                      movdqa  xmm3, xmm0
                      movdqa  xmm1, xmm2
                      pblendw xmm0, xmm2, 6
                      pshufb  xmm3, XMMWORD PTR .LC1[rip]
                      pshufb  xmm1, XMMWORD PTR .LC0[rip]
                      movdqa  xmm2, xmm0
                      por     xmm1, xmm3
                      pmaxsw  xmm2, xmm1
                      pminsw  xmm0, xmm1
                      movdqa  xmm1, xmm0
                      movdqa  xmm3, xmm2
                      pblendw xmm0, xmm2, 12
                      pshufb  xmm1, XMMWORD PTR .LC2[rip]
                      movdqa  xmm2, xmm0
                      pshufb  xmm3, XMMWORD PTR .LC3[rip]
                      por     xmm1, xmm3
                      pminsw  xmm2, xmm1
                      pmaxsw  xmm0, xmm1
                      pblendw xmm2, xmm0, 10
                      movq    rax, xmm2
                      ret
              .LC4:

              Правда первое перемешивание он догадался через pshuflw
              А последующие почему-то через джва pshufb.
              Ответить
              • >недавняя версия gcc 12.1 структуры векторизует хорошо, а массивы просто отлично.

                https://gcc.gnu.org/gcc-12/changes.html

                Vectorization is enabled at -O2 which is now equivalent to the original -O2 -ftree-vectorize -fvect-cost-model=very-cheap. Note that default vectorizer cost model has been changed which used to behave as -fvect-cost-model=cheap were specified.

                Интересно что даже с этими флагами прошлые версии GCC не могут нормально векторизовать код.
                Ответить
            • > Походу интринсиками ебашить -- пока единственный способ.
              Интринсики — непортабельное, трудночитаемое говно.
              А через массивы, у меня и на арме хороший векторный выхлоп получился
              sort:
                      fmov    d1, x0
                      adrp    x1, .LC0
                      adrp    x0, .LC1
                      rev32   v0.4h, v1.4h
                      ldr     d6, [x1, #:lo12:.LC0]
                      ldr     d5, [x0, #:lo12:.LC1]
                      adrp    x0, .LC2
                      ldr     d4, [x0, #:lo12:.LC2]
                      adrp    x0, .LC3
                      smax    v2.4h, v0.4h, v1.4h
                      smin    v0.4h, v0.4h, v1.4h
                      ldr     d3, [x0, #:lo12:.LC3]
                      mov     v1.8b, v2.8b
                      ins     v1.d[1], v0.d[0]
                      ins     v0.d[1], v2.d[0]
                      tbl     v1.8b, {v1.16b}, v6.8b
                      tbl     v0.8b, {v0.16b}, v5.8b
                      smax    v2.4h, v0.4h, v1.4h
                      smin    v0.4h, v0.4h, v1.4h
                      mov     v1.8b, v0.8b
                      ins     v0.s[1], v2.s[1]
                      ins     v1.d[1], v2.d[0]
                      tbl     v1.8b, {v1.16b}, v4.8b
                      smin    v2.4h, v0.4h, v1.4h
                      smax    v0.4h, v0.4h, v1.4h
                      mov     v1.8b, v2.8b
                      ins     v1.d[1], v0.d[0]
                      tbl     v0.8b, {v1.16b}, v3.8b
                      umov    x0, v0.d[0]
                      ret
              Ответить
                • Не совсем. Я не очень понимаю зачем он вообще взял 8b.

                  Видимо оно внутри решает что шаффлить батами лучше. Что мы видим и по SSE выхлопу: гцц и тут юзает pshufb

                  #define BATS   4  //кол-во бат
                  #define BAT    16 //размер бата
                  typedef struct
                  {
                      int16_t b[4];
                  } Num;
                  Ответить
                  • А может на арме и нету других шаффлов помимо побайтового? В общем-то он все задачи решает, просто маска больше получается.
                    Ответить
  • Кстати тут баг, пофиксил:
    void printshit(uint8_t a[restrict 9])
    {
      size_t i = 0;
      uint64_t cmp = cmp_bits(a);
      while(*a != 4)
      {
        a++;
        i++;
      }
      printf("arr[%" PRIu64 "] = %zu\n", cmp, i);
    }
    Ответить
  • Честно я не понял какая задача решается.

    Вдохной массив отсортирован или нет?

    Но говнище редкостное.
    Ответить
    • Я думаю нет, иначе смысл сравнивать что-то? Понятно что всё единичками будет.
      Ответить
      • Какая-то рекурсия permute ещё и в цикле. Похоже на школьный пузырёк за O(N*N) сравнений.

        Не проще ли будет за O(N*log N) его отсортировать и просто взять средний элемент?
        Ответить
        • Причём битовая маска, построенная выше не юзается. Вот меня это смущает. А не, юзается.
          Ответить
        • Это перебор всех перестановок хуйни.
          Находим индексы медианы для всех возможных перестановок хуйни, чтоб сделать таблицу соответствия, и потом можно сделать 36 сравнений, по результатам этих сравнений через эту таблицу можно найти, по какому индексу тут медиана
          Ответить
          • > потом можно сделать 36 сравнений
            36 сравнений это (N*N-N)/2=(9*9-9)/2.

            То есть O(N²)
            > для быстрого нахождения медианы

            Это так же "быстро", как осортировать массив наиболее тупым способом: питузком.
            Ответить
            • Для сортировки пузырьком нужно еще менять элементы массива местами, тут же прямолинейное сравнение кучи элементов, которое можно идеально распараллелить на какой-нибудь FPGA и за счет этого сделать всё очень быстро (по времени равно одному такому сравнению).
              А асимптотические оценки имеют смысл только на очень больших размерах
              Ответить
              • > FPGA

                Тратить O(n^2) по площади кристалла на компараторы тоже не айс.

                Хотя, возможно, в какой-то обработке сигналов может пригодиться такая сортировка по 4-8 элементов на каждый такт. Что-нибудь в духе поиска медианы в небольшом окне.
                Ответить
                • > FPGA

                  Привет. Посоветуйте актуальный FPGA для начала. Например по книжке вирта Проект Оберон пройти.
                  Ответить
                  • Хрен знает, что-нибудь от альтеры (интела) или зайлинкса из того что сейчас удастся найти?

                    У меня была de0 nano. Камень там неплохой, но вот по периферии она совсем голая. Можно ещё у марсохода посмотреть, вроде неплохие платы делали если ещё живы.

                    Ну и морально готовься к ёбле с жуткой, уёбищной проприетарщиной. С опенсурсом в этой области всё совсем плохо, хотя есть прогресс в том же Yosys.
                    Ответить
                    • Ты имеешь ввиду что софт для работы с платой проприетарный? А что там вообще за стек. Там что-то кроме Верилога бывает?
                      Ответить
                      • Там мало того, что синтез схемы сам по себе нетривиальная задача и требует кучи таблиц и знаний о кишках чипа, так ещё и формат битстрима, который в чип заливается везде закрытый... Поэтому с тулчейном для синтеза полная жопа. Для латтисов и старых зайлинков что-то опенсурсное уже запинали. Для альтеры нет.

                        Плюс многие IP Core (модули) закрытые и\или платные. Но с этим ситуация гораздо лучше, опенсурсных модулей и проектов куча.

                        Кроме верилога ещё обычно бывает VHDL. Ну и схемы в гуйне можно порисовать если хочется по-старинке.
                        Ответить
                        • > Для латтисов и старых зайлинков что-то опенсурсное уже запинали. Для альтеры нет.

                          Бля, я думал это область, в которой вообще по дефолту всё опенсурсное. Пиздец...

                          А нахуя это всё тогда? Чисто экспериментировать с архитектурой? Делать медленный процессор, для которого js буде ассемблером? Я хочу fpga чтобы гарантировать, что у меня в стеке нет аппаратных закладок, и для этого желаю контролировать всё начиная от кристалла. И получаю в итоге проприетарный программатор. Мда...
                          Ответить
                          • > А нахуя это всё тогда?

                            Сделать быструю аппаратную реализацию какого-то алгоритма.
                            Возможность не меняя железо перепрограммировать его в другой алгоритм.
                            Ответить
                          • > А нахуя это всё тогда?

                            ASIC'и на чём-то надо прототипировать. Ну и какие-нибудь реалтаймовые задачки, с которыми проц тупо не справится.

                            З.Ы. Если хочешь опенсурса -- кроме i386/amd64 вообще сложно какое-то актуальное железо найти. Это будут или какие-нибудь слабые микроконтроллеры или говно мамонта, на которое вендору уже насрать.
                            Ответить
                          • > проприетарный программатор

                            Опенсурсный программатор, к слову несложно найти или даже написать. Там достаточно высрать битстрим из файла в какой-нибудь jtag-over-usb.

                            Проприетарщина таится именно в синтезе этого битстрима из твоих исходников. Ну и причина довольно прозаичная -- чем больше кишков кристалла вендор опубликует, тем быстрее его идею склонируют другие. А без знаний о кишках чипа синтез невозможен, увы. Разве что для низкочастотных схем.
                            Ответить
    • Охулион итераций на одну команду. Ресурсоемненько.
      Ответить
  • Для 9ти элементов 8*9/2 = 36 сравнений.

    Не проще взять qsort?
    Ответить
    • Это генерация таблицы поиска, каким образом тут qsort поможет?
      Ответить
      • Походу интринсиками ебашить -- пока единственный способ.
        Ответить
  • Эхехехех. Я упоролся и портировал алгоритм Борманда на Царские мувы

    https://godbolt.org/z/8frGY1GG1

    Выхлоп после препроцессора:
    #pragma pack(push,1)
    
    typedef union
    {
        __int128_t v;
        struct
        {
    
            int b0:32; int b1:32; int b2:32; int b3:32;
    
        };
    } Num;
    
    int min(int a, int b)
    {
        return a < b ? a : b;
    }
    
    int max(int a, int b)
    {
        return a > b ? a : b;
    }
    Num nmin(Num n0, Num n1) { n0.b0 = min(n0.b0, n1.b0); n0.b1 = min(n0.b1, n1.b1); n0.b2 = min(n0.b2, n1.b2); n0.b3 = min(n0.b3, n1.b3); return n0; };
    
    Num nmax(Num n0, Num n1) { n0.b0 = max(n0.b0, n1.b0); n0.b1 = max(n0.b1, n1.b1); n0.b2 = max(n0.b2, n1.b2); n0.b3 = max(n0.b3, n1.b3); return n0; };
    
    Num nGT(Num n0, Num n1) { n0.b0 = -(n0.b0>n1.b0); n0.b1 = -(n0.b1>n1.b1); n0.b2 = -(n0.b2>n1.b2); n0.b3 = -(n0.b3>n1.b3); return n0; };
    
    Num nLT(Num n0, Num n1) { n0.b0 = -(n0.b0>n1.b0); n0.b1 = -(n0.b1>n1.b1); n0.b2 = -(n0.b2>n1.b2); n0.b3 = -(n0.b3>n1.b3); return n0; };
    Num n1001(Num n0, Num n1) { n0.b0 = n1.b0; n0.b3 = n1.b3; return n0; }
    
    
    Num n0011(Num n0, Num n1) { n0.b0 = n1.b0; n0.b1 = n1.b1; return n0; }
    
    
    Num n0101(Num n0, Num n1) { n0.b0 = n1.b0; n0.b2 = n1.b2; return n0; }
    Num shfl0(Num n0) { Num r={}; r.b0 = n0.b1; r.b1 = n0.b0; r.b2 = n0.b3; r.b3 = n0.b2; return r; }
    
    Num shfl1(Num n0) { Num r={}; r.b0 = n0.b2; r.b1 = n0.b3; r.b2 = n0.b0; r.b3 = n0.b1; return r; }
    
    
    inline Num shr0(Num n)
    {
        return shr(n,0);
    }
    
    inline Num slr0(Num n)
    {
        return shl(n,0);
    }
    
    Num sort(Num a){
    
        Num s1 = shfl0(a);
        Num x1 = nmax(a, s1);
        Num y1 = nmin(a, s1);
        a = n1001(x1, y1);
    
        Num s2 = shfl1(a);
        Num x2 = nmax(a, s2);
        Num y2 = nmin(a, s2);
        a = n0011(x2, y2);
    
        Num s3 = shfl0(a);
        Num x3 = nmax(a, s3);
        Num y3 = nmin(a, s3);
        a = n0101(x3, y3);
        return a;
    }
    
    int main()
    {
    
        Num x={.b0=42,15,60,3};
        x=sort(x);
        printf("%d %d %d %d\n",x.b0,x.b1,x.b2,x.b3);
    
        return 0;
    }
    
    Program returned: 0
    3 15 42 60
    Ответить
    • Выхлоп почему-то на cmovах (12 штук)
      sort:
              mov     rdx, rdi
              mov     rcx, rsi
              mov     eax, edi
              mov     r8d, esi
              sar     rdx, 32
              sar     rcx, 32
              cmp     edx, edi
              cmovge  eax, edx
              cmp     ecx, esi
              cmovge  r8d, ecx
              cmp     edx, edi
              cmovg   edx, edi
              cmp     ecx, esi
              mov     edi, eax
              cmovg   ecx, esi
              mov     esi, r8d
              cmp     edx, r8d
              cmovge  esi, edx
              cmp     ecx, eax
              cmovge  edi, ecx
              cmp     edx, r8d
              cmovg   edx, r8d
              cmp     ecx, eax
              cmovg   ecx, eax
              cmp     edx, ecx
              mov     eax, ecx
              cmovle  eax, edx
              cmovl   edx, ecx
              mov     eax, eax
              sal     rdx, 32
              or      rax, rdx
              cmp     esi, edi
              mov     edx, edi
              cmovle  edx, esi
              cmovl   esi, edi
              mov     edx, edx
              sal     rsi, 32
              or      rdx, rsi
      Ответить
    • Если поставить BAT (размер бата) равным 16ти, то ГЦЦ начинает юзать SSE
      sort:
              mov     eax, edi
              mov     rdx, rdi
              mov     rcx, rsi
              sar     eax, 16
              sal     rdx, 16
              movd    xmm1, eax
              movsx   eax, di
              sar     rdi, 48
              movd    xmm3, eax
              movd    xmm0, edi
              sar     rdx, 48
              movdqa  xmm7, xmm1
              movd    xmm2, edx
              pmaxsd  xmm7, xmm3
              pminsd  xmm1, xmm3
              movdqa  xmm4, xmm0
              movdqa  xmm5, xmm7
              pminsd  xmm0, xmm2
              pmaxsd  xmm4, xmm2
              movdqa  xmm7, xmm1
              pmaxsd  xmm7, xmm4
              movdqa  xmm6, xmm4
              movdqa  xmm4, xmm0
              pmaxsd  xmm4, xmm5
              pminsd  xmm1, xmm6
              movdqa  xmm6, xmm7
              pmaxsd  xmm6, xmm4
              pminsd  xmm0, xmm5
              movdqa  xmm5, xmm1
              movd    esi, xmm6
              pmaxsd  xmm5, xmm0
              movdqa  xmm2, xmm7
              movzx   esi, si
              movd    edx, xmm5
              pminsd  xmm1, xmm0
              mov     rax, rsi
              movzx   edx, dx
              pminsd  xmm2, xmm4
              sal     rax, 16
              or      rax, rsi
              movabs  rsi, -281470681743361
              sal     rax, 16
              or      rax, rdx
              sal     rax, 16
              or      rax, rdx
              movd    edx, xmm1
              mov     ax, dx
              movd    edx, xmm2
              movzx   edx, dx
              and     rax, rsi
              sal     rdx, 32
              or      rax, rdx
              mov     rdx, rcx
              ret
      Ответить
  • Как видим выхлоп хуже оригинала
    https://godbolt.org/z/EaEfGxe5M
    
    bormand_sort:
            movdqu  xmm2, XMMWORD PTR [rdi]
            pshufd  xmm0, xmm2, 177
            movdqa  xmm1, xmm0
            pminsd  xmm0, xmm2
            pmaxsd  xmm1, xmm2
            blendps xmm1, xmm0, 9
            pshufd  xmm2, xmm1, 78
            movdqa  xmm0, xmm2
            pminsd  xmm2, xmm1
            pmaxsd  xmm0, xmm1
            blendps xmm0, xmm2, 3
            pshufd  xmm1, xmm0, 177
            movdqa  xmm2, xmm1
            pminsd  xmm1, xmm0
            pmaxsd  xmm2, xmm0
            movaps  xmm0, xmm2
            blendps xmm0, xmm1, 5
            movaps  XMMWORD PTR [rdi], xmm0
            ret


    Нет blendps и shuffle.
    Хотя шаффлы вынесенные в отдельные функции нормально превращаются в SSE-инструкции.
    shfl0:
            movq    xmm1, rdi
            xor     edx, edx
            pshuflw xmm0, xmm1, 177
            movq    rax, xmm0
            ret
    shfl1:
            movq    xmm1, rdi
            xor     edx, edx
            pshuflw xmm0, xmm1, 78
            movq    rax, xmm0
            ret
    Ответить
    • Проблема тут, как мне видится, в том что blendps для плавающих 32 битных питухов.

      И компилятор не догадывается что его равноценно можно использовать для целых.

      В оригинале https://govnokod.ru/24496#comment452141 чтобы обойти это дерьмо кастят в флоаты: _mm_castsi128_ps, а потом обратно в целый __m128i.

      Наверное blend нетрудно реализовать через битовые маски чтобы сгенерить семейство инструкции pand.
      Ответить
      • Да, там даже с интринсиками приходится "кастовать" типы чтобы конпелятор успокоился. Хотя казалось бы какая разница для битовых и байтовых операций, которые никакой арифметики не делают.

        А бленд вручную лепить из and и or -- это же медленнее будет...

        З.Ы. А если версию SSE поднять, там не завезли для интов аналог?
        Ответить
        • > А бленд вручную лепить из and и or -- это же медленнее будет...
          Да. Плюс оно даже через and/or не понимает.

          > З.Ы. А если версию SSE поднять, там не завезли для интов аналог?

          Я вчера перепробовал все вореции с этим struct union.
          SSE4 — максимальная. От 4.2 пользы нет. А дальше AVX и VEX префиксы.
          Практически тоже самое, только с трехоперандными командами (меньше мувов).

          Меня спасла царская структура данных массив.
          С ней векторизуется хорошо. Но только на последнем гцц.

          https://govnokod.ru/28309#comment782800
          https://godbolt.org/z/478cY9jP7
          Ответить
      • А что такого? Кто-то считает слонов, а кто-то пузырки.
        Ответить

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

Где здесь C++, guest?!

    А не использовать ли нам bbcode?


    8