c/c++开发分享-O2将printf(“%s n”,str)优化为puts(str)

clang玩弄,我编译了一个包含这一行的C程序:

 printf("%sn", argv[0]); 

在没有优化的情况下进行编译时,在设置寄存器后,程序集输出称为printf

 movq (%rcx), %rsi movq %rax, %rdi movb $0, %al callq _printf 

我尝试使用clang -O2编译。 printf调用被替换为puts调用:

 movq (%rsi), %rdi callq _puts 

虽然这在这种情况下非常有意义,但它提出了两个问题:

    使用LLVM替换printf的优化是在LibCallSimplifier类中。 您可以在llvm / include / llvm / Transforms / Utils / SimplifyLibCalls.h中查看头文件,并在llvm / lib / Transforms / Utils / SimplifyLibCalls.cpp中查看实现。 查看这些文件将给出一些已完成的其他库调用替换优化的示例(头文件可能更容易开始)。 当然还有LLVM所做的其他许多其他优化,你可以通过查看LLVM传递列表来了解其中的一些优化。

    是的,你可以。 LLVM非常模块化,可以在一系列过程中对IR进行转换。 因此,如果您想为自己的库添加一个自定义传递,您可以这样做(尽管理解LLVM编译器流如何工作仍然是一项相当大的工作)。 一个很好的起点是文档: 编写LLVM Pass 。

    这种优化取决于编译器知道名为printf只能是C标准定义的printf函数。 如果程序将printf定义为其他内容,则程序将调用未定义的行为。 这使得编译器可以在调用标准printf函数的情况下替换调用printf 。 它并不担心它“工作”就像用户定义的printf函数被调用一样。 因此,这些函数替换优化几乎仅限于C或C ++标准中定义的函数。 (如果编译器以某种方式知道给定的标准生效,也许还有其他标准。)

    如果没有自己修改编译器的源代码,就无法通过自己的函数告诉编译器这些函数替换是可行的。 但是,由于存在限制,您可以使用内联函数执行类似操作。 例如,你可以用类似这样的东西实现类似于printf / puts优化的东西:

     inline int myprintf(char const *fmt, char const *arg) { if (strcmp(fmt, "%sn") == 0) { return myputs(args); } return _myprintf_impl(fmt, arg) } 

    启用优化后,编译器可以在编译时选择基于fmt参数调用哪个函数,但只有在它可以确定它是一个常量字符串时。 如果它不能,或者没有启用优化,那么编译器必须发出在每次调用时检查它的代码,这很容易将其转化为悲观。 请注意,此优化取决于编译器知道strcmp如何工作以及完全删除调用,因此编译器可以进行另一个库函数调用替换的示例。

    你可以使用GCC的__builtin_constant_p函数改进这个:

     inline int myprintf(char const *fmt, char const *arg) { if (__builtin_constant_p(fmt[0]) && strcmp(fmt, "%sn") == 0) { return myputs(arg); } return _myprintf_impl(fmt, arg); } 

    在GCC下,这导致代码永远不会检查格式字符串的运行时间。 如果在编译时可以确定fmt"%sn"那么它会生成无条件调用myputs代码,否则它将生成无条件调用_myprintf_impl代码。 因此,启用优化后,此function永远不会是悲观。 不幸的是,当clang支持__builtin_constant_p函数时,我的clang版本总是生成无条件调用_myprintf_impl代码。

    puts是一个比printf小得多的函数,可执行文件的大小通常只有一半。 只有在将数字转换为字符串进行打印时才需要printf,您可以使用itoa()执行此操作

      以上就是c/c++开发分享-O2将printf(“%s n”,str)优化为puts(str)相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注(猴子技术宅)。

      本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

      如若转载,请注明出处:https://www.ssfiction.com/c-cyuyankaifa/545836.html

      发表评论

      电子邮件地址不会被公开。 必填项已用*标注