How can I optimize LLVM assembly cross-compiled with gcc? - gcc

I am using LLVM to generate Alpha assembly. Their Alpha ISA support is experimental and I cannot find a way to work around a bug. If I use -O0 during LLVM bytecode-to-Alpha assembly creation, the assembly generated is fine.
I want optimized assembly, however. Is there some option in gcc (which is my final cross compiler) that would optimize the assembly? I tried -O3 while converting the Alpha assembly to object file, but I did not see any optimization happening. Is it even possible to do back-end optimization after assembly creation?

If you want optimized assembly, you obviously should ask LLVM for it. So pass -O3 to llc, not to gcc.

Related

gcc's option dose not work until newer version

I recently struggle with gcc's optimization, hope to help with performance improvement.
I found the option -freorder-blocks-and-partition.
(This option exist on very old versions of gcc, such as gcc 5.6.)
It can be used to partition cold/hot cold to separate function, together with -ffunction-sections and linker script, cold/hot code can be put into separate ELF sections (.text section and .text.cold section).
But this option only works on recent gcc version.
I test it on gcc 10.1, and use the following compiler exploration tool, make sure it works start from version 8.1:
in gcc8.1: https://godbolt.org/z/hGcnMM, the assembly code contains a function like this:
fa(int, int) [clone .cold.0]:
In gcc7.1: https://godbolt.org/z/rhqjE1, the assembly code does not contain such function.
Why does it not work on older gcc?
And is there any way to control the older version gcc to apply this optimization?

What is lto1.exe?

when you inspect mingw you will find the c compiler cc1.exe (funny growing in size in 9.2 it is almost 25 MB ) cc1plus.exe is c++ compiler (same sizes) collect2.exe is linker (afiak) nut what is lto1.exe?
i googled for it more than hour but not found info on this.. is there some good info on this avaliable to read? tnx
ps. i suspect that it may be related to link time optimisation but found nothing more about it and i would like to know better
there is also a question what is gcc.exe g++.exe and mingw32-gcc.exe mingw32-g++.exe then
i need more informatin, the most the better , tnx
This is not mingw / Windos specific; it's a feature / component of GCC.
what is lto1.exe?
It's the lto compiler :o). lto is basically byte code written when compiled with -flto where "lto" or "LTO" stands for "link-time optimization".
These optimizations are not performed by the linker but by the compiler at link time to perform global optimizations when (byte-)code from all the modules is available. The flow is as follows:
The C/C++ compiler (cc1 for C or cc1plus for C++) compiles C/C++ to byte-code and writes it to the assembly file *.s.
Assembly is assembled by the assembler to object code *.o as usual. lto-code is shipped in dedicated sections.
At link time, the linker (plugin) calls back the compiler and supplies all the objects and libraries as requested. byte-code is extracted, and the lto1 compiler compiles it to final machine code.
The final machine code is assembled by the assembler to object code.
The linker links / locates these objects to final executable code.
You see the byte-code in the lto sections with -save-temps and having a look at the saved *.s files. Recent versions of GCC don't even bother with writing assembly code; they are just writing lto code. To see the assembly code, specify -ffat-lto-objects. Notice however that this is not the final code.
funny growing in size in 9.2 it is almost 25 MB
The sizes of GCC executables depend not only on the GCC major version, but also highly on how well the compiler used to build GCC is optimizing.
[Edit] Some information on LTO can be found on the GCC wiki for LTO. Notice however that this page is no more active. One goto place for gory GCC internals is the gcc-help#gcc.gnu.org mailing list where all the developers are. There is also a section about LTO in the GCC internals.

How to enable address sanitizer for multiple C++ binaries

I am working on a product that is composed of multiple C++ executables and libraries that have various dependencies on one another. I am building them all with GCC and -fsanitize-address.
From what I understand, if I want to use address sanitizer with a library I have to build it as a shared object (which is the default option for GCC). Because of this, I thought the best option would be to build address sanitizer statically with -static-libasan for the executables and build it dinamically for the libraries. However, when I do that I get a link error when building one of the C++ executables:
==10823==Your application is linked against incompatible ASan runtimes
This makes me think that static and dynamic version of address sanitizer cannot be mixed with GCC, am I right? I was not able to find any information about this on the sanitizers GitHub page.
TLDR:
If you use GCC/Clang and both main executable and shlibs are sanitized, you don't need to do anything special - just stick with default -fsanitize=address.
If you use GCC and only shlibs are sanitized, again keep using -fsanitize=address and additionally export LD_PRELOAD=$(gcc -print-file-name=libasan.so) when running your application.
If you use Clang and only shlibs are sanitized, compile/link with -fsanitize-address -shared-libasan and additionally export LD_PRELOAD=$(clang -print-file-name=libclang_rt.asan-x86_64.so) when running the app.
Now some explanations. Originally Asan existed only in Clang which by default used (and still uses) -static-libasan. When it was ported to GCC, GCC developers decided that shared runtime is preferred (e.g. because it allows one to sanitize just one shared library and keep main executable unsanitized e.g. sanitize Python module without recompiling python.exe, see wiki for other examples). Both approaches are binary incompatible so you can't link part of your applications with static runtime and part with dynamic runtime.
Roughly
GCCs -fsanitize=address is equivalent to Clangs -fsanitize=address -shared-libasan (and -shared-libasan is second-class citizen in Clang so not as well supported)
Clangs -fsanitize=address is equivalent to GCCs -fsanitize=address -static-libasan (and again, -static-libasan is second-class citizen in GCC so has some issues)
As a side note, for other GCC/Clang Asan differences see this helpful wiki.

