g++ & gcc

46
GCC/G++ OPERATING SYSTEMS

Upload: beste-ekmen

Post on 22-May-2015

189 views

Category:

Education


0 download

DESCRIPTION

Introduction to G++ & GCC for Operating Systems course

TRANSCRIPT

Page 1: G++ & GCC

GCC/G++OPERATING SYSTEMS

Page 2: G++ & GCC

What is GNU? The GNU project was started in 1984 to create a complete Unix-like

operating system as free software, in order to promote freedom and

cooperation among computer users and programmers. Every Unix-like

operating system needs a C compiler, and as there were no free

compilers in existence at that time, the GNU Project had to develop one

from scratch. The work was funded by donations from individuals and

companies to the Free Software Foundation, a non-profit organization

set up to support the work of the GNU Project.

Page 3: G++ & GCC

What is GCC? GCC stands for “GNU Compiler Collection”. It is an integrated distribution of

compilers for several major programming languages: C, C++, Objective-C,

Objective-C++, Java, Fortran, Ada, and Go. The abbreviation GCC has

multiple meanings in common use. The current official meaning is “GNU

Compiler Collection”, which refers generically to the complete suite of tools.

The name historically stood for “GNU C Compiler”. The name is also used

when speaking of the language-independent component of GCC: code shared

among the compilers for all supported languages. The language-independent

component of GCC includes the majority of the optimizers, as well as the

“back ends” that generate machine code for various processors. The part of a

compiler that is specific to a particular language is called the “front end”.

Page 4: G++ & GCC

What is G++? Most of the compilers for languages other than C have their own names. The

“G++” is the compiler of C++. When compiling these languages, we might

refer to that compiler by its own name, or as “GCC”. Either is correct.

G++ is a compiler, not merely a preprocessor. G++ builds object code

directly from C++ program source. There is no intermediate C version of the

program. Avoiding an intermediate C representation of the program means

that it is possible to get better object code, and better debugging

information. The GNU debugger, GDB, works with this information in the

object code to give a comprehensive C++ source-level editing capabilities.

Page 5: G++ & GCC

GCC Command OptionsWhen GCC invoked, it normally does preprocessing, compilation, assembly

and linking. The “overall options” allows to stop this process at an

intermediate stage. For example, the -c option says not to run the linker. Then

the output consists of object files output by the assembler. Other options are

passed on to one stage of processing. Some options control the preprocessor

and others the compiler itself. Yet other options control the assembler and

linker.

Most of the command line options those used with GCC are useful for C

programs; when an option is only useful with another language (usually C++),

the explanation says so explicitly. If the description for a particular option does

not mention a source language, it is possible to use that option with all

supported languages.

Page 6: G++ & GCC

GCC Command Options (2) The GCC compiler accepts both single-letter options, such as -o, and multi-

letters, such as -ansi. Because it accepts both types of options, it is not

possible to group multiple single-letter options together as it may be done in

many GNU and Unix/Linux programs. For example, the multi-letter option -pg

is not the same as the two single-letter options -p -g. The -pg option creates

extra code in the final binary that outputs profile information for the GNU

code profiler, gprof. On the other hand, the -p -g options generate extra code

in the resulting binary that produces profiling information for use by the prof

code profiler (-p) and causes GCC to generate debugging information using

the operating system’s normal format (-g).

Page 7: G++ & GCC

GCC Command Options (3) Despite its sensitivity to the grouping of multiple single-letter options, it is

possible to mix the order of options and compiler arguments on the GCC

command line. That is, invoking GCC as

gcc -pg -fno-strength-reduce -g myprog.c -o myprog

has the same result as

gcc myprog.c -o myprog -g -fno-strength-reduce –pg

In some situations, order does matter if several options of the same kind

been used. For example, the -I option specifies the directory or directories to

search for include files. So if -I specified several times, GCC searches the

listed directories in the order specified.

Page 8: G++ & GCC

GCC Command Options (4) To compile a single source file, invoke GCC passing the name of the source

