# HG changeset patch # User Nobuyasu Oshiro # Date 1325456955 -32400 # Node ID 48de60dd51d16670f0b6209367c5885c881b88be # Parent 64d22e65489c4115b0384f73c26bf390f3c96d66 modify explanation of TCE diff -r 64d22e65489c -r 48de60dd51d1 presen/index.html --- a/presen/index.html Mon Jan 02 05:34:11 2012 +0900 +++ b/presen/index.html Mon Jan 02 07:29:15 2012 +0900 @@ -9,7 +9,7 @@ font-size:28px; } td.srctd { -height:20em; +height:18em; } pre.srcbox { height: 100%; @@ -312,7 +312,7 @@ - + @@ -670,7 +696,7 @@
  • 具体的な実装
  • @@ -687,7 +713,10 @@

    CbCの実装:TCE(末尾除去)

    -
  • try_tail_callフラグが落とされるif文
  • +
  • try_tail_callフラグが落とされる部分
  • +
    SSARTLRTL(一部)
    @@ -348,8 +348,34 @@
    -(call (mem:QI (symbol_ref:DI ("print_factorial") [flags 0x403]  <function_decl 0x146f6b200 print_factorial>) [0 S1 A8])
    -        (const_int 0 [0]))
    +(jump_insn 20 19 21 5 (set (pc)
    +        (if_then_else (le (reg:CCGC 17 flags)
    +                (const_int 0 [0]))
    +            (label_ref 17)
    +            (pc))) factorial.c:12 -1
    +     (nil)
    + -> 17)
    +
    +(note 21 20 22 6 [bb 6] NOTE_INSN_BASIC_BLOCK)
    +
    +(insn 22 21 23 6 (set (reg:SI 62)
    +        (mem/c/i:SI (plus:DI (reg/f:DI 54 virtual-stack-vars)
    +                (const_int -4 [0xfffffffffffffffc])) [0 prod+0 S4 A32])) factorial.c:15 -1
    +     (nil))
    +
    +(insn 23 22 24 6 (set (reg:SI 5 di)
    +        (reg:SI 62)) factorial.c:15 -1
    +     (nil))
    +
    +(call_insn 24 23 25 6 (call (mem:QI (symbol_ref:DI ("print_factorial") [flags 0x403]  ) [0 S1 A8])
    +        (const_int 0 [0])) factorial.c:15 -1
    +     (nil)
    +    (expr_list:REG_DEP_TRUE (use (reg:SI 5 di))
    +        (nil)))
    +
    +(code_label 25 24 26 7 2 "" [0 uses])
    +
    +(note 26 25 0 7 [bb 7] NOTE_INSN_BASIC_BLOCK)
                   
    + + + +
       if (currently_expanding_call++ != 0
           || ((!fndecl || !CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl))) 
    @@ -696,11 +725,16 @@
           || dbg_cnt (tail_call) == false)
         try_tail_call = 0;
     	
    +
    +
  • !CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl)により条件を回避
  • +

    CbCの実装:TCE(末尾除去)

  • try_tail_callフラグが落とされる部分
  • - +
    @@ -733,7 +767,89 @@
     	    
    +
  • 引数のスタックサイズ、関数の型のチェックが行われる。
  • +
    + +
    +

    CbCの実装:TCE(末尾除去)

    +
  • try_tail_callフラグが落とされる部分
  • + + + + +
    +
    +  /* Check if caller and callee disagree in promotion of function                                                                                                                      
    +     return value.  */
    +#ifndef noCbC
    +  if (try_tail_call && (!fndecl || !CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl))))
    +#else
    +    if (try_tail_call)
    +#endif
    +    {
    +      enum machine_mode caller_mode, caller_promoted_mode;
    +      enum machine_mode callee_mode, callee_promoted_mode;
    +      int caller_unsignedp, callee_unsignedp;
    +      tree caller_res = DECL_RESULT (current_function_decl);
     
    +      caller_unsignedp = TYPE_UNSIGNED (TREE_TYPE (caller_res));
    +      caller_mode = DECL_MODE (caller_res);
    +      callee_unsignedp = TYPE_UNSIGNED (TREE_TYPE (funtype));
    +      callee_mode = TYPE_MODE (TREE_TYPE (funtype));
    +      caller_promoted_mode
    +        = promote_function_mode (TREE_TYPE (caller_res), caller_mode,
    +                                 &caller_unsignedp,
    +                                 TREE_TYPE (current_function_decl), 1);
    +      callee_promoted_mode
    +        = promote_function_mode (TREE_TYPE (funtype), callee_mode,
    +                                 &callee_unsignedp,
    +                                 funtype, 1);
    +      if (caller_mode != VOIDmode
    +          && (caller_promoted_mode != callee_promoted_mode
    +              || ((caller_mode != caller_promoted_mode
    +                   || callee_mode != callee_promoted_mode)
    +                  && (caller_unsignedp != callee_unsignedp
    +                      || GET_MODE_BITSIZE (caller_mode)
    +                         < GET_MODE_BITSIZE (callee_mode)))))
    +        try_tail_call = 0;
    +    }
    +	
    +
    +
  • 関数の型のチェックが行われる。
  • +
    + +
    +

    CbCの実装:TCE(末尾除去)

    +
  • try_tail_callフラグ矯正付与のソースコード
  • + + + + +
    +
    +#ifndef noCbC
    +  if (fndecl && CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl))
    +      && CbC_IS_CODE_SEGMENT (TREE_TYPE (current_function_decl))
    +      && try_tail_call == 0)
    +    {
    +      location_t loc = EXPR_LOCATION (exp);
    +      char *name_callee = IDENTIFIER_POINTER(DECL_NAME(fndecl));
    +      warning_at (loc, 0, "transition to code segment \"%s\" with CbC goto, but tail call optimization was cut.",
    +                        name_callee);
    +      try_tail_call = 1;
    +    }
    +#endif
    +	
    +
    +
    + +
    +

    CbCの実装:TCE(末尾除去)

    +
    -

    -
  • -
    - -

    まとめ