How to find corresponding assembly for c++ code - c++

I have a rather long function containing a loop which I want to optimize. When I compile the code using gcc -S -O3 i get some thousand lines of assembly. How do I find the corresponding assembly code for the loop I am interested in ?

It will be best to use a debugger, such as ddd and look at the corresponding assembly code.

The easiest way is to set a breakpoint, run your code and you'll see the disassembly with all the symbols corresponding to your code.

Related

Force at least one pass of a do loop in legacy Fortran code

I have to compile an old fortran source already compiled using g77 but with the option -fonetrip to force execution of do loops at least once. I was not able to find this option or an equivalent in gfortran and the execution without this option aborts.
Any suggestions?
Probably I can go back to g77 but I do like if possible to use gfortran....

Checking the code generated implicitly by the C++ compiler

Is there a way (g++ option?) to check what code is generated implicitly by the C++ compiler (e.g. all the default constructors/destructors)?
Having the generated C++ code would be ideal, but at least the assembly would be good. Using:
g++ -S -g -O0 <file.cpp>
does not give me any label with generated constructors/destructors.
I think option the -fdump-tree-original is about as close as you can get. Unfortunately it'll show both your own code and automatically generated code, but it won't label which is which. However it's the most readable of GCC's dumps and it shows the generated code before any optimizations are performed.
Another option would be to use -fdump-translation-unit. That creates a raw dump of the tree with literally everything in it. The nodes that compiler made up will be marked as "artificial". However, the format isn't easy for humans to read and there's a lot of it wade through even for a trivial source file. To get any useful information out of it you'd probably need to write a program to read it in and then walk the tree to find the nodes you're interested in and print them out it a more readable format.

Assembly language output in a C++ compiler

Does a C++ compiler generate machine code via assembly language code (i.e., c++ compiler first converts C++ code to assembly language code and then uses assembly language compiler to convert it to machine code), or is assembly language output generation just an option for reference or debugging purposes?
It doesn't have to, but most do it anyway, as the same assembler (program) can be used for the output of the C/C++/whatever-to-assembler compiler.
g++ for example generates assembler code first (you can see the generated assembler using the -S switch).
MSVC does it too (/FAs).
They used to, a long time ago, although that was typical only for C compilers. The first one I used worked that way, a long time ago. Not unusual for ones that generated code for unusual hardware and operating systems, they saved the cost of writing the object file generator and leveraged existing linkers.
Modern compilers don't bother with the extra step of generating machine code as text and running an assembler afterward, they generate the machine code directly in binary form. The compile speed advantage is fairly significant, text isn't cheap. The option to generate it in textual form from binary is pretty simple to implement.

How to check code generated by C++ compiler?

just like in topic - is there any software to open (what?) and here I don't even know what to open - file with object code or exe?
My today's questions (if only todays ;)) may seem bit odd but I'm going through excersises in "The C++ Programming Language" by B.S. and sometimes I'm just stuck on particular question. I'm sometimes bit irritated by style of this book (excellent in many aspects) that he (B.S.) asks some questions which you won't find answer in his book on how to do it or even where to start.
Like this one for example:
Run some tests to see if your compiler really generates equivalent code for iteration using pointers and iteration using indexing. If different degrees of opimization can be requested, see if and how that affects the quality of the generated code.
Thats from chapter 5 question 8. Up to this point nowhere in this book is even mentioning testing and analyzing code generated by compiler.
Anyway, if someone could help me with this I'll be greatful.
Thank you.
The debugger will help you. Most debuggers let you halt the program and look into disassembly. The nice thing is they point you right to disassembly of the line you set the breakpoint to, not to just all the compilation result.
Once in a while I do that in Visual Studio - compile the program, put a breakpoint onto the beginning of code of interest, start the program, then when it is halted I open the disassembly and immediately see the code corresponding to that C++ code.
If you're using g++, you can do g++ -S main.cpp. This will output the assembly in a file called main.s. However, if the functions you're interested in are spread across different .cpp files, it might be more convenient to do an objdump on the final executable.
There's also a nice tool called embroider that pretty-prints the objdump output for you as HTML, crosslinking the various function calls and jumps.
Many compilers can generate "listing" files of the assembly code they are generating during compilation, interspersed with the statements from the C source code. Also, there are tools which disassemble object and executable files.
How these tools are actually activated is depending on your toolchain, obviously.

Verifying compiler optimizations in gcc/g++ by analyzing assembly listings

