LINUX.ORG.RU

Объясните сишную магию

 ,


11

14

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

Вот что это за ужас (src):

static unsigned char clampByte(int c)
{
    unsigned char buff[] = { static_cast<unsigned char>(c), 255, 0 };
    unsigned uc = static_cast<unsigned>(c);
    return buff[!!(uc & ~0xff) + !!(uc & ~(~0u >> 1))];
}

Я так понимаю, они проверяют что int в 0..255 диапазоне, но уж слишком странным образом.

UPD: коммит, который добавил этот код.

★★★★★

Последнее исправление: RazrFalcon (всего исправлений: 1)

Ответ на: комментарий от NishiragiShintaro

Проблема была продекларирована вначале.

давай ссылку.

Потому что ты кукарекал не про мою портянку.

...

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

про неё. а твои когнитивные способности меня огорчают.

С этим идёшь на помойку.

в очередной раз обосрался. с -O3 код тот же самый.

спастив портянку куда-то - что-то мне сообщи нового?

я тебе сообщил то, что до тебя не доходит:

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

задачу ты не решил. садись, два.

anonymous
()
Ответ на: комментарий от anonymous

Как только покажешь, что !!(expr) - это не ветвление.

Не, я знаю, конечно, что у дошколят «a == b» ветвление, но что-бы ! было ветвление. Чего с чем оно там ветвит?

NishiragiShintaro
()
Ответ на: комментарий от anonymous

Кто сказал, что expr - это только сравнение?

С какими же гениями я говорю. Причём тут твоё expr? Ты совсем оладушек?

Я тебе привёл == как пример того, что дошколята по ошибке считают ветвлением. Т.е. ты, как и они, увидел, что !/== пишут внутри if и вам показалось, что это какое-то ветвление. В ифе же пишут. Иди читай букварь.

По поводу самих потуг - что там в твоей expr находится - вообще насрать. ! работает со значением, которое вернёт твой expr.

NishiragiShintaro
()
Ответ на: комментарий от anonymous

Поехали по новой Объясните сишную магию (комментарий)

ерунда там написана. одну цитату из стандарта я уже привёл, привожу вторую:

[conv.integral]
2
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source
integer (modulo 2 n where n is the number of bits used to represent the unsigned type). [Note: In a two’s
complement representation, this conversion is conceptual and there is no change in the bit pattern (if there
is no truncation). —end note ]
это, как раз, приводит нас к вопросу о реализации static_cast на экзотических архитектурах. забыл об этом раньше написать.

Как только покажешь, что !!(expr) - это не ветвление.

!b <=> b ^ 1

дальше, надеюсь, расписывать не надо.

anonymous
()
Ответ на: комментарий от NishiragiShintaro

твоей тупостью я не унижен, а огорчён

anonymous
()
Ответ на: комментарий от anonymous

[conv.integral]

Ого, это полшага до стандартизации дополнительного кода. А при других системах двоичного счисления, каст к безнаковому - это сложная операция, возможно, содержащая ветвления.

!b <=> b ^ 1

Для integral-типов с таким же успехом можно ?: <=> mux
Квиты?

anonymous
()
Ответ на: комментарий от anonymous

Квиты?

не совсем. выражайся яснее: ты имел в виду потенциальное ветвление в static_cast<bool>(expr). посмотрел на доступных на godbolt.org платформах: не справился только avr.

таким образом, резюмируем: код в оп-посте зависит от отсутствия в реализациях static_cast<unsigned> и static_cast<bool> ветвлений.

надо думать дальше.

anonymous
()
Ответ на: комментарий от anonymous

Куда не плюнь, везде ветвления.

Дополню.
И как все это работает на одних ноликах и единичках? Как это умудрились ветвления преобразовать в 0 и 1? Цитирую тебя:

я не знаю как нужно упороться

anonymous
()
Ответ на: комментарий от anonymous

ты куда-то не туда плюёшь:

