You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多连续无符号整数比较的安全优化及类型双关实现正确性探讨

关于std::tuple比较的汇编优化与类型双关正确性的问题

当在GCC 13.2和Clang 18.0.1编译器开启-O3优化时,由四个std::uint16_t构成的std::tuple的operator<生成的汇编代码优化效果不佳。而采用reinterpret_cast和联合(union)两种*类型双关(type punning)*实现的比较逻辑,则能生成优化后的汇编代码。

编辑说明:因问题遭差评,特此补充:默认实现的汇编包含3个条件分支,在高性能循环中影响显著,而另外两种实现无分支。

技术问询

  • 这两种类型双关实现是否正确?
  • 若不正确,需满足哪些条件才能保证其正确性?
  • 假设存在可编译期验证的正确性测试,为何编译器不直接生成优化后的汇编代码?

测试代码

#include <cstdint>
#include <tuple>
#include <bit>

using TupleU16 = std::tuple<std::uint16_t, std::uint16_t, std::uint16_t, std::uint16_t>;

bool less(TupleU16 lhs, TupleU16 rhs) {
    return lhs < rhs;
}

constexpr bool canSafelyUseTypePunning() {
    TupleU16 t;
    std::uint16_t* val0 = &std::get<0>(t);
    std::uint16_t* val1 = &std::get<1>(t);
    std::uint16_t* val2 = &std::get<2>(t);
    std::uint16_t* val3 = &std::get<3>(t);

    if constexpr (std::endian::native == std::endian::little) {
        return sizeof(TupleU16) == 8 &&
            (val0 - val3) == 3 && (val0 - val2) == 2 && (val0 - val1) == 1;
    }
    else if constexpr (std::endian::native == std::endian::big) {
        return sizeof(TupleU16) == 8 &&
            (val3 - val0) == 3 && (val2 - val0) == 2 && (val1 - val0) == 1;
    }
    else {
        return false;
    }
}

bool less2(TupleU16 lhs, TupleU16 rhs) { // cannot be constexpr
    static_assert(canSafelyUseTypePunning());
    auto* lhsp = reinterpret_cast<const std::uint64_t*>(&lhs);
    auto* rhsp = reinterpret_cast<const std::uint64_t*>(&rhs);
    return *lhsp < *rhsp;
}

bool less3(TupleU16 lhs, TupleU16 rhs) { // can be constexpr
    static_assert(canSafelyUseTypePunning());
    union U {
        std::uint64_t u64;
        TupleU16 tu16;
    };
    return U{.tu16 = lhs}.u64 < U{.tu16 = rhs}.u64;
}

内容的提问来源于stack exchange,提问作者MarkB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 04:53:25