如何基于断言来指导GCC优化而无需运行时成本? [英] How to guide GCC optimizations based on assertions without runtime cost?

查看:178
本文介绍了如何基于断言来指导GCC优化而无需运行时成本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  #define contract(condition)\ 
if(!(condition))\
抛出异常(违反合约);

...但是在发布模式下:

< (条件))
__builtin_unreachable(); pre> #define contract(condition)

通过 assert()在发布版本中,编译器可以通过UB传播大量优化代码。



例如,使用以下代码进行测试:

  int foo(int i){
contract(i == 1);
返回i;
}

// ...

foo(0);

...在调试模式下抛出一个异常,但为无条件的返回1; 处于发布模式:

  foo(int):
mov eax ,1
ret

条件及其依赖的所有内容都已经过优化。



我的问题出现在更复杂的条件下。当编译器不能证明条件没有副作用时,它不会优化它,与不使用合约相比,这是一种严重的惩罚。



有没有方法可以表达合约中的条件没有副作用,所以它始终优化出来?

解决方案

无法强制优化代码,因为如果它是死代码,因为GCC必须始终对标准抱怨。


$ b $另一方面,可以通过使用属性 error 检查表达式,以确保没有任何副作用,只要函数的调用无法优化,就会显示错误

一个宏的例子,它检查优化过的任何内容并进行UB传播:

  #define _contract(condition)\ 
{
([&]()__attribute__((noinline,error(contract can not be out out))){
I f(condition){} //使用if中的条件似乎隐藏`unused`警告。
}());
if(!(condition))
__builtin_unreachable();



$ b $ p
$ b

如果没有优化,错误属性不起作用(所以这个宏只能用于用于发布优化模式编译)。
请注意,在链接过程中会显示错误,指示合同有任何副作用。



一个测试,显示错误与不可优化合同。



一个优化合同的测试,但是,UB会传播它吗?


I have a macro used all over my code that in debug mode does:

#define contract(condition) \
    if (!(condition)) \
        throw exception("a contract has been violated");

... but in release mode:

#define contract(condition) \
    if (!(condition)) \
        __builtin_unreachable();

What this does over an assert() is that, in release builds, the compiler can heavily optimize the code thanks to UB propagation.

For example, testing with the following code:

int foo(int i) {
    contract(i == 1);
    return i;
}

// ...

foo(0);

... throws an exception in debug mode, but produces assembly for an unconditional return 1; in release mode:

foo(int):
        mov     eax, 1
        ret

The condition, and everything that depended on it, has been optimized out.

My issue arises with more complex conditions. When compiler cannot prove that the condition has no side effect, it does not optimize it out, which is a runtme penalty compared to not using the contract.

Is there a way to express that the condition in the contract has no side effect, so that it is always optimized out?

解决方案

There is no way to force optimize out code as-if it was dead-code, because GCC has to always be complaint with the standard.

On the other hand the expression can be checked to not have any side effects by using the attribute error which will show an error whenever a function's call could not be optimized out.

An example of a macro that checks whatever is optimized out and does UB propagation:

#define _contract(condition) \
    {
        ([&]() __attribute__ ((noinline,error ("contract could not be optimized out"))) {
            if (condition) {} // using the condition in if seem to hide `unused` warnings.
        }());
        if (!(condition))
            __builtin_unreachable();
    }

The error attribute does not work without optimization (so this macro can only be used for release\optimization mode compilation). Note that the error that indicates whatever the contract has side effects is shown during linkage.

A test that shows an error with unoptimizable contract.

A test that optimizes out a contract but, does UB propagation with it.

这篇关于如何基于断言来指导GCC优化而无需运行时成本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