bool convert(int i) {
    bool retval = static_cast<bool>(i);
    return retval;
}
`-FunctionDecl 0x804180190 <static-cast-bool.cpp:1:1, line:4:1> line:1:6 convert 'bool (int)'
  |-ParmVarDecl 0x8041800c8 <col:14, col:18> col:18 used i 'int'
  `-CompoundStmt 0x8041803f0 <col:21, line:4:1>
    |-DeclStmt 0x804180380 <line:2:5, col:39>
    | `-VarDecl 0x804180288 <col:5, col:38> col:10 used retval 'bool' cinit
    |   `-CXXStaticCastExpr 0x804180350 <col:19, col:38> 'bool' static_cast<_Bool> <NoOp>
    |     `-ImplicitCastExpr 0x804180338 <col:37> 'bool' <IntegralToBoolean>
    |       `-ImplicitCastExpr 0x804180320 <col:37> 'int' <LValueToRValue>
    |         `-DeclRefExpr 0x8041802e8 <col:37> 'int' lvalue ParmVar 0x8041800c8 'i' 'int'
    `-ReturnStmt 0x8041803d8 <line:3:5, col:12>
      `-ImplicitCastExpr 0x8041803c0 <col:12> 'bool' <LValueToRValue>
        `-DeclRefExpr 0x804180398 <col:12> 'bool' lvalue Var 0x804180288 'retval' 'bool'

anonymous
()
Ответ на: комментарий от anonymous

вот так:

bool convert(int i) {
    bool retval = static_cast<bool>(i);
    return retval;
}
        test    edi, edi
        setne   al
        ret

Цитирую тебя

цитата не к месту: я говорил об ast

anonymous
()
Ответ на: комментарий от Harald

А почему компилятор такое не делает из тупого кода с ифами? Не научили?

Legioner ★★★★★
()
Ответ на: комментарий от anonymous

1. это не парсер

Это неизвестно-что, как аргумент. Если это AST, то AST обычно строится парсером. Это не существенное предположение (парсер) написал в скобках.

2. а как ещё можно реализовать?

Подумать только, реализация «зависит от реализации». Опять это сочетание - «зависит от реализации».

в <чем-то> подходящей инструкции нет. у <чего-то> — есть.

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

anonymous
()
Ответ на: комментарий от anonymous

2. а как ещё можно реализовать?

а как там кстати у ARM-ов с предикатными инструкциями в егойном ассемблере? их тут можно как-то использовать?

anonymous
()
Ответ на: комментарий от NishiragiShintaro

Мне кажется ты не совсем понял мой вопрос. Откуда компилятору знать, что программист хотел именно констант тайм?

Через пять лет другой программист запустит модную среду с профайлером и сконпеляет это в profile-guided на живых данных, где все значения лежат в 0..255. И конпелятор разберет это «~+>>&~» и воткнет вместо этого if (uc > 255), понимая, что ирл в 99.999% он бесплатен, а вычислений куда меньше. И за палец дернут уже этот коммит.

В общем-то вопрос и не был тебе, мне известно твое отношение к обслуживанию и поддержке ПО вне локалхоста.

---------------------

Еще было от анона: Объясните сишную магию (комментарий)

код из оп-поста правильно решает вполне конкретную задачу

Вот я и хочу понять, откуда инфа, что это время будет константным на любом компиляторе (хотя бы из тех, что имеют или будут иметь практическую ценность). Меня вполне устроит ответ «ТЕСТЫ», но может он скрывает что-то более фундаментальное, типа «есть гарантия, что AL-выражение никогда не превратится в оптимистичный бранч». Ведь наверное можно было

return buff[(uc > 255) + (c < 0)]

Но видимо не прокатило.

anonymous
()
Ответ на: комментарий от anonymous

писал уже: в порядке всё

bool convert2bool(int i) {
    bool retval = static_cast<bool>(i);
    return retval;
}
        cmp     w0, 0
        cset    w0, ne
        ret
unsigned convert2unsigned(int i) {
    unsigned retval = static_cast<unsigned>(i);
    return retval;
}
        ret

anonymous
()
Ответ на: комментарий от anonymous

Откуда компилятору знать, что программист хотел именно констант тайм?

Скоро введут какой-нибудь ключик к компилятору/компиляторам, если уже не ввели.

anonymous
()
Ответ на: комментарий от anonymous

код из оп-поста правильно решает вполне конкретную задачу

здесь ты меня цитируешь. ниже мы побеседовали с другим(?) аноном. попробую подытожить в одном комментарии.

рассматриваем код из оп-поста.

