C++ 关于拆卸输出的问题

C++ 关于拆卸输出的问题,c++,optimization,assembly,x86,C++,Optimization,Assembly,X86,考虑C++中的以下代码: bool foo(int x, int y, int z, int P) { return (x < P && y > P && z > P); } int tryout(int iS, int iP) { if(foo(iS,iS,iS,iP)) { printf("%d", 1000); } else { printf("%d", 10); } retur

考虑C++中的以下代码:

bool foo(int x, int y, int z, int P) {
  return (x < P && y > P && z > P);     
}

int tryout(int iS, int iP) {
  if(foo(iS,iS,iS,iP)) {
       printf("%d", 1000);
  } else {
        printf("%d", 10);
  }
  return 0;
}
我有两个问题:

  • 为什么在
    试用
    方法中有两个跳转到
    .B2.4
    ,而只有一个if语句
  • 来自方法
    foo
    的代码做什么

    movl      $1, %esi                                      #5.15
    xorl      %eax, %eax                                    #5.15
    cmpl      %ecx, %edx                                    #5.15
    cmovg     %esi, %eax                                    #5.15
    
  • xP&&z>P
    
    它有3个条件。将它放入一个
    if
    中并不意味着它只需要一个
    jcc
    进行评估。(注意,
    foo()
    已内联。没有
    调用
    指令`。)

    如果编译器不能将多个测试组合到一个表达式中,通常会按顺序对每个条件进行测试和分支。在本例中,
    icc
    只是内联了它为
    foo()
    所做的工作,但它可以省略第二个
    cmp
    ,因为它正在测试相同的两个变量。请注意,两个分支的分支目标是如何相同的,因为它们都在检查条件的不同部分是否具有相同的
    if
    。您没有得到第三个
    jcc
    ,因为第二个和第三个条件是相同的,所以编译器将它们组合起来

    正如评论所指出的,国际商会应该注意到,这种情况根本不需要任何测试。一个分支或另一个分支总是会被接受,因此它可以完成,并将其编译为对printf的简单调用,而不检查任何内容。

    xp&&z>p
    
    它有3个条件。将它放入一个
    if
    中并不意味着它只需要一个
    jcc
    进行评估。(注意,
    foo()
    已内联。没有
    调用
    指令`。)

    如果编译器不能将多个测试组合到一个表达式中,通常会按顺序对每个条件进行测试和分支。在本例中,
    icc
    只是内联了它为
    foo()
    所做的工作,但它可以省略第二个
    cmp
    ,因为它正在测试相同的两个变量。请注意,两个分支的分支目标是如何相同的,因为它们都在检查条件的不同部分是否具有相同的
    if
    。您没有得到第三个
    jcc
    ,因为第二个和第三个条件是相同的,所以编译器将它们组合起来


    正如评论所指出的,国际商会应该注意到,这种情况根本不需要任何测试。一个分支或另一个分支将始终被采用,因此它可以完成,并将其编译为对PrtTF的简单调用,而不需要对任何东西进行检查。

    这是C还是C++?您对FoE()/Cyto>的调用总是返回false,所以您总是要打印10。我想知道编译器最初是否允许两个条件,然后在优化期间添加第二个跳语句来调用PrtTf,时间为10,因为打印1000永远不会发生。@ CAD:代码是用C++编写的,用-O3编译的,你的表达式被简化为<代码>是 IP & & > IP < /代码>。由于
    iS
    不能为true,而
    iS>iP
    ,因此结果为0/false。由于该值始终为0/false,因此无论结果如何,都会跳转到
    .B2.4
    打印10。事实上,
    cmpl
    jge
    jle
    指令甚至不应该再存在了,因为它们是不必要的;它们应替换为
    jmp..B2.4
    。不知道为什么没有发生…@ChronoKitsune实际上,从
    cmpl%esi,%edi
    jmp..B2.5
    的所有内容都可以删除--无需跳转。该程序实际上是对PrtffIS的一个单独调用,这应该是C或C++。您调用<代码> FoE()/<代码>总是返回false,所以您总是要打印10。我想知道编译器最初是否允许两个条件,然后在优化期间添加第二个跳语句来调用PrtTf,时间为10,因为打印1000永远不会发生。@ CAD:代码是用C++编写的,用-O3编译的,你的表达式被简化为<代码>是 IP & & > IP < /代码>。由于
    iS
    不能为true,而
    iS>iP
    ,因此结果为0/false。由于该值始终为0/false,因此无论结果如何,都会跳转到
    .B2.4
    打印10。事实上,
    cmpl
    jge
    jle
    指令甚至不应该再存在了,因为它们是不必要的;它们应替换为
    jmp..B2.4
    。不知道为什么没有发生…@ChronoKitsune实际上,从
    cmpl%esi,%edi
    jmp..B2.5
    的所有内容都可以删除--无需跳转。该程序实际上是对printfthanks的一次调用,以供您解释。我也发现它内联了方法foo()。谢谢你的解释。我也发现它内联了方法foo()。
    movl      $1, %esi                                      #5.15
    xorl      %eax, %eax                                    #5.15
    cmpl      %ecx, %edx                                    #5.15
    cmovg     %esi, %eax                                    #5.15
    
    x < P && y > P && z > P