file as the argument.

$ gcc myprog.c

$ ls –l

By default, the result on Linux and Unix systems is an executable file named

a.out in the current directory, which you execute by typing ./a.out. On

Cygwin systems, you will wind up with a file named a.exe that you can

execute by typing either ./a or ./a.exe. To define the name of the output file

that GCC produces, use the -o option, as illustrated in the following example:

$ gcc myprog.c -o runme

Page 9: G++ & GCC

GCC Command Options (5) For compiling multiple source files, they may simply specified on the GCC

command line, as in the following example, which leaves the compiled and

linked executable in the file named showdate:

$ gcc showdate.c helper.c –o showdate

To compile these files incrementally and eventually to link them into a binary,

it is possible to use the –c option to halt compilation after producing an object

file, as in the following example:

$ gcc -c showdate.c

$ gcc -c helper.c

$ gcc showdate.o helper.o –o showdate

Page 10: G++ & GCC

G++ Command Options The G++ compiler also accepts both single-letter options and multi-letter

options as GCC. And also it is not possible to group multiple single-letter

options due to fact that it accepts both types of options together.

Despite its sensitivity to the grouping of multiple single-letter options, it is

free to mix the order of options and compiler arguments on the command

line. That is, invoking G++ as

g++ -pg -fno-strength-reduce -g myprog.c -o myprog

has the same result as

g++ myprog.c -o myprog -g -fno-strength-reduce -pg

Page 11: G++ & GCC

G++ Command Options (2) In some situations, order does matter if several options of the same kind

been used. For example, the -I option specifies the directory or directories to

search for include files. So if -I specified several times, it searches the listed

directories in the order specified.

To compile a single source file, myprog.cc, just invoke G++, passing the

name of the source file as the argument.

$ g++ myprog.cc

$ ls -l

Page 12: G++ & GCC

G++ Command Options (3) By default, the result on Linux and Unix systems is an executable file named

a.out in the current directory, which may be executed by typing ./a.out. On

Cygwin systems, result is a file named a.exe that you can execute by typing

either ./a or ./a.exe. To define the name of the output file that G++

produces, use the -o option, as illustrated in the following example:

$ g++ myprog.cc -o runme

$ ls –l

For compiling multiple source files using G++, and to get file named

showdate:

$ g++ showdate.cc helper.cc –o showdate

Page 13: G++ & GCC

G++ Command Options (4) If you want to compile these files incrementally and eventually link them into

a binary, you can use the –c option to halt compilation after producing an

object file, as in the following example:

$ g++ -c showdate.cc

$ g++ -c helper.cc

$ g++ showdate.o helper.o –o showdate

$ ls –l

Page 14: G++ & GCC

G++ Command Options (5) All GCC compilers evaluate filename suffixes to identify the type of compilation

that they will perform.

Suffix Operation

.C C++ source code to preprocess.

.cc C++ source code to preprocess. (Standard extension for C++

source files.)

.cpp C++ source code to preprocess.

.cp C++ source code to preprocess.

.c++ C++ source code to preprocess

.cxx C++ source code to preprocess

.ii C++ source code not to preprocess.

Page 15: G++ & GCC

Options SummaryHere is a summary of all the options, grouped by type.

Overall Options: Controlling the kind of output: an executable, object files,

assembler files, or preprocessed source.

C Dialect Options: Controlling the variant of C language compiled.

C++ Dialect Options: Variations on C++.

Objective-C Dialect Options: Variations on Objective-C.

Language Independent Options: Controlling how diagnostics should be formatted.

Warning Options: How picky should the compiler be?

Page 16: G++ & GCC

Options Summary (2)Debugging Options: Symbol tables, measurements, and debugging dumps.

Optimize Options: How much optimization?

Preprocessor Options: Controlling header files and macro definitions. Also, getting dependency information for Make.

Assembler Options: Passing options to the assembler.

Link Options: Specifying libraries and so on.

Directory Options: Where to find header files and libraries. Where to find the compiler executable files.