1. на уровне ast никаких ветвлений нет. представить себе оптимизацию, которая их воткнёт, я не могу.

2. на уровне генерации машинного кода есть нюанс: в коде используются static_cast<unsigned> и (неявно) static_cast<bool>. если они реализованы в компиляторе с использованием ветвлений (есть такой пример, но в микроконтроллерах), то карточный домик рассыпается.

3. чтобы защититься от использования ии в компиляторе (по-другому я идею анона о замене массива buff регистрами объяснить не могу), можно добавить в объявление buff модификатор volatile.

anonymous
()

развивай опенсорц, братан...

anonymous
()
Ответ на: комментарий от anonymous

1. на уровне ast никаких ветвлений нет. представить себе оптимизацию, которая их воткнёт, я не могу.

2. на уровне генерации машинного кода есть нюанс: в коде используются static_cast<unsigned> и (неявно) static_cast<bool>. если они реализованы в компиляторе с использованием ветвлений (есть такой пример, но в микроконтроллерах), то карточный домик рассыпается.

Ты рассматриваешь случай, когда оптимизатор и кодогенератор(со своим оптимизатором) не знают друг о друге (clang->llvm). Если оптимизатор знает, что кодогенератор использует ветвление, перестраивает ast, используя эти ветвлениями. Потом оптимизирует уже таргетозависимый ast, в котором есть полная инфа о языковых конструкциях. (clang скорее всего так не сможет)

3. чтобы защититься от использования ии в компиляторе (по-другому я идею анона о замене массива buff регистрами объяснить не могу), можно добавить в объявление buff модификатор volatile.

Это почти как векторизация, можно даже в 32+-битный регистр записать 3 байта.

anonymous
()
Ответ на: комментарий от anonymous

Мне кажется ты не совсем понял мой вопрос. Откуда компилятору знать, что программист хотел именно констант тайм?

Все на это насрать.

Через пять лет другой программист запустит модную среду с профайлером

Это бездарная макака, максимум что он там сделает - в лужу напердит.

и сконпеляет это в profile-guided на живых данных, где все значения лежат в 0..255.

Нету такого понятия как «живые данные».

И конпелятор разберет это «~+>>&~» и воткнет вместо этого if (uc > 255), понимая, что ирл в 99.999% он бесплатен, а вычислений куда меньше. И за палец дернут уже этот коммит.

Компилятор хоть и тупой, но ты уже дальше от него от понимания. Твои рассуждения «вычислений куда меньше» - нелепы.

Да и как я уже сказал - всем насрать. Вот когда будет - тогда будет какой-то разговор. Никого маня-фантазии экспертов с лора неволнуют.

В общем-то вопрос и не был тебе, мне известно твое отношение к обслуживанию и поддержке ПО вне локалхоста.

Ты хотел сказать «отношение всех»?

Вот я и хочу понять, откуда инфа, что это время будет константным на любом компиляторе

Всем насрать на «любой компилятор». К тому же, как я тебе уже говорил(или не тебе) - этот код вообще не решает никакой задачи.

Это какая-то малоразвитая макака решила набить себе очков, спастила откуда-то эту функцию и закоммитила в вебкит. Вчера макака, а сегодня мамкин гений безопасности.

Очевидно, что никакой адекватный человек такие задачи не ставит. Всем насрать, так же как и насрать этой макаке. Причины я описал выше.

Но видимо не прокатило.

Видимо не осилил. Спастил то, что было. К тому же никакой разницы нету.

NishiragiShintaro
()
Ответ на: комментарий от NishiragiShintaro

Нету такого понятия как «живые данные».

ну ты же не настоящий сварщик. чего в разговор лезешь?

anonymous
()
Ответ на: комментарий от NishiragiShintaro

такие задачи не ставит

поставлю тебе «такую» задачу. есть функция

bool isprime(int i);
если i простое — true, если нет — false. всё просто. нюанс. никакой мамкин хакер не должен узнать какое число функции скормили. т.е. она должна работать за одинаковое время независимо от входа.

на ко-ко-ко не смотрю. давай код.

anonymous
()
Ответ на: комментарий от anonymous

Нет, ламерок. Я не обязан доказывать отсутствие чего-то. А вот ты, трепло, должно доказывать присутствие чего-то. А теперь исполнять.

