1 / 24

Xtensa C and C++ Compiler Ding-Kai Chen Tensilica, Inc dkchen@tensilica

Xtensa C and C++ Compiler Ding-Kai Chen Tensilica, Inc dkchen@tensilica.com. Presentation Outline. XCC history XCC target -- Xtensa configurable processor XCC details with examples User defined C types Operator overloading VLIW scheduling Auto-SIMD vectorization Operation fusion

rollo
Download Presentation

Xtensa C and C++ Compiler Ding-Kai Chen Tensilica, Inc dkchen@tensilica

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Xtensa C and C++ CompilerDing-Kai Chen Tensilica, Inc dkchen@tensilica.com

  2. Presentation Outline • XCC history • XCC target -- Xtensa configurable processor • XCC details with examples • User defined C types • Operator overloading • VLIW scheduling • Auto-SIMD vectorization • Operation fusion • SWP Changes

  3. XCC History • Got the first version of SGI Pro64 in May 2000 • First customer release, August 2001 • Release with IPA, August 2002 • Release with SWP, Feedback, VLIW, September 2004 • Release with GCC 4.2 Front End, October 2009 • Supports C and C++ applications • Other languages are not as important for embedded applications

  4. Xtensa Processor • 32-bit RISC processor targeting embedded dataplane applications • 16 32-bit general registers (AR)‏ • 24-bit base instructions • Configurable at design-time (not at run-time)‏ Xtensa Core Architecture

  5. Xtensa Configuration Options • Many pre-defined options to choose from • Endianness • Windowed vs non-windowed register file • Narrow (16-bit) instructions • Multipliers • Coprocessors (HiFi, Vectra, BBE, FP) • Specialized (e.g., MAX) instructions, etc Configuration Options Xtensa Core Architecture

  6. Targeting XCC to Base Xtensa and Tensilica Configurations • As part of retargeting to Xtensa, we used/added • Code-generator generator tool Olive for WHIRL to CGIR translation • Handles a lot of configuration specific code • Support for Xtensa zero-overhead loop instructions • CG Code-size optimization that commonizes instructions from control-flow predecessors • Feedback-directed speed vs code-size tradeoff • Support for flexible VLIW formats • Formats of different bit width and different number of issue slots

  7. Tensilica Instruction Extension (TIE)‏ • TIE is a language to describe new custom: • Register files up to 512 bits wide • Instructions up to 128 bits • VLIW formats up to 15 slots • C types mapped to custom register files • Vectorization rules • Fusion patterns • Operator overloading Custom TIE Configuration Options Xtensa Architecture

  8. XCC Challenges • Custom extensions in TIE are written at customer site and cannot be configured at XCC build time • Design goals: • Separation of config-independent code and config-dependent libraries • Re-targeting in minutes after TIE is designed or modified by processor architect at customer site • programming new HW extensions as native C types/operations

  9. Xtensa - Full Development Automation Processor Complete Hardware Design Source pre-verified RTL, EDA scripts, test suite Extensions Processor Configuration Xtensa Processor Generator* Use standard ASIC/COT design techniques andlibraries for any IC fabrication process 1. Select from menu 2. Explicit instruction description (TIE) Customized Software Tools C/C++ compiler Debuggers, Simulators, RTOSes * US Patent: 6,477,697

  10. TIE register file and operation in C: void vsum() { int i; int32x4* va = (int32x4*)a; int32x4* vb = (int32x4*)b; int32x4* vc = (int32x4*)c; for (i=0; i<VSIZE; i++) { // C intrinsic call vc[i] = add_v(va[i] , vb[i]); } } // new register file for int32x4 // vectorization Regfile v 128 16 // a new C type based on <v> regfile // and has 128-bit size and // 128-bit alignment ctype int32x4 128 128 v operation add_v { out v vout, in v va, in v vb } {} { assign vout = { va[127:96] + vb[127:96], va[95:64] + vb[95:64], va[63:32] + vb[63:32], va[31:0] + vb[31:0] }; } add_v is an intrinsic call in C In WHIRL, it is an intrinsic_op  optimizer friendly

  11. TIE C type support • Each TIE C type maps to a new WHIRL mtype • Each TIE regfile maps to a ISA_REGCLASS • GCC FE declares new C types and new intrinsics (added new TIE_TYPE tree code)‏ • WGEN translates TIE C type references to WHIRL loads/stores • Olive tool adds dynamic rules to handle new types and WHIRL opcodes • Added TN_mtype() for register spills/reloads • Made BE optimizations (CSE, ebo, etc) work

  12. TIE example – generated code #<loop> Loop body line 28, nesting depth: 1, iterations: 8 #<loop> unrolled 4 times load_v v0,a2,0 # [0*II+0] id:20 b+0x0 load_v v1,a3,0 # [0*II+1] id:19 a+0x0 load_v v2,a2,16 # [0*II+2] id:20 b+0x0 load_v v3,a3,16 # [0*II+3] id:19 a+0x0 load_v v4,a2,32 # [0*II+4] id:20 b+0x0 load_v v5,a3,32 # [0*II+5] id:19 a+0x0 load_v v6,a2,48 # [0*II+6] id:20 b+0x0 load_v v7,a3,48 # [0*II+7] id:19 a+0x0 addi a2,a2,64 # [0*II+8] addi a3,a3,64 # [0*II+9] addi a4,a4,64 # [0*II+10] add_v v0,v1,v0 # [0*II+11] add_v v1,v3,v2 # [0*II+12] add_v v2,v5,v4 # [0*II+13] add_v v3,v7,v6 # [0*II+14] store_v v0,a4,-64 # [0*II+15] id:21 c+0x0 store_v v1,a4,-48 # [0*II+16] id:21 c+0x0 store_v v2,a4,-32 # [0*II+17] id:21 c+0x0 store_v v3,a4,-16 # [0*II+18] id:21 c+0x0 Total 19/4 = 4.75 cycles per iteration

  13. TIE updating ld/st // pre-increment load/store operation load_vu { out v vout, inout AR base, in simm8 offset } { out VAddr, in MemDataIn128 } { assign VAddr = base + offset; assign vout = MemDataIn128; assign base = base + offset; } operation store_vu { in v vin, inout AR base, in simm8 offset } { out VAddr, out MemDataOut128 } { assign VAddr = base + offset; assign MemDataOut128 = vin; assign base = base + offset; } proto int32x4_loadiu { out int32x4 vout, inout int32x4* base, in immediate offset } {} { load_vu vout, base, offset; } proto int32x4_storeiu { in int32x4 vin, inout int32x4* base, in immediate offset } {} { store_vu vin, base, offset; }

  14. TIE updating ld/st • XCC Identifies updating ld/st operations • Pre-bias ld/st bases to work with pre-increment • Combine ld/st with addi in CG • #<loop> Loop body line 28, nesting depth: 1, iterations: 32 • load_vu v0,a2,16 # [0*II+0] id:20 b+0x0 • load_vu v1,a3,16 # [0*II+1] id:19 a+0x0 • store_vu v2,a4,16 # [1*II+2] id:21 c+0x0 • add_v v2,v1,v0 # [0*II+3] • total 4 cycles per iteration

  15. TIE operator overloading • Check for TIE type operands and operator overloading in build_binary_op in c-typeck.c of GCC • Build proper call to mapped TIE intrinsic // map “+” operator to add_v for // type int32x4 operator "+" add_v in C: void vsum_op() { int i; int32x4* va = (int32x4*)a; int32x4* vb = (int32x4*)b; int32x4* vc = (int32x4*)c; for (i=0; i<VSIZE; i++) { // more natural using C “+” syntax vc[i] = va[i] + vb[i]; } }

  16. TIE VLIW scheduling format flix0 64 {slot0,slot1} // add 2-slots 64-bit VLIW format slot_opcodes slot0 { load_v, store_v, load_vu, store_vu, add_v } slot_opcodes slot1 { load_v, store_v, load_vu, store_vu, add_v } ---------------------------------- .s output -------------------------------------------------- #<loop> unrolled 2 times { # format flix0 load_vu v3,a2,32 # [0*II+0] id:20 b+0x0 add_v v5,v4,v3 # [1*II+0] } { # format flix0 load_v v0,a2,-16 # [0*II+1] id:20 b+0x0 add_v v2,v1,v0 # [1*II+1] } { # format flix0 load_v v1,a3,16 # [0*II+2] id:19 a+0x0 load_vu v4,a3,32 # [0*II+2] id:19 a+0x0 } { # format flix0 store_v v2,a4,16 # [1*II+3] id:21 c+0x0 store_vu v5,a4,32 # [1*II+3] id:21 c+0x0 } total 4/2=2 cycles per iteration

  17. TIE VLIW scheduling • XCC initialization includes analysis on TIE VLIW formats • Create resources that model bundling constraints • Consider a simpler case: 1 slot is allowed for each opcode • Each VLIW slot in a format is viewed as a resource • Different formats are treated separately • Each opcode consumes the resource of the slot it is allowed • For a group of operations, if the total resource usage is within the limit  can be scheduled in the same cycle • Get complicated when multiple slots are allowed for opcodes • Resource reservation modeling allows de-coupling of scheduling and slot assignment in CG • Extended resource reservation word type SI_RRW to arbitrary length bit-vectors • TI_RES_RES_Resources_Available() also checks for compatible formats

  18. TIE auto-SIMD vectorization propertyvector_ctype {int32x4, int32, 4} propertyvector_proto {add_v, xt_add, 4} in C: for (i=0; i<SIZE; i++) { c[i] = a[i] + b[i]; } with -O3 -LNO:simd -clist, in .w2c: int32x4 V_00; int32x4 V_; int32x4 V_0; int32x4 V_4; _INT32 i; for(i = 0; i <= 127; i = i + 4)‏ { V_00 = *(int32x4 *)(&a[i]); V_ = *(int32x4 *)(&b[i]); V_0 = add_v(V_00, V_); V_4 = V_0; * (int32x4 *)(&c[i]) = V_4; }

  19. TIE auto-SIMD vectorization • Developed independently (before) Open64 Vectorizer • Integrate into Phase2 of LNO • Scan all loops in a nest • Check for presence of vectorized versions of each op in the loop • Check for stride-1 or invariant memory references • Support for loads and stores with addresses not aligned as vector type • Pre-load once before the vector loop • Subsequent loads in the vector loop combine with the prior loads • Support for spatial reuse within a vector using select instruction • E.g. a[i] + a[i+1] in the scalar loop • Pre-load once before the vector loop • Only a single load is needed now for each iteration • Select instructions shuffle data from loads of consecutive iterations

  20. TIE operation fusion • Combine multiple operations to one • E.g., combines an add followed by a shift to one add_shift operation • Performed in CG • Build dataflow graphs from input patterns • Repeatedly search for matches in BBs • Peephole optimization with custom patterns imap add_shift_v { out v vout, in v va, in v vb, in immediate amount } { {} { // the output pattern add_shift_v vout, va, vb, amount; } } { { v v_temp } { // the input pattern add_v v_temp, va, vb; shift_v vout, v_temp, amount; } }

  21. TIE operation fusion • Example C code: • for (i=0; i<VSIZE; i++) { vc[i] = (va[i] + vb[i]) << 2; } • Original schedule is 5 cycles / 2 iter = 2.5 cycles per iteration • New schedule with operation fusion is 4 cycles / 2 iter = 2 cycles per iteration

  22. XCC SWP scheduler • Xtensa has no rotating registers – added 2 register allocators, simple and coloring. Use simple first to get tighter bound then try coloring. • Performance is critical: added back-tracking for the following • Unrolling (hard to guess best unrolling) • Different priority heuristics for choosing candidates • Different initial op orderings • Register allocation failures • Runs slightly longer but complements the original IA-64 based SWP algorithm well

  23. Conclusion • Open64 is versatile in providing optimized performance for embedded applications. • XCC experience shows that many of the optimizations can be adapted to retarget for ISA extensions quickly. • Sample Performance Data: • EEMBC Consumer benchmark gained 6x speedup with automatic vectorization + vliw scheduling + operation fusion • XCC solution is not final. It is still evolving with new HW features offered from Tensilica. • Want to explore new ways in TIE to describe HW that supports optimizations.

  24. Tensilica is looking for new talent to join the compiler team. http://www.tensilica.com dkchen@tensilica.com

More Related