760 likes | 956 Vues
TMS470 Compiler. Thomas Suchyta t-suchyta1@ti.com Raja Venkateswaran rajav@ti.com. Outline. Background Options Optimization Programming Hints Linker Updates Validation Overview. Background. 30+ software engineers 280+ years of experience in the development optimizing compilers
E N D
TMS470 Compiler Thomas Suchyta t-suchyta1@ti.com Raja Venkateswaran rajav@ti.com TMS470 Compiler Overview
Outline • Background • Options • Optimization • Programming Hints • Linker Updates • Validation Overview TMS470 Compiler Overview
Background • 30+ software engineers • 280+ years of experience in the development optimizing compilers • 7 Phd’s, including one distinguished professor • 1 TI Fellow, 3 Distinguished MTS, 3 Senior MTS • Close contact with key academic compiler research institutions TMS470 Compiler Overview
Background • World class software development toolset used on over 14 DSP and microcontroller architectures with installed base of over 30,000 toolsets • World class proprietary compiler technology, including state-of-the-art whole-program optimization • Focused on embedded systems applications • Real-time control • Telecom (terminal and infrastructure) • Automotive (safety critical applications) • Intensive, comprehensive validation and benchmarking processes • Extensive experience in compiling for high performance architectures (VLIW, DSP, SIMD, mC, RISC, CISC) TMS470 Compiler Overview
Shell cl470.exe Code Generator cg470.exe Assembler asm470.exe Linker lnk470.exe Optimizer opt470.exe COFF2 object file (may contain STABS or DWARF2 debug info): file.obj COFF2 executable: a.out Intermediate file of abstract syntax trees: file.if Assembly Code: file.asm Intermediate file of abstract syntax trees: file.opt Compiler Overview The shell will pass options to each executable Parser acp470.exe TMS470 Compiler Overview
Current Compiler Version • Latest version is 2.53 • Readme’s, defect histories, other info: • ftp://ftp.ti.com/pub/private-cs/armcgt_releases/tms470_releases.html • All versions since v2.00 TMS470 Compiler Overview
Compiler Execution • Invoked through CCS • Can also be executed from a command line • Tools available for pc, sun, linux platforms • Can be invoked through Makefiles TMS470 Compiler Overview
Static Stack Depth Profiler • New compiler tool to statically estimate the stack depth of an executable > sdp470 a.out • Will send data to standard out > sdp470 –c config.file a.out • Use config file to supply info on indirect and recursive functions • Details are found in docs/sdprof.doc TMS470 Compiler Overview
Static Stack Depth Profiler Output ****************************************************************************** * Static Stack Depth Analysis Profile ****************************************************************************** FCN:$main stack usage: 4, total stack need : 696 $func stack usage: 4, subtree stack need: 692 $printf stack usage: 32, subtree stack need: 688 $init stack usage: 0, subtree stack need: 0 ============================================================================== FCN:$func stack usage: 4, total stack need : 692 $printf stack usage: 32, subtree stack need: 688 ============================================================================== FCN:$printf stack usage: 32, total stack need : 688 $_printfi stack usage: 72, subtree stack need: 656 ============================================================================== FCN:$init stack usage: 0, total stack need : 0 ============================================================================== =================INTERRUPT SERVICE ROUTINES=================================== ============================================================================== =================ORPHAN FUNCTIONS==================================== _c_int00 total stack need: 696 $_printfi total stack need: 656 $_setfield total stack need: 584 $_pproc_fge total stack need: 552 $_pconv_f total stack need: 524 TMS470 Compiler Overview
Debug Options DWCU .dwtag DW_TAG_compile_unit .dwattr DWCU, DW_AT_name("file.c") DW$1 .dwtag DW_TAG_subprogram, DW_AT_name("func"), DW_AT_symbol_name("$func") .dwattr DW$1, DW_AT_low_pc($func) .dwattr DW$1, DW_AT_high_pc(0x00) .dwattr DW$1, DW_AT_frame_base[DW_OP_breg13 4] .dwpsn "file.c",2,1 $func: ADD SP, #-4 STR A1, [SP, #0] .dwpsn "file.c",3,5 ADD A1, A1, #1 DWT$11 .dwtag DW_TAG_base_type, DW_AT_name("int") .dwattr DWT$11, DW_AT_encoding(DW_ATE_signed) .dwattr DWT$11, DW_AT_byte_size(0x04) DWT$1018 .dwtag DW_TAG_subroutine_type, DW_AT_type(*DWT$11) .dwattr DWT$1018, DW_AT_language(DW_LANG_C) DW$3 .dwtag DW_TAG_formal_parameter, DW_AT_type(*DWT$11) .dwendtag DWT$1018 .dwattr DW$1, DW_AT_external(0x01) .dwattr DW$1, DW_AT_type(*DWT$11) .dwattr DWCU, DW_AT_language(DW_LANG_C) DW$4 .dwtag DW_TAG_assign_register, DW_AT_name("A1") .dwattr DW$4, DW_AT_location[DW_OP_reg0] • Nothing: > cl470 file.c • Some DWARF2 debug info, “skeletal DWARF”, is created: • global symbols • function call stack • line and column number • type information • register map • “Skeletal DWARF” has no impact on code generation • Debug info placed into COPY (no load) sections TMS470 Compiler Overview
Debug Options • “-g” > cl470 –g file.c • Full DWARF2 debug info • Verbose debug info, complete program description • Required for C++ debug • “-gt” > cl470 –gt file.c • STABS debug info TMS470 Compiler Overview
Debug Options • “-gn” > cl470 –gn file.c • No debug info is generated • “-mn” > cl470 –o2 –g –mn file.c • Debug with optimization can disable certain optimizations • This option prevents disabling • Code will be equivalent to optimized without debug TMS470 Compiler Overview
File options -fr=<dir> Object file directory -fs=<dir> Assembly file directory -ft=<dir> Temporary file directory -ff=<dir> Listing file directory -fp=<file> File is a C++ file -fc=<file> File is a C file -fo=<file> File is an object file -fa=<file> File is an assembly file -ea=<.ext> Assembly file extension -ec=<.ext> C file extension -ep=<.ext> C++ file extension -eo=<.ext> Object file extension -es=<.ext> Listing file extension -fg Treat files with C extensions as C++ > cl470 –fr=c:\tmp –eo=<.o> -fg file.c • file.c compiled as C++ and file.o placed in the c:\tmp directory TMS470 Compiler Overview
Diagnostic Options extern char a; char func() { a = foo(); return a; } -pden Emit diagnostic id number -pdr Issue remarks -pdse=<n> Treat id as error -pdsr=<n> Treat id as remark -pdsw=<n> Treat id as warning -pdel=<n> Set error limit -pdw Suppress warnings -pds=<n> Suppress diagnostic <n> • Legal C, function without prototype defined by compiler as having “int” return type • Find remark id: • > cl470 –pdr –pden file.c • "file.c", line 5: remark #225-D: function declared implicitly • Treat id as error: • > cl470 –pdse=225 file.c • "file.c", line 5: error: function • declared implicitly 1 error • detected in the compilation of • "file.c". • >> Compilation failure TMS470 Compiler Overview
Parser Options • -pe Embedded C++ http://www.caravan.net/ec2plus/ • -ps Strict ANSI mode • -rtti C++ run time type information support • --static_template_instantiation All template instantiations given local linkage TMS470 Compiler Overview
Preprocessing Options • -ppc Preprocess with comments • -ppo Preprocess only • -ppa Preprocess and compile > cl470 –ppo file.c • Will create a file.pp TMS470 Compiler Overview
Code Generation Options • -mt Generate 16-bit (thumb) code • -md Do not generate dual-mode code. No veneers are generated. • -me Generate little endian code TMS470 Compiler Overview
Misc. Shell Options • -version Print version of each executable only (no compilation) • --verbose Print version and function name • -n Do not assemble • -k Keep assembly file • -c Do not link • -D, -d Predefine symbol • -U, -u Undefine symbol • -I,-I Include search path • -s, -ss, Interlist src with assembly TMS470 Compiler Overview
Function Subsections unsigned int udiv(unsigned int src1, unsigned int src2) … int div(int src1, int src2) … • Controlled by –ms switch • Each function placed in its own section • Each function will be conditionally linked • Typically used in libraries • Only referenced functions linked, not entire .obj file • Over use can negatively impact code-size • Linker switch –j will disable .sect ".text:$udiv" .clink .state16 .global $udiv $udiv: ... .sect ".text:$div" .clink .state16 .global $div $div: ... TMS470 Compiler Overview
Linker Options • -z Tells shell to invoke linker. All following options are linker options. • -l <file> Include library or linker command file • --default_order Do not use size based output section allocation algorithm - Use if relying on old linker’s default placement of output sections • -b Turn off debug type merging - Can significantly improve link times • -c Run time global initialization • -cr Load time global initialization • -w Warn if unspecified output section is created • -x Reread libraries to resolve back references • --large_model Patch calls to far memory TMS470 Compiler Overview
Far Memory Calls & Trampolines • If "bar“ calls a function "foo“: • bar: ... call foo • If "foo" is out-of-range: • bar: ... call foo_trampoline • The linker will generate a trampoline containing code which executes a long branch to the original callee: • foo_trampoline: • branch_long foo • Enable with --large_model switch • All calls are generated as near calls • The linker will "fix" each call site which is linked out-of-range of its callee destination • The “fix” is trampolines near the call site TMS470 Compiler Overview
Pragmas • DATA_SECTION: place symbol in user defined section #pragma DATA_SECTION(symbol,”section name”); • CODE_STATE: change function compilation mode #pragma CODE_STATE(func,16 or 32); • DUAL_STATE: optimized veneers, will not be deleted #pragma DUAL_STATE(func); TMS470 Compiler Overview
Pragmas • INTERRUPT: Mark a function as an interrupt routine, and set its type #pragma INTERRUPT(func, DABT | FIQ | IRQ | PABT | RESET | SWI | UDEF); • TASK: Mark a function that never returns #pragma TASK(func); • SWI_ALIAS: Refer to software interrupt as a function call • Function must have a prototype #pragma SWI_ALIAS(func,swi_number); TMS470 Compiler Overview
Optimization Overview • Significant reduction in code-size or cycles can be obtained • Optimization can either be set for smallest size or fast code • The amount of optimization performed can be controlled • To control the accuracy of debug info, for example TMS470 Compiler Overview
Optimization Overview TMS470 Compiler Overview
Optimization Overview TMS470 Compiler Overview
Optimization Levels Less reliable debug info TMS470 Compiler Overview
Level 0 Simplify the control flow graph to remove unnecessary branches Register allocation, move variables to virtual registers Dead code elimination Simplify expressions: (b + 4) – (c - 1)becomes (b – c + 5) Level 1 All level 0 optimizations Basic block constant and copy propagation Remove dead assignments Remove common subexpressions Loop rotation Optimizer Overview TMS470 Compiler Overview
Optimizer Overview Inlining can be controlled, or turned off with –oi0. • Level 2 • All level 1 optimizations • Loop optimizations • Hoisting for example • Remove global (function-level) common subexpressions • Replace integer division with constant divisor with multiplication by reciprocal • Level 3 • All level 2 optimizations • Automatic inlining • Remove functions that are never called • Simplify functions with return values that are not used • File level constant propagation • To replace arguments for example TMS470 Compiler Overview
Code Generator Optimizations • Enabled at level 0 • Simplify control flow graph • Register allocation • Peephole optimization • Optimize use of close constant values • Delete unnecessary sign and zero extensions • Register tracking • Tail merging • Constant hoisting • Remove unnecessary compares to zero • Remove unnecessary shifts • Switch table compression • Branch chaining TMS470 Compiler Overview
Recommended Switches TMS470 Compiler Overview
Example – No Optimization $func: ADD SP, #-4 STR A1, [SP, #0] CMP A1, #3 BNE L1 MOV A2, #1 LDR A1, CON1 STR A2, [A1, #0] LDR A1, CON1 LDR A1, [A1, #0] B L2 L1: LDR A1, [SP, #0] CMP A1, #4 BNE L2 MOV A1, #2 LDR A2, CON1 STR A1, [A2, #0] LDR A1, CON1 LDR A1, [A1, #0] L2: ADD SP, #4 MOV PC, LR extern int a; int func(int b) { if (b == 3) { a = 1; return a; } else if (b == 4) { a = 2; return a; } } • Compiled in 16-bit mode, no optimization • 7 loads, 3 stores • .text size 44 bytes TMS470 Compiler Overview
Example – No Optimization extern int a; int func(int b) { if (b == 3) { a = 1; return a; } else if (b == 4) { a = 2; return a; } } • 16-bit mode, no optimization • Control Flow Graph represents code as written • Argument “b” stored on stack $func: ADD SP,#-4 STR A1,[SP,#0] CMP A1,#3 BNE L1 …. STR A2,[A1,#0] ….. LDR A1,[A1,#0] B L2 L1: …. BNE L2 …. STR A1,[A2,#0] ….. LDR A1,[A1,#0] L2: TMS470 Compiler Overview
Example - Optimization Level 0 extern int a; int func(int b) { if (b == 3) { a = 1; return a; } else if (b == 4) { a = 2; return a; } } $func: CMP A1, #3 BQNE L1 MOV A1, #1 B L2 L1: CMP A1, #4 BQNE L3 MOV A1, #2 L2: LDR A2, CON1 STR A1, [A2, #0] LDR A1, [A2, #0] L3: MOV PC, LR • Compiled in 16-bit mode, -o0 • 2 loads, 1 store • .text size 28 bytes TMS470 Compiler Overview
Example - Optimization Level 0 extern int a; int func(int b) { if (b == 3) { a = 1; return a; } else if (b == 4) { a = 2; return a; } } • 16-bit mode, optimization –o0 • Control Flow Graph rewritten • Update of “a” moved out of conditional blocks • Register allocation on “b” • Extra load is removed at level 1 $func: CMP A1,#3 BQNE L1 …. MOV A1,#1 B L2 L1: …. BQNE L3 MOV A1,#2 L2: …. STR A1,[A2,#0] LDR A1,[A2,#0] L3: TMS470 Compiler Overview
Optimization - Simple Loop Example $func: ADD SP, #-8 STR A1, [SP, #0] MOV A1, #0 STR A1, [SP, #4] CMP A1, #20 BGE L2 L1: LDR A1, [SP, #0] LDR A2, [SP, #4] LSL A2, A2, #2 LDR A3, CON1 STR A3, [A2, A1] LDR A1, [SP, #4] ADD A1, #1 STR A1, [SP, #4] CMP A1, #20 BLT L1 L2: LDR A1, [SP, #4] ADD SP, #8 MOV PC, LR extern int a; int func(int *p) { int i; for (i = 0; i < 20; i++) { p[i] = (int)&a; } return i; } • Compiled in 16-bit mode, no optimization • 5 loads, 4 stores • .text size 44 bytes TMS470 Compiler Overview
Optimization – Simple Loop Example $func: MOV A2, A1 MOV A1, #0 CMP A1, #20 BQGE L2 L1: LSL A3, A1, #2 LDR A4, CON1 STR A4, [A2, A3] ADD A1, #1 CMP A1, #20 BQLT L1 L2: MOV PC, LR extern int a; int func(int *p) { int i; for (i = 0; i < 20; i++) { p[i] = (int)&a; } return i; } • Compiled in 16-bit mode, -o0 • 1 load, 1 store • .text size 28 bytes • Register allocation of local variables TMS470 Compiler Overview
Optimization – Simple Loop Example $func: MOV A2, A1 MOV A1, #0 L1: LSL A3, A1, #2 LDR A4, CON1 STR A4, [A2, A3] ADD A1, #1 CMP A1, #20 BQLT L1 MOV PC, LR extern int a; int func(int *p) { int i; for (i = 0; i < 20; i++) { p[i] = (int)&a; } return i; } • Compiled in 16-bit mode, -o1 • 1 load, 1 store • .text size 24 bytes • Loop rotation TMS470 Compiler Overview
Optimization – Simple Loop Example extern int a; int func(int *p) { int i; for (i = 0; i < 20; i++) { p[i] = (int)&a; } return i; } $func: MOV A2, #20 LDR A3, CON1 L1: STR A3, [A1, #0] ADD A1, #4 SUB A2, #1 BQNE L1 MOV A1, #20 MOV PC, LR • Compiled in 16-bit mode, -o2 • 1 load, 1 store • .text size 20 bytes • Hoisting • Strength reduction TMS470 Compiler Overview
Optimization – Level 2 vs Level 3 32-bit mode, -o2 _foo: STMFD SP!, {LR} BL _func1 LDR V9, CON1 LDR A1, [V9, #0] BL _func2 LDR V9, CON2 STR A1, [V9, #0] LDMFD SP!, {PC} extern int a, b; void func1() { a = 3; } int func2(int c) { return c + 2; } void foo() { func1(); b = func2(a); } • File level analysis at level 3 • Functions can be inlined • Arguments can be replaced • Global common expressions can be removed 32-bit mode, -o3 _foo: MOV V9, #3 LDR A1, CON1 STR V9, [A1, #0] MOV A1, #5 LDR V9, CON2 STR A1, [V9, #0] MOV PC, LR TMS470 Compiler Overview
Propagation and Expression Elimination No optimization: $func: ADD SP, #-4 STR A1, [SP, #0] MOV A1, #3 LDR A2, CON1 STR A1, [A2, #0] LDR A2, [SP, #0] LDR A1, CON1 LDR A1, [A1, #0] ADD A1, A1, A2 LDR A2, CON2 STR A1, [A2, #0] LDR A1, [SP, #0] LDR A2, CON1 LDR A2, [A2, #0] ADD A1, A2, A1 LDR A2, CON3 STR A1, [A2, #0] ADD SP, #4 MOV PC, LR extern int a, c, d; int func(int b) { a = 3; c = b + a; d = b + a; } Level 0: register allocation, propagate ‘a’ $func: MOV A3, #3 LDR A2, CON1 STR A3, [A2, #0] LDR A3, [A2, #0] ADD A3, A3, A1 LDR A4, CON2 STR A3, [A4, #0] LDR A2, [A2, #0] ADD A1, A2, A1 LDR A2, CON3 STR A1, [A2, #0] MOV PC, LR Level 1: propagate ‘a’, eliminate ‘b + a’ $func: MOV A2, #3 LDR A3, CON1 STR A2, [A3, #0] ADD A1, A1, #3 LDR A2, CON2 STR A1, [A2, #0] LDR A2, CON3 STR A1, [A2, #0] MOV PC, LR TMS470 Compiler Overview
Tail Merging Example No debug snippet: LDR A2, CON1 LDR A1, [A2, #0] ADD A1, #1 STR A1, [A2, #0] LDR A1, CON1 LDR A1, [A1, #0] LSL A1, A1, #1 STR A1, [SP, #0] B L3 L1: LDR A1, [SP, #0] CMP A1, #0 BNE L2 LDR A2, CON1 LDR A1, [A2, #0] SUB A1, #1 STR A1, [A2, #0] LDR A1, CON1 LDR A1, [A1, #0] LSL A1, A1, #1 STR A1, [SP, #0] B L3 L2: LDR A2, CON1 LDR A1, [A2, #0] ADD A1, #2 STR A1, [A2, #0] LDR A1, CON1 LDR A1, [A1, #0] LSL A1, A1, #1 STR A1, [SP, #0] L3: … Level 1 optimization: $func: LDR A2, CON1 CMP A1, #0 BQGT L2 CMP A1, #0 BQNE L1 LDR A1, [A2, #0] SUB A1, A1, #1 B L3 L1: LDR A1, [A2, #0] ADD A1, A1, #2 B L3 L2: LDR A1, [A2, #0] ADD A1, A1, #1 L3: STR A1, [A2, #0] LSL A1, A1, #1 MOV PC, LR extern int a; int func (int b) { if (b > 0) { a++; b = a * 2; } else if (b == 0) { a--; b = a * 2; } else { a += 2; b = a * 2; } return b; } TMS470 Compiler Overview
Epilog Inlining int func(int a) { if (a < 0) a -= 3; else a += 3; return a; } 16-bit mode, no debug: $func: ADD SP, #-4 STR A1, [SP, #0] CMP A1, #0 BPL L1 LDR A1, [SP, #0] SUB A1, #3 STR A1, [SP, #0] B L2 L1: LDR A1, [SP, #0] ADD A1, #3 STR A1, [SP, #0] L2: LDR A1, [SP, #0] ADD SP, #4 MOV PC, LR 16-bit mode, level 0: $func: CMP A1, #0 BQPL L1 SUB A1, #3 MOV PC, LR L1: ADD A1, #3 MOV PC, LR TMS470 Compiler Overview
Branch Chaining If LABEL10 requires a large offset, assembler converts to 2 instructions requiring 4 or 6 bytes. LABEL1: BR LABEL10 … LABEL5: BR LABEL10 … LABEL10: The code generator will generate a pseudo-branch: BRcc target BTcc target,#depth and Bcc target BQcc target,#depth LABEL1: BT LABEL5 … LABEL5: BT LABEL10 … LABEL10: TMS470 Compiler Overview
Speed Optimizations – Integer Divide by Constant 32-bit mode, -o2: _func: STMFD SP!, {LR} LDR V9, CON1 LDR A1, [V9, #0] LDR A2, CON4 BL I_DIV LDR V9, CON3 STR A2, [V9, #0] LDMFD SP!, {PC} extern long a, b; void func() { a = b / 0x12345; } • Optimizer rewrites • b / 0x12345 • as • b * 1 / 0x12345 • Must use level 2 (-o2) and opt-for-speed switch (-mf) in 32-bit mode 32-bit mode, -o2 -mf _func: LDR V9, CON1 LDR A1, [V9, #0] LDR V9, CON3 SMULL A3, A2, V9, A1 MOV V9, A2, ASR #14 SUB V9, V9, A1, ASR #31 LDR A1, CON2 STR V9, [A1, #0] MOV PC, LR TMS470 Compiler Overview
Size Optimizations - Switch Table Compression 16-bit mode, level 0: ADR A3, SW1 LDRB A3, [A3, A2] .align 4 ADD A3, PC MOV PC, A3 ; |5| .align 4 SW1: .byte L18-SW1 ; 0 .byte L17-SW1 ; 1 .byte L16-SW1 ; 2 .byte L15-SW1 ; 3 .byte L14-SW1 ; 4 .byte L13-SW1 ; 5 .byte L12-SW1 ; 6 .byte L11-SW1 ; 7 .byte L10-SW1 ; 8 .byte L9-SW1 ; 9 .byte L8-SW1 ; 10 .byte L7-SW1 ; 11 .byte L6-SW1 ; 12 .byte L5-SW1 ; 13 .byte L4-SW1 ; 14 .byte L3-SW1 ; 15 .byte L2-SW1 ; 16 .byte 0x00 .byte 0x00 .byte 0x00 16-bit mode, no optimization: LSL A2, A1, #2 ADR A1, SW1 LDR A1, [A1, A2] MOV PC, A1 ; |5| .align 4 .align 4 SW1: .word L1 ; 0 .word L2 ; 1 .word L3 ; 2 .word L4 ; 3 .word L5 ; 4 .word L6 ; 5 .word L7 ; 6 .word L8 ; 7 .word L9 ; 8 .word L10 ; 9 .word L11 ; 10 .word L12 ; 11 .word L13 ; 12 .word L14 ; 13 .word L15 ; 14 .word L16 ; 15 .word L17 ; 16 extern int b; int func(int a) { switch (a) { case 0: b += 1; break; case 1: b += 2; break; case 2: b += 3; break; case 3: b += 4; break; ... • Table-size w/ no opt: 68 bytes • Compressed table size: 20 bytes TMS470 Compiler Overview
Optimization Hints • Optimization may uncover user errors like: • Uninitialized variables • Loose adherence to ANSI standard • Failure to use volatile • Use volatile on variables modified by: • Interrupts • Peripherals • Other processors • Issue remarks • “-pdr” • Compile with strict ANSI • “-ps” TMS470 Compiler Overview
Optimization Hints $func: ADD A1, A2, A1 MOV PC, LR int func(int a) { int t; return a + t; } • With optimization • auto variable now in • register as opposed • to a stack location • which may have • inadvertently worked. TMS470 Compiler Overview
Optimizer Hints volatile int *p; int x; void foo(int a) { x = a + 1; } void func(int a) { while (1) { *p++; foo(a); } } $func: LDR A2, CON1 SUB A2, #4 LDR A3, [A2, #0] ADD A4, A1, #1 MOV A1, A2 L1: LDR A2, [A3, #0] ADD A3, #4 STR A3, [A1, #0] STR A4, [A1, #4] B L1 • Optimizer • will remove • memory read • if ‘p’ is not • volatile TMS470 Compiler Overview
Programming Hints • Avoid embedded asm() statements in C • Act as barriers to optimization • Cannot assume any assignments to specific registers • Embedded assembly functions may not always work: void func(int a, int b, int c) { asm("\tMOV A4,A1"); asm("\tMOV V1,A2"); asm("\tMOV V2,A3"); } • The optimizer may • not pass any • arguments to ‘func’: • Could consider it an • empty function. • Could replace args • with constants TMS470 Compiler Overview