【问题标题】:g++ inline asm not working as expected with optimization flagg++ inline asm 在优化标志下无法按预期工作
【发布时间】:2014-04-10 15:42:43
【问题描述】:

我写了一个关于3x + 1问题的简单程序,打算告诉跳转指令和条件转移指令之间的区别。

代码在使用标志-O0 编译时运行良好。但是,当我使用-O1-O2 标志编译它时,代码似乎陷入了“无限循环”。

您有什么想法可以纠正我的代码以使其正常工作吗?谢谢

g++ 版本

$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

编译命令

g++ -std=c++0x -O1 -Wall -g -o "foo" "foo.cc"

这是我的代码。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <ctime>

using namespace std;

#define print(x) cout << x << endl
#define input(x) cin >> x
#define ENTER "\n\t"

#if defined(__i386__)
static __inline__ unsigned long long rdtsc(void)
{
    unsigned long long int x;
    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
    return x;
}
#elif defined(__x86_64__)
static __inline__ unsigned long long rdtsc(void)
{
    unsigned hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
#endif

const int SIZE = 100000;

int nums[SIZE];

void down_to_one(int v)
{
    if (v == 1) {
        return;
    } else if (v % 2 == 0) {
        down_to_one(v >> 1);
    } else {
        down_to_one(3 * v + 1);
    }
}

void down_to_one_asm(int v)
{
    if (v == 1) {
        return;
    }
    __asm__ __volatile__(
        "movl %0, %%eax" ENTER
        "sarl %%eax"     ENTER
        "leal 1(%0, %0, 2), %%ebx" ENTER
        "testl $1, %0" ENTER
        "cmovel  %%eax, %0" ENTER
        "cmovnel %%ebx, %0" ENTER
        :"=c"(v)
        :"c"(v)
    );
    down_to_one_asm(v);
}

int main()
{
    unsigned long long start, end;

    start = rdtsc();
    for (int i = 1; i <= SIZE; i++) {
        down_to_one(i);
    }
    end = rdtsc();
    print(end - start);

    ////
    __asm__ ("":::"memory");
    ////

    start = rdtsc();
    for (int i = 1; i <= SIZE; i++) {
        down_to_one_asm(i);
    }
    end = rdtsc();
    print(end - start);

    return 0;
}

【问题讨论】:

    标签: c++ g++ compiler-optimization inline-assembly


    【解决方案1】:

    您尚未指定无限循环发生的位置。问题的一个潜在来源是down_to_one_asm 函数。您还需要指定已破坏的寄存器,例如

    : "=c" (v) : "c" (v) : "%eax", "%ebx"

    "-O0" 可能让您侥幸逃脱,但更高级别可能正在优化调用堆栈/帧设置 - 而"-O2" 正在 (IIRC) 实现尾调用优化。

    【讨论】:

    • 非常感谢。我忘了申报“破坏登记册”。再次感谢。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 2015-08-25
    • 1970-01-01
    相关资源
    最近更新 更多