为什么cmov总是返回t_val? [英] Why does cmov always return t_val?

查看:143
本文介绍了为什么cmov总是返回t_val?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过上述cmov函数实现的结果是,如果pred = true,则返回t_val,否则返回f_val.但是在实际操作中,每次都会返回t_val.

The result I want to achieve with the above cmov function is, if pred=true, return t_val, otherwise return f_val. But in actual operation, t_val is returned every time.

#include<stdio.h>
#include <stdint.h>
#include <stdlib.h>
int cmov(uint8_t pred, uint32_t t_val, uint32_t f_val) {
uint32_t result;
 __asm__ volatile (
 "mov %2, %0;"
 "test %1, %1;"
 "cmovz %3, %0;"
 "test %2, %2;"
 : "=r" (result)
 : "r" (pred), "r" (t_val), "r" (f_val)
 : "cc"
 );
 return result;
 }
 
int main()  {  
  
     int a=1,b=4,c=5,d;
    int res = (a==3); //
    printf("res = %d\n",res);
    d = cmov(res,b,c);
    printf("d = %d\n",d);
    a=3;
    res = (a==3);
    d = cmov(res,b,c);
    printf("d = %d\n",d);
return 0;
};  

推荐答案

您在输出("=&r")上缺少早期提示,因此GCC可能会为输入选择与输入之一相同的寄存器,可能是pred.因此test %1,%1可能正在测试t_val(b).使用调试器单步调试asm,和/或查看GCC的asm输出. (在 https://godbolt.org/gcc -S上).

You're missing an early-clobber on the output ("=&r"), so probably GCC picks the same register for the output as one of the inputs, probably pred. So test %1,%1 is probably testing t_val (b). Single-step the asm with a debugger, and/or look at GCC's asm output. (On https://godbolt.org/ or with gcc -S).

这似乎效率很低;对输出使用"+r"(result)约束(带有uint32_t result=t_val;),这样在asm模板中就不需要mov了;让编译器为您完成result=t_val的工作,只需选择相同的寄存器即可.

This seems really inefficient; Use a "+r"(result) constraint for the output (with uint32_t result=t_val;) so you don't need a mov in the asm template; let the compiler get result=t_val done for you, possibly by simply choosing the same register.

cmoz之后的test %2,%2 也不执行任何操作;您甚至都没有使用GCC6标志输出操作数.这是完全浪费的指示.

The test %2,%2 after the cmoz is also doing nothing; you're not even using a GCC6 flag-output operand. It's a totally wasted instruction.

此外,也不必是volatile.输出是输入的纯函数,如果未使用输出,则根本不需要运行.

Also, this doesn't need to be volatile. The output is a pure function of the inputs, and doesn't need to run at all if the output is unused.

对于一个cmov完全使用内联asm可能不是一个好主意;使用-O3进行编译并编写源代码,以使GCC认为将if转换为无分支代码是一个好主意.内联汇编破坏了持续的传播并击败了其他优化.并且这种方式迫使您在模板中使用test指令,而不是从早期的add中读取FLAGS设置的内容,也不让编译器将相同的FLAGS结果重用于多个cmov或其他指令. https://gcc.gnu.org/wiki/DontUseInlineAsm

It's probably a bad idea to use inline asm at all for just a cmov; compile with -O3 and write your source such that GCC thinks its a good idea to do if-conversion into branchless code. inline asm destroys constant propagation and defeats other optimizations. And this way forces you to use a test instruction in the template, not reading FLAGS set from some earlier add or whatever, and not letting the compiler reuse the same FLAGS result for multiple cmov or other instructions. https://gcc.gnu.org/wiki/DontUseInlineAsm

或者,如果您不能让编译器自行创建所需的asm,请在asm中编写更多实际用例,而不仅仅是cmov周围的包装器.

Or if you can't hand-hold the compiler into making asm you want, write more of your real use-case in asm, not just a wrapper around cmov.

这篇关于为什么cmov总是返回t_val?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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