问题标签 [llvm-clang]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
llvm - 如何告诉clang不要将寄存器保存到堆栈?
目标
我目前正在尝试 avr-llvm(支持 AVR 作为目标的 llvm)。我的主要目标是使用它希望更好的优化器(与 gcc 相比)来实现更小的二进制文件。如果您对 AVR 稍有了解,您就会知道您只有很少的内存。
我目前使用 ATtiny45、4KB 闪存和 256 字节(只是字节而不是 KB!)的 SRAM。
问题
我正在尝试编译一个简单的 C 程序(见下文),以检查生成了哪些汇编代码以及机器代码大小是如何发展的。我使用“clang -Oz -S test.c”来生成汇编输出并优化它以实现最小尺寸。我的问题是不必要地保存了寄存器值,因为我知道这种方法永远不会返回。
我的问题...
如果需要,我如何告诉 llvm 它可以破坏任何寄存器而不保存/恢复它的内容?任何想法如何进一步优化它(例如更有效的堆栈设置)?
详细信息/示例
这是我的测试程序。如上所述,它是使用“clang -Oz -S test.c”编译的。
如您所见,它只有一个 uint8_t 类型的“易失性”变量(如果我不将其设置为易失性,一切都会被优化)。这个变量设置为1。最后有一个无限循环。现在让我们看看汇编输出:
是的!对于这样一个简单的程序,有很多机器代码。我刚刚测试了一些变化并查看了 AVR 的参考手册......所以我可以解释发生了什么。让我们来看看每个部分。
这就是“牛肉”,它只是在做我们的 c 程序要做的事情。它使用值“1”加载 r24,该值存储在 Y+1(堆栈指针 + 1)处的内存中。当然还有我们的无限循环:
注意:需要无限循环。否则将__attribute__ ((noreturn))
被忽略,堆栈指针+保存的寄存器稍后会恢复。
就在此之前,“Y”中的指针已设置:
这里发生的是:
- Y(寄存器对 r28:r29 相当于“Y”)从端口 61 和 62 加载,这些端口映射到一些“寄存器”,即 SPL 和 SPH(“S”的“L”ow 和“H”高字节大头钉“P”指针)
- 加载的值递减(sbiw r29:r28)
- 堆栈指针的更改值被保存回端口;我想避免问题:之前禁用中断;“cli/sti”的状态[存储在寄存器 63 (SREG)] 被保存到 r0,然后恢复到端口 63。
堆栈寄存器的这种设置似乎效率低下。要增加堆栈指针,我只需要将 r0 推入堆栈。然后我可以将 SPH/SPL 的值加载到 r29:r28 中。然而,这可能需要在源代码中对 llvm 的优化器进行一些更改。如果必须为局部变量保留超过 3 个字节的堆栈,则上面的代码才有意义(即使优化 -O3,对于 -Oz,最多 6 个字节也是有意义的)。怎么...我想我们需要为此接触llvm的来源;所以这超出了范围。
更有趣的是这部分:
由于 main() 不打算返回,这没有意义。这只会将 RAM 和闪存浪费在愚蠢的指令上(请记住:我们在某些设备中只有 64、128 或 256 字节的 SRAM)。
我对此进行了进一步调查:如果我们让 main 返回(例如没有无限循环)堆栈指针被恢复,我们在末尾有一个“ret”指令并且寄存器 r28 和 r29 通过“pop r29,pop”从堆栈中恢复28"。但是编译器应该知道,如果函数“main”的范围永远不会离开,那么所有寄存器都可以被破坏,而无需将它们存储到堆栈中。
当我们谈到 2 字节 RAM 时,这个问题似乎有点“愚蠢”。但是想想如果程序开始使用其余的寄存器会发生什么。
这一切真的改变了我对当前“编译器”的看法。我认为今天通过汇编程序进行优化的空间不大。不过好像有...
所以,问题仍然是......
您是否知道如何改善这种情况(提交错误报告/功能请求除外)?
我的意思是:是否有一些我可能忽略的编译器开关......?
附加信息
使用__attribute__ ((OS_main))
适用于 avr-gcc。
输出如下:
这(在我看来)在大小(6 条指令或 12 字节)上是最佳的,而且对于这个示例程序的速度也是最佳的。llvm 是否有任何等效属性?(clang version '3.2 (trunk 160228) (based on LLVM 3.2svn)' 既不知道 OS_task 也不知道 OS_main)。
ios - 在 iOS 上使用 NEON 乘积
即使我armv7
只编译,NEON 乘法累加内在函数似乎被分解为单独的乘法和加法。
我在 Xcode 最新 4.5 的多个版本、iOS SDK 5 到 6 以及不同的优化设置(通过 Xcode 和直接通过命令行构建)都体验过这一点。
例如,构建和拆卸一些test.cpp
包含
和
结果是
而不是vmla.f32
.
请问我做错了什么?
c - -fcatch-undefined-behavior 仅捕获超过大小超过 1 个元素的本地数组访问
我对 clang 中的 catch-undefined-behavior 标志有疑问。我在一个用 C 编写的大型项目中进行了尝试,其中有一次,用户提供的整数值 (i) 到达。然后我添加了以下代码:
但是当我使用 gdb 运行代码时,它只会在变量 i 的值为 4 或更大时停止。因此,当我将值 3 传递给 i 时,它仍然会访问其边界之外的数组而不会停止。
这是 -fcatch-undefined-behavior 的已知限制吗?还是只检查访问是否在堆栈框架之外,而不是在本地数组之外?
最好的问候克里斯蒂安
PS:我使用 clang+llvm 3.0 作为编译器/链接器。目标是 x86。该程序在 Windows XP 机器上的 xubuntu 12.04 虚拟机中运行。
llvm - 在 llvm 中为 CloneFunction 的 vmap 参数传递什么?
我正在尝试克隆另一个函数的确切副本。我无法在互联网上找到任何使用 CloneFunction 的示例。
compiler-errors - 如何解决错误:“snprintf”的类型冲突
在我的应用程序中,我使用Compiler for C/C++/Objective-C是用于模拟器的Apple LLVM 编译器 4.1 。对于模拟器,这是可行的。当我为设备编译相同的代码时,我将C/C++/Objective-C 的编译器更改为LLVM GCC 4.2。这次我在 stdio.h “冲突类型”中遇到错误“sprintf”。
我正在使用 Mac OS x 10.7.4 Xcode 4.5(iOS 6)
这在 (Mac OS x 10.7.4 & Xcode 4.2.3(iOS 5)) && (Mac OS x 10.6.8 & Xcode 3.2.3(iOS 4)) 中运行良好。
LLVM 编译器的 iOS 5 和 iOS 6 有什么区别。有人请帮帮我吗?
c++ - Clang 不工作。未定义的符号错误。代码在 gcc 中编译得很好
我决定尝试一下 Clang,因为我听说过关于它的好消息,并且我想尝试 C++11 的一些特性。所以,像往常一样,我从一个简单的 hello world 程序开始。
使用 GCC 编译得很好的东西不能在 Clang 中编译。相反,我得到了这个错误。
linux - 尝试构建 LLVM 和 clang 的问题
我正在尝试在我的机器(Ubuntu 12.04)上构建 LLVM 和 clang。我按照http://clang.llvm.org/get_started.html上的说明进行到第 6 步(构建 LLVM 和 clang)。当我制作时,我收到大量关于可能不兼容的插件版本的警告(与dragonegg有关?)。但是整个事情都因这些消息而失败:
所以你能给我的任何帮助都会非常有帮助。
谢谢
cygwin - 如何在cygwin上构建llvm和clang
我可以从cygwin上的源代码构建LLVM和 clang吗?
构建 LLVM 和 Clang 需要多长时间?因为我尝试在 VirtualBox 上构建它们,所以大约需要 2 个小时。
makefile - 如何用clang编译c99-to-c89转换器?
我正在尝试在 Windows 中为 VisualStudio 编译 ffmpeg,其中一个步骤是根据这篇文章使用 clang 编译c99-to-c89代码。我设法创建了 clang.exe,但我如何用它编译 c99-to-c89 代码?
我在 c99-to-c89 中更改了一点 makefile,所以CC
变量现在指向 clang.exe 编译器而不是 cl.exe
但是当我运行make
命令时,我得到clang: error: unsupported use of internal gcc -Z option '-Z7'
. 我猜是问题所在CFLAGS
,LDFLAGS
但我不知道如何解决它,因为缺乏对 makefile 和 clang 的了解。
clang - 通过 pragma clang 诊断禁用 -Werror
用于将-Werror
所有警告视为错误,我不想抑制已弃用的声明警告:
怎么做 ?