小编JCx*_*JCx的帖子

为什么这个函数将RAX作为第一个操作推送到堆栈?

在下面的C++源代码的汇编中.为什么RAX被推入堆栈?

正如我从ABI理解的那样,RAX可以包含来自调用函数的任何内容.但是我们将它保存在这里,然后将堆栈移回8个字节.所以堆栈上的RAX,我认为只与std::__throw_bad_function_call()操作相关......?

代码:-

#include <functional> 

void f(std::function<void()> a) 
{
  a(); 
}
Run Code Online (Sandbox Code Playgroud)

gcc.godbolt.org使用Clang 3.7.1 -O3 输出:

f(std::function<void ()>):                  # @f(std::function<void ()>)
        push    rax
        cmp     qword ptr [rdi + 16], 0
        je      .LBB0_1
        add     rsp, 8
        jmp     qword ptr [rdi + 24]    # TAILCALL
.LBB0_1:
        call    std::__throw_bad_function_call()
Run Code Online (Sandbox Code Playgroud)

我确定原因很明显,但我很难弄清楚.

这是一个没有std::function<void()>包装器的尾部调用,用于比较:

void g(void(*a)())
{
  a(); 
}
Run Code Online (Sandbox Code Playgroud)

琐碎的:

g(void (*)()):             # @g(void (*)())
        jmp     rdi        # TAILCALL
Run Code Online (Sandbox Code Playgroud)

c++ x86 assembly x86-64 abi

22
推荐指数
3
解决办法
2098
查看次数

优化写出循环

尽管存在__restrict关键字,但将成员变量移动到局部变量会减少此循环中的写入次数.这是使用GCC -O3.Clang和MSVC在两种情况下都优化写入. [注意,由于这个问题已经发布,我们观察到将__restrict添加到调用函数会导致GCC也将商店移出循环.请参阅下面的godbolt链接和评论]

class X
{
public:
    void process(float * __restrict d, int size)
    {
        for (int i = 0; i < size; ++i)
        {
            d[i] = v * c + d[i];
            v = d[i];
        }
    }

    void processFaster(float * __restrict d, int size)
    {
        float lv = v;
        for (int i = 0; i < size; ++i)
        {
            d[i] = lv * c + d[i];
            lv = d[i];
        }
        v = lv;
    }

    float c{0.0f};
    float v{0.0f};
};
Run Code Online (Sandbox Code Playgroud)

使用gcc …

c++ optimization g++

13
推荐指数
1
解决办法
353
查看次数

原子操作,std :: atomic <>和写入顺序

GCC汇编了这个:

#include <atomic>
std::atomic<int> a; 
int b(0);

void func()
{
  b = 2; 
  a = 1;
}
Run Code Online (Sandbox Code Playgroud)

对此:

func():
    mov DWORD PTR b[rip], 2
    mov DWORD PTR a[rip], 1
    mfence
    ret
Run Code Online (Sandbox Code Playgroud)

所以,为我澄清一些事情:

  • 读取'a'的任何其他线程是否保证将'b'读为2.
  • 为什么MFENCE在写入"a"之后才发生.
  • 无论如何,对"a"的写入保证是原子(在狭窄的非C++意义上)操作,这是否适用于所有英特尔处理器?我假设这个输出代码.

另外,clang(v3.5.1 -O3)这样做:

mov dword ptr [rip + b], 2
mov eax, 1
xchg    dword ptr [rip + a], eax
ret
Run Code Online (Sandbox Code Playgroud)

这似乎对我的小脑子更直接,但为什么不同的方法,每个方法的优势是什么?

c++ compiler-construction x86 assembly

11
推荐指数
1
解决办法
2267
查看次数

为什么编译器会为此循环的每次迭代将成员变量写入内存?

第一个版本通过将值从内存移动到局部变量来进行优化.第二个版本没有.

我原以为编译器可能会选择在这里进行localValue优化,而不是在循环的每次迭代中从内存中读取和写入值.为什么不呢?

class Example
{
    public:
        void processSamples(float * x, int num) 
        {
            float localValue = v1;

            for (int i = 0; i < num; ++i)
            {
                x[i] = x[i] + localValue;
                localValue = 0.5 * x[i];
            }

            v1 = localValue;
        }

        void processSamples2(float * x, int num)
        {

            for (int i = 0; i < num; ++i)
            {
                x[i] = x[i] + v1;
                v1 = 0.5 * x[i];
            }

        }

    float v1;
};
Run Code Online (Sandbox Code Playgroud)

processSamples组装成代码如下:

.L4:
  addss xmm0, DWORD PTR …
Run Code Online (Sandbox Code Playgroud)

c++ optimization g++ clang clang++

7
推荐指数
1
解决办法
236
查看次数

应用程序验证器与 Gflags

我正在尝试调试堆损坏问题。我看过一些帖子提到 gflags 和应用程序验证器。这两个工具之间有什么区别,或者应用程序验证器是围绕相同技术的漂亮 UI?

windows debugging

5
推荐指数
1
解决办法
687
查看次数

内联虚拟功能(Clang与GCC)

举个愚蠢的例子:

class Base
{
  public:
    virtual void ant() { i++; };
    virtual void dec() { i--; };
  int i;
};

void function(Base * base) 
{ 
  base->ant(); 
  base->dec(); 
}
Run Code Online (Sandbox Code Playgroud)

我想象这将由编译器实现的方式是两个虚函数调用。Clang就是这样做的(对dec()的调用使用尾部调用):

function(Base*):                      # @function(Base*)
        push    rbx
        mov     rbx, rdi
        mov     rax, qword ptr [rbx]
        call    qword ptr [rax]
        mov     rax, qword ptr [rbx]
        mov     rdi, rbx
        pop     rbx
        jmp     qword ptr [rax + 8]     # TAILCALL
Run Code Online (Sandbox Code Playgroud)

另一方面,GCC在部分内联函数调用方面还有很长的路要走:

Base::ant():
        add     DWORD PTR [rdi+8], 1      # this_2(D)->i,
        ret
Base::dec():
        sub     DWORD PTR [rdi+8], 1 …
Run Code Online (Sandbox Code Playgroud)

optimization x86 g++ clang

4
推荐指数
1
解决办法
621
查看次数