此处应用的确切编译器优化(除了尾递归消除之外)是什么?

问题描述 投票:0回答:1

我正在编译一个简单的C程序,实现一个中序树遍历函数:

void inorderTraversal(struct TreeNode* root) {
    if (root == NULL) {
        return;
    }
    inorderTraversal(root->left);  
    printf("%d ", root->val);  
    inorderTraversal(root->right);  
}

然后我使用以下命令编译 .c 文件:

gcc inorder.c -O2 -o inorder_O2

当我尝试使用 BinaryNinja 反编译 inorder_O2 文件时,我得到了该函数的高级 IL 版本:


void inorderTraversal(int32_t* arg1){
    int32_t* i_1 = arg1
    if (arg1 != 0)
        int32_t* i
        do
            int32_t* j_2 = *(i_1 + 8)
            int32_t* j_1 = j_2
            if (j_2 != 0)
                int32_t* j
                do
                    int32_t* k_2 = *(j_1 + 8)
                    int32_t* k_1 = k_2
                    if (k_2 != 0)
                        int32_t* k
                        do
                            int32_t* r15_1 = *(k_1 + 8)
                            if (r15_1 != 0)
                                do
                                    int32_t* rbx_1 = *(r15_1 + 8)
                                    if (rbx_1 != 0)
                                        do
                                            int32_t* r13_1 = *(rbx_1 + 8)
                                            if (r13_1 != 0)
                                                do
                                                    int32_t* r12_1 = *(r13_1 + 8)
                                                    if (r12_1 != 0)
                                                        do
                                                            int32_t* r14_1 = *(r12_1 + 8)
                                                            if (r14_1 != 0)
                                                                do
                                                                    int32_t* r9_1 = *(r14_1 + 8)
                                                                    if (r9_1 != 0)
                                                                        do
                                                                            inorderTraversal(*(r9_1 + 8))
                                                                            __printf_chk(flag: 1, format: &data_2004, zx.q(*r9_1))
                                                                            r9_1 = *(r9_1 + 0x10)
                                                                        while (r9_1 != 0)
                                                                    __printf_chk(flag: 1, format: &data_2004, zx.q(*r14_1))
                                                                    r14_1 = *(r14_1 + 0x10)
                                                                while (r14_1 != 0)
                                                            __printf_chk(flag: 1, format: &data_2004, zx.q(*r12_1))
                                                            r12_1 = *(r12_1 + 0x10)
                                                        while (r12_1 != 0)
                                                    __printf_chk(flag: 1, format: &data_2004, zx.q(*r13_1))
                                                    r13_1 = *(r13_1 + 0x10)
                                                while (r13_1 != 0)
                                            __printf_chk(flag: 1, format: &data_2004, zx.q(*rbx_1))
                                            rbx_1 = *(rbx_1 + 0x10)
                                        while (rbx_1 != 0)
                                    __printf_chk(flag: 1, format: &data_2004, zx.q(*r15_1))
                                    r15_1 = *(r15_1 + 0x10)
                                while (r15_1 != 0)
                            __printf_chk(flag: 1, format: &data_2004, zx.q(*k_1))
                            k = *(k_1 + 0x10)
                            k_1 = k
                        while (k != 0)
                    __printf_chk(flag: 1, format: &data_2004, zx.q(*j_1))
                    j = *(j_1 + 0x10)
                    j_1 = j
                while (j != 0)
            __printf_chk(flag: 1, format: &data_2004, zx.q(*i_1))
            i = *(i_1 + 0x10)
            i_1 = i
        while (i != 0)
}

我猜想进行尾递归消除,因为只剩下一个递归调用。我不知道是什么让这个函数成为一大堆嵌套循环?有确切的编译器优化名称吗?

也就是说,我主要想知道该技术的名称或描述,而不是打开或关闭它的编译器选项。

c compiler-construction compiler-optimization tail-recursion decompiler
1个回答
0
投票

root->right
上的递归是尾调用,因此可以消除。所有
do-while
循环都是这些被消除的尾部调用。

root->left
上的递归不在尾部位置,所以不能这样消除。相反,编译器使用嵌套的
if
语句对前 8 级递归进行开放代码。

如果树的深度超过 8 层,它会实际回调该函数。您可以在最里面的

do
块中看到这一点。

现在我再多思考一下,我可能会向后思考哪些优化是尾部调用,哪些是非尾部调用。

© www.soinside.com 2019 - 2024. All rights reserved.