4.07.2008
TinTin E-Book collection
01. Tintin in the Land of the Soviets (1930)
02. Tintin in the Congo (1931)
03. Tintin in America (1932)
04. Cigars of the Pharaoh
05. The Blue Lotus (1936)
06. The Broken Ear
07. The Black Island (1938)
08. King Ottokar's Sceptre (1939)
09. The Crab with the Golden Claws (1941)
10. The Shooting Star (1942)
Checkout TinTin ebook collection part2 for the books from 11 to 20
Checkout TinTin ebook collection part3 for the remaining editions.
4.03.2008
Optimization levels in GCC
In most situations, faster is better than smaller, because disk space and memory are quite cheap for desktop users. However, for embedded systems small is often at least as important as fast because of a commonplace environment consisting of extreme memory constraints and no disk space, making code optimization a very important task.
Optimization is a complex process. For each high-level command in the source code there are usually many possible combination's of machine instructions that can be used to achieve the appropriate final result. The compiler must consider these possibilities and choose among them.
In general, different code must be generated for different processors, as they use incompatible assembly and machine languages. Each type of processor also has its own characteristics -- some CPU's provide a large number of registers for holding intermediate results of calculations, while others must store and fetch intermediate results from memory. Appropriate code must be generated in each case.
Furthermore, different amounts of time are needed for different instructions, depending on how they are ordered. GCC takes all these factors into account and tries to produce the fastest executable for a given system when compiling with optimization.
Turning optimization flags ON makes the compiler attempt to improve the performance and/or code size at the expense of compilation time and possibly the ability to debug the program.
NOTE: While the GCC optimizer does a good job of code optimization, it can sometimes result in larger or slower images (the opposite of what you may be after). It’s important to test your image to ensure that you’re getting what you expect. When you don’t get what you expect, changing the options you provide to the optimizer can usually remedy the situation.
Let us see various optimization levels provided by GCC
LEVEL 0: -O0 Optimization
At this optimization level GCC does not perform any optimization and compiles the source code in the most straightforward way possible. Each command in the source code is converted directly to the corresponding instructions in the executable file, without rearrangement. This is the best option to use when debugging with a source code debugger (such as the GNU Debugger, GDB). It is the default level of optimization if no optimization level option is specified. It can be specified as
[bash]$gcc -O0 hello.c -o hello
or
[bash]$gcc hello.c -o hello
NOTE: -O0 is actually -(Capital O)(Number 0). Similarly -O1 is -(Capital O)(Number 1).
LEVEL 1: -O1 Optimization (-O)
In the first level of optimization, the optimizer’s goal is to compile as quickly as possible and also to reduce the resulting code size and execution time. Compilation may take more time with -O1 (over -O0), but depending upon the source being compiled, this is usually not noticeable. Level 1 also has two sometimes conflicting goals. These goals are to reduce the size of the compiled code while increasing its performance. The set of optimizations provided in -O1 support these goals, in most cases.
The -O1 optimization is usually a safe level if you still desire to safely debug the resulting image. Check out the table given below for optimizations enabled at different levels.
NOTE: Any optimization can be enabled outside of any level simply by specifying its name with the -f prefix, for example, to enable the defer-pop optimization, we would simply define this as
[bash]$ gcc -fdefer-pop hello.c –o hello
We could also enable level 1 optimization and then disable any particular optimization using the -fno- prefix, like this:
[bash]$ gcc -O1 -fno-defer-pop -o test test.c
This command would enable the first level of optimization and then specifically disable the defer-pop optimization.
LEVEL 2: -O2 Optimization
The second level of optimization provides even more optimizations (while including those in -O1, plus a large number of others). Only optimizations that do not require any speed-space tradeoffs are used, so the executable should not increase in size. The compiler will take longer to compile programs and require more memory than with -O1. This option is generally the best choice for deployment of a program, because it provides maximum optimization without increasing the executable size. It is the default optimization level for releases of GNU packages. The second level is enabled as shown below:
[bash]$gcc -O2 hello.c -o hello
LEVEL 2.5: -Os Optimization
The special optimization level (-Os or size) enables all -O2 optimizations that do not increase code size; it puts the emphasis on size over speed. This includes all second-level optimizations, except for the alignment optimizations. The alignment optimizations skip space to align functions, loops, jumps and labels to an address that is a multiple of a power of two, in an architecture-dependent manner. Skipping to these boundaries can increase performance as well as the size of the resulting code and data spaces; therefore, these particular optimizations are disabled.
-Os optimization level simply disables some -O2 optimizations like -falign-labels, -falign-jumps, -falign-labels, and -falign-functions. Each of these has the potential to increase the size of the resulting image, and therefore they are disabled to help build a smaller executable. The size optimization level is enabled as:
[bash]$gcc -Os hello.c -o hello
In gcc 3.2.2, reorder-blocks is enabled at -Os, but in gcc 3.3.2 reorder-blocks is disabled.
LEVEL 3: -O3 Optimization
The third and highest level enables even more optimizations by putting emphasis on speed over size. This includes optimizations enabled at -O2 and rename-register. The optimization inline-functions also is enabled here, which can increase performance but also can drastically increase the size of the object, depending upon the functions that are inlined. The third level is enabled as:
[bash]$gcc -O3 hello.c -o hello
Although -O3 can produce fast code, the increase in the size of the image can have adverse effects on its speed. For example, if the size of the image exceeds the size of the available instruction cache, severe performance penalties can be observed. Therefore, it may be better simply to compile at -O2 to increase the chances that the image fits in the instruction cache.
Architecture Specification
The optimizations discussed thus far can yield significant improvements in software performance and object size, but specifying the target architecture also can yield meaningful benefits.
The -march option of gcc allows the CPU type to be specified
The default architecture is i386. GCC runs on all other i386/x86 architectures, but it can result in degraded performance on more recent processors. If you're concerned about portability of an image, you should compile it with the default. If you're more interested in performance, pick the architecture that matches your own.
References:
1. Optimization in GCC
2. An Introduction to GCC - for the GNU compilers gcc and g++.
2.19.2008
Compilation process in GCC
Compiling a C program - Compiling a simple C program using gcc.
Above article is a high level view of compliation in gcc. In present article let us see in depth view of the compilation order or flow in gcc which is a default C compiler in GCC.
gcc goes through a sequence of different intermediate steps before generating final executable. Those intermediate steps are the result of different tools which are invoked internally to complete the compilation of the source code.
The whole Compilation process is broken down into following phases:
- Preprocessing
- Compilation
- Assembly
- Linking
As an example, we will examine these compilation stages individually using the same ‘hello.c’ program given below:
#include <stdio.h>
#define STRING "Hello World"
int main (void)
{
printf ("My First program - %s\n",STRING);
return 0;
}
NOTE: We dont need to manually go through all the intermediate stages to generate a executable using gcc. All these stages are directly taken care transparently by gcc internally, and can be seen using the -v option.
Although 'hello.c' program is very simple it uses external header files and libraries, and so exercises all the major steps of the compilation process. If we compile the 'hello.c' with a simple command namely gcc hello.c then we end-up creating an executable file called a.out.
Back in the days of the PDP computer, a.out stood for "assembler output". Today, it simply means an older executable file format. Modern versions of Unix and Linux use the ELF executable file format. The ELF format is much more sophisticated. So even though the default filename of the output of gcc is "a.out", its actually in ELF format.The Preprocessor
Basically C Preprocessor is responsible for 3 tasks namely:
- Text Substitution,
- Stripping of Comments, and
- File Inclusion.
The lines in our code that begin with the “#” character are preprocessor directives.
In 'hello.c' program the first preprocessor directive requests a standard header file, stdio.h, be included into our source file. The other one requests a string substitution to take place in our code.
So in preprocessor stage those included header files and defined macros are expanded and merged within the source file to produce a transitory source file, which the standard calls a Translation unit. Translation units are also known as compilation units.
The C preprocessor, often known as cpp, is a macro processor that is used automatically by the C compiler to transform a C program before compilation. To perform just preprocessing operation use the following command:
[bash]$ cpp hello.c > hello.iThe result is a file named hello.i which contains the source code with all macros expanded.
By convention, preprocessed files are given the file extension ‘.i’ for C programs and ‘.ii’ for C++ programs.
NOTE: By default the preprocessed file is not saved to disk unless the -save-temps option is used in gcc so we are just using the redirection operator to save a copy of preprocessed file.
By using gcc's “-E” flag we can directly do the pre-processing operation.
[bash]$ gcc -E hello.c -o hello.iNow we will try to check the contents of the preproccessed input file. Since the stdio.h file is fairly large the resultant output is cleaned up a bit.
# 1 "hello.c"Since our program has requested the stdio.h header be included into our source which in turn, requested a whole bunch of other header files. So, the preprocessor made a note of the file and line number where the request was made and made this information available to the next steps in the compilation process. Thus, the lines,
# 1 "/usr/include/stdio.h" 1 3
# 1 "/usr/include/_ansi.h" 1 3
# 1 "/usr/include/sys/config.h" 1 3
# 14 "/usr/include/sys/config.h" 3
# 25 "/usr/include/sys/config.h" 3
# 44 "/usr/include/sys/config.h" 3
# 40 "/usr/include/stdio.h" 2 3
# 1 "/usr/include/sys/reent.h" 1 3
int main(void){
printf ("My First Program - %s\n", "HELLO WORLD" );
return 0;
}
# 40 "/usr/include/stdio.h" 2 3indicates that the reent.h file was requested on line 40 of stdio.h. The preprocessor creates a line number and file name entry before what might be "interesting" to subsequent compilation steps, so that if there is an error, the compiler can report exactly where the error occurred.
# 1 "/usr/include/sys/reent.h" 1 3
The Compiler
The next stage of the process is the actual compilation of the preprocessed source code to assembly language, for a specific processor (Depending upon the target processor architecture the source code is converted into particular assembly language and it can be known as cross-compilation).
By using “-S” flag with gcc we can convert the preprocessed C source code into assembly language without creating an object file:
[bash]$ gcc -Wall -S hello.i -o hello.sThe resulting assembly language is stored in the file ‘hello.s’.
NOTE: The assembly code generated depends upon the PC architecture and other reasons. I am just attaching the assembly code generated with the Cygwin - Linux Emulator.
NOTE: Above Assembly code contains a call to the external printf function.
The Assembler
We know that MACHINES (i.e. a computer) can understand only Machine-Level Code. So we require an ASSEMBLER that converts assembly code in "hello.s" file into machine code. Eventhough it is a straightforward one-to-one mapping of assembly language statements to their machine language counterparts, it is tedious and error-prone if done manually.
NOTE: ASSEMBLER was one of the first software tools developed after the invention of the digital electronic computer.
If there are any calls to external functions in the assembly code, the Assembler leaves the addresses of the external functions undefined, to be filled in later by the Linker.
The Assembler as in gcc can be invoked as shown below.
[bash]$ as hello.s -o hello.oAs with gcc, the output file is specified with the -o option. The resulting file ‘hello.o’ contains the machine level code for 'hello.c' program.
or
By using “-c” flag in gcc we can convert the assembly code into machine level code:
[bash]$ gcc -c hello.cThe Linker
The final stage of the compilation process is producing a single executable program file by linking set of object files. An object file and an executable file come in several formats such as ELF (Executable and Linking Format) and COFF (Common Object-File Format). For example, ELF is used on Linux systems, while COFF is used on Windows systems.
In practice, an executable file requires many external functions from system and C run-time libraries. The linker will resolve all of these dependencies and plug in the actual address of the functions.
The linker also does a few additional tasks for us. It combines our program with some standard routines that are needed to make our program run. For example, there is standard code required at the beginning of our program that sets up the running environment, such as passing in command-line parameters and environment variables. Also, there is code that needs to be run at the end of our program so that it can pass back a return code, among other tasks. It turns out that this is no small amount of code.
Actually the mechanism used internally by gcc to link up different files is a bit complicated. For example, the full command for linking the 'hello.c' program might look as shown below:
[bash]$ ld -dynamic-linker /lib/ld-linux.so.2/usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc-lib/i686/3.3.1/crtbegin.o-L/usr/lib/gcc-lib/i686/3.3.1 hello.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh/usr/lib/gcc-lib/i686/3.3.1/crtend.o /usr/lib/crtn.oLuckily we are never asked to type the above command directly -- the entire linking process is handled transparently by gcc when invoked as follows:
[bash]$ gcc hello.oThis links the object file ‘hello.o’ to the C standard library, and produces an executable file ‘a.out’.
[bash]$ ./a.outAn object file for a C++ program can be linked to the C++ standard library in the same way with a single g++ command.
My First Program - Hello World
2.18.2008
Compiling a simple C program using GCC
#include <stdio.h>
int main (void)
{
printf ("Hello, world!\n");
return 0;
}
We will save the above 'C' code in a file named 'hello.c'. Inorder to compile a C file with gcc, use the following command:
[bash]$ gcc -Wall hello.c -o hello
This compiles the source code in ‘hello.c’ to machine code and stores it in an executable file ‘hello’.
NOTE: The output file for the machine code is specified using the -o option. This option is usually given as the last argument on the command line. If it is omitted, the output is written to a default file called ‘a.out’. If a file with the same name as the executable file already exists in the current directory it will be overwritten.
The option -Wall turns on all the most commonly-used compiler warnings---it is recommended that you always use this option! There are many other warning options, but -Wall is the most important. GCC will not produce any warnings unless they are enabled. Compiler warnings are an essential aid in detecting problems when programming in C and C++.
In this case, the compiler does not produce any warnings with the -Wall option, since the program is completely valid. Source code which does not produce any warnings is said to compile cleanly.
To run the program, type the path name of the executable like this:
[bash]$ ./hello
Hello, world!
This loads the executable file into memory and causes the CPU to begin executing the instructions contained within it. The path ./ refers to the current directory, so ./hello loads and runs the executable file ‘hello’ located in the current directory.
For a detailed view about how the who compilation process goes checkout Compilation process in GCC.
2.13.2008
World’s first optical drive for cell phones
Vmedia Research, Inc. unveiled its mobile entertainment media technology at the GSMA Mobile World Congress in Barcelona. Vmedia™ is an innovative miniature optical disc format designed to bring the quality of a big screen experience and the simplicity of home entertainment to mobile consumer electronics.
The technology consists of the ‘Vmedia disc’ that plays on the world’s smallest blue laser optical drive, the ‘Vmedia drive’. The disc – 32mm in diameter and cased in a slim cartridge – would retail at the same price as a DVD and have the same release dates.
Despite the tiny size, the company claimed that there wouldn’t be a loss in quality: A single disc can hold a complete feature-length movie at 576p resolution by combining blue laser technology with advanced video (H.264) and audio codecs (AAC).
The first generation of the single-layer Vmedia disc has a capacity of 1GB, which will hold the typical movie plus extra features such as out-takes, mobile phone wallpapers and ringtones. The storage could go up to 2GB once the company comes out with dual-layer discs in 2009.
Designed to withstand the rigours of today’s mobile applications, the Vmedia drives are resistant to shock and vibration, and also feature low power consumption, company officials said.
Vmedia has tied up with Indian mobile company, Spice Mobile. The company’s chairman Dr B K Modi introduced the Spice Movie Phone – the world’s first Vmedia-enabled mobile phone – at the Mobile World Congress in Barcelona.
Spice will be distributing Indian and Hollywood content on Vmedia throughout South Asia. “We believe the Movie Phone will become the most popular multimedia communications platform worldwide and may even change the way we all view movies, just as the iPod changed the way we listen to music.” he said.
That's great Spice Mobile is the first company to launch a phone with the optical drive.