Is there a binutils for llvm?

The LLVM compiler toolchain has a gcc that is compatible with normal gcc. The advantage of using llvm-gcc is that is goes to an arbitrary target, meaning normal gcc will say no such target when you try to compile to a random architecture, say mips-apple-darwin. llvm-gcc will, however, actually build a compiler for Mac OS X on a mips processor.
Here's the catch however: to build to a random target, you need the binutils built for that target already. So if you have a target that llvm would compile to but binutils can't, then you can't make the compiler because the GNU Binutils doesn't support that target.
So... Here's the question: Is there an equivalent llvm-binutils like an llvm-gcc that is compatable with GNU Binutils? (meaning one that builds to an arbitrary target, not one from a list.)
EDIT:
By arbitrary, I mean I don't pick the target when I run llvm-gcc, I pick the target when I compile llvm-gcc. Meaning: If I try to compile GCC for mips-apple-darwin, I get a target not supported. But If I build llvm-gcc for mips-apple-darwin, it works as long as I have mips-apple-darwin-as and mips-apple-darwin-ld.
As far as I can tell, LLVM does not compile for an arbitrary target. You must have all includes and definition to fit your target, and normally, llvm has a back-end to generate code for your said target. Read "Can I compile C or C++ code to platform-independent LLVM bitcode?" from http://llvm.org/docs/FAQ.html .
To answer the question, llvm does not uses GNU binutils, llvm has its own 'binutils' to generate code (called LLVM core project). Disassembler and debugger are part of LLDB project.
Where LLVM bring some independence, it's on the language level. Your project can be coded in C/C++, Ada, Fortran, etc ... llvm come with the ability to transform your code in an intermediate representation. That IR will eventually generate code.
llvm-gcc doesn't support arbitrary targets. llvm-gcc has to be built specifically for any given target. clang + LLVM can. I'm trying to do exactly that with ellcc: http://ellcc.org. I'm using binutils for assembly and linking.

How do I translate CIL to LLVM IR?

I want to compile C# to LLVM IR. So I think translate compiled CIL to LLVM IR is one way I can try.
There are some tools I can use such as vmkit and mono-llvm.
Is anybody using this tools? Or how can I translate CIL to LLVM?
The answer depends on your goals. Why do you want to translate C# to LLVM?
VMKit was designed as a framework for building virtual machine implementations. I believe it had some support for the CLR at one point, but that support since stagnated in favor of its JVM implementation. Its purpose is to make building a VM from scratch.
Mono-llvm is a project that replaces the mono JIT backend with an LLVM back end. It's goal is to improve the performance of JITed code on Mono.
If your goal is to use Mono, with better performance, mono-llvm is a good choice.
If you want to build an entire VM from scratch, then VMKit might work.
If you are just looking to implement an ahead-of-time compiler that produces executables with no CLR dependencies, you can just download the LLVM core libraries from:
http://llvm.org/
Basically it would translate the CIL into a textual representation of LLVM IR and then use the LLVM APIs to compile it to native machine code.
I don't know if LLVM will generate object files for you. You may have to generate them yourself, but that's pretty easy. It's basically just stuffing the machine code into a data structure, building up string, section, and symbol tables, and then serializing everything to disk.
To get LLVM IR code from CIL you need to use the tool il2bc (other name C# Native) which you can download from http://csnative.codeplex.com/.
You just need to perform some simple steps.
Il2Bc.exe <Your DLL>.dll
If you want to generate an executable from it, you need to compile the generated .ll file (LLVM IR Code).
For example, you have your "Hello World" app
Compile it (it will generate a helloworld.ll file)
Il2Bc.exe helloworld.cs /corelib:CoreLib.dll
Generate LLVM IR file for the core library (it will generate corelib.ll file)
Il2Bc.exe CoreLib.dll
You need to generate an EXE file (it will generate a .EXE file):
llc -filetype=obj -mtriple=i686-w64-mingw32 CoreLib.ll
llc -filetype=obj -mtriple=i686-w64-mingw32 helloworld.ll
g++ -o helloworld.exe helloworld.obj CoreLib.obj -lstdc++ -lgc-lib -march=i686 -L .
I think I understand the question to be that you want to use LLVM IR in the same way that the GCC can compile Java using gcj?
The LLVM had an option to output CIL directly from whatever front end you used (So in theory you could do C/C++ to CIL). The following command options:
llc -march=msil
would output CIL from (in theory) any supported LLVM Front-End.
Going from C# or CIL to LLVM IR hasn't been done yet (or at least finished). You'd need a C# front-end.
VMKit had some kind of C# front end scaffolding. Support was never feature complete and interest has since faded. They've moved to just supporting Java. You might try their source repository and see if there are any remnants of their early C# work can be reworked into a full C# frontend.
Also note that you can write your own C# to LLVM IR compiler in C# (using Mono or whatever) and use P/Invoke to call into LLVM libraries and create LLVM IR. There are some good information out there such as Writing Your Own Toy Compiler Using Flex, Bison and LLVM.
This area is also getting interesting now that the compiler as a service (Roslyn) project has had its first couple of CTP releases, and Mono has its Mono.CSharp project. Though I think Roslyn is a bit more feature-rich.

Resources