Spec Files: How to pass switches to sub-processes.

Target Options: Running a cross-compiler, or an old version of GCC.

Page 17: G++ & GCC

Optimization of Code with GCC These days, compilers are pretty smart. They can perform all sorts of code

transformations make compiled code run faster. 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.

In the absence of optimization, GCC’s goal, besides compiling code that

works, is to keep compilation time to a minimum and generate code that runs

predictably in a debugging environment.

Page 18: G++ & GCC

Optimization Theory Optimization refers to analyzing a straightforward compilation’s resulting

code to determine how to transform it to run faster, consume fewer

resources, or both. Compilers that do this are known as optimizing compilers,

and the resulting code is known as optimized code.

To produce optimized code, an optimizing compiler performs one or more

transformations on the source code provided as input. The purpose is to

replace less efficient code with more efficient code while at the same time

preserving the meaning and ultimate results of the code.

Page 19: G++ & GCC

Optimization Theory (2) Optimizing compilers use several methods to determine where generated

code can be improved. One method is control flow analysis, which

examines loops and other control constructs, such as if-then and case

statements, to identify the execution paths a program might take and, based

on this analysis, determine how the execution path can be streamlined.

Another typical optimization technique examines how data is used in a

program, a procedure known as data flow analysis. Data flow analysis

examines how and when variables are used (or not) in a program and then

applies various set equations to these usage patterns to derive optimization

opportunities.

Page 20: G++ & GCC

Optimization Techniques – Code Motion

It is an optimization technique to eliminate redundant code through common

sub-expression elimination. It does not entirely remove common sub-

expressions, but attempts to reduce the number of times they occur by

relocating them to more optimal locations in an intermediate representation

of the code. For example, in nested loops or other control constructs,

intermediate value calculations may be performed more times than

necessary. In order to optimize, compilers can move these calculations to

locations where they will be executed less frequently, but will still produce

the same result. Code motion that specifically moves redundant calculations

outside the scope of a loop is referred to as loop-invariant code motion. It is

also used in a technique that is related to common sub-expression

elimination known as partial redundancy elimination.

Page 21: G++ & GCC

Optimization Techniques – Common Sub-expression Elimination

Eliminating redundant computations is a standard optimization mechanism

because it reduces the number of instructions that a program has to execute

in order to arrive at the same result.

For example, given an expression whose value is computed only once, each

subsequent occurrence of that expression can be eliminated and its value

used instead, if the values of the variables in the expression have not

changed since first computed. The subsequent occurrences of the expression

are called common sub-expressions.

Page 22: G++ & GCC

Optimization Techniques – Common Sub-expression Elimination (2)

Example:#define STEP 3#define SIZE 100int i, j, k;int p[SIZE];for (i = 0; i < SIZE; ++i) {

j = 2 * STEP;k = p[i] * j; }

The expression j = 2 * STEP in the for loop is a common sub-expression

because its value is computed before entering the loop and its constituent

variable, STEP (actually a predefined value), has not changed.

Page 23: G++ & GCC

Optimization Techniques – Common Sub-expression Elimination (3)

Common sub-expression elimination (CSE) removes the repeated computation of j in the for loop. After CSE, the for loop might look like the following:

j = 2 * STEP;

for (i = 0; i < 100; ++i) {

k = p[i] * j; }

Admittedly, the example is contrived, but it makes the point: CSE has

eliminated 100 redundant computations of j. CSE improves performance by

eliminating unnecessary computations and typically also reduces the size of

the resulting binary by eliminating unnecessary instructions.

Page 24: G++ & GCC

Optimization Techniques – Constant Folding

It is an optimization technique that eliminates expressions that calculate a

value that can already be determined when the program is compiled. These

are typically calculations that only reference constant values or expressions

that reference variables whose values are constant. For example:

n = 10 * 20 * 400;

i = 10;

j = 20;

ij = i * j;

In the latter case, the assignments to the variables i and j could also be

eliminated if these variables were not used elsewhere in the code.

