作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
首先是一个微不足道的数学事实:给定整数 n
和 m
, 我们有 n < m
当且仅当 n <= m - 1
.
GCC 似乎更喜欢较小绝对值的即时值。因此,当 m
已知并且满足其他条件,编译器在等效比较表达式中选择一个最小化绝对值的表达式。例如,它更喜欢 n <= 1000
在 n < 1001
和 GCC 9.2 翻译了这个
bool f(uint32_t n) {
return n < 1001;
}
x86
汇编代码
f(unsigned int):
cmpl $1000, %edi
setbe %al
ret
constexpr
友好的解决方案似乎排除了内联
asm
.最后,我的目标是 C++17,它不包括
std::is_constant_evaluated
之类的东西。 . (话虽如此,请尽管不顾我的限制自由地提供答案,因为它可能对其他人仍然有用。)
x86_64
的“悲观”在以下示例中:
bool g(uint64_t n) {
n *= 5000000001;
return n < 5000000001;
}
g(unsigned long):
movabsq $5000000001, %rax
imulq %rax, %rdi
movabsq $5000000000, %rax
cmpq %rax, %rdi
setbe %al
ret
x86_64
,使用 64 位立即数的计算有一些限制,可能意味着将这些值加载到寄存器中。在上面的例子中,这发生了两次:常量
5000000001
和
5000000000
存储在
rax
用于乘法和比较。如果 GCC 保留 C++ 代码中出现的原始比较(即针对
5000000001
),则不需要第二个
movabs
.
g(unsigned long):
movabsq $5000000001, %rax
imulq %rax, %rdi
subq $1, %rax
cmpq %rax, %rdi
setbe %al
ret
movabs
被 4 字节长的
subq
取代操作说明。无论如何,
subq
似乎也没有必要。
最佳答案
这是一个 C++20 解决方案,遗憾的是,我不能使用
#include <cstdint>
#include <type_traits>
template <class U>
bool less_asm(U n, U m) noexcept {
bool r;
asm("cmp%z[m]\t{%[m], %[n]|%[n], %[m]}"
: "=@ccb"(r) : [n]"r"(n), [m]"re"(m) : "cc");
return r;
}
template <class U>
constexpr bool less(U n, U m) noexcept {
if (std::is_constant_evaluated())
return n < m;
return less_asm(n, m);
}
static_assert(less(uint64_t(0), uint64_t(1)));
bool g(uint64_t n) {
n *= 5000000001;
return less<uint64_t>(n, 5000000001);
}
g(unsigned long):
movabsq $5000000001, %rax
imulq %rax, %rdi
cmpq %rax, %rdi
setc %al
ret
__builtin_constant_p()
而不是 std::is_constant_evaluated()
。以前的 GCC 版本提示 asm
出现在 constexpr
函数中。) less_asm
。)template <class U>
constexpr bool less(U n, U m) noexcept {
if (__builtin_constant_p(n < m))
return n < m;
return [&]{
bool r;
asm("cmp\t{%[m], %[n]|%[n], %[m]}"
: "=@ccb"(r) : [n]"r"(n), [m]"re"(m) : "cc");
return r;
}();
}
关于c++ - 在比较中,GCC 似乎更喜欢小的即时值。有没有办法避免这种情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59117603/
我是一名优秀的程序员,十分优秀!