NishiragiShintaro
()
Ответ на: комментарий от NishiragiShintaro

ну нет «живых данных» и нет. доктор и санитар не возражают. доказательство — бремя того, кто утверждает.

т.е. ты отказываешься от своего утверждения?

anonymous
()
Ответ на: комментарий от anonymous

ну нет «живых данных» и нет. доктор и санитар не возражают. доказательство — бремя того, кто утверждает.

Маня, ты утверждаешь обратное - это раз. Ты не просил у меня доказательств, клону. Бегом побежал доказывать, что ты где-то там кукарекал про доказательства.

К тому же, никакого «утверждения» тут нет. Отверждения «чего-то нет» я не должен доказывать, потому что это доказать невозможно. Марш в школу, тебе там про логику расскажут.

NishiragiShintaro
()
Ответ на: комментарий от NishiragiShintaro

я не утверждаю, а спрашиваю. ты пацанам туфту гнал за живые данные? отвечай, ублюдок.

Ты не просил у меня доказательств

мне нечего у тебя просить. кукарекнул — отвечай.

Отверждения «чего-то нет» я не должен доказывать

значит балаболка.

anonymous
()
Ответ на: комментарий от anonymous

Да, с другим. Я спрашиваю, а он бесшовно продолжает, в лучших традициях «х пойми кто о чем».

volatile

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

anonymous
()
Ответ на: комментарий от anonymous

очевидно же. если решение есть — его надо предоставить, если нет — доказать это.

anonymous
()
Ответ на: комментарий от anonymous

а решение с конст-тайм есть?

Конечно есть, как минимум, всегда можно сделать проход до худшего случая

bool is_prime(unsigned n)
{
    assert(n >= 1);
    bool result = true;
    if (n == 1)
    {
        //return false;
        result = false;
    }
    if (n == 2)
    {
        //return true;
    }
    if (n % 2 == 0)
    {
        //return false;
        result = false;
    }
    //for (unsigned i = 3; i * i <= n; i+=2)
    for (unsigned i = 3; i <= 65536; i+=2) // sqrt(UINT32_MAX) == 65536
    {
/*
        if (n % i == 0)
        {
            return false;
        }
*/
        if ((n < i) & (n % i == 0))
        {
            result = false;
        }
    }
    return (n == 2) | result;
    // & и | используются вместо && и |, чтобы не отбрасывалась вторая часть
}

fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

(автор задачи)

+1 за прохождение первого уровня

но кроличья нора несколько глубже

anonymous
()
Ответ на: комментарий от vzzo

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

царь до такого додуматься не смог бы, в виду своего скудоумия.

anonymous
()
Ответ на: комментарий от NishiragiShintaro

Могут ли флаги оптимизации плохо повлиять на код реального проекта? Есть смысл переписывать некоторые куски кода на ассемблере в 21 веке?

extern "C" unsigned char _clampByteAsm(int c);
section .text

global _clampByteAsm

_clampByteAsm:
    push    rbp
    mov     rbp, rsp
    mov     eax, edi
    xor     al, al 
    
    test    eax, eax
    je      .ok
    
    bswap   eax
    sar     al, 7
    not     al
    jmp     .out

.ok: 
    mov     al, dil

.out:
    pop     rbp
    ret
Deleted
()
Ответ на: комментарий от Deleted

Могут ли флаги оптимизации плохо повлиять на код реального проекта?

Да. Допустим, упомянутая тут колхоз-векторизация. У птушноков нет понимания, что векторизация - не цель. То, что ты там что-то кое-как «векторизуешь» - это мало тебе что даст, а наоборот заберёт. Определяющим является качество реализации.

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

Ну и вот эта векторизация зачастую медленнее.

Есть смысл переписывать некоторые куски кода на ассемблере в 21 веке?

Смысл есть, но не таким образом. Писать подобное говно не имеет смысла, а вот если ты напишешь нормальный генератор - это другое дело.

Ты же не будешь регистры руками считать? Не будешь же руками шедулить иструкции? Не будешь руками заниматься каким-нибудь анролом, либо писать хвосты?

Ну и, очевидно, что писать функции на асм"е - полная херня, ведь её нельзя заинлайнить.

NishiragiShintaro
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.