Page 25: G++ & GCC

Optimization Techniques – Copy Propagation Transformations

It eliminate cases in which values are copied from one location or variable to

another in order to simply assign their value to another variable. Given an

assignment of the form f = g, subsequent uses of f, called copies, use g

instead. Consider a code fragment such as the following:

i = 10;

x[j] = i;

y[MIN] = b;

b = i; //After CPT it looks like “b=10”

Page 26: G++ & GCC

Optimization Techniques – Dead Code Elimination

Dead code elimination (DCE) is the term used for optimizations that remove

code that doesn’t actually do anything permanent or useful. Unreachable

code elimination is a related optimization that removes code that the

compiler can identify as impossible to reach. For example:

if ( i == 10 ) { . . . }

else { . . .

if ( i == 10) { . . . }

}

The nested test for whether i is equal to 10 can be eliminated because it can

never be reached.

Page 27: G++ & GCC

Optimization Techniques – If-Conversion

If-conversion is a technique where branch constructs, such as large if-then-

else if-else constructs, are broken into separate if statements to simplify

generated code, provide opportunities for further optimization, and eliminate

jumps and branches wherever possible.

Page 28: G++ & GCC

Optimization Techniques – Inlining

It is an optimization technique where code performance can improve by

replacing complex constructs and even function calls with inline

representations of the construct or function call. Code inlining, or loop

unrolling, are terms for replacing all or portions of a loop with an explicit

series of instructions. Function inlining is the term for replacing function calls

with the explicit set of instructions that are performed by the function. In

general, inlining can reduce code complexity and provide higher performance

than would be required by branching that would be done otherwise. It often

also provides opportunities for common sub-expression elimination and code

motion optimization.

Page 29: G++ & GCC

GCC Optimization BasicsGCC uses a sequence of different intermediate representations of code before

generating binaries. Converting language-specific code into simpler forms

provides several primary advantages:

- Breaking code into simpler, more low-level constructs exposes opportunities

for optimization that may not be directly visible in source code.

- Using intermediate representations enables the simpler form to more easily

and readably represent parse trees that are otherwise at varying levels of

complexity.

- Using a simpler form enables the GCC compilers to share optimization

mechanisms, regardless of the language in which your code was originally

written.

Page 30: G++ & GCC

GCC Optimization Basics (2) Traditionally, GCC has always internally used an intermediate form known as

Register Transfer Language (RTL), which is a very low-level language into

which all code compiled with a GCC compiler (in any high-level language) is

transformed before object code generation begins. Transforming high-level

input languages into an intermediate, internal form is a time-tested

mechanism for exposing opportunities for optimization. As a very low-level

representation of code, GCC’s RTL lends itself well to optimizations that are

similarly low-level, such as register allocation and stack and data

optimizations. Because it is relatively low-level, RTL is not as good as one

would like in terms of supporting higher-level optimizations related to data

types, array and variable references, and overall data and control flow within

code.

Page 31: G++ & GCC

GCC Optimization Basics (3) With GCC 4.0, the fine makers of the GCC compilers introduced a new

intermediate form, static single assignment (SSA), which operates on the

parse trees that are produced from code by GCC compilers, and is thus

known as Tree SSA. It is interesting to note that 4.0 and later GCC compilers

use two intermediate forms before arriving at a Tree SSA representation,

known as GENERIC and GIMPLE. A GENERIC representation is produced by

eliminating language-specific constructs from the parse tree that is

generated from code, and a GIMPLE representation is then produced from the

GENERIC representation by simplifying address references within the code. It

provides several additional points at which optimizations can occur at as high

a level as possible before zooming into the depths of the RTL.

Page 32: G++ & GCC

Architecture-Independent Optimizations

GCC’s most well-known optimization switches are –O; its variant -On, where n

is an integer between 0 and 3; and -Os. -OO turns off optimization. -O and -

O1 (which are level 1) are equivalent, telling GCC to optimize code. With -O