I just asked a question related to how the compiler optimizes certain C++ code, and I was looking around SO for any questions about how to verify that the compiler has performed certain optimizations. I was trying to look at the assembly listing generated with g++ (g++ -c -g -O2 -Wa,-ahl=file.s file.c) to possibly see what is going on under the hood, but the output is too cryptic to me. What techniques do people use to tackle this problem, and are there any good references on how to interpret the assembly listings of optimized code or articles specific to the GCC toolchain that talk about this problem?
GCC's optimization passes work on an intermediary representation of your code in a format called GIMPLE.
Using the -fdump-* family of options, you can ask GCC to output intermediary states of the tree.
For example, feed this to gcc -c -fdump-tree-all -O3
unsigned fib(unsigned n) {
if (n < 2) return n;
return fib(n - 2) + fib(n - 1);
}
and watch as it gradually transforms from simple exponential algorithm into a complex polynomial algorithm. (Really!)
A useful technique is to run the code under a good sampling profiler, e.g. Zoom under Linux or Instruments (with Time Profiler instrument) under Mac OS X. These profilers not only show you the hotspots in your code but also map source code to disassembled object code. Highlighting a source line shows the (not necessarily contiguous) lines of generated code that map to the source line (and vice versa). Online opcode references and optimization tips are a nice bonus.
Instruments: developer.apple.com
Zoom: www.rotateright.com
Not gcc, but when debugging in Visual Studio you have the option to intersperse assembly and source, which gives a good idea of what has been generated for what statement. But sometimes it's not quite aligned correctly.
The output of the gcc tool chain and objdump -dS isn't at the same granularity. This article on getting gcc to output source and assembly has the same options as you are using.
Adding the -L option (eg, gcc -L -ahl) may provide slightly more intelligible listings.
The equivalent MSVC option is /FAcs (and it's a little better because it intersperses the source, machine language, and binary, and includes some helpful comments).
About one third of my job consists of doing just what you're doing: juggling C code around and then looking at the assembly output to make sure it's been optimized correctly (which is preferred to just writing inline assembly all over the place).
Game-development blogs and articles can be a good resource for the topic since games are effectively real-time applications in constant memory -- I have some notes on it, so does Mike Acton, and others. I usually like to keep Intel's instruction set reference up in a window while going through listings.
The most helpful thing is to get a good ground-level understanding of assembly programming generally first -- not because you want to write assembly code, but because having done so makes reading disassembly much easier. I've had a hard time finding a good modern textbook though.
In order to output the optimizations applied you can use:
-fopt-info-optimized
To see those that have not been applied
-fopt-info-missed
Beware that the output is sent to standard error stream so to see it you actually have to redirect that : ( hint 2>&1 )
Here is nice example of :
g++ -O3 -std=c++11 -march=native -mtune=native
-fopt-info-optimized h2d.cpp -o h2d 2>&1
h2d.cpp:225:3: note: loop vectorized
h2d.cpp:213:3: note: loop vectorized
h2d.cpp:198:3: note: loop vectorized
h2d.cpp:186:3: note: loop vectorized
You can check the interleaved output, when having applied -g with objdump -dS|c++filt , but that will not get you that far.Enjoy!
Zoom from RotateRight ( http://rotateright.com ) is mentioned in another answer, but to expand on that: it shows you the mapping of source to assembly in what they call the "code browser". It's incredibly handy even if you're not an asm expert because they have also integrated assembly documentation into the app. And the assembly listing is annotated with comments and timing for several CPU types.
You can just open your object or executable file with Zoom and take a look at what the compiler has done with your code.
Victor, in your case the optimization you are looking for is just a smaller allocation of local memory on the stack. You should see a smaller allocation at function entry and a smaller deallocation at function exit if the space used by the empty class is optimized away.
As for the general question, I've been reading (and writing) assembly language for more than (gulp!) 30 years and all I can say is that it takes practice, especially to read the output of a compiler.
Instead of trying to read through an assembler dump, run your program inside a debugger. You can pause execution, single-step through instructions, set breakpoints on the code you want to check, etc. Many debuggers can display your original C code alongside the generated assembly so you can more easily see what the compiler did to optimize your code.
Also, if you are trying to test a specific compiler optimization you can create a short dummy function that contains the type of code that fits the optimization you are interested in (and not much else, the simpler it is the easier the assembly is to read). Compile the program once with optimizations on and once with them off; comparing the generated assembly code for the dummy function between builds should show you what the compiler's optimizers did.