提示C编译器(GCC或Clang)可能存在的变量值/范围。

10
在下面的代码中,只会进行一次比较,因为编译器知道这些条件是互斥的,我们将总是进入第二个条件,因为 bar 将必须 > 32:
int foo(int bar) {
    if (bar <= 64)
        return 1;
    if (bar > 32) {
        printf("Too many elements");
    }
    return 0;
}

现在,假设我知道 bar 总是大于64。这可能是因为系统输入、配置或其他原因。那么我该如何提示编译器根本不进行比较呢?就像如果编译了 if(bar<=64) return 一样,但实际上它没有被保留在最终的汇编代码中。

类似于:

int foo(int bar) {
    @precond(bar > 64);
    if (bar > 32) {
        printf("Too many elements");
    }
    return 0;
}

我的唯一解决方案是写一个LLVM pass吗?


1
为什么?在我看来,这是X-Y问题。 - 0___________
我认为你可以使用GCC的__builtin_expect:http://blog.man7.org/2012/10/how-much-do-builtinexpect-likely-and.html - ForceBru
1
谢谢@ForceBru,但那只是一个提示,并且会保留分支。它只是确保最可能的代码不在跳转路径上。我想删除跳转部分。也许我想要__builtin_enforced :p - MappaM
请注意,编写一个 pass 真的非常简单。 - arnt
1个回答

11

你可以在GCC中使用__builtin_unreachable

if (bar > 32) {
  __builtin_unreachable();
}

__builtin_assume 在 Clang 中:

__builtin_assume(bar <= 32);

在MSVC中的__assume

__assume(bar <= 32);

使用C++23,您还可以使用可移植语法

[[assume(bar <= 32)]];

是的,它有效!我使用gcc -S进行了验证,不再有任何比较。 - MappaM
11
也许我漏掉了一些明显的东西,但是你提供的两个例子似乎是相反的:GCC的示例声明 bar<=32false,而MSVC的示例声明 bar<=32true。对吗? - ruakh
@ruakh 哎呀!已修复。 - yugr
1
在Clang中,即使有__builtin_unreachable可用,你也应该使用__builtin_assume - 后者不会导致优化器省略代码,但前者会。 - user7761803
@user7761803 我曾在clang中看到__builtin_unreachable导致代码被省略。在我看来,__builtin_assume(Cond)应该等同于do if(!(Cond)) __builtin_unreachable(); while(0) - Petr Skocik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接