clang/gcc. Некоторые встроенные операнды могут быть удовлетворены несколькими ограничениями, например, "rm"
, когда операнд может быть удовлетворен регистром или ячейкой памяти. Например, 64 x 64 = 128 бит умножаются:
__asm__ ("mulq %q3" : "=a" (rl), "=d" (rh) : "%0" (x), "rm" (y) : "cc")
Сгенерированный код, как представляется, выбирает ограничение памяти для аргумента 3
, что было бы неплохо, если бы мы регистрировали голод, чтобы избежать разлива. Очевидно, что на x86-64 меньше давления на регистре, чем на IA32. Однако сгенерированный фрагмент сборки (clang):
movq %rcx, -8(%rbp)
## InlineAsm Start
mulq -8(%rbp)
## InlineAsm End
Выбор ограничения памяти явно бессмысленен! Однако изменение ограничения на: "r" (y)
(форсирование регистра) получим:
## InlineAsm Start
mulq %rcx
## InlineAsm End
как ожидалось. Эти результаты приведены для clang/LLVM 3.2 (текущий выпуск Xcode). Первый вопрос: Почему clang выбирает менее эффективное ограничение в этом случае?
Во-вторых, существует менее широко используемое, разделенное запятыми, множественное альтернативное ограничение: "r,m" (y)
, который должен оценивать затраты по каждой альтернативе и выбирать тот, который приводит к меньшему копированию. Это, похоже, работает, но clang просто выбирает первый - о чем свидетельствует: "m,r" (y)
Я мог бы просто отказаться от альтернативных ограничений "m"
, но это не отражает диапазон возможных законных операндов. Это подводит меня ко второму вопросу: Устранены ли эти проблемы или, по крайней мере, признаны в 3.3?. Я пробовал просматривать архивы LLVM dev, но я бы предпочел получить некоторые ответы, прежде чем излишне ограничивать ограничения дальше, или присоединение к обсуждениям проектов и т.д.