or -O1, the compiler attempts to minimize both code size and execution time

without dramatically increasing compilation time. Using -O2 and -O3 will

increase the level from that requested by -O1, while still invoking the

optimization options requested by -O1. To minimize code size, use option -Os.

To disable one of them while leaving the others enabled, negate the option

using no- between -f and the optimization name. For example, to disable

deferred stack pops, the command line might resemble this:

$ gcc myprog.c -o myprog -O1 -fno-defer-pop

Page 33: G++ & GCC

Architecture-Independent Level 1 GCC Optimizations

Page 34: G++ & GCC

Architecture-Independent Level 1 GCC Optimizations (2)

Page 35: G++ & GCC

Architecture-Independent Level 1 GCC Optimizations (3)

Page 36: G++ & GCC

Architecture-Independent Level 2 GCC Optimizations

-O2 optimization (level 2 optimization) includes all level 1 optimizations plus

the additional optimizations listed below. Applying these optimizations will

lengthen the compile time, but as a result a measurable increase should be

seen in the resulting code’s performance, or, rather, a measurable decrease

in execution time.

Page 37: G++ & GCC

Architecture-Independent Level 2 GCC Optimizations (2)

Page 38: G++ & GCC

Architecture-Independent Level 2 GCC Optimizations (3)

Page 39: G++ & GCC

Architecture-Independent Level 2 GCC Optimizations (4)

Page 40: G++ & GCC

Architecture-Independent GCC Optimizations for Code Size

The -Os option is becoming increasingly popular because it applies all of the

level 2 optimizations except those known to increase the code size. -Os also

applies additional techniques to attempt to reduce the code size. Code size, in

this context, refers to a program’s memory footprint at runtime rather than its

on-disk storage requirement. In particular, -Os disables the following

optimization flags (meaning they will be ignored if specified in conjunction

with -Os):

• -falign-functions

• -falign-jumps

• -falign-labels

• -falign-loops

Page 41: G++ & GCC

Architecture-Independent GCC Optimizations for Code Size (2)

• -fprefetch-loop-arrays

• -freorder-blocks

• -freorder-blocks-and-partition

• -ftree-ch

You might find it instructive to compile a program with -O2 and -Os and

compare runtime performance and memory footprint. For example, I have

found that recent versions of the Linux kernel have nearly the same runtime

performance when compiled with -O2 and -Os, but the runtime memory

footprint is 15 percent smaller when the kernel is compiled with -Os. Naturally,

your mileage may vary and, as always, if it breaks, you get to keep all of the

pieces.

Page 42: G++ & GCC

Architecture-Independent Level 3 GCC Optimizations

Specifying the –O3 optimization option enables all level 1 and level 2

optimizations plus the following:

• -fgcse-after-reload: Performs an extra load elimination pass after reloading

• -finline-functions: Integrates all “simple” functions into their callers

• -funswitch-loops: Moves branches with loop invariant conditions out of loops

Note: If you specify multiple -O options, the last one encountered takes

precedence. Thus, given the command gcc -O3 foo.c bar.c -O0 -o baz, no

optimization will be performed because -O0 overrides the earlier -O3.

Page 43: G++ & GCC

Architecture-Independent Manuel GCC Optimization Flags

In addition to the optimizations enabled using one of the -O options, GCC has a number of specialized optimizations that can only be enabled by specifically requesting them using -f.

Page 44: G++ & GCC

Architecture-Independent Manuel GCC Optimization Flags (2)

Note: Not all of GCC’s optimizations can be controlled using a flag. GCC

performs some optimizations automatically and we cannot disable these

optimizations when you request optimization using -O.

Page 45: G++ & GCC

Processor-Specific Optimizations In reality, though, the target-specific switches are not properly optimizations in

the traditional sense. Rather, they are options that give GCC more information

about the type of system on which the code being compiled will run. GCC can

use this additional information to generate code that takes advantage of

specific features or that works around known misfeatures of the given

processor.

Page 46: G++ & GCC

Thanks for listening…