Сообщение Re[4]: Что именно делают /volatile:ms и /volatile:iso на x86 от 06.01.2022 11:21
Изменено 06.01.2022 11:24 netch80
Re[4]: Что именно делают /volatile:ms и /volatile:iso на x86 ?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>>>поскольку компилятор ничего не обещает в плане атомарности.
AG>>Платформа обещает
ЕМ>Это лишь о чтении/записи, и только выровненных данных в пределах ширины магистрали. Разве такие операции не везде атомарны? Даже представить не могу, для чего могло бы потребоваться выполнять их иначе, чем за один цикл.
Ну вот пример: у тебя есть структура вида
Посмотри, как твой компилятор делает чтение поля b. Он его сложно собирает из частей. Возможно, это байты. Это ещё понятно. А что будет с полем e? Его соберёт или нет? Оно ведь чётко 2 байта на границе 2 байт, почему бы и нет?
Я закинул код чтения двух полей на godbolt и начал смотреть разные компиляторы. И опаньки — clang для x86 нормально читает двухбайтное значение чтением по word ptr, а вот для RV32 почему-то начал побайтно извлекать:
Аааа за что, дяденьки? Он же мог простейший lhu применить...
Видишь — чуть-чуть замаскировали и компилятор уже не понимает, что ему надо было делать.
AG>>Через __iso_volatile_load64 / __iso_volatile_store64 можно атомарно загрузить-сохранить 64-битную переменную в 32-битном x86
ЕМ>Это уже откровенное извращение через XMM.
Почему, если XMM декларирован доступным?
ЕМ>>>поскольку компилятор ничего не обещает в плане атомарности.
AG>>Платформа обещает
ЕМ>Это лишь о чтении/записи, и только выровненных данных в пределах ширины магистрали. Разве такие операции не везде атомарны? Даже представить не могу, для чего могло бы потребоваться выполнять их иначе, чем за один цикл.
Ну вот пример: у тебя есть структура вида
struct moo {
unsigned a: 31;
unsigned b: 5;
unsigned c: 22;
unsigned d: 6;
unsigned e: 16;
} __attribute__((packed));
Посмотри, как твой компилятор делает чтение поля b. Он его сложно собирает из частей. Возможно, это байты. Это ещё понятно. А что будет с полем e? Его соберёт или нет? Оно ведь чётко 2 байта на границе 2 байт, почему бы и нет?
Я закинул код чтения двух полей на godbolt и начал смотреть разные компиляторы. И опаньки — clang для x86 нормально читает двухбайтное значение чтением по word ptr, а вот для RV32 почему-то начал побайтно извлекать:
get_e: # @get_e
lbu a1, 9(a0)
lbu a0, 8(a0)
slli a1, a1, 8
or a0, a0, a1
ret
Аааа за что, дяденьки? Он же мог простейший lhu применить...
Видишь — чуть-чуть замаскировали и компилятор уже не понимает, что ему надо было делать.
AG>>Через __iso_volatile_load64 / __iso_volatile_store64 можно атомарно загрузить-сохранить 64-битную переменную в 32-битном x86
ЕМ>Это уже откровенное извращение через XMM.
Почему, если XMM декларирован доступным?
Re[4]: Что именно делают /volatile:ms и /volatile:iso на x86
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>>>поскольку компилятор ничего не обещает в плане атомарности.
AG>>Платформа обещает
ЕМ>Это лишь о чтении/записи, и только выровненных данных в пределах ширины магистрали. Разве такие операции не везде атомарны? Даже представить не могу, для чего могло бы потребоваться выполнять их иначе, чем за один цикл.
Ну вот пример: у тебя есть структура вида
Посмотри, как твой компилятор делает чтение поля b. Он его сложно собирает из частей. Возможно, это байты. Это ещё понятно. А что будет с полем e? Его соберёт или нет? Оно ведь чётко 2 байта на границе 2 байт, почему бы и нет?
Я закинул код чтения двух полей на godbolt и начал смотреть разные компиляторы. И опаньки — clang для x86 нормально читает двухбайтное значение чтением по word ptr, а вот для RV32 почему-то начал побайтно извлекать:
Аааа за что, дяденьки? Он же мог простейший lhu применить...
Видишь — чуть-чуть замаскировали и компилятор уже не понимает, что ему надо было делать.
(Ну да, если ты заточен на одну платформу и один компилятор, тебе пофиг. Мне не так.)
AG>>Через __iso_volatile_load64 / __iso_volatile_store64 можно атомарно загрузить-сохранить 64-битную переменную в 32-битном x86
ЕМ>Это уже откровенное извращение через XMM.
Почему, если XMM декларирован доступным?
ЕМ>>>поскольку компилятор ничего не обещает в плане атомарности.
AG>>Платформа обещает
ЕМ>Это лишь о чтении/записи, и только выровненных данных в пределах ширины магистрали. Разве такие операции не везде атомарны? Даже представить не могу, для чего могло бы потребоваться выполнять их иначе, чем за один цикл.
Ну вот пример: у тебя есть структура вида
struct moo {
unsigned a: 31;
unsigned b: 5;
unsigned c: 22;
unsigned d: 6;
unsigned e: 16;
} __attribute__((packed));
Посмотри, как твой компилятор делает чтение поля b. Он его сложно собирает из частей. Возможно, это байты. Это ещё понятно. А что будет с полем e? Его соберёт или нет? Оно ведь чётко 2 байта на границе 2 байт, почему бы и нет?
Я закинул код чтения двух полей на godbolt и начал смотреть разные компиляторы. И опаньки — clang для x86 нормально читает двухбайтное значение чтением по word ptr, а вот для RV32 почему-то начал побайтно извлекать:
get_e: # @get_e
lbu a1, 9(a0)
lbu a0, 8(a0)
slli a1, a1, 8
or a0, a0, a1
ret
Аааа за что, дяденьки? Он же мог простейший lhu применить...
Видишь — чуть-чуть замаскировали и компилятор уже не понимает, что ему надо было делать.
(Ну да, если ты заточен на одну платформу и один компилятор, тебе пофиг. Мне не так.)
AG>>Через __iso_volatile_load64 / __iso_volatile_store64 можно атомарно загрузить-сохранить 64-битную переменную в 32-битном x86
ЕМ>Это уже откровенное извращение через XMM.
Почему, если XMM декларирован доступным?